Normalize line endings and whitespace in source files

This commit is contained in:
Paul Bartell 2022-11-29 10:36:04 -08:00 committed by Paul Bartell
parent 151fb04ad1
commit 01820d3ed9
574 changed files with 162626 additions and 172362 deletions

2
.github/CODEOWNERS vendored
View file

@ -35,5 +35,3 @@
# directory in the root of your repository and any of its # directory in the root of your repository and any of its
# subdirectories. # subdirectories.
# /docs/ @doctocat # /docs/ @doctocat

View file

@ -3,4 +3,3 @@ contact_links:
- name: FreeRTOS Community Support Forum - name: FreeRTOS Community Support Forum
url: https://forums.freertos.org/ url: https://forums.freertos.org/
about: Please ask and answer questions about FreeRTOS here. about: Please ask and answer questions about FreeRTOS here.

View file

@ -60,4 +60,3 @@ function test {
} }
test test

View file

@ -4,4 +4,3 @@ new_text=$2
echo "Old text: ${old_text}" echo "Old text: ${old_text}"
echo "New text: ${new_text}" echo "New text: ${new_text}"
grep -rl "${old_text}" . | xargs gsed -i -e '1h;2,$H;$!d;g' -e "s/${old_text}/${new_text}/g" grep -rl "${old_text}" . | xargs gsed -i -e '1h;2,$H;$!d;g' -e "s/${old_text}/${new_text}/g"

View file

@ -149,4 +149,3 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
exit(main()) exit(main())

View file

@ -78,4 +78,3 @@ jobs:
- name: URL Checker - name: URL Checker
run: | run: |
bash kernel/.github/actions/url_verifier.sh kernel bash kernel/.github/actions/url_verifier.sh kernel

View file

@ -5,4 +5,3 @@ URL=https://github.com/FreeRTOS/FreeRTOS-Kernel
IconIndex=0 IconIndex=0
IDList= IDList=
HotKey=0 HotKey=0

View file

@ -3051,6 +3051,3 @@ Changes between V1.00 and V1.01
+ Prevent the call to kbhit() in main.c for debug builds as the debugger + Prevent the call to kbhit() in main.c for debug builds as the debugger
seems to have problems stepping over the call. This if for the PC port seems to have problems stepping over the call. This if for the PC port
only. only.

View file

@ -48,86 +48,86 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */ " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" movs r5, #4 \n"/* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r2] \n"/* Program RNR = 4. */ " str r5, [r2] \n"/* Program RNR = 4. */
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n"/* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r2] \n"/* Program RNR = 5. */ " str r5, [r2] \n"/* Program RNR = 5. */
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n"/* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r2] \n"/* Program RNR = 6. */ " str r5, [r2] \n"/* Program RNR = 6. */
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n"/* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r2] \n"/* Program RNR = 7. */ " str r5, [r2] \n"/* Program RNR = 7. */
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n"/* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r4 \n"/* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -137,19 +137,19 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -159,13 +159,13 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n"/* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -175,13 +175,13 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n"/* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -191,20 +191,20 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -214,11 +214,11 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, PRIMASK \n" " mrs r0, PRIMASK \n"
" cpsid i \n" " cpsid i \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -228,10 +228,10 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr PRIMASK, r0 \n" " msr PRIMASK, r0 \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -241,181 +241,181 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ " ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/ " ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
" mrs r2, psp \n"/* Read PSP in r2. */ " mrs r2, psp \n"/* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n"/* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n"/* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n"/* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ " subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */ " adds r2, r2, #16 \n"/* r2 = r2 + 16. */
" stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */ " stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r2, r2, #48 \n"/* r2 = r2 - 48. */ " subs r2, r2, #48 \n"/* r2 = r2 - 48. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ " stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r3] \n"/* Disable MPU. */ " str r4, [r3] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */ " ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r3] \n"/* Program MAIR0. */ " str r4, [r3] \n"/* Program MAIR0. */
" ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */ " ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r5, #4 \n"/* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r4] \n"/* Program RNR = 4. */ " str r5, [r4] \n"/* Program RNR = 4. */
" ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n"/* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r4] \n"/* Program RNR = 5. */ " str r5, [r4] \n"/* Program RNR = 5. */
" ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n"/* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r4] \n"/* Program RNR = 6. */ " str r5, [r4] \n"/* Program RNR = 6. */
" ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n"/* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r4] \n"/* Program RNR = 7. */ " str r5, [r4] \n"/* Program RNR = 7. */
" ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r3] \n"/* Enable MPU. */ " str r4, [r3] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ " ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" adds r2, r2, #16 \n"/* Move to the high registers. */ " adds r2, r2, #16 \n"/* Move to the high registers. */
" ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ " ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n"/* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n"/* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n"/* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n"/* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" subs r2, r2, #32 \n"/* Go back to the low registers. */ " subs r2, r2, #32 \n"/* Go back to the low registers. */
" ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */ " ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -425,22 +425,22 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" movs r0, #4 \n" " movs r0, #4 \n"
" mov r1, lr \n" " mov r1, lr \n"
" tst r0, r1 \n" " tst r0, r1 \n"
" beq stacking_used_msp \n" " beq stacking_used_msp \n"
" mrs r0, psp \n" " mrs r0, psp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" stacking_used_msp: \n" " stacking_used_msp: \n"
" mrs r0, msp \n" " mrs r0, msp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -449,10 +449,10 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" svc %0 \n"/* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
@ -462,16 +462,16 @@ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PR
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */ " ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */ " ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ " cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" bne free_secure_context \n"/* Branch if r1 != 0. */ " bne free_secure_context \n"/* Branch if r1 != 0. */
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */ " bx lr \n"/* There is no secure context (xSecureContext is NULL). */
" free_secure_context: \n" " free_secure_context: \n"
" svc %0 \n"/* Secure context is freed in the supervisor call. */ " svc %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }

View file

@ -48,81 +48,81 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n"/* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n"/* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n"/* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n"/* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n"/* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n"/* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r2 \n"/* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -132,19 +132,19 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -154,13 +154,13 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n"/* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -170,13 +170,13 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n"/* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -186,20 +186,20 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -209,11 +209,11 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, PRIMASK \n" " mrs r0, PRIMASK \n"
" cpsid i \n" " cpsid i \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -223,10 +223,10 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr PRIMASK, r0 \n" " msr PRIMASK, r0 \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -236,121 +236,121 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n"/* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ " stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */ " subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n"/* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ " stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n"/* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n"/* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n"/* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n"/* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n"/* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n"/* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" adds r0, r0, #28 \n"/* Move to the high registers. */ " adds r0, r0, #28 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n"/* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n"/* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n"/* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n"/* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #44 \n"/* Move to the starting of the saved context. */ " subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
" bx r3 \n" " bx r3 \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" adds r0, r0, #24 \n"/* Move to the high registers. */ " adds r0, r0, #24 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n"/* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n"/* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n"/* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n"/* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #40 \n"/* Move to the starting of the saved context. */ " subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" bx r3 \n" " bx r3 \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -360,22 +360,22 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" movs r0, #4 \n" " movs r0, #4 \n"
" mov r1, lr \n" " mov r1, lr \n"
" tst r0, r1 \n" " tst r0, r1 \n"
" beq stacking_used_msp \n" " beq stacking_used_msp \n"
" mrs r0, psp \n" " mrs r0, psp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" stacking_used_msp: \n" " stacking_used_msp: \n"
" mrs r0, msp \n" " mrs r0, msp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -44,88 +44,88 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */ " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r2] \n"/* Program RNR = 8. */ " str r4, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r2] \n"/* Program RNR = 12. */ " str r4, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n"/* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r4 \n"/* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -135,16 +135,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -154,12 +154,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -169,12 +169,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -184,21 +184,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -208,14 +208,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -225,12 +225,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -240,180 +240,180 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ " ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
" mrs r2, psp \n"/* Read PSP in r2. */ " mrs r2, psp \n"/* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n"/* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n"/* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n"/* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB.*/ " ldr r1, [r3] \n"/* Read pxCurrentTCB.*/
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ " subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */ " adds r2, r2, #16 \n"/* r2 = r2 + 16. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r2, r2, #16 \n"/* r2 = r2 - 16. */ " subs r2, r2, #16 \n"/* r2 = r2 - 16. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n"/* r2 = r2 + 12. */ " adds r2, r2, #12 \n"/* r2 = r2 + 12. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n"/* r2 = r2 - 12. */ " subs r2, r2, #12 \n"/* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r3] \n"/* Disable MPU. */ " str r4, [r3] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */ " ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r3] \n"/* Program MAIR0. */ " str r4, [r3] \n"/* Program MAIR0. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r3] \n"/* Program RNR = 4. */ " str r4, [r3] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r3] \n"/* Program RNR = 8. */ " str r4, [r3] \n"/* Program RNR = 8. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r3] \n"/* Program RNR = 12. */ " str r4, [r3] \n"/* Program RNR = 12. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r3] \n"/* Enable MPU. */ " str r4, [r3] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ " ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -424,17 +424,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -443,10 +443,10 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" svc %0 \n"/* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
@ -456,14 +456,14 @@ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PR
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */ " ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */ " ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ " cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" it ne \n" " it ne \n"
" svcne %0 \n"/* Secure context is freed in the supervisor call. */ " svcne %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }

View file

@ -44,83 +44,83 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r2 \n"/* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -130,16 +130,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -149,12 +149,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -164,12 +164,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -179,21 +179,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -203,14 +203,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -220,12 +220,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -235,110 +235,110 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n"/* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ " stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" mrs r2, psplim \n"/* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" \n" " \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" bx r3 \n" " bx r3 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -349,17 +349,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -33,27 +33,27 @@ the code is included in C files but excluded by the preprocessor in assembly
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */ files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN xSecureContext EXTERN xSecureContext
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN vPortSVCHandler_C EXTERN vPortSVCHandler_C
EXTERN SecureContext_SaveContext EXTERN SecureContext_SaveContext
EXTERN SecureContext_LoadContext EXTERN SecureContext_LoadContext
PUBLIC xIsPrivileged PUBLIC xIsPrivileged
PUBLIC vResetPrivilege PUBLIC vResetPrivilege
PUBLIC vPortAllocateSecureContext PUBLIC vPortAllocateSecureContext
PUBLIC vRestoreContextOfFirstTask PUBLIC vRestoreContextOfFirstTask
PUBLIC vRaisePrivilege PUBLIC vRaisePrivilege
PUBLIC vStartFirstTask PUBLIC vStartFirstTask
PUBLIC ulSetInterruptMask PUBLIC ulSetInterruptMask
PUBLIC vClearInterruptMask PUBLIC vClearInterruptMask
PUBLIC PendSV_Handler PUBLIC PendSV_Handler
PUBLIC SVC_Handler PUBLIC SVC_Handler
PUBLIC vPortFreeSecureContext PUBLIC vPortFreeSecureContext
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -61,331 +61,331 @@ files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler.
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2) SECTION .text:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xIsPrivileged: xIsPrivileged:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
movs r1, #1 /* r1 = 1. */ movs r1, #1 /* r1 = 1. */
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
beq running_privileged /* If the result of previous AND operation was 0, branch. */ beq running_privileged /* If the result of previous AND operation was 0, branch. */
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
bx lr /* Return. */ bx lr /* Return. */
running_privileged: running_privileged:
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vResetPrivilege: vResetPrivilege:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
movs r1, #1 /* r1 = 1. */ movs r1, #1 /* r1 = 1. */
orrs r0, r1 /* r0 = r0 | r1. */ orrs r0, r1 /* r0 = r0 | r1. */
msr control, r0 /* CONTROL = r0. */ msr control, r0 /* CONTROL = r0. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortAllocateSecureContext: vPortAllocateSecureContext:
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */ svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*----------------- Privileged Functions --------------------*/ /*----------------- Privileged Functions --------------------*/
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION privileged_functions:CODE:NOROOT(2) SECTION privileged_functions:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRestoreContextOfFirstTask: vRestoreContextOfFirstTask:
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r3, [r2] /* Read pxCurrentTCB. */ ldr r3, [r2] /* Read pxCurrentTCB. */
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
movs r5, #1 /* r5 = 1. */ movs r5, #1 /* r5 = 1. */
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
str r4, [r2] /* Disable MPU. */ str r4, [r2] /* Disable MPU. */
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */ ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
str r4, [r2] /* Program MAIR0. */ str r4, [r2] /* Program MAIR0. */
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */ ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
movs r5, #4 /* r5 = 4. */ movs r5, #4 /* r5 = 4. */
str r5, [r2] /* Program RNR = 4. */ str r5, [r2] /* Program RNR = 4. */
ldmia r3!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */ ldmia r3!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */ ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
stmia r4!, {r6,r7} /* Write first set of RBAR/RLAR registers. */ stmia r4!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
movs r5, #5 /* r5 = 5. */ movs r5, #5 /* r5 = 5. */
str r5, [r2] /* Program RNR = 5. */ str r5, [r2] /* Program RNR = 5. */
ldmia r3!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */ ldmia r3!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */ ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
stmia r4!, {r6,r7} /* Write second set of RBAR/RLAR registers. */ stmia r4!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
movs r5, #6 /* r5 = 6. */ movs r5, #6 /* r5 = 6. */
str r5, [r2] /* Program RNR = 6. */ str r5, [r2] /* Program RNR = 6. */
ldmia r3!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */ ldmia r3!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */ ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
stmia r4!, {r6,r7} /* Write third set of RBAR/RLAR registers. */ stmia r4!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
movs r5, #7 /* r5 = 7. */ movs r5, #7 /* r5 = 7. */
str r5, [r2] /* Program RNR = 7. */ str r5, [r2] /* Program RNR = 7. */
ldmia r3!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */ ldmia r3!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */ ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
stmia r4!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */ stmia r4!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
movs r5, #1 /* r5 = 1. */ movs r5, #1 /* r5 = 1. */
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
str r4, [r2] /* Enable MPU. */ str r4, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
ldr r5, =xSecureContext ldr r5, =xSecureContext
str r1, [r5] /* Set xSecureContext to this task's value for the same. */ str r1, [r5] /* Set xSecureContext to this task's value for the same. */
msr psplim, r2 /* Set this task's PSPLIM value. */ msr psplim, r2 /* Set this task's PSPLIM value. */
msr control, r3 /* Set this task's CONTROL value. */ msr control, r3 /* Set this task's CONTROL value. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
bx r4 /* Finally, branch to EXC_RETURN. */ bx r4 /* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
msr psplim, r2 /* Set this task's PSPLIM value. */ msr psplim, r2 /* Set this task's PSPLIM value. */
movs r1, #2 /* r1 = 2. */ movs r1, #2 /* r1 = 2. */
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */ msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
bx r3 /* Finally, branch to EXC_RETURN. */ bx r3 /* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRaisePrivilege: vRaisePrivilege:
mrs r0, control /* Read the CONTROL register. */ mrs r0, control /* Read the CONTROL register. */
movs r1, #1 /* r1 = 1. */ movs r1, #1 /* r1 = 1. */
bics r0, r1 /* Clear the bit 0. */ bics r0, r1 /* Clear the bit 0. */
msr control, r0 /* Write back the new CONTROL value. */ msr control, r0 /* Write back the new CONTROL value. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vStartFirstTask: vStartFirstTask:
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */ ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */ ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
ldr r0, [r0] /* The first entry in vector table is stack pointer. */ ldr r0, [r0] /* The first entry in vector table is stack pointer. */
msr msp, r0 /* Set the MSP back to the start of the stack. */ msr msp, r0 /* Set the MSP back to the start of the stack. */
cpsie i /* Globally enable interrupts. */ cpsie i /* Globally enable interrupts. */
dsb dsb
isb isb
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */ svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
ulSetInterruptMask: ulSetInterruptMask:
mrs r0, PRIMASK mrs r0, PRIMASK
cpsid i cpsid i
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vClearInterruptMask: vClearInterruptMask:
msr PRIMASK, r0 msr PRIMASK, r0
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
PendSV_Handler: PendSV_Handler:
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} push {r0-r2, r14}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r3} /* LR is now in r3. */
mov lr, r3 /* LR = r3. */ mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mrs r3, control /* r3 = CONTROL. */ mrs r3, control /* r3 = CONTROL. */
mov r4, lr /* r4 = LR/EXC_RETURN. */ mov r4, lr /* r4 = LR/EXC_RETURN. */
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */ subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */ stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
b select_next_task b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #16 /* r2 = r2 + 16. */ adds r2, r2, #16 /* r2 = r2 + 16. */
stmia r2!, {r4-r7} /* Store the low registers that are not saved automatically. */ stmia r2!, {r4-r7} /* Store the low registers that are not saved automatically. */
mov r4, r8 /* r4 = r8. */ mov r4, r8 /* r4 = r8. */
mov r5, r9 /* r5 = r9. */ mov r5, r9 /* r5 = r9. */
mov r6, r10 /* r6 = r10. */ mov r6, r10 /* r6 = r10. */
mov r7, r11 /* r7 = r11. */ mov r7, r11 /* r7 = r11. */
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */ stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mrs r3, control /* r3 = CONTROL. */ mrs r3, control /* r3 = CONTROL. */
mov r4, lr /* r4 = LR/EXC_RETURN. */ mov r4, lr /* r4 = LR/EXC_RETURN. */
subs r2, r2, #48 /* r2 = r2 - 48. */ subs r2, r2, #48 /* r2 = r2 - 48. */
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmia r2!, {r0, r1, r3-r7} /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ stmia r2!, {r0, r1, r3-r7} /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
mov r4, r8 /* r4 = r8. */ mov r4, r8 /* r4 = r8. */
mov r5, r9 /* r5 = r9. */ mov r5, r9 /* r5 = r9. */
mov r6, r10 /* r6 = r10. */ mov r6, r10 /* r6 = r10. */
mov r7, r11 /* r7 = r11. */ mov r7, r11 /* r7 = r11. */
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */ stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
select_next_task: select_next_task:
cpsid i cpsid i
bl vTaskSwitchContext bl vTaskSwitchContext
cpsie i cpsie i
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r3] /* Read the value of MPU_CTRL. */ ldr r4, [r3] /* Read the value of MPU_CTRL. */
movs r5, #1 /* r5 = 1. */ movs r5, #1 /* r5 = 1. */
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
str r4, [r3] /* Disable MPU. */ str r4, [r3] /* Disable MPU. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */ ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */ ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
str r4, [r3] /* Program MAIR0. */ str r4, [r3] /* Program MAIR0. */
ldr r4, =0xe000ed98 /* r4 = 0xe000ed98 [Location of RNR]. */ ldr r4, =0xe000ed98 /* r4 = 0xe000ed98 [Location of RNR]. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
movs r5, #4 /* r5 = 4. */ movs r5, #4 /* r5 = 4. */
str r5, [r4] /* Program RNR = 4. */ str r5, [r4] /* Program RNR = 4. */
ldmia r1!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */ ldmia r1!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r6,r7} /* Write first set of RBAR/RLAR registers. */ stmia r3!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
movs r5, #5 /* r5 = 5. */ movs r5, #5 /* r5 = 5. */
str r5, [r4] /* Program RNR = 5. */ str r5, [r4] /* Program RNR = 5. */
ldmia r1!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */ ldmia r1!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r6,r7} /* Write second set of RBAR/RLAR registers. */ stmia r3!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
movs r5, #6 /* r5 = 6. */ movs r5, #6 /* r5 = 6. */
str r5, [r4] /* Program RNR = 6. */ str r5, [r4] /* Program RNR = 6. */
ldmia r1!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */ ldmia r1!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r6,r7} /* Write third set of RBAR/RLAR registers. */ stmia r3!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
movs r5, #7 /* r5 = 7. */ movs r5, #7 /* r5 = 7. */
str r5, [r4] /* Program RNR = 7. */ str r5, [r4] /* Program RNR = 7. */
ldmia r1!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */ ldmia r1!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */ stmia r3!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r3] /* Read the value of MPU_CTRL. */ ldr r4, [r3] /* Read the value of MPU_CTRL. */
movs r5, #1 /* r5 = 1. */ movs r5, #1 /* r5 = 1. */
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
str r4, [r3] /* Enable MPU. */ str r4, [r3] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ msr psplim, r1 /* Restore the PSPLIM register value for the task. */
msr control, r3 /* Restore the CONTROL register value for the task. */ msr control, r3 /* Restore the CONTROL register value for the task. */
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's xSecureContext. */ str r0, [r3] /* Restore the task's xSecureContext. */
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */ cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
push {r2, r4} push {r2, r4}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r2, r4}
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ msr psplim, r1 /* Restore the PSPLIM register value for the task. */
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's xSecureContext. */ str r0, [r3] /* Restore the task's xSecureContext. */
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */ cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
push {r2, r4} push {r2, r4}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r2, r4}
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
restore_ns_context: restore_ns_context:
adds r2, r2, #16 /* Move to the high registers. */ adds r2, r2, #16 /* Move to the high registers. */
ldmia r2!, {r4-r7} /* Restore the high registers that are not automatically restored. */ ldmia r2!, {r4-r7} /* Restore the high registers that are not automatically restored. */
mov r8, r4 /* r8 = r4. */ mov r8, r4 /* r8 = r4. */
mov r9, r5 /* r9 = r5. */ mov r9, r5 /* r9 = r5. */
mov r10, r6 /* r10 = r6. */ mov r10, r6 /* r10 = r6. */
mov r11, r7 /* r11 = r7. */ mov r11, r7 /* r11 = r7. */
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
subs r2, r2, #32 /* Go back to the low registers. */ subs r2, r2, #32 /* Go back to the low registers. */
ldmia r2!, {r4-r7} /* Restore the low registers that are not automatically restored. */ ldmia r2!, {r4-r7} /* Restore the low registers that are not automatically restored. */
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SVC_Handler: SVC_Handler:
movs r0, #4 movs r0, #4
mov r1, lr mov r1, lr
tst r0, r1 tst r0, r1
beq stacking_used_msp beq stacking_used_msp
mrs r0, psp mrs r0, psp
b vPortSVCHandler_C b vPortSVCHandler_C
stacking_used_msp: stacking_used_msp:
mrs r0, msp mrs r0, msp
b vPortSVCHandler_C b vPortSVCHandler_C
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortFreeSecureContext: vPortFreeSecureContext:
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */ ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */ ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */ cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
bne free_secure_context /* Branch if r1 != 0. */ bne free_secure_context /* Branch if r1 != 0. */
bx lr /* There is no secure context (xSecureContext is NULL). */ bx lr /* There is no secure context (xSecureContext is NULL). */
free_secure_context: free_secure_context:
svc 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */ svc 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
END END

View file

@ -32,22 +32,22 @@ the code is included in C files but excluded by the preprocessor in assembly
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */ files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN vPortSVCHandler_C EXTERN vPortSVCHandler_C
PUBLIC xIsPrivileged PUBLIC xIsPrivileged
PUBLIC vResetPrivilege PUBLIC vResetPrivilege
PUBLIC vRestoreContextOfFirstTask PUBLIC vRestoreContextOfFirstTask
PUBLIC vRaisePrivilege PUBLIC vRaisePrivilege
PUBLIC vStartFirstTask PUBLIC vStartFirstTask
PUBLIC ulSetInterruptMask PUBLIC ulSetInterruptMask
PUBLIC vClearInterruptMask PUBLIC vClearInterruptMask
PUBLIC PendSV_Handler PUBLIC PendSV_Handler
PUBLIC SVC_Handler PUBLIC SVC_Handler
#if ( configENABLE_FPU == 1 ) #if ( configENABLE_FPU == 1 )
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -55,256 +55,256 @@ files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler.
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2) SECTION .text:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xIsPrivileged: xIsPrivileged:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
movs r1, #1 /* r1 = 1. */ movs r1, #1 /* r1 = 1. */
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
beq running_privileged /* If the result of previous AND operation was 0, branch. */ beq running_privileged /* If the result of previous AND operation was 0, branch. */
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
bx lr /* Return. */ bx lr /* Return. */
running_privileged: running_privileged:
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vResetPrivilege: vResetPrivilege:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
movs r1, #1 /* r1 = 1. */ movs r1, #1 /* r1 = 1. */
orrs r0, r1 /* r0 = r0 | r1. */ orrs r0, r1 /* r0 = r0 | r1. */
msr control, r0 /* CONTROL = r0. */ msr control, r0 /* CONTROL = r0. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*----------------- Privileged Functions --------------------*/ /*----------------- Privileged Functions --------------------*/
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION privileged_functions:CODE:NOROOT(2) SECTION privileged_functions:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRestoreContextOfFirstTask: vRestoreContextOfFirstTask:
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */ ldr r3, [r2] /* Read the value of MPU_CTRL. */
movs r4, #1 /* r4 = 1. */ movs r4, #1 /* r4 = 1. */
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
str r3, [r2] /* Disable MPU. */ str r3, [r2] /* Disable MPU. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */ ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
str r4, [r2] /* Program MAIR0. */ str r4, [r2] /* Program MAIR0. */
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */ ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
movs r4, #4 /* r4 = 4. */ movs r4, #4 /* r4 = 4. */
str r4, [r2] /* Program RNR = 4. */ str r4, [r2] /* Program RNR = 4. */
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
movs r4, #5 /* r4 = 5. */ movs r4, #5 /* r4 = 5. */
str r4, [r2] /* Program RNR = 5. */ str r4, [r2] /* Program RNR = 5. */
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
movs r4, #6 /* r4 = 6. */ movs r4, #6 /* r4 = 6. */
str r4, [r2] /* Program RNR = 6. */ str r4, [r2] /* Program RNR = 6. */
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
movs r4, #7 /* r4 = 7. */ movs r4, #7 /* r4 = 7. */
str r4, [r2] /* Program RNR = 7. */ str r4, [r2] /* Program RNR = 7. */
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */ ldr r3, [r2] /* Read the value of MPU_CTRL. */
movs r4, #1 /* r4 = 1. */ movs r4, #1 /* r4 = 1. */
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
str r3, [r2] /* Enable MPU. */ str r3, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
msr control, r2 /* Set this task's CONTROL value. */ msr control, r2 /* Set this task's CONTROL value. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
bx r3 /* Finally, branch to EXC_RETURN. */ bx r3 /* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
movs r1, #2 /* r1 = 2. */ movs r1, #2 /* r1 = 2. */
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */ msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
bx r2 /* Finally, branch to EXC_RETURN. */ bx r2 /* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRaisePrivilege: vRaisePrivilege:
mrs r0, control /* Read the CONTROL register. */ mrs r0, control /* Read the CONTROL register. */
movs r1, #1 /* r1 = 1. */ movs r1, #1 /* r1 = 1. */
bics r0, r1 /* Clear the bit 0. */ bics r0, r1 /* Clear the bit 0. */
msr control, r0 /* Write back the new CONTROL value. */ msr control, r0 /* Write back the new CONTROL value. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vStartFirstTask: vStartFirstTask:
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */ ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */ ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
ldr r0, [r0] /* The first entry in vector table is stack pointer. */ ldr r0, [r0] /* The first entry in vector table is stack pointer. */
msr msp, r0 /* Set the MSP back to the start of the stack. */ msr msp, r0 /* Set the MSP back to the start of the stack. */
cpsie i /* Globally enable interrupts. */ cpsie i /* Globally enable interrupts. */
dsb dsb
isb isb
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */ svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
nop nop
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
ulSetInterruptMask: ulSetInterruptMask:
mrs r0, PRIMASK mrs r0, PRIMASK
cpsid i cpsid i
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vClearInterruptMask: vClearInterruptMask:
msr PRIMASK, r0 msr PRIMASK, r0
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
PendSV_Handler: PendSV_Handler:
mrs r0, psp /* Read PSP in r0. */ mrs r0, psp /* Read PSP in r0. */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
subs r0, r0, #44 /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ subs r0, r0, #44 /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mrs r2, control /* r2 = CONTROL. */ mrs r2, control /* r2 = CONTROL. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmia r0!, {r1-r7} /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ stmia r0!, {r1-r7} /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
mov r4, r8 /* r4 = r8. */ mov r4, r8 /* r4 = r8. */
mov r5, r9 /* r5 = r9. */ mov r5, r9 /* r5 = r9. */
mov r6, r10 /* r6 = r10. */ mov r6, r10 /* r6 = r10. */
mov r7, r11 /* r7 = r11. */ mov r7, r11 /* r7 = r11. */
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */ stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
subs r0, r0, #40 /* Make space for PSPLIM, LR and the remaining registers on the stack. */ subs r0, r0, #40 /* Make space for PSPLIM, LR and the remaining registers on the stack. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
mrs r2, psplim /* r2 = PSPLIM. */ mrs r2, psplim /* r2 = PSPLIM. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmia r0!, {r2-r7} /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ stmia r0!, {r2-r7} /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
mov r4, r8 /* r4 = r8. */ mov r4, r8 /* r4 = r8. */
mov r5, r9 /* r5 = r9. */ mov r5, r9 /* r5 = r9. */
mov r6, r10 /* r6 = r10. */ mov r6, r10 /* r6 = r10. */
mov r7, r11 /* r7 = r11. */ mov r7, r11 /* r7 = r11. */
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */ stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
cpsid i cpsid i
bl vTaskSwitchContext bl vTaskSwitchContext
cpsie i cpsie i
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */ ldr r3, [r2] /* Read the value of MPU_CTRL. */
movs r4, #1 /* r4 = 1. */ movs r4, #1 /* r4 = 1. */
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
str r3, [r2] /* Disable MPU. */ str r3, [r2] /* Disable MPU. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */ ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
str r4, [r2] /* Program MAIR0. */ str r4, [r2] /* Program MAIR0. */
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */ ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
movs r4, #4 /* r4 = 4. */ movs r4, #4 /* r4 = 4. */
str r4, [r2] /* Program RNR = 4. */ str r4, [r2] /* Program RNR = 4. */
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
movs r4, #5 /* r4 = 5. */ movs r4, #5 /* r4 = 5. */
str r4, [r2] /* Program RNR = 5. */ str r4, [r2] /* Program RNR = 5. */
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
movs r4, #6 /* r4 = 6. */ movs r4, #6 /* r4 = 6. */
str r4, [r2] /* Program RNR = 6. */ str r4, [r2] /* Program RNR = 6. */
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
movs r4, #7 /* r4 = 7. */ movs r4, #7 /* r4 = 7. */
str r4, [r2] /* Program RNR = 7. */ str r4, [r2] /* Program RNR = 7. */
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */ ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */ stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r3, [r2] /* Read the value of MPU_CTRL. */ ldr r3, [r2] /* Read the value of MPU_CTRL. */
movs r4, #1 /* r4 = 1. */ movs r4, #1 /* r4 = 1. */
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
str r3, [r2] /* Enable MPU. */ str r3, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
adds r0, r0, #28 /* Move to the high registers. */ adds r0, r0, #28 /* Move to the high registers. */
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */ ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
mov r8, r4 /* r8 = r4. */ mov r8, r4 /* r8 = r4. */
mov r9, r5 /* r9 = r5. */ mov r9, r5 /* r9 = r5. */
mov r10, r6 /* r10 = r6. */ mov r10, r6 /* r10 = r6. */
mov r11, r7 /* r11 = r7. */ mov r11, r7 /* r11 = r7. */
msr psp, r0 /* Remember the new top of stack for the task. */ msr psp, r0 /* Remember the new top of stack for the task. */
subs r0, r0, #44 /* Move to the starting of the saved context. */ subs r0, r0, #44 /* Move to the starting of the saved context. */
ldmia r0!, {r1-r7} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ ldmia r0!, {r1-r7} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ msr psplim, r1 /* Restore the PSPLIM register value for the task. */
msr control, r2 /* Restore the CONTROL register value for the task. */ msr control, r2 /* Restore the CONTROL register value for the task. */
bx r3 bx r3
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
adds r0, r0, #24 /* Move to the high registers. */ adds r0, r0, #24 /* Move to the high registers. */
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */ ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
mov r8, r4 /* r8 = r4. */ mov r8, r4 /* r8 = r4. */
mov r9, r5 /* r9 = r5. */ mov r9, r5 /* r9 = r5. */
mov r10, r6 /* r10 = r6. */ mov r10, r6 /* r10 = r6. */
mov r11, r7 /* r11 = r7. */ mov r11, r7 /* r11 = r7. */
msr psp, r0 /* Remember the new top of stack for the task. */ msr psp, r0 /* Remember the new top of stack for the task. */
subs r0, r0, #40 /* Move to the starting of the saved context. */ subs r0, r0, #40 /* Move to the starting of the saved context. */
ldmia r0!, {r2-r7} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ ldmia r0!, {r2-r7} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
msr psplim, r2 /* Restore the PSPLIM register value for the task. */ msr psplim, r2 /* Restore the PSPLIM register value for the task. */
bx r3 bx r3
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SVC_Handler: SVC_Handler:
movs r0, #4 movs r0, #4
mov r1, lr mov r1, lr
tst r0, r1 tst r0, r1
beq stacking_used_msp beq stacking_used_msp
mrs r0, psp mrs r0, psp
b vPortSVCHandler_C b vPortSVCHandler_C
stacking_used_msp: stacking_used_msp:
mrs r0, msp mrs r0, msp
b vPortSVCHandler_C b vPortSVCHandler_C
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
END END

View file

@ -32,322 +32,322 @@ the code is included in C files but excluded by the preprocessor in assembly
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */ files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN xSecureContext EXTERN xSecureContext
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN vPortSVCHandler_C EXTERN vPortSVCHandler_C
EXTERN SecureContext_SaveContext EXTERN SecureContext_SaveContext
EXTERN SecureContext_LoadContext EXTERN SecureContext_LoadContext
PUBLIC xIsPrivileged PUBLIC xIsPrivileged
PUBLIC vResetPrivilege PUBLIC vResetPrivilege
PUBLIC vPortAllocateSecureContext PUBLIC vPortAllocateSecureContext
PUBLIC vRestoreContextOfFirstTask PUBLIC vRestoreContextOfFirstTask
PUBLIC vRaisePrivilege PUBLIC vRaisePrivilege
PUBLIC vStartFirstTask PUBLIC vStartFirstTask
PUBLIC ulSetInterruptMask PUBLIC ulSetInterruptMask
PUBLIC vClearInterruptMask PUBLIC vClearInterruptMask
PUBLIC PendSV_Handler PUBLIC PendSV_Handler
PUBLIC SVC_Handler PUBLIC SVC_Handler
PUBLIC vPortFreeSecureContext PUBLIC vPortFreeSecureContext
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*---------------- Unprivileged Functions -------------------*/ /*---------------- Unprivileged Functions -------------------*/
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2) SECTION .text:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xIsPrivileged: xIsPrivileged:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
ite ne ite ne
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */ moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vResetPrivilege: vResetPrivilege:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
orr r0, r0, #1 /* r0 = r0 | 1. */ orr r0, r0, #1 /* r0 = r0 | 1. */
msr control, r0 /* CONTROL = r0. */ msr control, r0 /* CONTROL = r0. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortAllocateSecureContext: vPortAllocateSecureContext:
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */ svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*----------------- Privileged Functions --------------------*/ /*----------------- Privileged Functions --------------------*/
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION privileged_functions:CODE:NOROOT(2) SECTION privileged_functions:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRestoreContextOfFirstTask: vRestoreContextOfFirstTask:
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r3, [r2] /* Read pxCurrentTCB. */ ldr r3, [r2] /* Read pxCurrentTCB. */
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
str r4, [r2] /* Disable MPU. */ str r4, [r2] /* Disable MPU. */
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */ ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
str r4, [r2] /* Program MAIR0. */ str r4, [r2] /* Program MAIR0. */
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */ ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
movs r4, #4 /* r4 = 4. */ movs r4, #4 /* r4 = 4. */
str r4, [r2] /* Program RNR = 4. */ str r4, [r2] /* Program RNR = 4. */
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
str r4, [r2] /* Enable MPU. */ str r4, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
ldr r5, =xSecureContext ldr r5, =xSecureContext
str r1, [r5] /* Set xSecureContext to this task's value for the same. */ str r1, [r5] /* Set xSecureContext to this task's value for the same. */
msr psplim, r2 /* Set this task's PSPLIM value. */ msr psplim, r2 /* Set this task's PSPLIM value. */
msr control, r3 /* Set this task's CONTROL value. */ msr control, r3 /* Set this task's CONTROL value. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
mov r0, #0 mov r0, #0
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
bx r4 /* Finally, branch to EXC_RETURN. */ bx r4 /* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
msr psplim, r2 /* Set this task's PSPLIM value. */ msr psplim, r2 /* Set this task's PSPLIM value. */
movs r1, #2 /* r1 = 2. */ movs r1, #2 /* r1 = 2. */
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */ msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
mov r0, #0 mov r0, #0
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
bx r3 /* Finally, branch to EXC_RETURN. */ bx r3 /* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRaisePrivilege: vRaisePrivilege:
mrs r0, control /* Read the CONTROL register. */ mrs r0, control /* Read the CONTROL register. */
bic r0, r0, #1 /* Clear the bit 0. */ bic r0, r0, #1 /* Clear the bit 0. */
msr control, r0 /* Write back the new CONTROL value. */ msr control, r0 /* Write back the new CONTROL value. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vStartFirstTask: vStartFirstTask:
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */ ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */ ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
ldr r0, [r0] /* The first entry in vector table is stack pointer. */ ldr r0, [r0] /* The first entry in vector table is stack pointer. */
msr msp, r0 /* Set the MSP back to the start of the stack. */ msr msp, r0 /* Set the MSP back to the start of the stack. */
cpsie i /* Globally enable interrupts. */ cpsie i /* Globally enable interrupts. */
cpsie f cpsie f
dsb dsb
isb isb
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */ svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
ulSetInterruptMask: ulSetInterruptMask:
mrs r0, basepri /* r0 = basepri. Return original basepri value. */ mrs r0, basepri /* r0 = basepri. Return original basepri value. */
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
dsb dsb
isb isb
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vClearInterruptMask: vClearInterruptMask:
msr basepri, r0 /* basepri = ulMask. */ msr basepri, r0 /* basepri = ulMask. */
dsb dsb
isb isb
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
PendSV_Handler: PendSV_Handler:
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} push {r0-r2, r14}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r3} /* LR is now in r3. */
mov lr, r3 /* LR = r3. */ mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mrs r3, control /* r3 = CONTROL. */ mrs r3, control /* r3 = CONTROL. */
mov r4, lr /* r4 = LR/EXC_RETURN. */ mov r4, lr /* r4 = LR/EXC_RETURN. */
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */ subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */ stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
b select_next_task b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #16 /* r2 = r2 + 16. */ adds r2, r2, #16 /* r2 = r2 + 16. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */ stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mrs r3, control /* r3 = CONTROL. */ mrs r3, control /* r3 = CONTROL. */
mov r4, lr /* r4 = LR/EXC_RETURN. */ mov r4, lr /* r4 = LR/EXC_RETURN. */
subs r2, r2, #16 /* r2 = r2 - 16. */ subs r2, r2, #16 /* r2 = r2 - 16. */
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #12 /* r2 = r2 + 12. */ adds r2, r2, #12 /* r2 = r2 + 12. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */ stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
subs r2, r2, #12 /* r2 = r2 - 12. */ subs r2, r2, #12 /* r2 = r2 - 12. */
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */ stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
select_next_task: select_next_task:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
dsb dsb
isb isb
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r3] /* Read the value of MPU_CTRL. */ ldr r4, [r3] /* Read the value of MPU_CTRL. */
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
str r4, [r3] /* Disable MPU. */ str r4, [r3] /* Disable MPU. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */ ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */ ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
str r4, [r3] /* Program MAIR0. */ str r4, [r3] /* Program MAIR0. */
ldr r3, =0xe000ed98 /* r3 = 0xe000ed98 [Location of RNR]. */ ldr r3, =0xe000ed98 /* r3 = 0xe000ed98 [Location of RNR]. */
movs r4, #4 /* r4 = 4. */ movs r4, #4 /* r4 = 4. */
str r4, [r3] /* Program RNR = 4. */ str r4, [r3] /* Program RNR = 4. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */ ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
stmia r3!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ stmia r3!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r3] /* Read the value of MPU_CTRL. */ ldr r4, [r3] /* Read the value of MPU_CTRL. */
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
str r4, [r3] /* Enable MPU. */ str r4, [r3] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ msr psplim, r1 /* Restore the PSPLIM register value for the task. */
msr control, r3 /* Restore the CONTROL register value for the task. */ msr control, r3 /* Restore the CONTROL register value for the task. */
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's xSecureContext. */ str r0, [r3] /* Restore the task's xSecureContext. */
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */ cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
push {r2, r4} push {r2, r4}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r2, r4}
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ msr psplim, r1 /* Restore the PSPLIM register value for the task. */
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's xSecureContext. */ str r0, [r3] /* Restore the task's xSecureContext. */
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */ cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ ldr r1, [r3] /* Read pxCurrentTCB. */
push {r2, r4} push {r2, r4}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r2, r4}
mov lr, r4 /* LR = r4. */ mov lr, r4 /* LR = r4. */
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
restore_ns_context: restore_ns_context:
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SVC_Handler: SVC_Handler:
tst lr, #4 tst lr, #4
ite eq ite eq
mrseq r0, msp mrseq r0, msp
mrsne r0, psp mrsne r0, psp
b vPortSVCHandler_C b vPortSVCHandler_C
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortFreeSecureContext: vPortFreeSecureContext:
/* r0 = uint32_t *pulTCB. */ /* r0 = uint32_t *pulTCB. */
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */ ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */ ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */ cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
it ne it ne
svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */ svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
END END

View file

@ -32,231 +32,231 @@ the code is included in C files but excluded by the preprocessor in assembly
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */ files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN vPortSVCHandler_C EXTERN vPortSVCHandler_C
PUBLIC xIsPrivileged PUBLIC xIsPrivileged
PUBLIC vResetPrivilege PUBLIC vResetPrivilege
PUBLIC vRestoreContextOfFirstTask PUBLIC vRestoreContextOfFirstTask
PUBLIC vRaisePrivilege PUBLIC vRaisePrivilege
PUBLIC vStartFirstTask PUBLIC vStartFirstTask
PUBLIC ulSetInterruptMask PUBLIC ulSetInterruptMask
PUBLIC vClearInterruptMask PUBLIC vClearInterruptMask
PUBLIC PendSV_Handler PUBLIC PendSV_Handler
PUBLIC SVC_Handler PUBLIC SVC_Handler
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*---------------- Unprivileged Functions -------------------*/ /*---------------- Unprivileged Functions -------------------*/
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION .text:CODE:NOROOT(2) SECTION .text:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xIsPrivileged: xIsPrivileged:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
ite ne ite ne
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */ moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vResetPrivilege: vResetPrivilege:
mrs r0, control /* r0 = CONTROL. */ mrs r0, control /* r0 = CONTROL. */
orr r0, r0, #1 /* r0 = r0 | 1. */ orr r0, r0, #1 /* r0 = r0 | 1. */
msr control, r0 /* CONTROL = r0. */ msr control, r0 /* CONTROL = r0. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*----------------- Privileged Functions --------------------*/ /*----------------- Privileged Functions --------------------*/
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SECTION privileged_functions:CODE:NOROOT(2) SECTION privileged_functions:CODE:NOROOT(2)
THUMB THUMB
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRestoreContextOfFirstTask: vRestoreContextOfFirstTask:
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
str r4, [r2] /* Disable MPU. */ str r4, [r2] /* Disable MPU. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */ ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
str r3, [r2] /* Program MAIR0. */ str r3, [r2] /* Program MAIR0. */
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */ ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
movs r3, #4 /* r3 = 4. */ movs r3, #4 /* r3 = 4. */
str r3, [r2] /* Program RNR = 4. */ str r3, [r2] /* Program RNR = 4. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
str r4, [r2] /* Enable MPU. */ str r4, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
msr control, r2 /* Set this task's CONTROL value. */ msr control, r2 /* Set this task's CONTROL value. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
mov r0, #0 mov r0, #0
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
bx r3 /* Finally, branch to EXC_RETURN. */ bx r3 /* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
movs r1, #2 /* r1 = 2. */ movs r1, #2 /* r1 = 2. */
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */ msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
adds r0, #32 /* Discard everything up to r0. */ adds r0, #32 /* Discard everything up to r0. */
msr psp, r0 /* This is now the new top of stack to use in the task. */ msr psp, r0 /* This is now the new top of stack to use in the task. */
isb isb
mov r0, #0 mov r0, #0
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
bx r2 /* Finally, branch to EXC_RETURN. */ bx r2 /* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vRaisePrivilege: vRaisePrivilege:
mrs r0, control /* Read the CONTROL register. */ mrs r0, control /* Read the CONTROL register. */
bic r0, r0, #1 /* Clear the bit 0. */ bic r0, r0, #1 /* Clear the bit 0. */
msr control, r0 /* Write back the new CONTROL value. */ msr control, r0 /* Write back the new CONTROL value. */
bx lr /* Return to the caller. */ bx lr /* Return to the caller. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vStartFirstTask: vStartFirstTask:
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */ ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */ ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
ldr r0, [r0] /* The first entry in vector table is stack pointer. */ ldr r0, [r0] /* The first entry in vector table is stack pointer. */
msr msp, r0 /* Set the MSP back to the start of the stack. */ msr msp, r0 /* Set the MSP back to the start of the stack. */
cpsie i /* Globally enable interrupts. */ cpsie i /* Globally enable interrupts. */
cpsie f cpsie f
dsb dsb
isb isb
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */ svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
ulSetInterruptMask: ulSetInterruptMask:
mrs r0, basepri /* r0 = basepri. Return original basepri value. */ mrs r0, basepri /* r0 = basepri. Return original basepri value. */
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
dsb dsb
isb isb
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vClearInterruptMask: vClearInterruptMask:
msr basepri, r0 /* basepri = ulMask. */ msr basepri, r0 /* basepri = ulMask. */
dsb dsb
isb isb
bx lr /* Return. */ bx lr /* Return. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
PendSV_Handler: PendSV_Handler:
mrs r0, psp /* Read PSP in r0. */ mrs r0, psp /* Read PSP in r0. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r0!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r0!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
mrs r1, psplim /* r1 = PSPLIM. */ mrs r1, psplim /* r1 = PSPLIM. */
mrs r2, control /* r2 = CONTROL. */ mrs r2, control /* r2 = CONTROL. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r1-r11} /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ stmdb r0!, {r1-r11} /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
mrs r2, psplim /* r2 = PSPLIM. */ mrs r2, psplim /* r2 = PSPLIM. */
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */ stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
dsb dsb
isb isb
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
dmb /* Complete outstanding transfers before disabling MPU. */ dmb /* Complete outstanding transfers before disabling MPU. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
str r4, [r2] /* Disable MPU. */ str r4, [r2] /* Disable MPU. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */ ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
str r3, [r2] /* Program MAIR0. */ str r3, [r2] /* Program MAIR0. */
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */ ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
movs r3, #4 /* r3 = 4. */ movs r3, #4 /* r3 = 4. */
str r3, [r2] /* Program RNR = 4. */ str r3, [r2] /* Program RNR = 4. */
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
ldr r4, [r2] /* Read the value of MPU_CTRL. */ ldr r4, [r2] /* Read the value of MPU_CTRL. */
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
str r4, [r2] /* Enable MPU. */ str r4, [r2] /* Enable MPU. */
dsb /* Force memory writes before continuing. */ dsb /* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
ldmia r0!, {r1-r11} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ ldmia r0!, {r1-r11} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst r3, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst r3, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r0!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r0!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ msr psplim, r1 /* Restore the PSPLIM register value for the task. */
msr control, r2 /* Restore the CONTROL register value for the task. */ msr control, r2 /* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
msr psplim, r2 /* Restore the PSPLIM register value for the task. */ msr psplim, r2 /* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
msr psp, r0 /* Remember the new top of stack for the task. */ msr psp, r0 /* Remember the new top of stack for the task. */
bx r3 bx r3
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
SVC_Handler: SVC_Handler:
tst lr, #4 tst lr, #4
ite eq ite eq
mrseq r0, msp mrseq r0, msp
mrsne r0, psp mrsne r0, psp
b vPortSVCHandler_C b vPortSVCHandler_C
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
END END

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -29,14 +29,14 @@
/* /*
Changes from V1.00: Changes from V1.00:
+ Call to taskYIELD() from within tick ISR has been replaced by the more + Call to taskYIELD() from within tick ISR has been replaced by the more
efficient portSWITCH_CONTEXT(). efficient portSWITCH_CONTEXT().
+ ISR function definitions renamed to include the prv prefix. + ISR function definitions renamed to include the prv prefix.
Changes from V2.6.1 Changes from V2.6.1
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
macro to be consistent with the later ports. macro to be consistent with the later ports.
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -54,13 +54,13 @@ Changes from V2.6.1
/*lint -e950 Non ANSI reserved words okay in this file only. */ /*lint -e950 Non ANSI reserved words okay in this file only. */
#define portTIMER_EOI_TYPE ( 8 ) #define portTIMER_EOI_TYPE ( 8 )
#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE ) #define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
#define portTIMER_INT_NUMBER 0x12 #define portTIMER_INT_NUMBER 0x12
#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e ) #define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 ) #define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 ) #define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
/* Setup the hardware to generate the required tick frequency. */ /* Setup the hardware to generate the required tick frequency. */
static void prvSetTickFrequency( uint32_t ulTickRateHz ); static void prvSetTickFrequency( uint32_t ulTickRateHz );
@ -71,13 +71,13 @@ static void prvExitFunction( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
is being used. */ is being used. */
#if( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is /* Tick service routine used by the scheduler when preemptive scheduling is
being used. */ being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is /* Tick service routine used by the scheduler when cooperative scheduling is
being used. */ being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
/* Trap routine used by taskYIELD() to manually cause a context switch. */ /* Trap routine used by taskYIELD() to manually cause a context switch. */
@ -101,87 +101,87 @@ static jmp_buf xJumpBuf;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use /* Remember what was on the interrupts we are going to use
so we can put them back later if required. */ so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
vector. */ vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
#if( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
{ {
/* Put our tick switch function on the timer interrupt. */ /* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
} }
#else #else
{ {
/* We want the timer interrupt to just increment the tick count. */ /* We want the timer interrupt to just increment the tick count. */
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
} }
#endif #endif
prvSetTickFrequency( configTICK_RATE_HZ ); prvSetTickFrequency( configTICK_RATE_HZ );
/* Clean up function if we want to return to DOS. */ /* Clean up function if we want to return to DOS. */
if( setjmp( xJumpBuf ) != 0 ) if( setjmp( xJumpBuf ) != 0 )
{ {
prvExitFunction(); prvExitFunction();
xSchedulerRunning = pdFALSE; xSchedulerRunning = pdFALSE;
} }
else else
{ {
xSchedulerRunning = pdTRUE; xSchedulerRunning = pdTRUE;
/* Kick off the scheduler by setting up the context of the first task. */ /* Kick off the scheduler by setting up the context of the first task. */
portFIRST_CONTEXT(); portFIRST_CONTEXT();
} }
return xSchedulerRunning; return xSchedulerRunning;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
is being used. */ is being used. */
#if( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* Switch in the context of the next task to be run. */ /* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT(); portSWITCH_CONTEXT();
} }
/* Reset the PIC ready for the next time. */ /* Reset the PIC ready for the next time. */
portRESET_PIC(); portRESET_PIC();
} }
#else #else
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
so we don't have to switch in the context of the next task. */ so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
portRESET_PIC(); portRESET_PIC();
} }
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
{ {
/* Switch in the context of the next task to be run. */ /* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT(); portSWITCH_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Jump back to the processor state prior to starting the /* Jump back to the processor state prior to starting the
scheduler. This means we are not going to be using a scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */ task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 ); longjmp( xJumpBuf, 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -190,28 +190,28 @@ static void prvExitFunction( void )
const uint16_t usTimerDisable = 0x0000; const uint16_t usTimerDisable = 0x0000;
uint16_t usTimer0Control; uint16_t usTimer0Control;
/* Interrupts should be disabled here anyway - but no /* Interrupts should be disabled here anyway - but no
harm in making sure. */ harm in making sure. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE ) if( xSchedulerRunning == pdTRUE )
{ {
/* Put back the switch interrupt routines that was in place /* Put back the switch interrupt routines that was in place
before the scheduler started. */ before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
} }
/* Disable the timer used for the tick to ensure the scheduler is /* Disable the timer used for the tick to ensure the scheduler is
not called before restoring interrupts. There was previously nothing not called before restoring interrupts. There was previously nothing
on this timer so there is no old ISR to restore. */ on this timer so there is no old ISR to restore. */
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable ); portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
/* Restart the DOS tick. */ /* Restart the DOS tick. */
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER ); usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
usTimer0Control |= portTIMER_INTERRUPT_ENABLE; usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control ); portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -230,16 +230,15 @@ const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz; uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger ); portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount ); portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority ); portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
/* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */ /* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER ); usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE; usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control ); portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
} }
/*lint +e950 */ /*lint +e950 */

View file

@ -40,53 +40,53 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE long #define portDOUBLE long
#define portLONG long #define portLONG long
#define portSHORT int #define portSHORT int
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portBASE_TYPE portSHORT #define portBASE_TYPE portSHORT
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
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 handling. */ /* Critical section handling. */
#define portENTER_CRITICAL() __asm{ pushf } \ #define portENTER_CRITICAL() __asm{ pushf } \
__asm{ cli } \ __asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf } #define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm{ cli } #define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm{ sti } #define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portNOP() __asm{ nop } #define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80 #define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER } #define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ #define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Compiler specifics. */ /* Compiler specifics. */
#define portINPUT_BYTE( xAddr ) inp( xAddr ) #define portINPUT_BYTE( xAddr ) inp( xAddr )
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue ) #define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
#define portINPUT_WORD( xAddr ) inpw( xAddr ) #define portINPUT_WORD( xAddr ) inpw( xAddr )
#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue ) #define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -95,4 +95,3 @@ typedef unsigned short UBaseType_t;
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -29,13 +29,13 @@
/* /*
Changes from V2.6.1 Changes from V2.6.1
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
macro to be consistent with the later ports. macro to be consistent with the later ports.
Changes from V4.0.1 Changes from V4.0.1
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to + Add function prvSetTickFrequencyDefault() to set the DOS tick back to
its proper value when the scheduler exits. its proper value when the scheduler exits.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -53,7 +53,7 @@ Changes from V4.0.1
/*lint -e950 Non ANSI reserved words okay in this file only. */ /*lint -e950 Non ANSI reserved words okay in this file only. */
#define portTIMER_INT_NUMBER 0x08 #define portTIMER_INT_NUMBER 0x08
/* Setup hardware for required tick interrupt rate. */ /* Setup hardware for required tick interrupt rate. */
static void prvSetTickFrequency( uint32_t ulTickRateHz ); static void prvSetTickFrequency( uint32_t ulTickRateHz );
@ -69,13 +69,13 @@ static void prvPortResetPIC( void );
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */ scheduler is being used. */
#if( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is /* Tick service routine used by the scheduler when preemptive scheduling is
being used. */ being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is /* Tick service routine used by the scheduler when cooperative scheduling is
being used. */ being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
/* Trap routine used by taskYIELD() to manually cause a context switch. */ /* Trap routine used by taskYIELD() to manually cause a context switch. */
@ -109,125 +109,125 @@ BaseType_t xPortStartScheduler( void )
{ {
pxISR pxOriginalTickISR; pxISR pxOriginalTickISR;
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use /* Remember what was on the interrupts we are going to use
so we can put them back later if required. */ so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER ); pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
prvSetTickFrequency( configTICK_RATE_HZ ); prvSetTickFrequency( configTICK_RATE_HZ );
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
vector. */ vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put the old tick on a different interrupt number so we can /* Put the old tick on a different interrupt number so we can
call it when we want. */ call it when we want. */
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR ); _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */ scheduler is being used. */
#if( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
{ {
/* Put our tick switch function on the timer interrupt. */ /* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
} }
#else #else
{ {
/* We want the timer interrupt to just increment the tick count. */ /* We want the timer interrupt to just increment the tick count. */
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
} }
#endif #endif
/* Setup a counter that is used to call the DOS interrupt as close /* Setup a counter that is used to call the DOS interrupt as close
to it's original frequency as can be achieved given our chosen tick to it's original frequency as can be achieved given our chosen tick
frequency. */ frequency. */
sDOSTickCounter = portTICKS_PER_DOS_TICK; sDOSTickCounter = portTICKS_PER_DOS_TICK;
/* Clean up function if we want to return to DOS. */ /* Clean up function if we want to return to DOS. */
if( setjmp( xJumpBuf ) != 0 ) if( setjmp( xJumpBuf ) != 0 )
{ {
prvExitFunction(); prvExitFunction();
xSchedulerRunning = pdFALSE; xSchedulerRunning = pdFALSE;
} }
else else
{ {
xSchedulerRunning = pdTRUE; xSchedulerRunning = pdTRUE;
/* Kick off the scheduler by setting up the context of the first task. */ /* Kick off the scheduler by setting up the context of the first task. */
portFIRST_CONTEXT(); portFIRST_CONTEXT();
} }
return xSchedulerRunning; return xSchedulerRunning;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
scheduler is being used. */ scheduler is being used. */
#if( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* Switch in the context of the next task to be run. */ /* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT(); portSWITCH_CONTEXT();
} }
/* Reset the PIC ready for the next time. */ /* Reset the PIC ready for the next time. */
prvPortResetPIC(); prvPortResetPIC();
} }
#else #else
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
so we don't have to switch in the context of the next task. */ so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
prvPortResetPIC(); prvPortResetPIC();
} }
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
{ {
/* Switch in the context of the next task to be run. */ /* Switch in the context of the next task to be run. */
portSWITCH_CONTEXT(); portSWITCH_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvPortResetPIC( void ) static void prvPortResetPIC( void )
{ {
/* We are going to call the DOS tick interrupt at as close a /* We are going to call the DOS tick interrupt at as close a
frequency to the normal DOS tick as possible. */ frequency to the normal DOS tick as possible. */
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */ /* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
--sDOSTickCounter; --sDOSTickCounter;
if( sDOSTickCounter <= 0 ) if( sDOSTickCounter <= 0 )
{ {
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK; sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
__asm{ int portSWITCH_INT_NUMBER + 1 }; __asm{ int portSWITCH_INT_NUMBER + 1 };
} }
else else
{ {
/* Reset the PIC as the DOS tick is not being called to /* Reset the PIC as the DOS tick is not being called to
do it. */ do it. */
__asm __asm
{ {
mov al, 20H mov al, 20H
out 20H, al out 20H, al
}; };
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Jump back to the processor state prior to starting the /* Jump back to the processor state prior to starting the
scheduler. This means we are not going to be using a scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */ task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 ); longjmp( xJumpBuf, 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -235,24 +235,24 @@ static void prvExitFunction( void )
{ {
void ( __interrupt __far *pxOriginalTickISR )(); void ( __interrupt __far *pxOriginalTickISR )();
/* Interrupts should be disabled here anyway - but no /* Interrupts should be disabled here anyway - but no
harm in making sure. */ harm in making sure. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE ) if( xSchedulerRunning == pdTRUE )
{ {
/* Set the DOS tick back onto the timer ticker. */ /* Set the DOS tick back onto the timer ticker. */
pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
_dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR ); _dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR );
prvSetTickFrequencyDefault(); prvSetTickFrequencyDefault();
/* Put back the switch interrupt routines that was in place /* Put back the switch interrupt routines that was in place
before the scheduler started. */ before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 ); _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
} }
/* The tick timer is back how DOS wants it. We can re-enable /* The tick timer is back how DOS wants it. We can re-enable
interrupts without the scheduler being called. */ interrupts without the scheduler being called. */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -264,12 +264,12 @@ const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
uint32_t ulOutput; uint32_t ulOutput;
/* Setup the 8245 to tick at the wanted frequency. */ /* Setup the 8245 to tick at the wanted frequency. */
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
ulOutput = ulPIT_CONST / ulTickRateHz; ulOutput = ulPIT_CONST / ulTickRateHz;
portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) ); portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) );
ulOutput >>= 8; ulOutput >>= 8;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -279,11 +279,10 @@ const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40; const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
portOUTPUT_BYTE( usPIT0,0 ); portOUTPUT_BYTE( usPIT0,0 );
portOUTPUT_BYTE( usPIT0,0 ); portOUTPUT_BYTE( usPIT0,0 );
} }
/*lint +e950 */ /*lint +e950 */

View file

@ -40,53 +40,53 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT long #define portFLOAT long
#define portDOUBLE long #define portDOUBLE long
#define portLONG long #define portLONG long
#define portSHORT int #define portSHORT int
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portBASE_TYPE portSHORT #define portBASE_TYPE portSHORT
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
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. */
#define portENTER_CRITICAL() __asm{ pushf } \ #define portENTER_CRITICAL() __asm{ pushf } \
__asm{ cli } \ __asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf } #define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm{ cli } #define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm{ sti } #define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portNOP() __asm{ nop } #define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80 #define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER } #define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portDOS_TICK_RATE ( 18.20648 ) #define portDOS_TICK_RATE ( 18.20648 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) ) #define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ #define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
#define portBYTE_ALIGNMENT ( 2 ) #define portBYTE_ALIGNMENT ( 2 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Compiler specifics. */ /* Compiler specifics. */
#define portINPUT_BYTE( xAddr ) inp( xAddr ) #define portINPUT_BYTE( xAddr ) inp( xAddr )
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue ) #define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -95,4 +95,3 @@ typedef unsigned short UBaseType_t;
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -53,36 +53,35 @@ are a couple of extra bytes left of the ISR stack (presumably for use by the
debugger). The true stack pointer is then stored in the bp register. We add debugger). The true stack pointer is then stored in the bp register. We add
2 to the stack pointer to remove the extra bytes before we restore our context. */ 2 to the stack pointer to remove the extra bytes before we restore our context. */
#define portSWITCH_CONTEXT() \ #define portSWITCH_CONTEXT() \
asm { mov ax, seg pxCurrentTCB } \ asm { mov ax, seg pxCurrentTCB } \
asm { mov ds, ax } \ asm { mov ds, ax } \
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \ asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
asm { mov es:0x2[ bx ], ss } \ asm { mov es:0x2[ bx ], ss } \
asm { mov es:[ bx ], sp } \ asm { mov es:[ bx ], sp } \
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \ asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \ asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
asm { mov ds, ax } \ asm { mov ds, ax } \
asm { les bx, dword ptr pxCurrentTCB } \ asm { les bx, dword ptr pxCurrentTCB } \
asm { mov ss, es:[ bx + 2 ] } \ asm { mov ss, es:[ bx + 2 ] } \
asm { mov sp, es:[ bx ] } asm { mov sp, es:[ bx ] }
#define portFIRST_CONTEXT() \ #define portFIRST_CONTEXT() \
__asm { mov ax, seg pxCurrentTCB } \ __asm { mov ax, seg pxCurrentTCB } \
__asm { mov ds, ax } \ __asm { mov ds, ax } \
__asm { les bx, dword ptr pxCurrentTCB } \ __asm { les bx, dword ptr pxCurrentTCB } \
__asm { mov ss, es:[ bx + 2 ] } \ __asm { mov ss, es:[ bx + 2 ] } \
__asm { mov sp, es:[ bx ] } \ __asm { mov sp, es:[ bx ] } \
__asm { pop bp } \ __asm { pop bp } \
__asm { pop di } \ __asm { pop di } \
__asm { pop si } \ __asm { pop si } \
__asm { pop ds } \ __asm { pop ds } \
__asm { pop es } \ __asm { pop es } \
__asm { pop dx } \ __asm { pop dx } \
__asm { pop cx } \ __asm { pop cx } \
__asm { pop bx } \ __asm { pop bx } \
__asm { pop ax } \ __asm { pop ax } \
__asm { iret } __asm { iret }
#endif #endif

View file

@ -29,13 +29,13 @@
/* /*
Changes from V1.00: Changes from V1.00:
+ pxPortInitialiseStack() now initialises the stack of new tasks to the + pxPortInitialiseStack() now initialises the stack of new tasks to the
same format used by the compiler. This allows the compiler generated same format used by the compiler. This allows the compiler generated
interrupt mechanism to be used for context switches. interrupt mechanism to be used for context switches.
Changes from V2.6.1 Changes from V2.6.1
+ Move usPortCheckFreeStackSpace() to tasks.c. + Move usPortCheckFreeStackSpace() to tasks.c.
*/ */
@ -50,72 +50,71 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
{ {
StackType_t DS_Reg = 0; StackType_t DS_Reg = 0;
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. */ This is just useful for debugging. */
*pxTopOfStack = 0x1111; *pxTopOfStack = 0x1111;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2222; *pxTopOfStack = 0x2222;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x3333; *pxTopOfStack = 0x3333;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x4444; *pxTopOfStack = 0x4444;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x5555; *pxTopOfStack = 0x5555;
pxTopOfStack--; pxTopOfStack--;
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* We are going to start the scheduler using a return from interrupt /* We are going to start the scheduler using a return from interrupt
instruction to load the program counter, so first there would be the instruction to load the program counter, so first there would be the
function call with parameters preamble. */ function call with parameters preamble. */
*pxTopOfStack = FP_SEG( pvParameters ); *pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = FP_OFF( pvParameters ); *pxTopOfStack = FP_OFF( pvParameters );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = FP_SEG( pxCode ); *pxTopOfStack = FP_SEG( pxCode );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = FP_OFF( pxCode ); *pxTopOfStack = FP_OFF( pxCode );
pxTopOfStack--; pxTopOfStack--;
/* Next the status register and interrupt return address. */ /* Next the status register and interrupt return address. */
*pxTopOfStack = portINITIAL_SW; *pxTopOfStack = portINITIAL_SW;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = FP_SEG( pxCode ); *pxTopOfStack = FP_SEG( pxCode );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = FP_OFF( pxCode ); *pxTopOfStack = FP_OFF( pxCode );
pxTopOfStack--; pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context /* The remaining registers would be pushed on the stack by our context
switch function. These are loaded with values simply to make debugging switch function. These are loaded with values simply to make debugging
easier. */ easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */ *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */ *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */ *pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
pxTopOfStack--; pxTopOfStack--;
/* We need the true data segment. */ /* We need the true data segment. */
__asm{ MOV DS_Reg, DS }; __asm{ MOV DS_Reg, DS };
*pxTopOfStack = DS_Reg; /* DS */ *pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x0123; /* SI */ *pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */ *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */ *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
/*lint +e950 +e611 +e923 */ /*lint +e950 +e611 +e923 */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -370,9 +370,9 @@ void xPortSysTickHandler( void )
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
* method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm( " cpsid i"); __asm( " cpsid i");
__asm( " dsb"); __asm( " dsb");
__asm( " isb"); __asm( " isb");
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
* to be unsuspended then abandon the low power entry. */ * to be unsuspended then abandon the low power entry. */
@ -380,7 +380,7 @@ void xPortSysTickHandler( void )
{ {
/* Re-enable interrupts - see comments above the cpsid instruction /* Re-enable interrupts - see comments above the cpsid instruction
* above. */ * above. */
__asm( " cpsie i"); __asm( " cpsie i");
} }
else else
{ {
@ -441,9 +441,9 @@ void xPortSysTickHandler( void )
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm( " dsb"); __asm( " dsb");
__asm( " wfi"); __asm( " wfi");
__asm( " isb"); __asm( " isb");
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
@ -451,17 +451,17 @@ void xPortSysTickHandler( void )
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
* out of sleep mode to execute immediately. See comments above * out of sleep mode to execute immediately. See comments above
* the cpsid instruction above. */ * the cpsid instruction above. */
__asm( " cpsie i"); __asm( " cpsie i");
__asm( " dsb"); __asm( " dsb");
__asm( " isb"); __asm( " isb");
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
* and interrupts that execute while the clock is stopped will increase * and interrupts that execute while the clock is stopped will increase
* any slippage between the time maintained by the RTOS and calendar * any slippage between the time maintained by the RTOS and calendar
* time. */ * time. */
__asm( " cpsid i"); __asm( " cpsid i");
__asm( " dsb"); __asm( " dsb");
__asm( " isb"); __asm( " isb");
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
* portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
@ -569,7 +569,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods ); vTaskStepTick( ulCompleteTickPeriods );
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm( " cpsie i"); __asm( " cpsie i");
} }
} }
@ -630,10 +630,10 @@ void vPortSetupTimerInterrupt( void )
* be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.

View file

@ -26,120 +26,119 @@
; * ; *
; */ ; */
.thumb .thumb
.ref pxCurrentTCB .ref pxCurrentTCB
.ref vTaskSwitchContext .ref vTaskSwitchContext
.ref ulMaxSyscallInterruptPriority .ref ulMaxSyscallInterruptPriority
.def xPortPendSVHandler .def xPortPendSVHandler
.def ulPortGetIPSR .def ulPortGetIPSR
.def vPortSVCHandler .def vPortSVCHandler
.def vPortStartFirstTask .def vPortStartFirstTask
NVICOffsetConst: .word 0xE000ED08 NVICOffsetConst: .word 0xE000ED08
CPACRConst: .word 0xE000ED88 CPACRConst: .word 0xE000ED88
pxCurrentTCBConst: .word pxCurrentTCB pxCurrentTCBConst: .word pxCurrentTCB
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
ulPortGetIPSR: .asmfunc ulPortGetIPSR: .asmfunc
mrs r0, ipsr mrs r0, ipsr
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortSetInterruptMask: .asmfunc vPortSetInterruptMask: .asmfunc
push {r0} push {r0}
ldr r0, ulMaxSyscallInterruptPriorityConst ldr r0, ulMaxSyscallInterruptPriorityConst
msr basepri, r0 msr basepri, r0
pop {r0} pop {r0}
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
xPortPendSVHandler: .asmfunc xPortPendSVHandler: .asmfunc
mrs r0, psp mrs r0, psp
isb isb
;/* Get the location of the current TCB. */ ;/* Get the location of the current TCB. */
ldr r3, pxCurrentTCBConst ldr r3, pxCurrentTCBConst
ldr r2, [r3] ldr r2, [r3]
;/* Save the core registers. */ ;/* Save the core registers. */
stmdb r0!, {r4-r11} stmdb r0!, {r4-r11}
;/* Save the new top of stack into the first member of the TCB. */ ;/* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
stmdb sp!, {r3, r14} stmdb sp!, {r3, r14}
ldr r0, ulMaxSyscallInterruptPriorityConst ldr r0, ulMaxSyscallInterruptPriorityConst
ldr r1, [r0] ldr r1, [r0]
msr basepri, r1 msr basepri, r1
dsb dsb
isb isb
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
ldmia sp!, {r3, r14} ldmia sp!, {r3, r14}
;/* The first item in pxCurrentTCB is the task top of stack. */ ;/* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
;/* Pop the core registers. */ ;/* Pop the core registers. */
ldmia r0!, {r4-r11} ldmia r0!, {r4-r11}
msr psp, r0 msr psp, r0
isb isb
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortSVCHandler: .asmfunc vPortSVCHandler: .asmfunc
;/* Get the location of the current TCB. */ ;/* Get the location of the current TCB. */
ldr r3, pxCurrentTCBConst ldr r3, pxCurrentTCBConst
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
;/* Pop the core registers. */ ;/* Pop the core registers. */
ldmia r0!, {r4-r11} ldmia r0!, {r4-r11}
msr psp, r0 msr psp, r0
isb isb
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
orr r14, #0xd orr r14, #0xd
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortStartFirstTask: .asmfunc vPortStartFirstTask: .asmfunc
;/* Use the NVIC offset register to locate the stack. */ ;/* Use the NVIC offset register to locate the stack. */
ldr r0, NVICOffsetConst ldr r0, NVICOffsetConst
ldr r0, [r0] ldr r0, [r0]
ldr r0, [r0] ldr r0, [r0]
;/* Set the msp back to the start of the stack. */ ;/* Set the msp back to the start of the stack. */
msr msp, r0 msr msp, r0
;/* Clear the bit that indicates the FPU is in use in case the FPU was used ;/* Clear the bit that indicates the FPU is in use in case the FPU was used
;before the scheduler was started - which would otherwise result in the ;before the scheduler was started - which would otherwise result in the
;unnecessary leaving of space in the SVC stack for lazy saving of FPU ;unnecessary leaving of space in the SVC stack for lazy saving of FPU
;registers. */ ;registers. */
mov r0, #0 mov r0, #0
msr control, r0 msr control, r0
;/* Call SVC to start the first task. */ ;/* Call SVC to start the first task. */
cpsie i cpsie i
cpsie f cpsie f
dsb dsb
isb isb
svc #0 svc #0
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------

View file

@ -87,8 +87,8 @@
{ \ { \
/* Set a PendSV to request a context switch. */ \ /* Set a PendSV to request a context switch. */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
__asm( " dsb"); \ __asm( " dsb"); \
__asm( " isb"); \ __asm( " isb"); \
} }
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
@ -128,14 +128,14 @@
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
{ \ { \
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
__asm( " dsb"); \ __asm( " dsb"); \
__asm( " isb"); \ __asm( " isb"); \
} }
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 ) #define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb") #define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -395,9 +395,9 @@ void xPortSysTickHandler( void )
/* Enter a critical section but don't use the taskENTER_CRITICAL() /* Enter a critical section but don't use the taskENTER_CRITICAL()
* method as that will mask interrupts that should exit sleep mode. */ * method as that will mask interrupts that should exit sleep mode. */
__asm( " cpsid i"); __asm( " cpsid i");
__asm( " dsb"); __asm( " dsb");
__asm( " isb"); __asm( " isb");
/* If a context switch is pending or a task is waiting for the scheduler /* If a context switch is pending or a task is waiting for the scheduler
* to be unsuspended then abandon the low power entry. */ * to be unsuspended then abandon the low power entry. */
@ -405,7 +405,7 @@ void xPortSysTickHandler( void )
{ {
/* Re-enable interrupts - see comments above the cpsid instruction /* Re-enable interrupts - see comments above the cpsid instruction
* above. */ * above. */
__asm( " cpsie i"); __asm( " cpsie i");
} }
else else
{ {
@ -466,9 +466,9 @@ void xPortSysTickHandler( void )
if( xModifiableIdleTime > 0 ) if( xModifiableIdleTime > 0 )
{ {
__asm( " dsb"); __asm( " dsb");
__asm( " wfi"); __asm( " wfi");
__asm( " isb"); __asm( " isb");
} }
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
@ -476,17 +476,17 @@ void xPortSysTickHandler( void )
/* Re-enable interrupts to allow the interrupt that brought the MCU /* Re-enable interrupts to allow the interrupt that brought the MCU
* out of sleep mode to execute immediately. See comments above * out of sleep mode to execute immediately. See comments above
* the cpsid instruction above. */ * the cpsid instruction above. */
__asm( " cpsie i"); __asm( " cpsie i");
__asm( " dsb"); __asm( " dsb");
__asm( " isb"); __asm( " isb");
/* Disable interrupts again because the clock is about to be stopped /* Disable interrupts again because the clock is about to be stopped
* and interrupts that execute while the clock is stopped will increase * and interrupts that execute while the clock is stopped will increase
* any slippage between the time maintained by the RTOS and calendar * any slippage between the time maintained by the RTOS and calendar
* time. */ * time. */
__asm( " cpsid i"); __asm( " cpsid i");
__asm( " dsb"); __asm( " dsb");
__asm( " isb"); __asm( " isb");
/* Disable the SysTick clock without reading the /* Disable the SysTick clock without reading the
* portNVIC_SYSTICK_CTRL_REG register to ensure the * portNVIC_SYSTICK_CTRL_REG register to ensure the
@ -594,7 +594,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods ); vTaskStepTick( ulCompleteTickPeriods );
/* Exit with interrupts enabled. */ /* Exit with interrupts enabled. */
__asm( " cpsie i"); __asm( " cpsie i");
} }
} }
@ -655,10 +655,10 @@ void vPortSetupTimerInterrupt( void )
* be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.

View file

@ -26,147 +26,146 @@
; * ; *
; */ ; */
.thumb .thumb
.ref pxCurrentTCB .ref pxCurrentTCB
.ref vTaskSwitchContext .ref vTaskSwitchContext
.ref ulMaxSyscallInterruptPriority .ref ulMaxSyscallInterruptPriority
.def xPortPendSVHandler .def xPortPendSVHandler
.def ulPortGetIPSR .def ulPortGetIPSR
.def vPortSVCHandler .def vPortSVCHandler
.def vPortStartFirstTask .def vPortStartFirstTask
.def vPortEnableVFP .def vPortEnableVFP
NVICOffsetConst: .word 0xE000ED08 NVICOffsetConst: .word 0xE000ED08
CPACRConst: .word 0xE000ED88 CPACRConst: .word 0xE000ED88
pxCurrentTCBConst: .word pxCurrentTCB pxCurrentTCBConst: .word pxCurrentTCB
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
ulPortGetIPSR: .asmfunc ulPortGetIPSR: .asmfunc
mrs r0, ipsr mrs r0, ipsr
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortSetInterruptMask: .asmfunc vPortSetInterruptMask: .asmfunc
push {r0} push {r0}
ldr r0, ulMaxSyscallInterruptPriorityConst ldr r0, ulMaxSyscallInterruptPriorityConst
msr basepri, r0 msr basepri, r0
pop {r0} pop {r0}
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
xPortPendSVHandler: .asmfunc xPortPendSVHandler: .asmfunc
mrs r0, psp mrs r0, psp
isb isb
;/* Get the location of the current TCB. */ ;/* Get the location of the current TCB. */
ldr r3, pxCurrentTCBConst ldr r3, pxCurrentTCBConst
ldr r2, [r3] ldr r2, [r3]
;/* Is the task using the FPU context? If so, push high vfp registers. */ ;/* Is the task using the FPU context? If so, push high vfp registers. */
tst r14, #0x10 tst r14, #0x10
it eq it eq
vstmdbeq r0!, {s16-s31} vstmdbeq r0!, {s16-s31}
;/* Save the core registers. */ ;/* Save the core registers. */
stmdb r0!, {r4-r11, r14} stmdb r0!, {r4-r11, r14}
;/* Save the new top of stack into the first member of the TCB. */ ;/* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
stmdb sp!, {r0, r3} stmdb sp!, {r0, r3}
ldr r0, ulMaxSyscallInterruptPriorityConst ldr r0, ulMaxSyscallInterruptPriorityConst
ldr r1, [r0] ldr r1, [r0]
msr basepri, r1 msr basepri, r1
dsb dsb
isb isb
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
ldmia sp!, {r0, r3} ldmia sp!, {r0, r3}
;/* The first item in pxCurrentTCB is the task top of stack. */ ;/* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
;/* Pop the core registers. */ ;/* Pop the core registers. */
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
;/* Is the task using the FPU context? If so, pop the high vfp registers ;/* Is the task using the FPU context? If so, pop the high vfp registers
;too. */ ;too. */
tst r14, #0x10 tst r14, #0x10
it eq it eq
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
isb isb
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortSVCHandler: .asmfunc vPortSVCHandler: .asmfunc
;/* Get the location of the current TCB. */ ;/* Get the location of the current TCB. */
ldr r3, pxCurrentTCBConst ldr r3, pxCurrentTCBConst
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
;/* Pop the core registers. */ ;/* Pop the core registers. */
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
msr psp, r0 msr psp, r0
isb isb
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortStartFirstTask: .asmfunc vPortStartFirstTask: .asmfunc
;/* Use the NVIC offset register to locate the stack. */ ;/* Use the NVIC offset register to locate the stack. */
ldr r0, NVICOffsetConst ldr r0, NVICOffsetConst
ldr r0, [r0] ldr r0, [r0]
ldr r0, [r0] ldr r0, [r0]
;/* Set the msp back to the start of the stack. */ ;/* Set the msp back to the start of the stack. */
msr msp, r0 msr msp, r0
;/* Clear the bit that indicates the FPU is in use in case the FPU was used ;/* Clear the bit that indicates the FPU is in use in case the FPU was used
;before the scheduler was started - which would otherwise result in the ;before the scheduler was started - which would otherwise result in the
;unnecessary leaving of space in the SVC stack for lazy saving of FPU ;unnecessary leaving of space in the SVC stack for lazy saving of FPU
;registers. */ ;registers. */
mov r0, #0 mov r0, #0
msr control, r0 msr control, r0
;/* Call SVC to start the first task. */ ;/* Call SVC to start the first task. */
cpsie i cpsie i
cpsie f cpsie f
dsb dsb
isb isb
svc #0 svc #0
.endasmfunc .endasmfunc
; ----------------------------------------------------------- ; -----------------------------------------------------------
.align 4 .align 4
vPortEnableVFP: .asmfunc vPortEnableVFP: .asmfunc
;/* The FPU enable bits are in the CPACR. */ ;/* The FPU enable bits are in the CPACR. */
ldr.w r0, CPACRConst ldr.w r0, CPACRConst
ldr r1, [r0] ldr r1, [r0]
;/* Enable CP10 and CP11 coprocessors, then save back. */ ;/* Enable CP10 and CP11 coprocessors, then save back. */
orr r1, r1, #( 0xf << 20 ) orr r1, r1, #( 0xf << 20 )
str r1, [r0] str r1, [r0]
bx r14 bx r14
.endasmfunc .endasmfunc
.end .end
; ----------------------------------------------------------- ; -----------------------------------------------------------

View file

@ -81,8 +81,8 @@
{ \ { \
/* Set a PendSV to request a context switch. */ \ /* Set a PendSV to request a context switch. */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
__asm( " dsb"); \ __asm( " dsb"); \
__asm( " isb"); \ __asm( " isb"); \
} }
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
@ -122,14 +122,14 @@
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
{ \ { \
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
__asm( " dsb"); \ __asm( " dsb"); \
__asm( " isb"); \ __asm( " isb"); \
} }
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 ) #define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb") #define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -38,28 +38,28 @@ uint32_t ulCriticalNesting = 9999;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Registers required to configure the RTI. */ /* Registers required to configure the RTI. */
#define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) ) #define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) )
#define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) ) #define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) )
#define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) ) #define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) )
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) ) #define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) )
#define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) ) #define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) )
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) ) #define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) )
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) ) #define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) )
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) ) #define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) )
#define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) ) #define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) )
#define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) ) #define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) )
#define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) ) #define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) )
/* Constants required to set up the initial stack of each task. */ /* Constants required to set up the initial stack of each task. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1F ) #define portINITIAL_SPSR ( ( StackType_t ) 0x1F )
#define portINITIAL_FPSCR ( ( StackType_t ) 0x00 ) #define portINITIAL_FPSCR ( ( StackType_t ) 0x00 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 )
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
/* The number of words on the stack frame between the saved Top Of Stack and /* The number of words on the stack frame between the saved Top Of Stack and
R0 (in which the parameters are passed. */ R0 (in which the parameters are passed. */
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 ) #define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -82,117 +82,117 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
#if __TI_VFP_SUPPORT__ #if __TI_VFP_SUPPORT__
{ {
/* Ensure the stack is correctly aligned on exit. */ /* Ensure the stack is correctly aligned on exit. */
pxTopOfStack--; pxTopOfStack--;
} }
#endif #endif
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which is the start of the as /* First on the stack is the return address - which is the start of the as
the task has not executed yet. The offset is added to make the return the task has not executed yet. The offset is added to make the return
address appear as it would within an IRQ ISR. */ address appear as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */ *pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
#ifdef portPRELOAD_TASK_REGISTERS #ifdef portPRELOAD_TASK_REGISTERS
{ {
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
} }
#else #else
{ {
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS; pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
} }
#endif #endif
/* Function parameters are passed in R0. */ /* Function parameters are passed in R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* Set the status register for system mode, with interrupts enabled. */ /* Set the status register for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR ); *pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 ) if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
{ {
/* The task will start in thumb mode. */ /* The task will start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
#ifdef __TI_VFP_SUPPORT__ #ifdef __TI_VFP_SUPPORT__
{ {
pxTopOfStack--; pxTopOfStack--;
/* The last thing on the stack is the tasks ulUsingFPU value, which by /* The last thing on the stack is the tasks ulUsingFPU value, which by
default is set to indicate that the stack frame does not include FPU default is set to indicate that the stack frame does not include FPU
registers. */ registers. */
*pxTopOfStack = pdFALSE; *pxTopOfStack = pdFALSE;
} }
#endif #endif
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt(void) static void prvSetupTimerInterrupt(void)
{ {
/* Disable timer 0. */ /* Disable timer 0. */
portRTI_GCTRL_REG &= 0xFFFFFFFEUL; portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
/* Use the internal counter. */ /* Use the internal counter. */
portRTI_TBCTRL_REG = 0x00000000U; portRTI_TBCTRL_REG = 0x00000000U;
/* COMPSEL0 will use the RTIFRC0 counter. */ /* COMPSEL0 will use the RTIFRC0 counter. */
portRTI_COMPCTRL_REG = 0x00000000U; portRTI_COMPCTRL_REG = 0x00000000U;
/* Initialise the counter and the prescale counter registers. */ /* Initialise the counter and the prescale counter registers. */
portRTI_CNT0_UC0_REG = 0x00000000U; portRTI_CNT0_UC0_REG = 0x00000000U;
portRTI_CNT0_FRC0_REG = 0x00000000U; portRTI_CNT0_FRC0_REG = 0x00000000U;
/* Set Prescalar for RTI clock. */ /* Set Prescalar for RTI clock. */
portRTI_CNT0_CPUC0_REG = 0x00000001U; portRTI_CNT0_CPUC0_REG = 0x00000001U;
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ; portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ; portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
/* Clear interrupts. */ /* Clear interrupts. */
portRTI_INTFLAG_REG = 0x0007000FU; portRTI_INTFLAG_REG = 0x0007000FU;
portRTI_CLEARINTENA_REG = 0x00070F0FU; portRTI_CLEARINTENA_REG = 0x00070F0FU;
/* Enable the compare 0 interrupt. */ /* Enable the compare 0 interrupt. */
portRTI_SETINTENA_REG = 0x00000001U; portRTI_SETINTENA_REG = 0x00000001U;
portRTI_GCTRL_REG |= 0x00000001U; portRTI_GCTRL_REG |= 0x00000001U;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -201,18 +201,18 @@ static void prvSetupTimerInterrupt(void)
*/ */
BaseType_t xPortStartScheduler(void) BaseType_t xPortStartScheduler(void)
{ {
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Reset the critical section nesting count read to execute the first task. */ /* Reset the critical section nesting count read to execute the first task. */
ulCriticalNesting = 0; ulCriticalNesting = 0;
/* Start the first task. This is done from portASM.asm as ARM mode must be /* Start the first task. This is done from portASM.asm as ARM mode must be
used. */ used. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return pdFAIL; return pdFAIL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -221,36 +221,36 @@ BaseType_t xPortStartScheduler(void)
*/ */
void vPortEndScheduler(void) void vPortEndScheduler(void)
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */ * simply increment the system tick. */
__interrupt void vPortNonPreemptiveTick( void ) __interrupt void vPortNonPreemptiveTick( void )
{ {
/* clear clock interrupt flag */ /* clear clock interrupt flag */
portRTI_INTFLAG_REG = 0x00000001; portRTI_INTFLAG_REG = 0x00000001;
/* Increment the tick count - this may make a delaying task ready /* Increment the tick count - this may make a delaying task ready
to run - but a context switch is not performed. */ to run - but a context switch is not performed. */
xTaskIncrementTick(); xTaskIncrementTick();
} }
#else #else
/* /*
************************************************************************** **************************************************************************
* The preemptive scheduler ISR is written in assembler and can be found * The preemptive scheduler ISR is written in assembler and can be found
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION * in the portASM.asm file. This will only get used if portUSE_PREEMPTION
* is set to 1 in portmacro.h * is set to 1 in portmacro.h
************************************************************************** **************************************************************************
*/ */
void vPortPreemptiveTick( void ); void vPortPreemptiveTick( void );
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -261,13 +261,13 @@ void vPortEndScheduler(void)
*/ */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -277,37 +277,36 @@ void vPortEnterCritical( void )
*/ */
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > 0 ) if( ulCriticalNesting > 0 )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ re-enabled. */
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
/* Enable interrupts as per portENABLE_INTERRUPTS(). */ /* Enable interrupts as per portENABLE_INTERRUPTS(). */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if __TI_VFP_SUPPORT__ #if __TI_VFP_SUPPORT__
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
extern void vPortInitialiseFPSCR( void ); extern void vPortInitialiseFPSCR( void );
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (saved as part of the task context. */ FPU flag (saved as part of the task context. */
ulTaskHasFPUContext = pdTRUE; ulTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
vPortInitialiseFPSCR(); vPortInitialiseFPSCR();
} }
#endif /* __TI_VFP_SUPPORT__ */ #endif /* __TI_VFP_SUPPORT__ */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -31,63 +31,63 @@
.ref vTaskSwitchContext .ref vTaskSwitchContext
.ref xTaskIncrementTick .ref xTaskIncrementTick
.ref ulTaskHasFPUContext .ref ulTaskHasFPUContext
.ref pxCurrentTCB .ref pxCurrentTCB
;/*-----------------------------------------------------------*/ ;/*-----------------------------------------------------------*/
; ;
; Save Task Context ; Save Task Context
; ;
portSAVE_CONTEXT .macro portSAVE_CONTEXT .macro
DSB DSB
; Push R0 as we are going to use it ; Push R0 as we are going to use it
STMDB SP!, {R0} STMDB SP!, {R0}
; Set R0 to point to the task stack pointer. ; Set R0 to point to the task stack pointer.
STMDB SP,{SP}^ STMDB SP,{SP}^
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!,{R0} LDMIA SP!,{R0}
; Push the return address onto the stack. ; Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; Now LR has been saved, it can be used instead of R0. ; Now LR has been saved, it can be used instead of R0.
MOV LR, R0 MOV LR, R0
; Pop R0 so it can be saved onto the task stack. ; Pop R0 so it can be saved onto the task stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; Push all the system mode registers onto the task stack. ; Push all the system mode registers onto the task stack.
STMDB LR,{R0-LR}^ STMDB LR,{R0-LR}^
SUB LR, LR, #60 SUB LR, LR, #60
; Push the SPSR onto the task stack. ; Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
.if (__TI_VFP_SUPPORT__) .if (__TI_VFP_SUPPORT__)
;Determine if the task maintains an FPU context. ;Determine if the task maintains an FPU context.
LDR R0, ulFPUContextConst LDR R0, ulFPUContextConst
LDR R0, [R0] LDR R0, [R0]
; Test the flag ; Test the flag
CMP R0, #0 CMP R0, #0
; If the task is not using a floating point context then skip the ; If the task is not using a floating point context then skip the
; saving of the FPU registers. ; saving of the FPU registers.
BEQ $+16 BEQ $+16
FSTMDBD LR!, {D0-D15} FSTMDBD LR!, {D0-D15}
FMRX R1, FPSCR FMRX R1, FPSCR
STMFD LR!, {R1} STMFD LR!, {R1}
; Save the flag ; Save the flag
STMDB LR!, {R0} STMDB LR!, {R0}
.endif .endif
; Store the new top of stack for the task. ; Store the new top of stack for the task.
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R0, [R0] LDR R0, [R0]
STR LR, [R0] STR LR, [R0]
.endm .endm
@ -96,42 +96,42 @@ portSAVE_CONTEXT .macro
; Restore Task Context ; Restore Task Context
; ;
portRESTORE_CONTEXT .macro portRESTORE_CONTEXT .macro
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R0, [R0] LDR R0, [R0]
LDR LR, [R0] LDR LR, [R0]
.if (__TI_VFP_SUPPORT__) .if (__TI_VFP_SUPPORT__)
; The floating point context flag is the first thing on the stack. ; The floating point context flag is the first thing on the stack.
LDR R0, ulFPUContextConst LDR R0, ulFPUContextConst
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; Test the flag ; Test the flag
CMP R1, #0 CMP R1, #0
; If the task is not using a floating point context then skip the ; If the task is not using a floating point context then skip the
; VFP register loads. ; VFP register loads.
BEQ $+16 BEQ $+16
; Restore the floating point context. ; Restore the floating point context.
LDMFD LR!, {R0} LDMFD LR!, {R0}
FLDMIAD LR!, {D0-D15} FLDMIAD LR!, {D0-D15}
FMXR FPSCR, R0 FMXR FPSCR, R0
.endif .endif
; Get the SPSR from the stack. ; Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_CSXF, R0 MSR SPSR_CSXF, R0
; Restore all system mode registers for the task. ; Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
; Restore the return address. ; Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; And return - correcting the offset in the LR to obtain the ; And return - correcting the offset in the LR to obtain the
; correct address. ; correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
.endm .endm
;/*-----------------------------------------------------------*/ ;/*-----------------------------------------------------------*/
@ -148,9 +148,9 @@ vPortStartFirstTask:
.def vPortYieldProcessor .def vPortYieldProcessor
vPortYieldProcessor: vPortYieldProcessor:
; Within an IRQ ISR the link register has an offset from the true return ; Within an IRQ ISR the link register has an offset from the true return
; address. SWI doesn't do this. Add the offset manually so the ISR ; address. SWI doesn't do this. Add the offset manually so the ISR
; return code can be used. ; return code can be used.
ADD LR, LR, #4 ADD LR, LR, #4
; First save the context of the current task. ; First save the context of the current task.
@ -165,18 +165,18 @@ vPortYieldProcessor:
;/*-----------------------------------------------------------*/ ;/*-----------------------------------------------------------*/
; Yield to another task from within the FreeRTOS API ; Yield to another task from within the FreeRTOS API
.def vPortYeildWithinAPI .def vPortYeildWithinAPI
vPortYeildWithinAPI: vPortYeildWithinAPI:
; Save the context of the current task. ; Save the context of the current task.
portSAVE_CONTEXT portSAVE_CONTEXT
; Clear SSI flag. ; Clear SSI flag.
MOVW R0, #0xFFF4 MOVW R0, #0xFFF4
MOVT R0, #0xFFFF MOVT R0, #0xFFFF
LDR R0, [R0] LDR R0, [R0]
; Select the next task to execute. */ ; Select the next task to execute. */
BL vTaskSwitchContext BL vTaskSwitchContext
; Restore the context of the task selected to execute. ; Restore the context of the task selected to execute.
@ -189,7 +189,7 @@ vPortYeildWithinAPI:
vPortPreemptiveTick: vPortPreemptiveTick:
; Save the context of the current task. ; Save the context of the current task.
portSAVE_CONTEXT portSAVE_CONTEXT
; Clear interrupt flag ; Clear interrupt flag
@ -203,7 +203,7 @@ vPortPreemptiveTick:
BL xTaskIncrementTick BL xTaskIncrementTick
; Select the next task to execute. ; Select the next task to execute.
CMP R0, #0 CMP R0, #0
BLNE vTaskSwitchContext BLNE vTaskSwitchContext
; Restore the context of the task selected to execute. ; Restore the context of the task selected to execute.
@ -211,20 +211,19 @@ vPortPreemptiveTick:
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
.if (__TI_VFP_SUPPORT__) .if (__TI_VFP_SUPPORT__)
.def vPortInitialiseFPSCR .def vPortInitialiseFPSCR
vPortInitialiseFPSCR: vPortInitialiseFPSCR:
MOV R0, #0 MOV R0, #0
FMXR FPSCR, R0 FMXR FPSCR, R0
BX LR BX LR
.endif ;__TI_VFP_SUPPORT__ .endif ;__TI_VFP_SUPPORT__
pxCurrentTCBConst .word pxCurrentTCB pxCurrentTCBConst .word pxCurrentTCB
ulFPUContextConst .word ulTaskHasFPUContext ulFPUContextConst .word ulTaskHasFPUContext
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------

View file

@ -59,9 +59,9 @@ typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t) 0xFFFFFFFFF #define portMAX_DELAY (TickType_t) 0xFFFFFFFFF
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
@ -73,39 +73,39 @@ typedef unsigned long UBaseType_t;
/* Critical section handling. */ /* Critical section handling. */
extern void vPortEnterCritical(void); extern void vPortEnterCritical(void);
extern void vPortExitCritical(void); extern void vPortExitCritical(void);
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm( " CPSID I" ) #define portDISABLE_INTERRUPTS() asm( " CPSID I" )
#define portENABLE_INTERRUPTS() asm( " CPSIE I" ) #define portENABLE_INTERRUPTS() asm( " CPSIE I" )
/* Scheduler utilities. */ /* Scheduler utilities. */
#pragma SWI_ALIAS( vPortYield, 0 ) #pragma SWI_ALIAS( vPortYield, 0 )
extern void vPortYield( void ); extern void vPortYield( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portSYS_SSIR1_REG ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) ) #define portSYS_SSIR1_REG ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
#define portSYS_SSIR1_SSKEY ( 0x7500UL ) #define portSYS_SSIR1_SSKEY ( 0x7500UL )
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); } #define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); }
#define portYIELD_FROM_ISR( x ) do { if( x != pdFALSE ) { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; } } while( 0 ) #define portYIELD_FROM_ISR( x ) do { if( x != pdFALSE ) { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; } } while( 0 )
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
@ -115,4 +115,3 @@ extern void vPortYield( void );
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters) #define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#endif /* __PORTMACRO_H__ */ #endif /* __PORTMACRO_H__ */

View file

@ -26,29 +26,24 @@
; * ; *
; */ ; */
.if $DEFINED( __LARGE_DATA_MODEL__ ) .if $DEFINED( __LARGE_DATA_MODEL__ )
.define "pushm.a", pushm_x .define "pushm.a", pushm_x
.define "popm.a", popm_x .define "popm.a", popm_x
.define "push.a", push_x .define "push.a", push_x
.define "pop.a", pop_x .define "pop.a", pop_x
.define "mov.a", mov_x .define "mov.a", mov_x
.else .else
.define "pushm.w", pushm_x .define "pushm.w", pushm_x
.define "popm.w", popm_x .define "popm.w", popm_x
.define "push.w", push_x .define "push.w", push_x
.define "pop.w", pop_x .define "pop.w", pop_x
.define "mov.w", mov_x .define "mov.w", mov_x
.endif .endif
.if $DEFINED( __LARGE_CODE_MODEL__ )
.define "calla", call_x
.define "reta", ret_x
.else
.define "call", call_x
.define "ret", ret_x
.endif
.if $DEFINED( __LARGE_CODE_MODEL__ )
.define "calla", call_x
.define "reta", ret_x
.else
.define "call", call_x
.define "ret", ret_x
.endif

View file

@ -36,9 +36,9 @@
/* Constants required for hardware setup. The tick ISR runs off the ACLK, /* Constants required for hardware setup. The tick ISR runs off the ACLK,
not the MCLK. */ not the MCLK. */
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 ) #define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 ) #define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 ) #define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
any details of its type. */ any details of its type. */
@ -75,89 +75,89 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
uint16_t *pusTopOfStack; uint16_t *pusTopOfStack;
uint32_t *pulTopOfStack, ulTemp; uint32_t *pulTopOfStack, ulTemp;
/* /*
Place a few bytes of known values on the bottom of the stack. Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging and can be included if required. This is just useful for debugging and can be included if required.
*pxTopOfStack = ( StackType_t ) 0x1111; *pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x3333; *pxTopOfStack = ( StackType_t ) 0x3333;
pxTopOfStack--; pxTopOfStack--;
*/ */
/* Data types are need either 16 bits or 32 bits depending on the data /* Data types are need either 16 bits or 32 bits depending on the data
and code model used. */ and code model used. */
if( sizeof( pxCode ) == sizeof( uint16_t ) ) if( sizeof( pxCode ) == sizeof( uint16_t ) )
{ {
pusTopOfStack = ( uint16_t * ) pxTopOfStack; pusTopOfStack = ( uint16_t * ) pxTopOfStack;
ulTemp = ( uint32_t ) pxCode; ulTemp = ( uint32_t ) pxCode;
*pusTopOfStack = ( uint16_t ) ulTemp; *pusTopOfStack = ( uint16_t ) ulTemp;
} }
else else
{ {
/* Make room for a 20 bit value stored as a 32 bit value. */ /* Make room for a 20 bit value stored as a 32 bit value. */
pusTopOfStack = ( uint16_t * ) pxTopOfStack; pusTopOfStack = ( uint16_t * ) pxTopOfStack;
pusTopOfStack--; pusTopOfStack--;
pulTopOfStack = ( uint32_t * ) pusTopOfStack; pulTopOfStack = ( uint32_t * ) pusTopOfStack;
*pulTopOfStack = ( uint32_t ) pxCode; *pulTopOfStack = ( uint32_t ) pxCode;
} }
pusTopOfStack--; pusTopOfStack--;
*pusTopOfStack = portFLAGS_INT_ENABLED; *pusTopOfStack = portFLAGS_INT_ENABLED;
pusTopOfStack -= ( sizeof( StackType_t ) / 2 ); pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
/* From here on the size of stacked items depends on the memory model. */ /* From here on the size of stacked items depends on the memory model. */
pxTopOfStack = ( StackType_t * ) pusTopOfStack; pxTopOfStack = ( StackType_t * ) pusTopOfStack;
/* Next the general purpose registers. */ /* Next the general purpose registers. */
#ifdef PRELOAD_REGISTER_VALUES #ifdef PRELOAD_REGISTER_VALUES
*pxTopOfStack = ( StackType_t ) 0xffff; *pxTopOfStack = ( StackType_t ) 0xffff;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xeeee; *pxTopOfStack = ( StackType_t ) 0xeeee;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd; *pxTopOfStack = ( StackType_t ) 0xdddd;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xbbbb; *pxTopOfStack = ( StackType_t ) 0xbbbb;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaa; *pxTopOfStack = ( StackType_t ) 0xaaaa;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x9999; *pxTopOfStack = ( StackType_t ) 0x9999;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x8888; *pxTopOfStack = ( StackType_t ) 0x8888;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555; *pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x6666; *pxTopOfStack = ( StackType_t ) 0x6666;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555; *pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x4444; *pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--; pxTopOfStack--;
#else #else
pxTopOfStack -= 3; pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack -= 9; pxTopOfStack -= 9;
#endif #endif
/* A variable is used to keep track of the critical section nesting. /* A variable is used to keep track of the critical section nesting.
This variable has to be stored as part of the task context and is This variable has to be stored as part of the task context and is
initially set to zero. */ initially set to zero. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack we have generated so this can /* Return a pointer to the top of the stack we have generated so this can
be stored in the task control block for the task. */ be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the MSP430 port will get stopped. If required simply /* It is unlikely that the MSP430 port will get stopped. If required simply
disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -166,7 +166,7 @@ void vPortEndScheduler( void )
*/ */
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
vApplicationSetupTimerInterrupt(); vApplicationSetupTimerInterrupt();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -175,14 +175,14 @@ interrupt void vTickISREntry( void )
{ {
extern void vPortTickISR( void ); extern void vPortTickISR( void );
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF ); __bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
extern void vPortPreemptiveTickISR( void ); extern void vPortPreemptiveTickISR( void );
vPortPreemptiveTickISR(); vPortPreemptiveTickISR();
#else #else
extern void vPortCooperativeTickISR( void ); extern void vPortCooperativeTickISR( void );
vPortCooperativeTickISR(); vPortCooperativeTickISR();
#endif #endif
} }

View file

@ -29,44 +29,44 @@
; * The definition of the "register test" tasks, as described at the top of ; * The definition of the "register test" tasks, as described at the top of
; * main.c ; * main.c
.include data_model.h .include data_model.h
.global xTaskIncrementTick .global xTaskIncrementTick
.global vTaskSwitchContext .global vTaskSwitchContext
.global vPortSetupTimerInterrupt .global vPortSetupTimerInterrupt
.global pxCurrentTCB .global pxCurrentTCB
.global usCriticalNesting .global usCriticalNesting
.def vPortPreemptiveTickISR .def vPortPreemptiveTickISR
.def vPortCooperativeTickISR .def vPortCooperativeTickISR
.def vPortYield .def vPortYield
.def xPortStartScheduler .def xPortStartScheduler
;----------------------------------------------------------- ;-----------------------------------------------------------
portSAVE_CONTEXT .macro portSAVE_CONTEXT .macro
;Save the remaining registers. ;Save the remaining registers.
pushm_x #12, r15 pushm_x #12, r15
mov.w &usCriticalNesting, r14 mov.w &usCriticalNesting, r14
push_x r14 push_x r14
mov_x &pxCurrentTCB, r12 mov_x &pxCurrentTCB, r12
mov_x sp, 0( r12 ) mov_x sp, 0( r12 )
.endm .endm
;----------------------------------------------------------- ;-----------------------------------------------------------
portRESTORE_CONTEXT .macro portRESTORE_CONTEXT .macro
mov_x &pxCurrentTCB, r12 mov_x &pxCurrentTCB, r12
mov_x @r12, sp mov_x @r12, sp
pop_x r15 pop_x r15
mov.w r15, &usCriticalNesting mov.w r15, &usCriticalNesting
popm_x #12, r15 popm_x #12, r15
nop nop
pop.w sr pop.w sr
nop nop
ret_x ret_x
.endm .endm
;----------------------------------------------------------- ;-----------------------------------------------------------
;* ;*
@ -78,63 +78,63 @@ portRESTORE_CONTEXT .macro
;* If the preemptive scheduler is in use a context switch can also occur. ;* If the preemptive scheduler is in use a context switch can also occur.
;*/ ;*/
.text .text
.align 2 .align 2
vPortPreemptiveTickISR: .asmfunc vPortPreemptiveTickISR: .asmfunc
; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs ; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
;to save it manually before it gets modified (interrupts get disabled). ;to save it manually before it gets modified (interrupts get disabled).
push.w sr push.w sr
portSAVE_CONTEXT portSAVE_CONTEXT
call_x #xTaskIncrementTick call_x #xTaskIncrementTick
call_x #vTaskSwitchContext call_x #vTaskSwitchContext
portRESTORE_CONTEXT portRESTORE_CONTEXT
.endasmfunc .endasmfunc
;----------------------------------------------------------- ;-----------------------------------------------------------
.align 2 .align 2
vPortCooperativeTickISR: .asmfunc vPortCooperativeTickISR: .asmfunc
; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs ; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
;to save it manually before it gets modified (interrupts get disabled). ;to save it manually before it gets modified (interrupts get disabled).
push.w sr push.w sr
portSAVE_CONTEXT portSAVE_CONTEXT
call_x #xTaskIncrementTick call_x #xTaskIncrementTick
portRESTORE_CONTEXT portRESTORE_CONTEXT
.endasmfunc .endasmfunc
;----------------------------------------------------------- ;-----------------------------------------------------------
; ;
; Manual context switch called by the portYIELD() macro. ; Manual context switch called by the portYIELD() macro.
; ;
.align 2 .align 2
vPortYield: .asmfunc vPortYield: .asmfunc
; The sr needs saving before it is modified. ; The sr needs saving before it is modified.
push.w sr push.w sr
; Now the SR is stacked we can disable interrupts. ; Now the SR is stacked we can disable interrupts.
dint dint
nop nop
; Save the context of the current task. ; Save the context of the current task.
portSAVE_CONTEXT portSAVE_CONTEXT
; Select the next task to run. ; Select the next task to run.
call_x #vTaskSwitchContext call_x #vTaskSwitchContext
; Restore the context of the new task. ; Restore the context of the new task.
portRESTORE_CONTEXT portRESTORE_CONTEXT
.endasmfunc .endasmfunc
;----------------------------------------------------------- ;-----------------------------------------------------------
@ -143,18 +143,17 @@ vPortYield: .asmfunc
; the context of the first task. ; the context of the first task.
; ;
.align 2 .align 2
xPortStartScheduler: .asmfunc xPortStartScheduler: .asmfunc
; Setup the hardware to generate the tick. Interrupts are disabled ; Setup the hardware to generate the tick. Interrupts are disabled
; when this function is called. ; when this function is called.
call_x #vPortSetupTimerInterrupt call_x #vPortSetupTimerInterrupt
; Restore the context of the first task that is going to run. ; Restore the context of the first task that is going to run.
portRESTORE_CONTEXT portRESTORE_CONTEXT
.endasmfunc .endasmfunc
;----------------------------------------------------------- ;-----------------------------------------------------------
.end .end

View file

@ -43,19 +43,19 @@
#include "msp430.h" #include "msp430.h"
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT int #define portSHORT int
#define portBASE_TYPE portSHORT #define portBASE_TYPE portSHORT
/* The stack type changes depending on the data model. */ /* The stack type changes depending on the data model. */
#ifdef __LARGE_DATA_MODEL__ #ifdef __LARGE_DATA_MODEL__
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#else #else
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portPOINTER_SIZE_TYPE uint16_t #define portPOINTER_SIZE_TYPE uint16_t
#endif #endif
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
@ -63,51 +63,51 @@ typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Interrupt control macros. */ /* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop() #define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop()
#define portENABLE_INTERRUPTS() _enable_interrupt(); _nop() #define portENABLE_INTERRUPTS() _enable_interrupt(); _nop()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section control macros. */ /* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
\ \
/* Now interrupts are disabled usCriticalNesting can be accessed */ \ /* Now interrupts are disabled usCriticalNesting can be accessed */ \
/* directly. Increment ulCriticalNesting to keep a count of how many */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
/* Decrement the nesting count as we are leaving a critical section. */ \ /* Decrement the nesting count as we are leaving a critical section. */ \
usCriticalNesting--; \ usCriticalNesting--; \
\ \
/* If the nesting level has reached zero then interrupts should be */ \ /* If the nesting level has reached zero then interrupts should be */ \
/* re-enabled. */ \ /* re-enabled. */ \
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -121,10 +121,10 @@ extern void vPortYield( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __no_operation() #define portNOP() __no_operation()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
@ -141,4 +141,3 @@ run time stats information is to be displayed. */
#define portLU_PRINTF_SPECIFIER_REQUIRED #define portLU_PRINTF_SPECIFIER_REQUIRED
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -31,16 +31,16 @@
#include "task.h" #include "task.h"
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 ) #define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
/* Supervisor mode set. */ /* Supervisor mode set. */
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000) #define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
/* The clock prescale into the timer peripheral. */ /* The clock prescale into the timer peripheral. */
#define portPRESCALE_VALUE ( ( uint8_t ) 10 ) #define portPRESCALE_VALUE ( ( uint8_t ) 10 )
/* The clock frequency into the RTC. */ /* The clock frequency into the RTC. */
#define portRTC_CLOCK_HZ ( ( uint32_t ) 1000 ) #define portRTC_CLOCK_HZ ( ( uint32_t ) 1000 )
asm void interrupt VectorNumber_VL1swi vPortYieldISR( void ); asm void interrupt VectorNumber_VL1swi vPortYieldISR( void );
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
@ -56,29 +56,29 @@ StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t p
uint32_t ulOriginalA5; uint32_t ulOriginalA5;
__asm{ MOVE.L A5, ulOriginalA5 }; __asm{ MOVE.L A5, ulOriginalA5 };
*pxTopOfStack = (StackType_t) 0xDEADBEEF; *pxTopOfStack = (StackType_t) 0xDEADBEEF;
pxTopOfStack--; pxTopOfStack--;
/* Exception stack frame starts with the return address. */ /* Exception stack frame starts with the return address. */
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER ); *pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/ *pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
pxTopOfStack -= 14; /* A5 to D0. */ pxTopOfStack -= 14; /* A5 to D0. */
/* Parameter in A0. */ /* Parameter in A0. */
*( pxTopOfStack + 8 ) = ( StackType_t ) pvParameters; *( pxTopOfStack + 8 ) = ( StackType_t ) pvParameters;
/* A5 must be maintained as it is resurved by the compiler. */ /* A5 must be maintained as it is resurved by the compiler. */
*( pxTopOfStack + 13 ) = ulOriginalA5; *( pxTopOfStack + 13 ) = ulOriginalA5;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -86,67 +86,67 @@ BaseType_t xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL; ulCriticalNesting = 0UL;
/* Configure a timer to generate the tick interrupt. */ /* Configure a timer to generate the tick interrupt. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task executing. */ /* Start the first task executing. */
vPortStartFirstTask(); vPortStartFirstTask();
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
/* Prescale by 1 - ie no prescale. */ /* Prescale by 1 - ie no prescale. */
RTCSC |= 8; RTCSC |= 8;
/* Compare match value. */ /* Compare match value. */
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ; RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
/* Enable the RTC to generate interrupts - interrupts are already disabled /* Enable the RTC to generate interrupts - interrupts are already disabled
when this code executes. */ when this code executes. */
RTCSC_RTIE = 1; RTCSC_RTIE = 1;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented as there is nothing to return to. */ /* Not implemented as there is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
if( ulCriticalNesting == 0UL ) if( ulCriticalNesting == 0UL )
{ {
/* Guard against context switches being pended simultaneously with a /* Guard against context switches being pended simultaneously with a
critical section being entered. */ critical section being entered. */
do do
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( INTC_FRC == 0UL ) if( INTC_FRC == 0UL )
{ {
break; break;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} while( 1 ); } while( 1 );
} }
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -154,13 +154,13 @@ void vPortYieldHandler( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
/* Note this will clear all forced interrupts - this is done for speed. */ /* Note this will clear all forced interrupts - this is done for speed. */
INTC_CFRC = 0x3E; INTC_CFRC = 0x3E;
vTaskSwitchContext(); vTaskSwitchContext();
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -168,17 +168,16 @@ void interrupt VectorNumber_Vrtc vPortTickISR( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
/* Clear the interrupt. */ /* Clear the interrupt. */
RTCSC |= RTCSC_RTIF_MASK; RTCSC |= RTCSC_RTIF_MASK;
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
taskYIELD(); taskYIELD();
} }
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
} }

View file

@ -50,22 +50,22 @@
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
lea.l (-60, sp), sp lea.l (-60, sp), sp
movem.l d0-a6, (sp) movem.l d0-a6, (sp)
move.l _pxCurrentTCB, a0 move.l _pxCurrentTCB, a0
move.l sp, (a0) move.l sp, (a0)
.endm .endm
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
move.l _pxCurrentTCB, a0 move.l _pxCurrentTCB, a0
move.l (a0), sp move.l (a0), sp
movem.l (sp), d0-a6 movem.l (sp), d0-a6
lea.l (60, sp), sp lea.l (60, sp), sp
rte rte
.endm .endm
/********************************************************************/ /********************************************************************/
/* /*
@ -96,7 +96,7 @@ _ulPortSetIPL:
or.l D0,D7 /* place new IPL in sr */ or.l D0,D7 /* place new IPL in sr */
move.w D7,SR move.w D7,SR
move.l D6, D0 /* Return value in D0. */ move.l D6, D0 /* Return value in D0. */
movem.l (SP),D6-D7 movem.l (SP),D6-D7
lea 8(SP),SP lea 8(SP),SP
unlk A6 unlk A6
@ -115,17 +115,15 @@ _mcf5xxx_wr_cacrx:
/* Yield interrupt. */ /* Yield interrupt. */
_vPortYieldISR: _vPortYieldISR:
vPortYieldISR: vPortYieldISR:
portSAVE_CONTEXT portSAVE_CONTEXT
jsr _vPortYieldHandler jsr _vPortYieldHandler
portRESTORE_CONTEXT portRESTORE_CONTEXT
/********************************************************************/ /********************************************************************/
vPortStartFirstTask: vPortStartFirstTask:
_vPortStartFirstTask: _vPortStartFirstTask:
portRESTORE_CONTEXT portRESTORE_CONTEXT
.end .end

View file

@ -44,13 +44,13 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
@ -58,42 +58,42 @@ typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
uint32_t ulPortSetIPL( uint32_t ); uint32_t ulPortSetIPL( uint32_t );
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 ) #define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
extern UBaseType_t uxPortSetInterruptMaskFromISR( void ); extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
extern void vPortClearInterruptMaskFromISR( UBaseType_t ); extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portNOP() asm volatile ( "nop" ) #define portNOP() asm volatile ( "nop" )
/* Context switches are requested using the force register. */ /* Context switches are requested using the force register. */
#define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP() #define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -102,7 +102,7 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 ) #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 )
#ifdef __cplusplus #ifdef __cplusplus
@ -110,4 +110,3 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -31,28 +31,28 @@
#include "task.h" #include "task.h"
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 ) #define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
/* Supervisor mode set. */ /* Supervisor mode set. */
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000) #define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This /* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
will be set to 0 prior to the first task being started. */ will be set to 0 prior to the first task being started. */
static uint32_t ulCriticalNesting = 0x9999UL; static uint32_t ulCriticalNesting = 0x9999UL;
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
lea.l (-60, %sp), %sp; \ lea.l (-60, %sp), %sp; \
movem.l %d0-%fp, (%sp); \ movem.l %d0-%fp, (%sp); \
move.l pxCurrentTCB, %a0; \ move.l pxCurrentTCB, %a0; \
move.l %sp, (%a0); move.l %sp, (%a0);
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
move.l pxCurrentTCB, %a0; \ move.l pxCurrentTCB, %a0; \
move.l (%a0), %sp; \ move.l (%a0), %sp; \
movem.l (%sp), %d0-%fp; \ movem.l (%sp), %d0-%fp; \
lea.l %sp@(60), %sp; \ lea.l %sp@(60), %sp; \
rte rte
@ -60,21 +60,21 @@ static uint32_t ulCriticalNesting = 0x9999UL;
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{ {
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = (StackType_t) 0xDEADBEEF; *pxTopOfStack = (StackType_t) 0xDEADBEEF;
pxTopOfStack--; pxTopOfStack--;
/* Exception stack frame starts with the return address. */ /* Exception stack frame starts with the return address. */
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER ); *pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/ *pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
pxTopOfStack -= 14; /* A5 to D0. */ pxTopOfStack -= 14; /* A5 to D0. */
return pxTopOfStack; return pxTopOfStack;
} }
@ -84,53 +84,53 @@ BaseType_t xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL; ulCriticalNesting = 0UL;
/* Configure the interrupts used by this port. */ /* Configure the interrupts used by this port. */
vApplicationSetupInterrupts(); vApplicationSetupInterrupts();
/* Start the first task executing. */ /* Start the first task executing. */
vPortStartFirstTask(); vPortStartFirstTask();
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented as there is nothing to return to. */ /* Not implemented as there is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
if( ulCriticalNesting == 0UL ) if( ulCriticalNesting == 0UL )
{ {
/* Guard against context switches being pended simultaneously with a /* Guard against context switches being pended simultaneously with a
critical section being entered. */ critical section being entered. */
do do
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( MCF_INTC0_INTFRCH == 0UL ) if( MCF_INTC0_INTFRCH == 0UL )
{ {
break; break;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} while( 1 ); } while( 1 );
} }
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -138,11 +138,10 @@ void vPortYieldHandler( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
/* Note this will clear all forced interrupts - this is done for speed. */ /* Note this will clear all forced interrupts - this is done for speed. */
MCF_INTC0_INTFRCL = 0; MCF_INTC0_INTFRCL = 0;
vTaskSwitchContext(); vTaskSwitchContext();
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -50,22 +50,22 @@
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
lea.l (-60, sp), sp lea.l (-60, sp), sp
movem.l d0-a6, (sp) movem.l d0-a6, (sp)
move.l _pxCurrentTCB, a0 move.l _pxCurrentTCB, a0
move.l sp, (a0) move.l sp, (a0)
.endm .endm
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
move.l _pxCurrentTCB, a0 move.l _pxCurrentTCB, a0
move.l (a0), sp move.l (a0), sp
movem.l (sp), d0-a6 movem.l (sp), d0-a6
lea.l (60, sp), sp lea.l (60, sp), sp
rte rte
.endm .endm
/********************************************************************/ /********************************************************************/
/* /*
@ -115,17 +115,15 @@ _mcf5xxx_wr_cacrx:
/* Yield interrupt. */ /* Yield interrupt. */
_vPortYieldISR: _vPortYieldISR:
vPortYieldISR: vPortYieldISR:
portSAVE_CONTEXT portSAVE_CONTEXT
jsr _vPortYieldHandler jsr _vPortYieldHandler
portRESTORE_CONTEXT portRESTORE_CONTEXT
/********************************************************************/ /********************************************************************/
vPortStartFirstTask: vPortStartFirstTask:
_vPortStartFirstTask: _vPortStartFirstTask:
portRESTORE_CONTEXT portRESTORE_CONTEXT
.end .end

View file

@ -44,55 +44,55 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
uint32_t ulPortSetIPL( uint32_t ); uint32_t ulPortSetIPL( uint32_t );
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 ) #define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
extern UBaseType_t uxPortSetInterruptMaskFromISR( void ); extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
extern void vPortClearInterruptMaskFromISR( UBaseType_t ); extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portNOP() asm volatile ( "nop" ) #define portNOP() asm volatile ( "nop" )
/* Note this will overwrite all other bits in the force register, it is done this way for speed. */ /* Note this will overwrite all other bits in the force register, it is done this way for speed. */
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */ #define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -101,7 +101,7 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 ) #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 )
#ifdef __cplusplus #ifdef __cplusplus
@ -109,4 +109,3 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -46,17 +46,17 @@ static void prvSetupTimerInterrupt( void );
scheduler startup function. */ scheduler startup function. */
#pragma CODE_SEG __NEAR_SEG NON_BANKED #pragma CODE_SEG __NEAR_SEG NON_BANKED
/* Manual context switch function. This is the SWI ISR. */ /* Manual context switch function. This is the SWI ISR. */
void interrupt vPortYield( void ); void interrupt vPortYield( void );
/* Tick context switch function. This is the timer ISR. */ /* Tick context switch function. This is the timer ISR. */
void interrupt vPortTickInterrupt( void ); void interrupt vPortTickInterrupt( void );
/* Simply called by xPortStartScheduler(). xPortStartScheduler() does not /* Simply called by xPortStartScheduler(). xPortStartScheduler() does not
start the scheduler directly because the header file containing the start the scheduler directly because the header file containing the
xPortStartScheduler() prototype is part of the common kernel code, and xPortStartScheduler() prototype is part of the common kernel code, and
therefore cannot use the CODE_SEG pragma. */ therefore cannot use the CODE_SEG pragma. */
static BaseType_t xBankedStartScheduler( void ); static BaseType_t xBankedStartScheduler( void );
#pragma CODE_SEG DEFAULT #pragma CODE_SEG DEFAULT
@ -75,94 +75,94 @@ volatile UBaseType_t uxCriticalNesting = 0xff;
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{ {
/* /*
Place a few bytes of known values on the bottom of the stack. Place a few bytes of known values on the bottom of the stack.
This can be uncommented to provide useful stack markers when debugging. This can be uncommented to provide useful stack markers when debugging.
*pxTopOfStack = ( StackType_t ) 0x11; *pxTopOfStack = ( StackType_t ) 0x11;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22; *pxTopOfStack = ( StackType_t ) 0x22;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x33; *pxTopOfStack = ( StackType_t ) 0x33;
pxTopOfStack--; pxTopOfStack--;
*/ */
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. In this case the stack as expected by the portRESTORE_CONTEXT() macro. In this case the stack as
expected by the HCS12 RTI instruction. */ expected by the HCS12 RTI instruction. */
/* The address of the task function is placed in the stack byte at a time. */ /* The address of the task function is placed in the stack byte at a time. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 );
pxTopOfStack--; pxTopOfStack--;
/* Next are all the registers that form part of the task context. */ /* Next are all the registers that form part of the task context. */
/* Y register */ /* Y register */
*pxTopOfStack = ( StackType_t ) 0xff; *pxTopOfStack = ( StackType_t ) 0xff;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xee; *pxTopOfStack = ( StackType_t ) 0xee;
pxTopOfStack--; pxTopOfStack--;
/* X register */ /* X register */
*pxTopOfStack = ( StackType_t ) 0xdd; *pxTopOfStack = ( StackType_t ) 0xdd;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xcc; *pxTopOfStack = ( StackType_t ) 0xcc;
pxTopOfStack--; pxTopOfStack--;
/* A register contains parameter high byte. */ /* A register contains parameter high byte. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
pxTopOfStack--; pxTopOfStack--;
/* B register contains parameter low byte. */ /* B register contains parameter low byte. */
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
pxTopOfStack--; pxTopOfStack--;
/* CCR: Note that when the task starts interrupts will be enabled since /* CCR: Note that when the task starts interrupts will be enabled since
"I" bit of CCR is cleared */ "I" bit of CCR is cleared */
*pxTopOfStack = ( StackType_t ) 0x00; *pxTopOfStack = ( StackType_t ) 0x00;
pxTopOfStack--; pxTopOfStack--;
#ifdef BANKED_MODEL #ifdef BANKED_MODEL
/* The page of the task. */ /* The page of the task. */
*pxTopOfStack = ( StackType_t ) ( ( int ) pxCode ); *pxTopOfStack = ( StackType_t ) ( ( int ) pxCode );
pxTopOfStack--; pxTopOfStack--;
#endif #endif
/* Finally the critical nesting depth is initialised with 0 (not within /* Finally the critical nesting depth is initialised with 0 (not within
a critical section). */ a critical section). */
*pxTopOfStack = ( StackType_t ) 0x00; *pxTopOfStack = ( StackType_t ) 0x00;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the HCS12 port will get stopped. */ /* It is unlikely that the HCS12 port will get stopped. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
TickTimer_SetFreqHz( configTICK_RATE_HZ ); TickTimer_SetFreqHz( configTICK_RATE_HZ );
TickTimer_Enable(); TickTimer_Enable();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* xPortStartScheduler() does not start the scheduler directly because /* xPortStartScheduler() does not start the scheduler directly because
the header file containing the xPortStartScheduler() prototype is part the header file containing the xPortStartScheduler() prototype is part
of the common kernel code, and therefore cannot use the CODE_SEG pragma. of the common kernel code, and therefore cannot use the CODE_SEG pragma.
Instead it simply calls the locally defined xBankedStartScheduler() - Instead it simply calls the locally defined xBankedStartScheduler() -
which does use the CODE_SEG pragma. */ which does use the CODE_SEG pragma. */
return xBankedStartScheduler(); return xBankedStartScheduler();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -170,18 +170,18 @@ BaseType_t xPortStartScheduler( void )
static BaseType_t xBankedStartScheduler( void ) static BaseType_t xBankedStartScheduler( void )
{ {
/* Configure the timer that will generate the RTOS tick. Interrupts are /* Configure the timer that will generate the RTOS tick. Interrupts are
disabled when this function is called. */ disabled when this function is called. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Restore the context of the first task. */ /* Restore the context of the first task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
/* Simulate the end of an interrupt to start the scheduler off. */ /* Simulate the end of an interrupt to start the scheduler off. */
__asm( "rti" ); __asm( "rti" );
/* Should not get here! */ /* Should not get here! */
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -195,9 +195,9 @@ static BaseType_t xBankedStartScheduler( void )
*/ */
void interrupt vPortYield( void ) void interrupt vPortYield( void )
{ {
portSAVE_CONTEXT(); portSAVE_CONTEXT();
vTaskSwitchContext(); vTaskSwitchContext();
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -208,31 +208,29 @@ void interrupt vPortYield( void )
*/ */
void interrupt vPortTickInterrupt( void ) void interrupt vPortTickInterrupt( void )
{ {
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
{ {
/* A context switch might happen so save the context. */ /* A context switch might happen so save the context. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Increment the tick ... */ /* Increment the tick ... */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
vTaskSwitchContext(); vTaskSwitchContext();
} }
TFLG1 = 1; TFLG1 = 1;
/* Restore the context of a task - which may be a different task /* Restore the context of a task - which may be a different task
to that interrupted. */ to that interrupted. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#else #else
{ {
xTaskIncrementTick(); xTaskIncrementTick();
TFLG1 = 1; TFLG1 = 1;
} }
#endif #endif
} }
#pragma CODE_SEG DEFAULT #pragma CODE_SEG DEFAULT

View file

@ -41,38 +41,38 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint8_t #define portSTACK_TYPE uint8_t
#define portBASE_TYPE char #define portBASE_TYPE char
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef signed char BaseType_t; typedef signed char BaseType_t;
typedef unsigned char UBaseType_t; typedef unsigned char UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 1 #define portBYTE_ALIGNMENT 1
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portYIELD() __asm( "swi" ); #define portYIELD() __asm( "swi" );
#define portNOP() __asm( "nop" ); #define portNOP() __asm( "nop" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
#define portENABLE_INTERRUPTS() __asm( "cli" ) #define portENABLE_INTERRUPTS() __asm( "cli" )
#define portDISABLE_INTERRUPTS() __asm( "sei" ) #define portDISABLE_INTERRUPTS() __asm( "sei" )
/* /*
* Disable interrupts before incrementing the count of critical section nesting. * Disable interrupts before incrementing the count of critical section nesting.
@ -80,12 +80,12 @@ typedef unsigned char UBaseType_t;
* re-enabled. Once interrupts are disabled the nesting count can be accessed * re-enabled. Once interrupts are disabled the nesting count can be accessed
* directly. Each task maintains its own nesting count. * directly. Each task maintains its own nesting count.
*/ */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
uxCriticalNesting++; \ uxCriticalNesting++; \
} }
/* /*
@ -93,15 +93,15 @@ typedef unsigned char UBaseType_t;
* nesting is found to be 0 (no nesting) then we are leaving the critical * nesting is found to be 0 (no nesting) then we are leaving the critical
* section and interrupts can be re-enabled. * section and interrupts can be re-enabled.
*/ */
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
uxCriticalNesting--; \ uxCriticalNesting--; \
if( uxCriticalNesting == 0 ) \ if( uxCriticalNesting == 0 ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -118,69 +118,69 @@ typedef unsigned char UBaseType_t;
*/ */
#ifdef BANKED_MODEL #ifdef BANKED_MODEL
/* /*
* Load the stack pointer for the task, then pull the critical nesting * Load the stack pointer for the task, then pull the critical nesting
* count and PPAGE register from the stack. The remains of the * count and PPAGE register from the stack. The remains of the
* context are restored by the RTI instruction. * context are restored by the RTI instruction.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * pxCurrentTCB; \ extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "lds 0, x" ); \ __asm( "lds 0, x" ); \
__asm( "pula" ); \ __asm( "pula" ); \
__asm( "staa uxCriticalNesting" ); \ __asm( "staa uxCriticalNesting" ); \
__asm( "pula" ); \ __asm( "pula" ); \
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \ __asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
} }
/* /*
* By the time this macro is called the processor has already stacked the * By the time this macro is called the processor has already stacked the
* registers. Simply stack the nesting count and PPAGE value, then save * registers. Simply stack the nesting count and PPAGE value, then save
* the task stack pointer. * the task stack pointer.
*/ */
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * pxCurrentTCB; \ extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
__asm( "ldaa 0x30" ); /* 0x30 = PPAGE */ \ __asm( "ldaa 0x30" ); /* 0x30 = PPAGE */ \
__asm( "psha" ); \ __asm( "psha" ); \
__asm( "ldaa uxCriticalNesting" ); \ __asm( "ldaa uxCriticalNesting" ); \
__asm( "psha" ); \ __asm( "psha" ); \
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \ __asm( "sts 0, x" ); \
} }
#else #else
/* /*
* These macros are as per the BANKED versions above, but without saving * These macros are as per the BANKED versions above, but without saving
* and restoring the PPAGE register. * and restoring the PPAGE register.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * pxCurrentTCB; \ extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "lds 0, x" ); \ __asm( "lds 0, x" ); \
__asm( "pula" ); \ __asm( "pula" ); \
__asm( "staa uxCriticalNesting" ); \ __asm( "staa uxCriticalNesting" ); \
} }
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * pxCurrentTCB; \ extern volatile void * pxCurrentTCB; \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
__asm( "ldaa uxCriticalNesting" ); \ __asm( "ldaa uxCriticalNesting" ); \
__asm( "psha" ); \ __asm( "psha" ); \
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \ __asm( "sts 0, x" ); \
} }
#endif #endif
/* /*
@ -189,10 +189,10 @@ typedef unsigned char UBaseType_t;
* the ISR does not use any local (stack) variables. If the ISR uses stack * the ISR does not use any local (stack) variables. If the ISR uses stack
* variables portYIELD() should be used in it's place. * variables portYIELD() should be used in it's place.
*/ */
#define portTASK_SWITCH_FROM_ISR() \ #define portTASK_SWITCH_FROM_ISR() \
portSAVE_CONTEXT(); \ portSAVE_CONTEXT(); \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
@ -200,4 +200,3 @@ typedef unsigned char UBaseType_t;
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -50,11 +50,11 @@
#include "tc.h" #include "tc.h"
/* Constants required to setup the task context. */ /* Constants required to setup the task context. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
#define portTICK_PRIORITY_6 ( 6 ) #define portTICK_PRIORITY_6 ( 6 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Setup the timer to generate the tick interrupts. */ /* Setup the timer to generate the tick interrupts. */
@ -78,96 +78,96 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
{ {
/* We want the task to start in thumb mode. */ /* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
#endif #endif
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
vPortISRStartFirstTask(); vPortISRStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -178,62 +178,61 @@ static void prvSetupTimerInterrupt( void )
{ {
volatile uint32_t ulDummy; volatile uint32_t ulDummy;
/* Enable clock to the tick timer... */ /* Enable clock to the tick timer... */
AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT; AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT;
/* Stop the tick timer... */ /* Stop the tick timer... */
portTIMER_REG_BASE_PTR->TC_CCR = TC_CLKDIS; portTIMER_REG_BASE_PTR->TC_CCR = TC_CLKDIS;
/* Start with tick timer interrupts disabled... */ /* Start with tick timer interrupts disabled... */
portTIMER_REG_BASE_PTR->TC_IDR = 0xFFFFFFFF; portTIMER_REG_BASE_PTR->TC_IDR = 0xFFFFFFFF;
/* Clear any pending tick timer interrupts... */ /* Clear any pending tick timer interrupts... */
ulDummy = portTIMER_REG_BASE_PTR->TC_SR; ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
/* Store interrupt handler function address in tick timer vector register... /* Store interrupt handler function address in tick timer vector register...
The ISR installed depends on whether the preemptive or cooperative The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */ scheduler is being used. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
{ {
extern void ( vPreemptiveTick )( void ); extern void ( vPreemptiveTick )( void );
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vPreemptiveTick; AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vPreemptiveTick;
} }
#else // else use cooperative scheduler #else // else use cooperative scheduler
{ {
extern void ( vNonPreemptiveTick )( void ); extern void ( vNonPreemptiveTick )( void );
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vNonPreemptiveTick; AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vNonPreemptiveTick;
} }
#endif #endif
/* Tick timer interrupt level-sensitive, priority 6... */ /* Tick timer interrupt level-sensitive, priority 6... */
AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6; AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6;
/* Enable the tick timer interrupt... /* Enable the tick timer interrupt...
First at timer level */ First at timer level */
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS; portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
/* Then at the AIC level. */ /* Then at the AIC level. */
AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL); AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL);
/* Calculate timer compare value to achieve the desired tick rate... */ /* Calculate timer compare value to achieve the desired tick rate... */
if( (configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2) ) <= 0xFFFF ) if( (configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2) ) <= 0xFFFF )
{ {
/* The tick rate is fast enough for us to use the faster timer input /* The tick rate is fast enough for us to use the faster timer input
clock (main clock / 2). */ clock (main clock / 2). */
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG; portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG;
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2); portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2);
} }
else else
{ {
/* We must use a slower timer input clock (main clock / 8) because the /* We must use a slower timer input clock (main clock / 8) because the
tick rate is too slow for the faster input clock. */ tick rate is too slow for the faster input clock. */
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG; portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG;
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 8); portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 8);
} }
/* Start tick timer... */ /* Start tick timer... */
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN; portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -34,10 +34,10 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
Changes from V3.2.4 Changes from V3.2.4
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
*/ */
@ -46,10 +46,10 @@
#include "task.h" #include "task.h"
/* Constants required to handle interrupts. */ /* Constants required to handle interrupts. */
#define portCLEAR_AIC_INTERRUPT ( ( uint32_t ) 0 ) #define portCLEAR_AIC_INTERRUPT ( ( uint32_t ) 0 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -66,9 +66,9 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -82,19 +82,19 @@ void vPortISRStartFirstTask( void )
*/ */
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ ISR return code can be used in both cases. */
asm volatile ( "ADD LR, LR, #4" ); asm volatile ( "ADD LR, LR, #4" );
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */ /* Find the highest priority task that is ready to run. */
vTaskSwitchContext(); vTaskSwitchContext();
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -105,52 +105,52 @@ void vPortYieldProcessor( void )
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
simply increment the system tick. */ simply increment the system tick. */
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
void vNonPreemptiveTick( void ) void vNonPreemptiveTick( void )
{ {
static volatile uint32_t ulDummy; static volatile uint32_t ulDummy;
/* Clear tick timer interrupt indication. */ /* Clear tick timer interrupt indication. */
ulDummy = portTIMER_REG_BASE_PTR->TC_SR; ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
xTaskIncrementTick(); xTaskIncrementTick();
/* Acknowledge the interrupt at AIC level... */ /* Acknowledge the interrupt at AIC level... */
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT; AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
} }
#else /* else preemption is turned on */ #else /* else preemption is turned on */
/* The preemptive scheduler is defined as "naked" as the full context is /* The preemptive scheduler is defined as "naked" as the full context is
saved on entry as part of the context switch. */ saved on entry as part of the context switch. */
void vPreemptiveTick( void ) __attribute__((naked)); void vPreemptiveTick( void ) __attribute__((naked));
void vPreemptiveTick( void ) void vPreemptiveTick( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* WARNING - Do not use local (stack) variables here. Use globals /* WARNING - Do not use local (stack) variables here. Use globals
if you must! */ if you must! */
static volatile uint32_t ulDummy; static volatile uint32_t ulDummy;
/* Clear tick timer interrupt indication. */ /* Clear tick timer interrupt indication. */
ulDummy = portTIMER_REG_BASE_PTR->TC_SR; ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
/* Increment the RTOS tick count, then look for the highest priority /* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */ task that is ready to run. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
vTaskSwitchContext(); vTaskSwitchContext();
} }
/* Acknowledge the interrupt at AIC level... */ /* Acknowledge the interrupt at AIC level... */
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT; AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -163,30 +163,30 @@ void vPortYieldProcessor( void )
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
@ -196,39 +196,38 @@ be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
asm volatile ( asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
} }
} }
} }

View file

@ -27,26 +27,26 @@
*/ */
/* /*
Changes from V3.2.3 Changes from V3.2.3
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
Changes from V3.2.4 Changes from V3.2.4
+ Removed the use of the %0 parameter within the assembler macros and + Removed the use of the %0 parameter within the assembler macros and
replaced them with hard coded registers. This will ensure the replaced them with hard coded registers. This will ensure the
assembler does not select the link register as the temp register as assembler does not select the link register as the temp register as
was occasionally happening previously. was occasionally happening previously.
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
Changes from V4.5.0 Changes from V4.5.0
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code. macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -67,42 +67,42 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm volatile ( "SWI 0" ) #define portYIELD() asm volatile ( "SWI 0" )
#define portNOP() asm volatile ( "NOP" ) #define portNOP() asm volatile ( "NOP" )
/* /*
* These define the timer to use for generating the tick interrupt. * These define the timer to use for generating the tick interrupt.
* They are put in this file so they can be shared between "port.c" * They are put in this file so they can be shared between "port.c"
* and "portisr.c". * and "portisr.c".
*/ */
#define portTIMER_REG_BASE_PTR AT91C_BASE_TC0 #define portTIMER_REG_BASE_PTR AT91C_BASE_TC0
#define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0 #define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0
#define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 ) #define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -114,87 +114,87 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
asm volatile ( \ asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t" \
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t" \
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t" \
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t" \
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t" \
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t" \
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
asm volatile ( \ asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t" \
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t" \
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t" \
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t" \
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t" \
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t" \
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t" \
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
@ -210,37 +210,37 @@ extern volatile uint32_t ulCriticalNesting; \
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
asm volatile ( \ asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
asm volatile ( \ asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -253,4 +253,3 @@ extern void vPortExitCritical( void );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -48,4 +48,3 @@
//* \fn AT91F_AIC_ConfigureIt //* \fn AT91F_AIC_ConfigureIt
//* \brief Interrupt Handler Initialization //* \brief Interrupt Handler Initialization
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------

File diff suppressed because it is too large Load diff

View file

@ -46,24 +46,24 @@
#include "AT91SAM7X256.h" #include "AT91SAM7X256.h"
/* Constants required to setup the task context. */ /* Constants required to setup the task context. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
/* Constants required to setup the tick ISR. */ /* Constants required to setup the tick ISR. */
#define portENABLE_TIMER ( ( uint8_t ) 0x01 ) #define portENABLE_TIMER ( ( uint8_t ) 0x01 )
#define portPRESCALE_VALUE 0x00 #define portPRESCALE_VALUE 0x00
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 ) #define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 ) #define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
/* Constants required to setup the PIT. */ /* Constants required to setup the PIT. */
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 ) #define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS ) #define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
#define portINT_LEVEL_SENSITIVE 0 #define portINT_LEVEL_SENSITIVE 0
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 ) #define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 ) #define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Setup the timer to generate the tick interrupts. */ /* Setup the timer to generate the tick interrupts. */
@ -87,96 +87,96 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */ *pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
{ {
/* We want the task to start in thumb mode. */ /* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
#endif #endif
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
vPortISRStartFirstTask(); vPortISRStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -187,28 +187,25 @@ static void prvSetupTimerInterrupt( void )
{ {
AT91PS_PITC pxPIT = AT91C_BASE_PITC; AT91PS_PITC pxPIT = AT91C_BASE_PITC;
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends /* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
on whether the preemptive or cooperative scheduler is being used. */ on whether the preemptive or cooperative scheduler is being used. */
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
extern void ( vNonPreemptiveTick ) ( void ); extern void ( vNonPreemptiveTick ) ( void );
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick ); AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );
#else #else
extern void ( vPreemptiveTick )( void ); extern void ( vPreemptiveTick )( void );
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick ); AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick );
#endif #endif
/* Configure the PIT period. */ /* Configure the PIT period. */
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE; pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
/* Enable the interrupt. Global interrupts are disables at this point so /* Enable the interrupt. Global interrupts are disables at this point so
this is safe. */ this is safe. */
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS; AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -34,10 +34,10 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
Changes from V3.2.4 Changes from V3.2.4
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
*/ */
/* Scheduler includes. */ /* Scheduler includes. */
@ -47,11 +47,11 @@
#include "AT91SAM7X256.h" #include "AT91SAM7X256.h"
/* Constants required to handle interrupts. */ /* Constants required to handle interrupts. */
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 ) #define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 ) #define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -68,9 +68,9 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -84,19 +84,19 @@ void vPortISRStartFirstTask( void )
*/ */
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" ); __asm volatile ( "ADD LR, LR, #4" );
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */ /* Find the highest priority task that is ready to run. */
vTaskSwitchContext(); vTaskSwitchContext();
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -107,47 +107,47 @@ void vPortYieldProcessor( void )
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
simply increment the system tick. */ simply increment the system tick. */
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
void vNonPreemptiveTick( void ) void vNonPreemptiveTick( void )
{ {
uint32_t ulDummy; uint32_t ulDummy;
/* Increment the tick count - which may wake some tasks but as the /* Increment the tick count - which may wake some tasks but as the
preemptive scheduler is not being used any woken task is not given preemptive scheduler is not being used any woken task is not given
processor time no matter what its priority. */ processor time no matter what its priority. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Clear the PIT interrupt. */ /* Clear the PIT interrupt. */
ulDummy = AT91C_BASE_PITC->PITC_PIVR; ulDummy = AT91C_BASE_PITC->PITC_PIVR;
/* End the interrupt in the AIC. */ /* End the interrupt in the AIC. */
AT91C_BASE_AIC->AIC_EOICR = ulDummy; AT91C_BASE_AIC->AIC_EOICR = ulDummy;
} }
#else #else
/* The preemptive scheduler is defined as "naked" as the full context is /* The preemptive scheduler is defined as "naked" as the full context is
saved on entry as part of the context switch. */ saved on entry as part of the context switch. */
void vPreemptiveTick( void ) __attribute__((naked)); void vPreemptiveTick( void ) __attribute__((naked));
void vPreemptiveTick( void ) void vPreemptiveTick( void )
{ {
/* Save the context of the current task. */ /* Save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Increment the tick count - this may wake a task. */ /* Increment the tick count - this may wake a task. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* Find the highest priority task that is ready to run. */ /* Find the highest priority task that is ready to run. */
vTaskSwitchContext(); vTaskSwitchContext();
} }
/* End the interrupt in the AIC. */ /* End the interrupt in the AIC. */
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR; AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -163,24 +163,24 @@ void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
@ -190,39 +190,38 @@ be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
} }
} }
} }

View file

@ -27,26 +27,26 @@
*/ */
/* /*
Changes from V3.2.3 Changes from V3.2.3
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
Changes from V3.2.4 Changes from V3.2.4
+ Removed the use of the %0 parameter within the assembler macros and + Removed the use of the %0 parameter within the assembler macros and
replaced them with hard coded registers. This will ensure the replaced them with hard coded registers. This will ensure the
assembler does not select the link register as the temp register as assembler does not select the link register as the temp register as
was occasionally happening previously. was occasionally happening previously.
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
Changes from V4.5.0 Changes from V4.5.0
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code. macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -67,32 +67,32 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE portLONG #define portBASE_TYPE portLONG
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() __asm volatile ( "NOP" ); #define portNOP() __asm volatile ( "NOP" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -105,92 +105,92 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
__asm volatile ( \ __asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t" \
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t" \
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t" \
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t" \
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t" \
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t" \
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t" \
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t" \
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t" \
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t" \
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t" \
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t" \
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t" \
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
#define portYIELD() __asm volatile ( "SWI 0" ) #define portYIELD() __asm volatile ( "SWI 0" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -205,37 +205,37 @@ extern volatile uint32_t ulCriticalNesting; \
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
@ -247,4 +247,3 @@ extern void vPortExitCritical( void );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -44,21 +44,21 @@
#include "task.h" #include "task.h"
/* Constants required to setup the task context. */ /* Constants required to setup the task context. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
/* Constants required to setup the tick ISR. */ /* Constants required to setup the tick ISR. */
#define portENABLE_TIMER ( ( uint8_t ) 0x01 ) #define portENABLE_TIMER ( ( uint8_t ) 0x01 )
#define portPRESCALE_VALUE 0x00 #define portPRESCALE_VALUE 0x00
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 ) #define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 ) #define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
/* Constants required to setup the VIC for the tick ISR. */ /* Constants required to setup the VIC for the tick ISR. */
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 ) #define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 ) #define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 ) #define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -83,95 +83,95 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 ) if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
{ {
/* We want the task to start in thumb mode. */ /* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
vPortISRStartFirstTask(); vPortISRStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -183,40 +183,37 @@ static void prvSetupTimerInterrupt( void )
uint32_t ulCompareMatch; uint32_t ulCompareMatch;
extern void ( vTickISR )( void ); extern void ( vTickISR )( void );
/* A 1ms tick does not require the use of the timer prescale. This is /* A 1ms tick does not require the use of the timer prescale. This is
defaulted to zero but can be used if necessary. */ defaulted to zero but can be used if necessary. */
T0_PR = portPRESCALE_VALUE; T0_PR = portPRESCALE_VALUE;
/* Calculate the match value required for our wanted tick rate. */ /* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Protect against divide by zero. Using an if() statement still results /* Protect against divide by zero. Using an if() statement still results
in a warning - hence the #if. */ in a warning - hence the #if. */
#if portPRESCALE_VALUE != 0 #if portPRESCALE_VALUE != 0
{ {
ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
} }
#endif #endif
T0_MR0 = ulCompareMatch; T0_MR0 = ulCompareMatch;
/* Generate tick with timer 0 compare match. */ /* Generate tick with timer 0 compare match. */
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH; T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
/* Setup the VIC for the timer. */ /* Setup the VIC for the timer. */
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT ); VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT; VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
/* The ISR installed depends on whether the preemptive or cooperative /* The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */ scheduler is being used. */
VICVectAddr0 = ( int32_t ) vTickISR; VICVectAddr0 = ( int32_t ) vTickISR;
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
/* Start the timer - interrupts are disabled when this function is called /* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */ so it is okay to do this here. */
T0_TCR = portENABLE_TIMER; T0_TCR = portENABLE_TIMER;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -34,21 +34,21 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
Changes from V2.5.2 Changes from V2.5.2
+ The critical section management functions have been changed. These no + The critical section management functions have been changed. These no
longer modify the stack and are safe to use at all optimisation levels. longer modify the stack and are safe to use at all optimisation levels.
The functions are now also the same for both ARM and THUMB modes. The functions are now also the same for both ARM and THUMB modes.
Changes from V2.6.0 Changes from V2.6.0
+ Removed the 'static' from the definition of vNonPreemptiveTick() to + Removed the 'static' from the definition of vNonPreemptiveTick() to
allow the demo to link when using the cooperative scheduler. allow the demo to link when using the cooperative scheduler.
Changes from V3.2.4 Changes from V3.2.4
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
*/ */
@ -56,11 +56,11 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
/* Constants required to handle interrupts. */ /* Constants required to handle interrupts. */
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 ) #define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 ) #define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -77,9 +77,9 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -93,19 +93,19 @@ void vPortISRStartFirstTask( void )
*/ */
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" ); __asm volatile ( "ADD LR, LR, #4" );
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */ /* Find the highest priority task that is ready to run. */
__asm volatile ( "bl vTaskSwitchContext" ); __asm volatile ( "bl vTaskSwitchContext" );
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -115,26 +115,26 @@ void vPortYieldProcessor( void )
void vTickISR( void ) __attribute__((naked)); void vTickISR( void ) __attribute__((naked));
void vTickISR( void ) void vTickISR( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Increment the RTOS tick count, then look for the highest priority /* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */ task that is ready to run. */
__asm volatile __asm volatile
( (
" bl xTaskIncrementTick \t\n" \ " bl xTaskIncrementTick \t\n" \
" cmp r0, #0 \t\n" \ " cmp r0, #0 \t\n" \
" beq SkipContextSwitch \t\n" \ " beq SkipContextSwitch \t\n" \
" bl vTaskSwitchContext \t\n" \ " bl vTaskSwitchContext \t\n" \
"SkipContextSwitch: \t\n" "SkipContextSwitch: \t\n"
); );
/* Ready for the next interrupt. */ /* Ready for the next interrupt. */
T0_IR = portTIMER_MATCH_ISR_BIT; T0_IR = portTIMER_MATCH_ISR_BIT;
VICVectAddr = portCLEAR_VIC_INTERRUPT; VICVectAddr = portCLEAR_VIC_INTERRUPT;
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -146,30 +146,30 @@ void vTickISR( void )
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
@ -179,38 +179,38 @@ be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
} }
} }
} }

View file

@ -44,32 +44,32 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE portLONG #define portBASE_TYPE portLONG
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() __asm volatile ( "NOP" ); #define portNOP() __asm volatile ( "NOP" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -82,92 +82,92 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
__asm volatile ( \ __asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t" \
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t" \
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t" \
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t" \
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t" \
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t" \
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t" \
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t" \
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t" \
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t" \
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t" \
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t" \
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t" \
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
extern void vTaskSwitchContext( void ); extern void vTaskSwitchContext( void );
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
#define portYIELD() __asm volatile ( "SWI 0" ) #define portYIELD() __asm volatile ( "SWI 0" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -182,37 +182,37 @@ extern void vTaskSwitchContext( void );
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
@ -224,4 +224,3 @@ extern void vPortExitCritical( void );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -44,10 +44,10 @@
#include "task.h" #include "task.h"
/* Constants required to setup the task context. */ /* Constants required to setup the task context. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
/* Constants required to setup the tick ISR. */ /* Constants required to setup the tick ISR. */
#define portENABLE_TIMER ( ( uint8_t ) 0x01 ) #define portENABLE_TIMER ( ( uint8_t ) 0x01 )
@ -83,95 +83,95 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */ *pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for /* The last thing onto the stack is the status register, which is set for
system mode, with interrupts enabled. */ system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 ) if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
{ {
/* We want the task to start in thumb mode. */ /* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
pxTopOfStack--; pxTopOfStack--;
/* Some optimisation levels use the stack differently to others. This /* Some optimisation levels use the stack differently to others. This
means the interrupt flags cannot always be stored on the stack and will means the interrupt flags cannot always be stored on the stack and will
instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
vPortISRStartFirstTask(); vPortISRStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -182,53 +182,50 @@ static void prvSetupTimerInterrupt( void )
{ {
uint32_t ulCompareMatch; uint32_t ulCompareMatch;
PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);
T0TCR = 2; /* Stop and reset the timer */ T0TCR = 2; /* Stop and reset the timer */
T0CTCR = 0; /* Timer mode */ T0CTCR = 0; /* Timer mode */
/* A 1ms tick does not require the use of the timer prescale. This is /* A 1ms tick does not require the use of the timer prescale. This is
defaulted to zero but can be used if necessary. */ defaulted to zero but can be used if necessary. */
T0PR = portPRESCALE_VALUE; T0PR = portPRESCALE_VALUE;
/* Calculate the match value required for our wanted tick rate. */ /* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Protect against divide by zero. Using an if() statement still results /* Protect against divide by zero. Using an if() statement still results
in a warning - hence the #if. */ in a warning - hence the #if. */
#if portPRESCALE_VALUE != 0 #if portPRESCALE_VALUE != 0
{ {
ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
} }
#endif #endif
T0MR1 = ulCompareMatch; T0MR1 = ulCompareMatch;
/* Generate tick with timer 0 compare match. */ /* Generate tick with timer 0 compare match. */
T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */ T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */
/* Setup the VIC for the timer. */ /* Setup the VIC for the timer. */
VICIntEnable = 0x00000010; VICIntEnable = 0x00000010;
/* The ISR installed depends on whether the preemptive or cooperative /* The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */ scheduler is being used. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
{ {
extern void ( vPreemptiveTick )( void ); extern void ( vPreemptiveTick )( void );
VICVectAddr4 = ( int32_t ) vPreemptiveTick; VICVectAddr4 = ( int32_t ) vPreemptiveTick;
} }
#else #else
{ {
extern void ( vNonPreemptiveTick )( void ); extern void ( vNonPreemptiveTick )( void );
VICVectAddr4 = ( int32_t ) vNonPreemptiveTick; VICVectAddr4 = ( int32_t ) vNonPreemptiveTick;
} }
#endif #endif
VICVectCntl4 = 1; VICVectCntl4 = 1;
/* Start the timer - interrupts are disabled when this function is called /* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */ so it is okay to do this here. */
T0TCR = portENABLE_TIMER; T0TCR = portENABLE_TIMER;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -38,11 +38,11 @@
#include "task.h" #include "task.h"
/* Constants required to handle interrupts. */ /* Constants required to handle interrupts. */
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 ) #define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 ) #define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -59,9 +59,9 @@ void vPortISRStartFirstTask( void );
void vPortISRStartFirstTask( void ) void vPortISRStartFirstTask( void )
{ {
/* Simply start the scheduler. This is included here as it can only be /* Simply start the scheduler. This is included here as it can only be
called from ARM mode. */ called from ARM mode. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -75,19 +75,19 @@ void vPortISRStartFirstTask( void )
*/ */
void vPortYieldProcessor( void ) void vPortYieldProcessor( void )
{ {
/* Within an IRQ ISR the link register has an offset from the true return /* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */ ISR return code can be used in both cases. */
__asm volatile ( "ADD LR, LR, #4" ); __asm volatile ( "ADD LR, LR, #4" );
/* Perform the context switch. First save the context of the current task. */ /* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */ /* Find the highest priority task that is ready to run. */
__asm volatile( "bl vTaskSwitchContext" ); __asm volatile( "bl vTaskSwitchContext" );
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -99,44 +99,44 @@ void vPortYieldProcessor( void )
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
simply increment the system tick. */ simply increment the system tick. */
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
void vNonPreemptiveTick( void ) void vNonPreemptiveTick( void )
{ {
xTaskIncrementTick(); xTaskIncrementTick();
T0IR = 2; T0IR = 2;
VICVectAddr = portCLEAR_VIC_INTERRUPT; VICVectAddr = portCLEAR_VIC_INTERRUPT;
} }
#else #else
/* The preemptive scheduler is defined as "naked" as the full context is /* The preemptive scheduler is defined as "naked" as the full context is
saved on entry as part of the context switch. */ saved on entry as part of the context switch. */
void vPreemptiveTick( void ) __attribute__((naked)); void vPreemptiveTick( void ) __attribute__((naked));
void vPreemptiveTick( void ) void vPreemptiveTick( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
/* Increment the RTOS tick count, then look for the highest priority /* Increment the RTOS tick count, then look for the highest priority
task that is ready to run. */ task that is ready to run. */
__asm volatile __asm volatile
( (
" bl xTaskIncrementTick \t\n" \ " bl xTaskIncrementTick \t\n" \
" cmp r0, #0 \t\n" \ " cmp r0, #0 \t\n" \
" beq SkipContextSwitch \t\n" \ " beq SkipContextSwitch \t\n" \
" bl vTaskSwitchContext \t\n" \ " bl vTaskSwitchContext \t\n" \
"SkipContextSwitch: \t\n" "SkipContextSwitch: \t\n"
); );
/* Ready for the next interrupt. */ /* Ready for the next interrupt. */
T0IR = 2; T0IR = 2;
VICVectAddr = portCLEAR_VIC_INTERRUPT; VICVectAddr = portCLEAR_VIC_INTERRUPT;
/* Restore the context of the new task. */ /* Restore the context of the new task. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -149,30 +149,30 @@ void vPortYieldProcessor( void )
*/ */
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
void vPortDisableInterruptsFromThumb( void ) void vPortDisableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
void vPortEnableInterruptsFromThumb( void ) void vPortEnableInterruptsFromThumb( void )
{ {
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0} \n\t" /* Pop R0. */ "LDMIA SP!, {R0} \n\t" /* Pop R0. */
"BX R14" ); /* Return back to thumb. */ "BX R14" ); /* Return back to thumb. */
} }
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
@ -182,38 +182,38 @@ be saved to the stack. Instead the critical section nesting level is stored
in a variable, which is then saved as part of the stack context. */ in a variable, which is then saved as part of the stack context. */
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable interrupts as per portEXIT_CRITICAL(). */ /* Enable interrupts as per portEXIT_CRITICAL(). */
__asm volatile ( __asm volatile (
"STMDB SP!, {R0} \n\t" /* Push R0. */ "STMDB SP!, {R0} \n\t" /* Push R0. */
"MRS R0, CPSR \n\t" /* Get CPSR. */ "MRS R0, CPSR \n\t" /* Get CPSR. */
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
"MSR CPSR, R0 \n\t" /* Write back modified value. */ "MSR CPSR, R0 \n\t" /* Write back modified value. */
"LDMIA SP!, {R0}" ); /* Pop R0. */ "LDMIA SP!, {R0}" ); /* Pop R0. */
} }
} }
} }

View file

@ -27,26 +27,26 @@
*/ */
/* /*
Changes from V3.2.3 Changes from V3.2.3
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
Changes from V3.2.4 Changes from V3.2.4
+ Removed the use of the %0 parameter within the assembler macros and + Removed the use of the %0 parameter within the assembler macros and
replaced them with hard coded registers. This will ensure the replaced them with hard coded registers. This will ensure the
assembler does not select the link register as the temp register as assembler does not select the link register as the temp register as
was occasionally happening previously. was occasionally happening previously.
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
Changes from V4.5.0 Changes from V4.5.0
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code. macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -67,32 +67,32 @@ extern "C" {
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE portLONG #define portBASE_TYPE portLONG
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portNOP() __asm volatile ( "NOP" ); #define portNOP() __asm volatile ( "NOP" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -105,92 +105,92 @@ typedef unsigned long UBaseType_t;
* THUMB mode code will result in a compile time error. * THUMB mode code will result in a compile time error.
*/ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Set the LR to the task stack. */ \ /* Set the LR to the task stack. */ \
__asm volatile ( \ __asm volatile ( \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"LDR LR, [R0] \n\t" \ "LDR LR, [R0] \n\t" \
\ \
/* The critical nesting depth is the first item on the stack. */ \ /* The critical nesting depth is the first item on the stack. */ \
/* Load it into the ulCriticalNesting variable. */ \ /* Load it into the ulCriticalNesting variable. */ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDMFD LR!, {R1} \n\t" \ "LDMFD LR!, {R1} \n\t" \
"STR R1, [R0] \n\t" \ "STR R1, [R0] \n\t" \
\ \
/* Get the SPSR from the stack. */ \ /* Get the SPSR from the stack. */ \
"LDMFD LR!, {R0} \n\t" \ "LDMFD LR!, {R0} \n\t" \
"MSR SPSR, R0 \n\t" \ "MSR SPSR, R0 \n\t" \
\ \
/* Restore all system mode registers for the task. */ \ /* Restore all system mode registers for the task. */ \
"LDMFD LR, {R0-R14}^ \n\t" \ "LDMFD LR, {R0-R14}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
\ \
/* Restore the return address. */ \ /* Restore the return address. */ \
"LDR LR, [LR, #+60] \n\t" \ "LDR LR, [LR, #+60] \n\t" \
\ \
/* And return - correcting the offset in the LR to obtain the */ \ /* And return - correcting the offset in the LR to obtain the */ \
/* correct address. */ \ /* correct address. */ \
"SUBS PC, LR, #4 \n\t" \ "SUBS PC, LR, #4 \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
{ \ { \
extern volatile void * volatile pxCurrentTCB; \ extern volatile void * volatile pxCurrentTCB; \
extern volatile uint32_t ulCriticalNesting; \ extern volatile uint32_t ulCriticalNesting; \
\ \
/* Push R0 as we are going to use the register. */ \ /* Push R0 as we are going to use the register. */ \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" \ "STMDB SP!, {R0} \n\t" \
\ \
/* Set R0 to point to the task stack pointer. */ \ /* Set R0 to point to the task stack pointer. */ \
"STMDB SP,{SP}^ \n\t" \ "STMDB SP,{SP}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB SP, SP, #4 \n\t" \ "SUB SP, SP, #4 \n\t" \
"LDMIA SP!,{R0} \n\t" \ "LDMIA SP!,{R0} \n\t" \
\ \
/* Push the return address onto the stack. */ \ /* Push the return address onto the stack. */ \
"STMDB R0!, {LR} \n\t" \ "STMDB R0!, {LR} \n\t" \
\ \
/* Now we have saved LR we can use it instead of R0. */ \ /* Now we have saved LR we can use it instead of R0. */ \
"MOV LR, R0 \n\t" \ "MOV LR, R0 \n\t" \
\ \
/* Pop R0 so we can save it onto the system mode stack. */ \ /* Pop R0 so we can save it onto the system mode stack. */ \
"LDMIA SP!, {R0} \n\t" \ "LDMIA SP!, {R0} \n\t" \
\ \
/* Push all the system mode registers onto the task stack. */ \ /* Push all the system mode registers onto the task stack. */ \
"STMDB LR,{R0-LR}^ \n\t" \ "STMDB LR,{R0-LR}^ \n\t" \
"NOP \n\t" \ "NOP \n\t" \
"SUB LR, LR, #60 \n\t" \ "SUB LR, LR, #60 \n\t" \
\ \
/* Push the SPSR onto the task stack. */ \ /* Push the SPSR onto the task stack. */ \
"MRS R0, SPSR \n\t" \ "MRS R0, SPSR \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
"LDR R0, =ulCriticalNesting \n\t" \ "LDR R0, =ulCriticalNesting \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STMDB LR!, {R0} \n\t" \ "STMDB LR!, {R0} \n\t" \
\ \
/* Store the new top of stack for the task. */ \ /* Store the new top of stack for the task. */ \
"LDR R0, =pxCurrentTCB \n\t" \ "LDR R0, =pxCurrentTCB \n\t" \
"LDR R0, [R0] \n\t" \ "LDR R0, [R0] \n\t" \
"STR LR, [R0] \n\t" \ "STR LR, [R0] \n\t" \
); \ ); \
( void ) ulCriticalNesting; \ ( void ) ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
#define portYIELD_FROM_ISR() vTaskSwitchContext() #define portYIELD_FROM_ISR() vTaskSwitchContext()
#define portYIELD() __asm volatile ( "SWI 0" ) #define portYIELD() __asm volatile ( "SWI 0" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -205,37 +205,37 @@ extern volatile uint32_t ulCriticalNesting; \
#ifdef THUMB_INTERWORK #ifdef THUMB_INTERWORK
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
#else #else
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( \ __asm volatile ( \
"STMDB SP!, {R0} \n\t" /* Push R0. */ \ "STMDB SP!, {R0} \n\t" /* Push R0. */ \
"MRS R0, CPSR \n\t" /* Get CPSR. */ \ "MRS R0, CPSR \n\t" /* Get CPSR. */ \
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \ "MSR CPSR, R0 \n\t" /* Write back modified value. */ \
"LDMIA SP!, {R0} " ) /* Pop R0. */ "LDMIA SP!, {R0} " ) /* Pop R0. */
#endif /* THUMB_INTERWORK */ #endif /* THUMB_INTERWORK */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
@ -247,4 +247,3 @@ extern void vPortExitCritical( void );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -34,104 +34,104 @@
#include "task.h" #include "task.h"
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET #ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configUNIQUE_INTERRUPT_PRIORITIES #ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0 #error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES #if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority #error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* In case security extensions are implemented. */ /* In case security extensions are implemented. */
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#endif #endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
portmacro.h. */ portmacro.h. */
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /* In all GICs 255 can be written to the priority mask register to unmask all
(but the lowest) interrupt priority. */ (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
#define portSP_ELx ( ( StackType_t ) 0x01 ) #define portSP_ELx ( ( StackType_t ) 0x01 )
#define portSP_EL0 ( ( StackType_t ) 0x00 ) #define portSP_EL0 ( ( StackType_t ) 0x00 )
#if defined( GUEST ) #if defined( GUEST )
#define portEL1 ( ( StackType_t ) 0x04 ) #define portEL1 ( ( StackType_t ) 0x04 )
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 ) #define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
#else #else
#define portEL3 ( ( StackType_t ) 0x0c ) #define portEL3 ( ( StackType_t ) 0x0c )
/* At the time of writing, the BSP only supports EL3. */ /* At the time of writing, the BSP only supports EL3. */
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 ) #define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
#endif #endif
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
point is zero. */ point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) #define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x0C ) #define portAPSR_MODE_BITS_MASK ( 0x0C )
/* The I bit in the DAIF bits. */ /* The I bit in the DAIF bits. */
#define portDAIF_I ( 0x80 ) #define portDAIF_I ( 0x80 )
/* Macro to unmask all interrupt priorities. */ /* Macro to unmask all interrupt priorities. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm volatile ( "DSB SY \n" \ __asm volatile ( "DSB SY \n" \
"ISB SY \n" ); \ "ISB SY \n" ); \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} }
/* Hardware specifics used when sanity checking the configuration. */ /* Hardware specifics used when sanity checking the configuration. */
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL #define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portBIT_0_SET ( ( uint8_t ) 0x01 ) #define portBIT_0_SET ( ( uint8_t ) 0x01 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -174,93 +174,93 @@ __attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_C
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First all the general purpose registers. */ /* First all the general purpose registers. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */ *pxTopOfStack = 0x0101010101010101ULL; /* R1 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */ *pxTopOfStack = 0x0303030303030303ULL; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */ *pxTopOfStack = 0x0202020202020202ULL; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */ *pxTopOfStack = 0x0505050505050505ULL; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */ *pxTopOfStack = 0x0404040404040404ULL; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */ *pxTopOfStack = 0x0707070707070707ULL; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */ *pxTopOfStack = 0x0606060606060606ULL; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */ *pxTopOfStack = 0x0909090909090909ULL; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */ *pxTopOfStack = 0x0808080808080808ULL; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */ *pxTopOfStack = 0x1111111111111111ULL; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */ *pxTopOfStack = 0x1010101010101010ULL; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */ *pxTopOfStack = 0x1313131313131313ULL; /* R13 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */ *pxTopOfStack = 0x1212121212121212ULL; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */ *pxTopOfStack = 0x1515151515151515ULL; /* R15 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */ *pxTopOfStack = 0x1414141414141414ULL; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */ *pxTopOfStack = 0x1717171717171717ULL; /* R17 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */ *pxTopOfStack = 0x1616161616161616ULL; /* R16 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */ *pxTopOfStack = 0x1919191919191919ULL; /* R19 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */ *pxTopOfStack = 0x1818181818181818ULL; /* R18 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */ *pxTopOfStack = 0x2121212121212121ULL; /* R21 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */ *pxTopOfStack = 0x2020202020202020ULL; /* R20 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */ *pxTopOfStack = 0x2323232323232323ULL; /* R23 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */ *pxTopOfStack = 0x2222222222222222ULL; /* R22 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */ *pxTopOfStack = 0x2525252525252525ULL; /* R25 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */ *pxTopOfStack = 0x2424242424242424ULL; /* R24 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */ *pxTopOfStack = 0x2727272727272727ULL; /* R27 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */ *pxTopOfStack = 0x2626262626262626ULL; /* R26 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */ *pxTopOfStack = 0x2929292929292929ULL; /* R29 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */ *pxTopOfStack = 0x2828282828282828ULL; /* R28 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */ *pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */ *pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSTATE; *pxTopOfStack = portINITIAL_PSTATE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */ *pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */ any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -268,191 +268,191 @@ BaseType_t xPortStartScheduler( void )
{ {
uint32_t ulAPSR; uint32_t ulAPSR;
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
volatile uint32_t ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC. /* Determine how many priority bits are implemented in the GIC.
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to /* Determine the number of priority bits available. First write to
all possible bits. */ all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister; ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Shift to the least significant bits. */ /* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET ) while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{ {
ucMaxPriorityValue >>= ( uint8_t ) 0x01; ucMaxPriorityValue >>= ( uint8_t ) 0x01;
} }
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
value. */ value. */
configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY ); configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* At the time of writing, the BSP only supports EL3. */ /* At the time of writing, the BSP only supports EL3. */
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
#if defined( GUEST ) #if defined( GUEST )
#warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH. #warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH.
configASSERT( ulAPSR == portEL1 ); configASSERT( ulAPSR == portEL1 );
if( ulAPSR == portEL1 ) if( ulAPSR == portEL1 )
#else #else
configASSERT( ulAPSR == portEL3 ); configASSERT( ulAPSR == portEL3 );
if( ulAPSR == portEL3 ) if( ulAPSR == portEL3 )
#endif #endif
{ {
/* Only continue if the binary point value is set to its lowest possible /* Only continue if the binary point value is set to its lowest possible
setting. See the comments in vPortValidateInterruptPriority() below for setting. See the comments in vPortValidateInterruptPriority() below for
more information. */ more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Interrupts are turned off in the CPU itself to ensure a tick does /* Interrupts are turned off in the CPU itself to ensure a tick does
not execute while the scheduler is being started. Interrupts are not execute while the scheduler is being started. Interrupts are
automatically turned back on in the CPU when the first task starts automatically turned back on in the CPU when the first task starts
executing. */ executing. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Start the first task executing. */ /* Start the first task executing. */
vPortRestoreTaskContext(); vPortRestoreTaskContext();
} }
} }
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ Artificially force an assert. */
configASSERT( ullCriticalNesting == 1000ULL ); configASSERT( ullCriticalNesting == 1000ULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Mask interrupts up to the max syscall interrupt priority. */ /* Mask interrupts up to the max syscall interrupt priority. */
uxPortSetInterruptMask(); uxPortSetInterruptMask();
/* Now interrupts are disabled ullCriticalNesting can be accessed /* Now interrupts are disabled ullCriticalNesting can be accessed
directly. Increment ullCriticalNesting to keep a count of how many times directly. Increment ullCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ullCriticalNesting++; ullCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */
if( ullCriticalNesting == 1ULL ) if( ullCriticalNesting == 1ULL )
{ {
configASSERT( ullPortInterruptNesting == 0 ); configASSERT( ullPortInterruptNesting == 0 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ullCriticalNesting > portNO_CRITICAL_NESTING ) if( ullCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
exited. */ exited. */
ullCriticalNesting--; ullCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */ priorities must be re-enabled. */
if( ullCriticalNesting == portNO_CRITICAL_NESTING ) if( ullCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */ should be unmasked. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
/* Must be the lowest possible priority. */ /* Must be the lowest possible priority. */
#if !defined( QEMU ) #if !defined( QEMU )
{ {
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER == ( uint32_t ) ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER == ( uint32_t ) ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
} }
#endif #endif
/* Interrupts should not be enabled before this point. */ /* Interrupts should not be enabled before this point. */
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
uint32_t ulMaskBits; uint32_t ulMaskBits;
__asm volatile( "mrs %0, daif" : "=r"( ulMaskBits ) :: "memory" ); __asm volatile( "mrs %0, daif" : "=r"( ulMaskBits ) :: "memory" );
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 ); configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Set interrupt mask before altering scheduler structures. The tick /* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked, handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */ updated. */
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb sy \n" __asm volatile ( "dsb sy \n"
"isb sy \n" ::: "memory" ); "isb sy \n" ::: "memory" );
/* Ok to enable interrupts after the interrupt source has been cleared. */ /* Ok to enable interrupts after the interrupt source has been cleared. */
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ullPortYieldRequired = pdTRUE; ullPortYieldRequired = pdTRUE;
} }
/* Ensure all interrupt priorities are active again. */ /* Ensure all interrupt priorities are active again. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ullPortTaskHasFPUContext = pdTRUE; ullPortTaskHasFPUContext = pdTRUE;
/* Consider initialising the FPSR here - but probably not necessary in /* Consider initialising the FPSR here - but probably not necessary in
AArch64. */ AArch64. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue ) void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
{ {
if( uxNewMaskValue == pdFALSE ) if( uxNewMaskValue == pdFALSE )
{ {
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -460,60 +460,59 @@ UBaseType_t uxPortSetInterruptMask( void )
{ {
uint32_t ulReturn; uint32_t ulReturn;
/* 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. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
ulReturn = pdTRUE; ulReturn = pdTRUE;
} }
else else
{ {
ulReturn = pdFALSE; ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb sy \n" __asm volatile ( "dsb sy \n"
"isb sy \n" ::: "memory" ); "isb sy \n" ::: "memory" );
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
return ulReturn; return ulReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
FreeRTOS maintains separate thread and ISR API functions to ensure FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. */ interrupt entry is as fast and simple as possible. */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits /* Priority grouping: The interrupt controller (GIC) allows the bits
that define each interrupt's priority to be split between bits that that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
The priority grouping is configured by the GIC's binary point register The priority grouping is configured by the GIC's binary point register
(ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
possible value (which may be above 0). */ possible value (which may be above 0). */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,195 +26,195 @@
* *
*/ */
.text .text
/* Variables and functions. */ /* Variables and functions. */
.extern ullMaxAPIPriorityMask .extern ullMaxAPIPriorityMask
.extern pxCurrentTCB .extern pxCurrentTCB
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vApplicationIRQHandler .extern vApplicationIRQHandler
.extern ullPortInterruptNesting .extern ullPortInterruptNesting
.extern ullPortTaskHasFPUContext .extern ullPortTaskHasFPUContext
.extern ullCriticalNesting .extern ullCriticalNesting
.extern ullPortYieldRequired .extern ullPortYieldRequired
.extern ullICCEOIR .extern ullICCEOIR
.extern ullICCIAR .extern ullICCIAR
.extern _freertos_vector_table .extern _freertos_vector_table
.global FreeRTOS_IRQ_Handler .global FreeRTOS_IRQ_Handler
.global FreeRTOS_SWI_Handler .global FreeRTOS_SWI_Handler
.global vPortRestoreTaskContext .global vPortRestoreTaskContext
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
/* Switch to use the EL0 stack pointer. */ /* Switch to use the EL0 stack pointer. */
MSR SPSEL, #0 MSR SPSEL, #0
/* Save the entire context. */ /* Save the entire context. */
STP X0, X1, [SP, #-0x10]! STP X0, X1, [SP, #-0x10]!
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
STP X4, X5, [SP, #-0x10]! STP X4, X5, [SP, #-0x10]!
STP X6, X7, [SP, #-0x10]! STP X6, X7, [SP, #-0x10]!
STP X8, X9, [SP, #-0x10]! STP X8, X9, [SP, #-0x10]!
STP X10, X11, [SP, #-0x10]! STP X10, X11, [SP, #-0x10]!
STP X12, X13, [SP, #-0x10]! STP X12, X13, [SP, #-0x10]!
STP X14, X15, [SP, #-0x10]! STP X14, X15, [SP, #-0x10]!
STP X16, X17, [SP, #-0x10]! STP X16, X17, [SP, #-0x10]!
STP X18, X19, [SP, #-0x10]! STP X18, X19, [SP, #-0x10]!
STP X20, X21, [SP, #-0x10]! STP X20, X21, [SP, #-0x10]!
STP X22, X23, [SP, #-0x10]! STP X22, X23, [SP, #-0x10]!
STP X24, X25, [SP, #-0x10]! STP X24, X25, [SP, #-0x10]!
STP X26, X27, [SP, #-0x10]! STP X26, X27, [SP, #-0x10]!
STP X28, X29, [SP, #-0x10]! STP X28, X29, [SP, #-0x10]!
STP X30, XZR, [SP, #-0x10]! STP X30, XZR, [SP, #-0x10]!
/* Save the SPSR. */ /* Save the SPSR. */
#if defined( GUEST ) #if defined( GUEST )
MRS X3, SPSR_EL1 MRS X3, SPSR_EL1
MRS X2, ELR_EL1 MRS X2, ELR_EL1
#else #else
MRS X3, SPSR_EL3 MRS X3, SPSR_EL3
/* Save the ELR. */ /* Save the ELR. */
MRS X2, ELR_EL3 MRS X2, ELR_EL3
#endif #endif
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
/* Save the critical section nesting depth. */ /* Save the critical section nesting depth. */
LDR X0, ullCriticalNestingConst LDR X0, ullCriticalNestingConst
LDR X3, [X0] LDR X3, [X0]
/* Save the FPU context indicator. */ /* Save the FPU context indicator. */
LDR X0, ullPortTaskHasFPUContextConst LDR X0, ullPortTaskHasFPUContextConst
LDR X2, [X0] LDR X2, [X0]
/* Save the FPU context, if any (32 128-bit registers). */ /* Save the FPU context, if any (32 128-bit registers). */
CMP X2, #0 CMP X2, #0
B.EQ 1f B.EQ 1f
STP Q0, Q1, [SP,#-0x20]! STP Q0, Q1, [SP,#-0x20]!
STP Q2, Q3, [SP,#-0x20]! STP Q2, Q3, [SP,#-0x20]!
STP Q4, Q5, [SP,#-0x20]! STP Q4, Q5, [SP,#-0x20]!
STP Q6, Q7, [SP,#-0x20]! STP Q6, Q7, [SP,#-0x20]!
STP Q8, Q9, [SP,#-0x20]! STP Q8, Q9, [SP,#-0x20]!
STP Q10, Q11, [SP,#-0x20]! STP Q10, Q11, [SP,#-0x20]!
STP Q12, Q13, [SP,#-0x20]! STP Q12, Q13, [SP,#-0x20]!
STP Q14, Q15, [SP,#-0x20]! STP Q14, Q15, [SP,#-0x20]!
STP Q16, Q17, [SP,#-0x20]! STP Q16, Q17, [SP,#-0x20]!
STP Q18, Q19, [SP,#-0x20]! STP Q18, Q19, [SP,#-0x20]!
STP Q20, Q21, [SP,#-0x20]! STP Q20, Q21, [SP,#-0x20]!
STP Q22, Q23, [SP,#-0x20]! STP Q22, Q23, [SP,#-0x20]!
STP Q24, Q25, [SP,#-0x20]! STP Q24, Q25, [SP,#-0x20]!
STP Q26, Q27, [SP,#-0x20]! STP Q26, Q27, [SP,#-0x20]!
STP Q28, Q29, [SP,#-0x20]! STP Q28, Q29, [SP,#-0x20]!
STP Q30, Q31, [SP,#-0x20]! STP Q30, Q31, [SP,#-0x20]!
1: 1:
/* Store the critical nesting count and FPU context indicator. */ /* Store the critical nesting count and FPU context indicator. */
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
LDR X0, pxCurrentTCBConst LDR X0, pxCurrentTCBConst
LDR X1, [X0] LDR X1, [X0]
MOV X0, SP /* Move SP into X0 for saving. */ MOV X0, SP /* Move SP into X0 for saving. */
STR X0, [X1] STR X0, [X1]
/* Switch to use the ELx stack pointer. */ /* Switch to use the ELx stack pointer. */
MSR SPSEL, #1 MSR SPSEL, #1
.endm .endm
; /**********************************************************************/ ; /**********************************************************************/
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
/* Switch to use the EL0 stack pointer. */ /* Switch to use the EL0 stack pointer. */
MSR SPSEL, #0 MSR SPSEL, #0
/* Set the SP to point to the stack of the task being restored. */ /* Set the SP to point to the stack of the task being restored. */
LDR X0, pxCurrentTCBConst LDR X0, pxCurrentTCBConst
LDR X1, [X0] LDR X1, [X0]
LDR X0, [X1] LDR X0, [X1]
MOV SP, X0 MOV SP, X0
LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */ LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
/* Set the PMR register to be correct for the current critical nesting /* Set the PMR register to be correct for the current critical nesting
depth. */ depth. */
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */ LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
MOV X1, #255 /* X1 holds the unmask value. */ MOV X1, #255 /* X1 holds the unmask value. */
LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */ LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
CMP X3, #0 CMP X3, #0
LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */ LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
B.EQ 1f B.EQ 1f
LDR X6, ullMaxAPIPriorityMaskConst LDR X6, ullMaxAPIPriorityMaskConst
LDR X1, [X6] /* X1 holds the mask value. */ LDR X1, [X6] /* X1 holds the mask value. */
1: 1:
STR W1, [X5] /* Write the mask value to ICCPMR. */ STR W1, [X5] /* Write the mask value to ICCPMR. */
DSB SY /* _RB_Barriers probably not required here. */ DSB SY /* _RB_Barriers probably not required here. */
ISB SY ISB SY
STR X3, [X0] /* Restore the task's critical nesting count. */ STR X3, [X0] /* Restore the task's critical nesting count. */
/* Restore the FPU context indicator. */ /* Restore the FPU context indicator. */
LDR X0, ullPortTaskHasFPUContextConst LDR X0, ullPortTaskHasFPUContextConst
STR X2, [X0] STR X2, [X0]
/* Restore the FPU context, if any. */ /* Restore the FPU context, if any. */
CMP X2, #0 CMP X2, #0
B.EQ 1f B.EQ 1f
LDP Q30, Q31, [SP], #0x20 LDP Q30, Q31, [SP], #0x20
LDP Q28, Q29, [SP], #0x20 LDP Q28, Q29, [SP], #0x20
LDP Q26, Q27, [SP], #0x20 LDP Q26, Q27, [SP], #0x20
LDP Q24, Q25, [SP], #0x20 LDP Q24, Q25, [SP], #0x20
LDP Q22, Q23, [SP], #0x20 LDP Q22, Q23, [SP], #0x20
LDP Q20, Q21, [SP], #0x20 LDP Q20, Q21, [SP], #0x20
LDP Q18, Q19, [SP], #0x20 LDP Q18, Q19, [SP], #0x20
LDP Q16, Q17, [SP], #0x20 LDP Q16, Q17, [SP], #0x20
LDP Q14, Q15, [SP], #0x20 LDP Q14, Q15, [SP], #0x20
LDP Q12, Q13, [SP], #0x20 LDP Q12, Q13, [SP], #0x20
LDP Q10, Q11, [SP], #0x20 LDP Q10, Q11, [SP], #0x20
LDP Q8, Q9, [SP], #0x20 LDP Q8, Q9, [SP], #0x20
LDP Q6, Q7, [SP], #0x20 LDP Q6, Q7, [SP], #0x20
LDP Q4, Q5, [SP], #0x20 LDP Q4, Q5, [SP], #0x20
LDP Q2, Q3, [SP], #0x20 LDP Q2, Q3, [SP], #0x20
LDP Q0, Q1, [SP], #0x20 LDP Q0, Q1, [SP], #0x20
1: 1:
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
/* Restore the SPSR. */ /* Restore the SPSR. */
MSR SPSR_EL1, X3 MSR SPSR_EL1, X3
/* Restore the ELR. */ /* Restore the ELR. */
MSR ELR_EL1, X2 MSR ELR_EL1, X2
#else #else
/* Restore the SPSR. */ /* Restore the SPSR. */
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */ MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
/* Restore the ELR. */ /* Restore the ELR. */
MSR ELR_EL3, X2 MSR ELR_EL3, X2
#endif #endif
LDP X30, XZR, [SP], #0x10 LDP X30, XZR, [SP], #0x10
LDP X28, X29, [SP], #0x10 LDP X28, X29, [SP], #0x10
LDP X26, X27, [SP], #0x10 LDP X26, X27, [SP], #0x10
LDP X24, X25, [SP], #0x10 LDP X24, X25, [SP], #0x10
LDP X22, X23, [SP], #0x10 LDP X22, X23, [SP], #0x10
LDP X20, X21, [SP], #0x10 LDP X20, X21, [SP], #0x10
LDP X18, X19, [SP], #0x10 LDP X18, X19, [SP], #0x10
LDP X16, X17, [SP], #0x10 LDP X16, X17, [SP], #0x10
LDP X14, X15, [SP], #0x10 LDP X14, X15, [SP], #0x10
LDP X12, X13, [SP], #0x10 LDP X12, X13, [SP], #0x10
LDP X10, X11, [SP], #0x10 LDP X10, X11, [SP], #0x10
LDP X8, X9, [SP], #0x10 LDP X8, X9, [SP], #0x10
LDP X6, X7, [SP], #0x10 LDP X6, X7, [SP], #0x10
LDP X4, X5, [SP], #0x10 LDP X4, X5, [SP], #0x10
LDP X2, X3, [SP], #0x10 LDP X2, X3, [SP], #0x10
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */ /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
MSR SPSEL, #1 MSR SPSEL, #1
ERET ERET
.endm .endm
/****************************************************************************** /******************************************************************************
@ -223,29 +223,29 @@
.align 8 .align 8
.type FreeRTOS_SWI_Handler, %function .type FreeRTOS_SWI_Handler, %function
FreeRTOS_SWI_Handler: FreeRTOS_SWI_Handler:
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
#if defined( GUEST ) #if defined( GUEST )
MRS X0, ESR_EL1 MRS X0, ESR_EL1
#else #else
MRS X0, ESR_EL3 MRS X0, ESR_EL3
#endif #endif
LSR X1, X0, #26 LSR X1, X0, #26
#if defined( GUEST ) #if defined( GUEST )
CMP X1, #0x15 /* 0x15 = SVC instruction. */ CMP X1, #0x15 /* 0x15 = SVC instruction. */
#else #else
CMP X1, #0x17 /* 0x17 = SMC instruction. */ CMP X1, #0x17 /* 0x17 = SMC instruction. */
#endif #endif
B.NE FreeRTOS_Abort B.NE FreeRTOS_Abort
BL vTaskSwitchContext BL vTaskSwitchContext
portRESTORE_CONTEXT portRESTORE_CONTEXT
FreeRTOS_Abort: FreeRTOS_Abort:
/* Full ESR is in X0, exception class code is in X1. */ /* Full ESR is in X0, exception class code is in X1. */
B . B .
/****************************************************************************** /******************************************************************************
* vPortRestoreTaskContext is used to start the scheduler. * vPortRestoreTaskContext is used to start the scheduler.
@ -253,20 +253,20 @@ FreeRTOS_Abort:
.align 8 .align 8
.type vPortRestoreTaskContext, %function .type vPortRestoreTaskContext, %function
vPortRestoreTaskContext: vPortRestoreTaskContext:
.set freertos_vector_base, _freertos_vector_table .set freertos_vector_base, _freertos_vector_table
/* Install the FreeRTOS interrupt handlers. */ /* Install the FreeRTOS interrupt handlers. */
LDR X1, =freertos_vector_base LDR X1, =freertos_vector_base
#if defined( GUEST ) #if defined( GUEST )
MSR VBAR_EL1, X1 MSR VBAR_EL1, X1
#else #else
MSR VBAR_EL3, X1 MSR VBAR_EL3, X1
#endif #endif
DSB SY DSB SY
ISB SY ISB SY
/* Start the first task. */ /* Start the first task. */
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
@ -275,136 +275,136 @@ vPortRestoreTaskContext:
.align 8 .align 8
.type FreeRTOS_IRQ_Handler, %function .type FreeRTOS_IRQ_Handler, %function
FreeRTOS_IRQ_Handler: FreeRTOS_IRQ_Handler:
/* Save volatile registers. */ /* Save volatile registers. */
STP X0, X1, [SP, #-0x10]! STP X0, X1, [SP, #-0x10]!
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
STP X4, X5, [SP, #-0x10]! STP X4, X5, [SP, #-0x10]!
STP X6, X7, [SP, #-0x10]! STP X6, X7, [SP, #-0x10]!
STP X8, X9, [SP, #-0x10]! STP X8, X9, [SP, #-0x10]!
STP X10, X11, [SP, #-0x10]! STP X10, X11, [SP, #-0x10]!
STP X12, X13, [SP, #-0x10]! STP X12, X13, [SP, #-0x10]!
STP X14, X15, [SP, #-0x10]! STP X14, X15, [SP, #-0x10]!
STP X16, X17, [SP, #-0x10]! STP X16, X17, [SP, #-0x10]!
STP X18, X19, [SP, #-0x10]! STP X18, X19, [SP, #-0x10]!
STP X29, X30, [SP, #-0x10]! STP X29, X30, [SP, #-0x10]!
/* Save the SPSR and ELR. */ /* Save the SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
MRS X3, SPSR_EL1 MRS X3, SPSR_EL1
MRS X2, ELR_EL1 MRS X2, ELR_EL1
#else #else
MRS X3, SPSR_EL3 MRS X3, SPSR_EL3
MRS X2, ELR_EL3 MRS X2, ELR_EL3
#endif #endif
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
/* Increment the interrupt nesting counter. */ /* Increment the interrupt nesting counter. */
LDR X5, ullPortInterruptNestingConst LDR X5, ullPortInterruptNestingConst
LDR X1, [X5] /* Old nesting count in X1. */ LDR X1, [X5] /* Old nesting count in X1. */
ADD X6, X1, #1 ADD X6, X1, #1
STR X6, [X5] /* Address of nesting count variable in X5. */ STR X6, [X5] /* Address of nesting count variable in X5. */
/* Maintain the interrupt nesting information across the function call. */ /* Maintain the interrupt nesting information across the function call. */
STP X1, X5, [SP, #-0x10]! STP X1, X5, [SP, #-0x10]!
/* Read value from the interrupt acknowledge register, which is stored in W0 /* Read value from the interrupt acknowledge register, which is stored in W0
for future parameter and interrupt clearing use. */ for future parameter and interrupt clearing use. */
LDR X2, ullICCIARConst LDR X2, ullICCIARConst
LDR X3, [X2] LDR X3, [X2]
LDR W0, [X3] /* ICCIAR in W0 as parameter. */ LDR W0, [X3] /* ICCIAR in W0 as parameter. */
/* Maintain the ICCIAR value across the function call. */ /* Maintain the ICCIAR value across the function call. */
STP X0, X1, [SP, #-0x10]! STP X0, X1, [SP, #-0x10]!
/* Call the C handler. */ /* Call the C handler. */
BL vApplicationIRQHandler BL vApplicationIRQHandler
/* Disable interrupts. */ /* Disable interrupts. */
MSR DAIFSET, #2 MSR DAIFSET, #2
DSB SY DSB SY
ISB SY ISB SY
/* Restore the ICCIAR value. */ /* Restore the ICCIAR value. */
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
/* End IRQ processing by writing ICCIAR to the EOI register. */ /* End IRQ processing by writing ICCIAR to the EOI register. */
LDR X4, ullICCEOIRConst LDR X4, ullICCEOIRConst
LDR X4, [X4] LDR X4, [X4]
STR W0, [X4] STR W0, [X4]
/* Restore the critical nesting count. */ /* Restore the critical nesting count. */
LDP X1, X5, [SP], #0x10 LDP X1, X5, [SP], #0x10
STR X1, [X5] STR X1, [X5]
/* Has interrupt nesting unwound? */ /* Has interrupt nesting unwound? */
CMP X1, #0 CMP X1, #0
B.NE Exit_IRQ_No_Context_Switch B.NE Exit_IRQ_No_Context_Switch
/* Is a context switch required? */ /* Is a context switch required? */
LDR X0, ullPortYieldRequiredConst LDR X0, ullPortYieldRequiredConst
LDR X1, [X0] LDR X1, [X0]
CMP X1, #0 CMP X1, #0
B.EQ Exit_IRQ_No_Context_Switch B.EQ Exit_IRQ_No_Context_Switch
/* Reset ullPortYieldRequired to 0. */ /* Reset ullPortYieldRequired to 0. */
MOV X2, #0 MOV X2, #0
STR X2, [X0] STR X2, [X0]
/* Restore volatile registers. */ /* Restore volatile registers. */
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */ LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
MSR SPSR_EL1, X5 MSR SPSR_EL1, X5
MSR ELR_EL1, X4 MSR ELR_EL1, X4
#else #else
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */ MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
MSR ELR_EL3, X4 MSR ELR_EL3, X4
#endif #endif
DSB SY DSB SY
ISB SY ISB SY
LDP X29, X30, [SP], #0x10 LDP X29, X30, [SP], #0x10
LDP X18, X19, [SP], #0x10 LDP X18, X19, [SP], #0x10
LDP X16, X17, [SP], #0x10 LDP X16, X17, [SP], #0x10
LDP X14, X15, [SP], #0x10 LDP X14, X15, [SP], #0x10
LDP X12, X13, [SP], #0x10 LDP X12, X13, [SP], #0x10
LDP X10, X11, [SP], #0x10 LDP X10, X11, [SP], #0x10
LDP X8, X9, [SP], #0x10 LDP X8, X9, [SP], #0x10
LDP X6, X7, [SP], #0x10 LDP X6, X7, [SP], #0x10
LDP X4, X5, [SP], #0x10 LDP X4, X5, [SP], #0x10
LDP X2, X3, [SP], #0x10 LDP X2, X3, [SP], #0x10
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
BL vTaskSwitchContext BL vTaskSwitchContext
portRESTORE_CONTEXT portRESTORE_CONTEXT
Exit_IRQ_No_Context_Switch: Exit_IRQ_No_Context_Switch:
/* Restore volatile registers. */ /* Restore volatile registers. */
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */ LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
MSR SPSR_EL1, X5 MSR SPSR_EL1, X5
MSR ELR_EL1, X4 MSR ELR_EL1, X4
#else #else
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */ MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
MSR ELR_EL3, X4 MSR ELR_EL3, X4
#endif #endif
DSB SY DSB SY
ISB SY ISB SY
LDP X29, X30, [SP], #0x10 LDP X29, X30, [SP], #0x10
LDP X18, X19, [SP], #0x10 LDP X18, X19, [SP], #0x10
LDP X16, X17, [SP], #0x10 LDP X16, X17, [SP], #0x10
LDP X14, X15, [SP], #0x10 LDP X14, X15, [SP], #0x10
LDP X12, X13, [SP], #0x10 LDP X12, X13, [SP], #0x10
LDP X10, X11, [SP], #0x10 LDP X10, X11, [SP], #0x10
LDP X8, X9, [SP], #0x10 LDP X8, X9, [SP], #0x10
LDP X6, X7, [SP], #0x10 LDP X6, X7, [SP], #0x10
LDP X4, X5, [SP], #0x10 LDP X4, X5, [SP], #0x10
LDP X2, X3, [SP], #0x10 LDP X2, X3, [SP], #0x10
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
ERET ERET
@ -418,15 +418,10 @@ ullICCPMRConst: .dword ullICCPMR
ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
ullPortInterruptNestingConst: .dword ullPortInterruptNesting ullPortInterruptNestingConst: .dword ullPortInterruptNesting
ullPortYieldRequiredConst: .dword ullPortYieldRequired ullPortYieldRequiredConst: .dword ullPortYieldRequired
ullICCIARConst: .dword ullICCIAR ullICCIARConst: .dword ullICCIAR
ullICCEOIRConst: .dword ullICCEOIR ullICCEOIRConst: .dword ullICCEOIR
vApplicationIRQHandlerConst: .word vApplicationIRQHandler vApplicationIRQHandlerConst: .word vApplicationIRQHandler
.end .end

View file

@ -30,7 +30,7 @@
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -44,13 +44,13 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE size_t #define portSTACK_TYPE size_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t; typedef portBASE_TYPE BaseType_t;
@ -66,10 +66,10 @@ not need to be guarded with a critical section. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 16 #define portBYTE_ALIGNMENT 16
#define portPOINTER_SIZE_TYPE uint64_t #define portPOINTER_SIZE_TYPE uint64_t
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -77,20 +77,20 @@ not need to be guarded with a critical section. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired )\ #define portEND_SWITCHING_ISR( xSwitchRequired )\
{ \ { \
extern uint64_t ullPortYieldRequired; \ extern uint64_t ullPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ullPortYieldRequired = pdTRUE; \ ullPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#if defined( GUEST ) #if defined( GUEST )
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" ) #define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
#else #else
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" ) #define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
@ -102,31 +102,31 @@ extern UBaseType_t uxPortSetInterruptMask( void );
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue ); extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void ); extern void vPortInstallFreeRTOSVectorTable( void );
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \ __asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \ __asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" ); __asm volatile ( "ISB SY" );
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \ __asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \ __asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" ); __asm volatile ( "ISB SY" );
/* These macros do not globally disable/enable interrupts. They do mask off /* These macros do not globally disable/enable interrupts. They do mask off
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
not required for this port but included in case common demo code that uses these not required for this port but included in case common demo code that uses these
macros is used. */ macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
handler for whichever peripheral is used to generate the RTOS tick. */ handler for whichever peripheral is used to generate the RTOS tick. */
@ -142,71 +142,70 @@ void vPortTaskUsesFPU( void );
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#define portINLINE __inline #define portINLINE __inline
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#endif #endif
/* The number of bits to shift for an interrupt priority is dependent on the /* The number of bits to shift for an interrupt priority is dependent on the
number of bits implemented by the interrupt controller. */ number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16 #if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else #else
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif #endif
/* Interrupt controller access addresses. */ /* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 ) #define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 ) #define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 ) #define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 ) #define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) ) #define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET ) #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -34,91 +34,91 @@
#include "task.h" #include "task.h"
#ifndef configUNIQUE_INTERRUPT_PRIORITIES #ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0 #error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES #if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority #error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* In case security extensions are implemented. */ /* In case security extensions are implemented. */
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#endif #endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
portmacro.h. */ portmacro.h. */
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /* In all GICs 255 can be written to the priority mask register to unmask all
(but the lowest) interrupt priority. */ (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
#define portSP_ELx ( ( StackType_t ) 0x01 ) #define portSP_ELx ( ( StackType_t ) 0x01 )
#define portSP_EL0 ( ( StackType_t ) 0x00 ) #define portSP_EL0 ( ( StackType_t ) 0x00 )
#if defined( GUEST ) #if defined( GUEST )
#define portEL1 ( ( StackType_t ) 0x04 ) #define portEL1 ( ( StackType_t ) 0x04 )
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 ) #define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
#else #else
#define portEL3 ( ( StackType_t ) 0x0c ) #define portEL3 ( ( StackType_t ) 0x0c )
/* At the time of writing, the BSP only supports EL3. */ /* At the time of writing, the BSP only supports EL3. */
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 ) #define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
#endif #endif
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x0C ) #define portAPSR_MODE_BITS_MASK ( 0x0C )
/* The I bit in the DAIF bits. */ /* The I bit in the DAIF bits. */
#define portDAIF_I ( 0x80 ) #define portDAIF_I ( 0x80 )
/* Macro to unmask all interrupt priorities. */ /* Macro to unmask all interrupt priorities. */
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */ /* s3_0_c4_c6_0 is ICC_PMR_EL1. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
__asm volatile ( "MSR DAIFSET, #2 \n" \ __asm volatile ( "MSR DAIFSET, #2 \n" \
"DSB SY \n" \ "DSB SY \n" \
"ISB SY \n" \ "ISB SY \n" \
"MSR s3_0_c4_c6_0, %0 \n" \ "MSR s3_0_c4_c6_0, %0 \n" \
"DSB SY \n" \ "DSB SY \n" \
"ISB SY \n" \ "ISB SY \n" \
"MSR DAIFCLR, #2 \n" \ "MSR DAIFCLR, #2 \n" \
"DSB SY \n" \ "DSB SY \n" \
"ISB SY \n" \ "ISB SY \n" \
::"r"( portUNMASK_VALUE ) ); \ ::"r"( portUNMASK_VALUE ) ); \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -159,93 +159,93 @@ __attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_C
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First all the general purpose registers. */ /* First all the general purpose registers. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */ *pxTopOfStack = 0x0101010101010101ULL; /* R1 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */ *pxTopOfStack = 0x0303030303030303ULL; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */ *pxTopOfStack = 0x0202020202020202ULL; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */ *pxTopOfStack = 0x0505050505050505ULL; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */ *pxTopOfStack = 0x0404040404040404ULL; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */ *pxTopOfStack = 0x0707070707070707ULL; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */ *pxTopOfStack = 0x0606060606060606ULL; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */ *pxTopOfStack = 0x0909090909090909ULL; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */ *pxTopOfStack = 0x0808080808080808ULL; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */ *pxTopOfStack = 0x1111111111111111ULL; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */ *pxTopOfStack = 0x1010101010101010ULL; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */ *pxTopOfStack = 0x1313131313131313ULL; /* R13 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */ *pxTopOfStack = 0x1212121212121212ULL; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */ *pxTopOfStack = 0x1515151515151515ULL; /* R15 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */ *pxTopOfStack = 0x1414141414141414ULL; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */ *pxTopOfStack = 0x1717171717171717ULL; /* R17 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */ *pxTopOfStack = 0x1616161616161616ULL; /* R16 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */ *pxTopOfStack = 0x1919191919191919ULL; /* R19 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */ *pxTopOfStack = 0x1818181818181818ULL; /* R18 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */ *pxTopOfStack = 0x2121212121212121ULL; /* R21 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */ *pxTopOfStack = 0x2020202020202020ULL; /* R20 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */ *pxTopOfStack = 0x2323232323232323ULL; /* R23 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */ *pxTopOfStack = 0x2222222222222222ULL; /* R22 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */ *pxTopOfStack = 0x2525252525252525ULL; /* R25 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */ *pxTopOfStack = 0x2424242424242424ULL; /* R24 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */ *pxTopOfStack = 0x2727272727272727ULL; /* R27 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */ *pxTopOfStack = 0x2626262626262626ULL; /* R26 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */ *pxTopOfStack = 0x2929292929292929ULL; /* R29 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */ *pxTopOfStack = 0x2828282828282828ULL; /* R28 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */ *pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */ *pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSTATE; *pxTopOfStack = portINITIAL_PSTATE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */ *pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */ any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -253,149 +253,149 @@ BaseType_t xPortStartScheduler( void )
{ {
uint32_t ulAPSR; uint32_t ulAPSR;
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
#if defined( GUEST ) #if defined( GUEST )
configASSERT( ulAPSR == portEL1 ); configASSERT( ulAPSR == portEL1 );
if( ulAPSR == portEL1 ) if( ulAPSR == portEL1 )
#else #else
configASSERT( ulAPSR == portEL3 ); configASSERT( ulAPSR == portEL3 );
if( ulAPSR == portEL3 ) if( ulAPSR == portEL3 )
#endif #endif
{ {
/* Interrupts are turned off in the CPU itself to ensure a tick does /* Interrupts are turned off in the CPU itself to ensure a tick does
not execute while the scheduler is being started. Interrupts are not execute while the scheduler is being started. Interrupts are
automatically turned back on in the CPU when the first task starts automatically turned back on in the CPU when the first task starts
executing. */ executing. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Start the first task executing. */ /* Start the first task executing. */
vPortRestoreTaskContext(); vPortRestoreTaskContext();
} }
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ Artificially force an assert. */
configASSERT( ullCriticalNesting == 1000ULL ); configASSERT( ullCriticalNesting == 1000ULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Mask interrupts up to the max syscall interrupt priority. */ /* Mask interrupts up to the max syscall interrupt priority. */
uxPortSetInterruptMask(); uxPortSetInterruptMask();
/* Now interrupts are disabled ullCriticalNesting can be accessed /* Now interrupts are disabled ullCriticalNesting can be accessed
directly. Increment ullCriticalNesting to keep a count of how many times directly. Increment ullCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ullCriticalNesting++; ullCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */
if( ullCriticalNesting == 1ULL ) if( ullCriticalNesting == 1ULL )
{ {
configASSERT( ullPortInterruptNesting == 0 ); configASSERT( ullPortInterruptNesting == 0 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ullCriticalNesting > portNO_CRITICAL_NESTING ) if( ullCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
exited. */ exited. */
ullCriticalNesting--; ullCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */ priorities must be re-enabled. */
if( ullCriticalNesting == portNO_CRITICAL_NESTING ) if( ullCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */ should be unmasked. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
/* Must be the lowest possible priority. */ /* Must be the lowest possible priority. */
#if !defined( QEMU ) #if !defined( QEMU )
{ {
uint64_t ullRunningInterruptPriority; uint64_t ullRunningInterruptPriority;
/* s3_0_c12_c11_3 is ICC_RPR_EL1. */ /* s3_0_c12_c11_3 is ICC_RPR_EL1. */
__asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) ); __asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) );
configASSERT( ullRunningInterruptPriority == ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( ullRunningInterruptPriority == ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
} }
#endif #endif
/* Interrupts should not be enabled before this point. */ /* Interrupts should not be enabled before this point. */
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
uint32_t ulMaskBits; uint32_t ulMaskBits;
__asm volatile( "MRS %0, DAIF" : "=r"( ulMaskBits ) :: "memory" ); __asm volatile( "MRS %0, DAIF" : "=r"( ulMaskBits ) :: "memory" );
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 ); configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Set interrupt mask before altering scheduler structures. The tick /* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked, handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */ updated. */
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */ /* s3_0_c4_c6_0 is ICC_PMR_EL1. */
__asm volatile ( "MSR s3_0_c4_c6_0, %0 \n" __asm volatile ( "MSR s3_0_c4_c6_0, %0 \n"
"DSB SY \n" "DSB SY \n"
"ISB SY \n" "ISB SY \n"
:: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" ); :: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
/* Ok to enable interrupts after the interrupt source has been cleared. */ /* Ok to enable interrupts after the interrupt source has been cleared. */
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ullPortYieldRequired = pdTRUE; ullPortYieldRequired = pdTRUE;
} }
/* Ensure all interrupt priorities are active again. */ /* Ensure all interrupt priorities are active again. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ullPortTaskHasFPUContext = pdTRUE; ullPortTaskHasFPUContext = pdTRUE;
/* Consider initialising the FPSR here - but probably not necessary in /* Consider initialising the FPSR here - but probably not necessary in
AArch64. */ AArch64. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue ) void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
{ {
if( uxNewMaskValue == pdFALSE ) if( uxNewMaskValue == pdFALSE )
{ {
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -404,56 +404,55 @@ UBaseType_t uxPortSetInterruptMask( void )
uint32_t ulReturn; uint32_t ulReturn;
uint64_t ullPMRValue; uint64_t ullPMRValue;
/* 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. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */ /* s3_0_c4_c6_0 is ICC_PMR_EL1. */
__asm volatile ( "MRS %0, s3_0_c4_c6_0" : "=r" ( ullPMRValue ) ); __asm volatile ( "MRS %0, s3_0_c4_c6_0" : "=r" ( ullPMRValue ) );
if( ullPMRValue == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( ullPMRValue == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
ulReturn = pdTRUE; ulReturn = pdTRUE;
} }
else else
{ {
ulReturn = pdFALSE; ulReturn = pdFALSE;
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */ /* s3_0_c4_c6_0 is ICC_PMR_EL1. */
__asm volatile ( "MSR s3_0_c4_c6_0, %0 \n" __asm volatile ( "MSR s3_0_c4_c6_0, %0 \n"
"DSB SY \n" "DSB SY \n"
"ISB SY \n" "ISB SY \n"
:: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" ); :: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
return ulReturn; return ulReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
FreeRTOS maintains separate thread and ISR API functions to ensure FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. */ interrupt entry is as fast and simple as possible. */
uint64_t ullRunningInterruptPriority; uint64_t ullRunningInterruptPriority;
/* s3_0_c12_c11_3 is ICC_RPR_EL1. */ /* s3_0_c12_c11_3 is ICC_RPR_EL1. */
__asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) ); __asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) );
configASSERT( ullRunningInterruptPriority >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( ullRunningInterruptPriority >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,191 +26,191 @@
* *
*/ */
.text .text
/* Variables and functions. */ /* Variables and functions. */
.extern ullMaxAPIPriorityMask .extern ullMaxAPIPriorityMask
.extern pxCurrentTCB .extern pxCurrentTCB
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vApplicationIRQHandler .extern vApplicationIRQHandler
.extern ullPortInterruptNesting .extern ullPortInterruptNesting
.extern ullPortTaskHasFPUContext .extern ullPortTaskHasFPUContext
.extern ullCriticalNesting .extern ullCriticalNesting
.extern ullPortYieldRequired .extern ullPortYieldRequired
.extern _freertos_vector_table .extern _freertos_vector_table
.global FreeRTOS_IRQ_Handler .global FreeRTOS_IRQ_Handler
.global FreeRTOS_SWI_Handler .global FreeRTOS_SWI_Handler
.global vPortRestoreTaskContext .global vPortRestoreTaskContext
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
/* Switch to use the EL0 stack pointer. */ /* Switch to use the EL0 stack pointer. */
MSR SPSEL, #0 MSR SPSEL, #0
/* Save the entire context. */ /* Save the entire context. */
STP X0, X1, [SP, #-0x10]! STP X0, X1, [SP, #-0x10]!
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
STP X4, X5, [SP, #-0x10]! STP X4, X5, [SP, #-0x10]!
STP X6, X7, [SP, #-0x10]! STP X6, X7, [SP, #-0x10]!
STP X8, X9, [SP, #-0x10]! STP X8, X9, [SP, #-0x10]!
STP X10, X11, [SP, #-0x10]! STP X10, X11, [SP, #-0x10]!
STP X12, X13, [SP, #-0x10]! STP X12, X13, [SP, #-0x10]!
STP X14, X15, [SP, #-0x10]! STP X14, X15, [SP, #-0x10]!
STP X16, X17, [SP, #-0x10]! STP X16, X17, [SP, #-0x10]!
STP X18, X19, [SP, #-0x10]! STP X18, X19, [SP, #-0x10]!
STP X20, X21, [SP, #-0x10]! STP X20, X21, [SP, #-0x10]!
STP X22, X23, [SP, #-0x10]! STP X22, X23, [SP, #-0x10]!
STP X24, X25, [SP, #-0x10]! STP X24, X25, [SP, #-0x10]!
STP X26, X27, [SP, #-0x10]! STP X26, X27, [SP, #-0x10]!
STP X28, X29, [SP, #-0x10]! STP X28, X29, [SP, #-0x10]!
STP X30, XZR, [SP, #-0x10]! STP X30, XZR, [SP, #-0x10]!
/* Save the SPSR. */ /* Save the SPSR. */
#if defined( GUEST ) #if defined( GUEST )
MRS X3, SPSR_EL1 MRS X3, SPSR_EL1
MRS X2, ELR_EL1 MRS X2, ELR_EL1
#else #else
MRS X3, SPSR_EL3 MRS X3, SPSR_EL3
/* Save the ELR. */ /* Save the ELR. */
MRS X2, ELR_EL3 MRS X2, ELR_EL3
#endif #endif
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
/* Save the critical section nesting depth. */ /* Save the critical section nesting depth. */
LDR X0, ullCriticalNestingConst LDR X0, ullCriticalNestingConst
LDR X3, [X0] LDR X3, [X0]
/* Save the FPU context indicator. */ /* Save the FPU context indicator. */
LDR X0, ullPortTaskHasFPUContextConst LDR X0, ullPortTaskHasFPUContextConst
LDR X2, [X0] LDR X2, [X0]
/* Save the FPU context, if any (32 128-bit registers). */ /* Save the FPU context, if any (32 128-bit registers). */
CMP X2, #0 CMP X2, #0
B.EQ 1f B.EQ 1f
STP Q0, Q1, [SP,#-0x20]! STP Q0, Q1, [SP,#-0x20]!
STP Q2, Q3, [SP,#-0x20]! STP Q2, Q3, [SP,#-0x20]!
STP Q4, Q5, [SP,#-0x20]! STP Q4, Q5, [SP,#-0x20]!
STP Q6, Q7, [SP,#-0x20]! STP Q6, Q7, [SP,#-0x20]!
STP Q8, Q9, [SP,#-0x20]! STP Q8, Q9, [SP,#-0x20]!
STP Q10, Q11, [SP,#-0x20]! STP Q10, Q11, [SP,#-0x20]!
STP Q12, Q13, [SP,#-0x20]! STP Q12, Q13, [SP,#-0x20]!
STP Q14, Q15, [SP,#-0x20]! STP Q14, Q15, [SP,#-0x20]!
STP Q16, Q17, [SP,#-0x20]! STP Q16, Q17, [SP,#-0x20]!
STP Q18, Q19, [SP,#-0x20]! STP Q18, Q19, [SP,#-0x20]!
STP Q20, Q21, [SP,#-0x20]! STP Q20, Q21, [SP,#-0x20]!
STP Q22, Q23, [SP,#-0x20]! STP Q22, Q23, [SP,#-0x20]!
STP Q24, Q25, [SP,#-0x20]! STP Q24, Q25, [SP,#-0x20]!
STP Q26, Q27, [SP,#-0x20]! STP Q26, Q27, [SP,#-0x20]!
STP Q28, Q29, [SP,#-0x20]! STP Q28, Q29, [SP,#-0x20]!
STP Q30, Q31, [SP,#-0x20]! STP Q30, Q31, [SP,#-0x20]!
1: 1:
/* Store the critical nesting count and FPU context indicator. */ /* Store the critical nesting count and FPU context indicator. */
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
LDR X0, pxCurrentTCBConst LDR X0, pxCurrentTCBConst
LDR X1, [X0] LDR X1, [X0]
MOV X0, SP /* Move SP into X0 for saving. */ MOV X0, SP /* Move SP into X0 for saving. */
STR X0, [X1] STR X0, [X1]
/* Switch to use the ELx stack pointer. */ /* Switch to use the ELx stack pointer. */
MSR SPSEL, #1 MSR SPSEL, #1
.endm .endm
; /**********************************************************************/ ; /**********************************************************************/
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
/* Switch to use the EL0 stack pointer. */ /* Switch to use the EL0 stack pointer. */
MSR SPSEL, #0 MSR SPSEL, #0
/* Set the SP to point to the stack of the task being restored. */ /* Set the SP to point to the stack of the task being restored. */
LDR X0, pxCurrentTCBConst LDR X0, pxCurrentTCBConst
LDR X1, [X0] LDR X1, [X0]
LDR X0, [X1] LDR X0, [X1]
MOV SP, X0 MOV SP, X0
LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */ LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
/* Set the PMR register to be correct for the current critical nesting /* Set the PMR register to be correct for the current critical nesting
depth. */ depth. */
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */ LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
MOV X1, #255 /* X1 holds the unmask value. */ MOV X1, #255 /* X1 holds the unmask value. */
CMP X3, #0 CMP X3, #0
B.EQ 1f B.EQ 1f
LDR X6, ullMaxAPIPriorityMaskConst LDR X6, ullMaxAPIPriorityMaskConst
LDR X1, [X6] /* X1 holds the mask value. */ LDR X1, [X6] /* X1 holds the mask value. */
1: 1:
MSR s3_0_c4_c6_0, X1 /* Write the mask value to ICCPMR. s3_0_c4_c6_0 is ICC_PMR_EL1. */ MSR s3_0_c4_c6_0, X1 /* Write the mask value to ICCPMR. s3_0_c4_c6_0 is ICC_PMR_EL1. */
DSB SY /* _RB_Barriers probably not required here. */ DSB SY /* _RB_Barriers probably not required here. */
ISB SY ISB SY
STR X3, [X0] /* Restore the task's critical nesting count. */ STR X3, [X0] /* Restore the task's critical nesting count. */
/* Restore the FPU context indicator. */ /* Restore the FPU context indicator. */
LDR X0, ullPortTaskHasFPUContextConst LDR X0, ullPortTaskHasFPUContextConst
STR X2, [X0] STR X2, [X0]
/* Restore the FPU context, if any. */ /* Restore the FPU context, if any. */
CMP X2, #0 CMP X2, #0
B.EQ 1f B.EQ 1f
LDP Q30, Q31, [SP], #0x20 LDP Q30, Q31, [SP], #0x20
LDP Q28, Q29, [SP], #0x20 LDP Q28, Q29, [SP], #0x20
LDP Q26, Q27, [SP], #0x20 LDP Q26, Q27, [SP], #0x20
LDP Q24, Q25, [SP], #0x20 LDP Q24, Q25, [SP], #0x20
LDP Q22, Q23, [SP], #0x20 LDP Q22, Q23, [SP], #0x20
LDP Q20, Q21, [SP], #0x20 LDP Q20, Q21, [SP], #0x20
LDP Q18, Q19, [SP], #0x20 LDP Q18, Q19, [SP], #0x20
LDP Q16, Q17, [SP], #0x20 LDP Q16, Q17, [SP], #0x20
LDP Q14, Q15, [SP], #0x20 LDP Q14, Q15, [SP], #0x20
LDP Q12, Q13, [SP], #0x20 LDP Q12, Q13, [SP], #0x20
LDP Q10, Q11, [SP], #0x20 LDP Q10, Q11, [SP], #0x20
LDP Q8, Q9, [SP], #0x20 LDP Q8, Q9, [SP], #0x20
LDP Q6, Q7, [SP], #0x20 LDP Q6, Q7, [SP], #0x20
LDP Q4, Q5, [SP], #0x20 LDP Q4, Q5, [SP], #0x20
LDP Q2, Q3, [SP], #0x20 LDP Q2, Q3, [SP], #0x20
LDP Q0, Q1, [SP], #0x20 LDP Q0, Q1, [SP], #0x20
1: 1:
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
/* Restore the SPSR. */ /* Restore the SPSR. */
MSR SPSR_EL1, X3 MSR SPSR_EL1, X3
/* Restore the ELR. */ /* Restore the ELR. */
MSR ELR_EL1, X2 MSR ELR_EL1, X2
#else #else
/* Restore the SPSR. */ /* Restore the SPSR. */
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */ MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
/* Restore the ELR. */ /* Restore the ELR. */
MSR ELR_EL3, X2 MSR ELR_EL3, X2
#endif #endif
LDP X30, XZR, [SP], #0x10 LDP X30, XZR, [SP], #0x10
LDP X28, X29, [SP], #0x10 LDP X28, X29, [SP], #0x10
LDP X26, X27, [SP], #0x10 LDP X26, X27, [SP], #0x10
LDP X24, X25, [SP], #0x10 LDP X24, X25, [SP], #0x10
LDP X22, X23, [SP], #0x10 LDP X22, X23, [SP], #0x10
LDP X20, X21, [SP], #0x10 LDP X20, X21, [SP], #0x10
LDP X18, X19, [SP], #0x10 LDP X18, X19, [SP], #0x10
LDP X16, X17, [SP], #0x10 LDP X16, X17, [SP], #0x10
LDP X14, X15, [SP], #0x10 LDP X14, X15, [SP], #0x10
LDP X12, X13, [SP], #0x10 LDP X12, X13, [SP], #0x10
LDP X10, X11, [SP], #0x10 LDP X10, X11, [SP], #0x10
LDP X8, X9, [SP], #0x10 LDP X8, X9, [SP], #0x10
LDP X6, X7, [SP], #0x10 LDP X6, X7, [SP], #0x10
LDP X4, X5, [SP], #0x10 LDP X4, X5, [SP], #0x10
LDP X2, X3, [SP], #0x10 LDP X2, X3, [SP], #0x10
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */ /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
MSR SPSEL, #1 MSR SPSEL, #1
ERET ERET
.endm .endm
/****************************************************************************** /******************************************************************************
@ -219,29 +219,29 @@
.align 8 .align 8
.type FreeRTOS_SWI_Handler, %function .type FreeRTOS_SWI_Handler, %function
FreeRTOS_SWI_Handler: FreeRTOS_SWI_Handler:
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
#if defined( GUEST ) #if defined( GUEST )
MRS X0, ESR_EL1 MRS X0, ESR_EL1
#else #else
MRS X0, ESR_EL3 MRS X0, ESR_EL3
#endif #endif
LSR X1, X0, #26 LSR X1, X0, #26
#if defined( GUEST ) #if defined( GUEST )
CMP X1, #0x15 /* 0x15 = SVC instruction. */ CMP X1, #0x15 /* 0x15 = SVC instruction. */
#else #else
CMP X1, #0x17 /* 0x17 = SMC instruction. */ CMP X1, #0x17 /* 0x17 = SMC instruction. */
#endif #endif
B.NE FreeRTOS_Abort B.NE FreeRTOS_Abort
BL vTaskSwitchContext BL vTaskSwitchContext
portRESTORE_CONTEXT portRESTORE_CONTEXT
FreeRTOS_Abort: FreeRTOS_Abort:
/* Full ESR is in X0, exception class code is in X1. */ /* Full ESR is in X0, exception class code is in X1. */
B . B .
/****************************************************************************** /******************************************************************************
* vPortRestoreTaskContext is used to start the scheduler. * vPortRestoreTaskContext is used to start the scheduler.
@ -249,20 +249,20 @@ FreeRTOS_Abort:
.align 8 .align 8
.type vPortRestoreTaskContext, %function .type vPortRestoreTaskContext, %function
vPortRestoreTaskContext: vPortRestoreTaskContext:
.set freertos_vector_base, _freertos_vector_table .set freertos_vector_base, _freertos_vector_table
/* Install the FreeRTOS interrupt handlers. */ /* Install the FreeRTOS interrupt handlers. */
LDR X1, =freertos_vector_base LDR X1, =freertos_vector_base
#if defined( GUEST ) #if defined( GUEST )
MSR VBAR_EL1, X1 MSR VBAR_EL1, X1
#else #else
MSR VBAR_EL3, X1 MSR VBAR_EL3, X1
#endif #endif
DSB SY DSB SY
ISB SY ISB SY
/* Start the first task. */ /* Start the first task. */
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
@ -279,132 +279,132 @@ vPortRestoreTaskContext:
.align 8 .align 8
.type FreeRTOS_IRQ_Handler, %function .type FreeRTOS_IRQ_Handler, %function
FreeRTOS_IRQ_Handler: FreeRTOS_IRQ_Handler:
/* Save volatile registers. */ /* Save volatile registers. */
STP X0, X1, [SP, #-0x10]! STP X0, X1, [SP, #-0x10]!
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
STP X4, X5, [SP, #-0x10]! STP X4, X5, [SP, #-0x10]!
STP X6, X7, [SP, #-0x10]! STP X6, X7, [SP, #-0x10]!
STP X8, X9, [SP, #-0x10]! STP X8, X9, [SP, #-0x10]!
STP X10, X11, [SP, #-0x10]! STP X10, X11, [SP, #-0x10]!
STP X12, X13, [SP, #-0x10]! STP X12, X13, [SP, #-0x10]!
STP X14, X15, [SP, #-0x10]! STP X14, X15, [SP, #-0x10]!
STP X16, X17, [SP, #-0x10]! STP X16, X17, [SP, #-0x10]!
STP X18, X19, [SP, #-0x10]! STP X18, X19, [SP, #-0x10]!
STP X29, X30, [SP, #-0x10]! STP X29, X30, [SP, #-0x10]!
/* Save the SPSR and ELR. */ /* Save the SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
MRS X3, SPSR_EL1 MRS X3, SPSR_EL1
MRS X2, ELR_EL1 MRS X2, ELR_EL1
#else #else
MRS X3, SPSR_EL3 MRS X3, SPSR_EL3
MRS X2, ELR_EL3 MRS X2, ELR_EL3
#endif #endif
STP X2, X3, [SP, #-0x10]! STP X2, X3, [SP, #-0x10]!
/* Increment the interrupt nesting counter. */ /* Increment the interrupt nesting counter. */
LDR X5, ullPortInterruptNestingConst LDR X5, ullPortInterruptNestingConst
LDR X1, [X5] /* Old nesting count in X1. */ LDR X1, [X5] /* Old nesting count in X1. */
ADD X6, X1, #1 ADD X6, X1, #1
STR X6, [X5] /* Address of nesting count variable in X5. */ STR X6, [X5] /* Address of nesting count variable in X5. */
/* Maintain the interrupt nesting information across the function call. */ /* Maintain the interrupt nesting information across the function call. */
STP X1, X5, [SP, #-0x10]! STP X1, X5, [SP, #-0x10]!
/* Read interrupt ID from the interrupt acknowledge register and store it /* Read interrupt ID from the interrupt acknowledge register and store it
in X0 for future parameter and interrupt clearing use. */ in X0 for future parameter and interrupt clearing use. */
MRS X0, S3_0_C12_C12_0 /* S3_0_C12_C12_0 is ICC_IAR1_EL1. */ MRS X0, S3_0_C12_C12_0 /* S3_0_C12_C12_0 is ICC_IAR1_EL1. */
/* Maintain the interrupt ID value across the function call. */ /* Maintain the interrupt ID value across the function call. */
STP X0, X1, [SP, #-0x10]! STP X0, X1, [SP, #-0x10]!
/* Call the C handler. */ /* Call the C handler. */
BL vApplicationIRQHandler BL vApplicationIRQHandler
/* Disable interrupts. */ /* Disable interrupts. */
MSR DAIFSET, #2 MSR DAIFSET, #2
DSB SY DSB SY
ISB SY ISB SY
/* Restore the interrupt ID value. */ /* Restore the interrupt ID value. */
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
/* End IRQ processing by writing interrupt ID value to the EOI register. */ /* End IRQ processing by writing interrupt ID value to the EOI register. */
MSR S3_0_C12_C12_1, X0 /* S3_0_C12_C12_1 is ICC_EOIR1_EL1. */ MSR S3_0_C12_C12_1, X0 /* S3_0_C12_C12_1 is ICC_EOIR1_EL1. */
/* Restore the critical nesting count. */ /* Restore the critical nesting count. */
LDP X1, X5, [SP], #0x10 LDP X1, X5, [SP], #0x10
STR X1, [X5] STR X1, [X5]
/* Has interrupt nesting unwound? */ /* Has interrupt nesting unwound? */
CMP X1, #0 CMP X1, #0
B.NE Exit_IRQ_No_Context_Switch B.NE Exit_IRQ_No_Context_Switch
/* Is a context switch required? */ /* Is a context switch required? */
LDR X0, ullPortYieldRequiredConst LDR X0, ullPortYieldRequiredConst
LDR X1, [X0] LDR X1, [X0]
CMP X1, #0 CMP X1, #0
B.EQ Exit_IRQ_No_Context_Switch B.EQ Exit_IRQ_No_Context_Switch
/* Reset ullPortYieldRequired to 0. */ /* Reset ullPortYieldRequired to 0. */
MOV X2, #0 MOV X2, #0
STR X2, [X0] STR X2, [X0]
/* Restore volatile registers. */ /* Restore volatile registers. */
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */ LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
MSR SPSR_EL1, X5 MSR SPSR_EL1, X5
MSR ELR_EL1, X4 MSR ELR_EL1, X4
#else #else
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */ MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
MSR ELR_EL3, X4 MSR ELR_EL3, X4
#endif #endif
DSB SY DSB SY
ISB SY ISB SY
LDP X29, X30, [SP], #0x10 LDP X29, X30, [SP], #0x10
LDP X18, X19, [SP], #0x10 LDP X18, X19, [SP], #0x10
LDP X16, X17, [SP], #0x10 LDP X16, X17, [SP], #0x10
LDP X14, X15, [SP], #0x10 LDP X14, X15, [SP], #0x10
LDP X12, X13, [SP], #0x10 LDP X12, X13, [SP], #0x10
LDP X10, X11, [SP], #0x10 LDP X10, X11, [SP], #0x10
LDP X8, X9, [SP], #0x10 LDP X8, X9, [SP], #0x10
LDP X6, X7, [SP], #0x10 LDP X6, X7, [SP], #0x10
LDP X4, X5, [SP], #0x10 LDP X4, X5, [SP], #0x10
LDP X2, X3, [SP], #0x10 LDP X2, X3, [SP], #0x10
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
BL vTaskSwitchContext BL vTaskSwitchContext
portRESTORE_CONTEXT portRESTORE_CONTEXT
Exit_IRQ_No_Context_Switch: Exit_IRQ_No_Context_Switch:
/* Restore volatile registers. */ /* Restore volatile registers. */
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */ LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
#if defined( GUEST ) #if defined( GUEST )
MSR SPSR_EL1, X5 MSR SPSR_EL1, X5
MSR ELR_EL1, X4 MSR ELR_EL1, X4
#else #else
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */ MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
MSR ELR_EL3, X4 MSR ELR_EL3, X4
#endif #endif
DSB SY DSB SY
ISB SY ISB SY
LDP X29, X30, [SP], #0x10 LDP X29, X30, [SP], #0x10
LDP X18, X19, [SP], #0x10 LDP X18, X19, [SP], #0x10
LDP X16, X17, [SP], #0x10 LDP X16, X17, [SP], #0x10
LDP X14, X15, [SP], #0x10 LDP X14, X15, [SP], #0x10
LDP X12, X13, [SP], #0x10 LDP X12, X13, [SP], #0x10
LDP X10, X11, [SP], #0x10 LDP X10, X11, [SP], #0x10
LDP X8, X9, [SP], #0x10 LDP X8, X9, [SP], #0x10
LDP X6, X7, [SP], #0x10 LDP X6, X7, [SP], #0x10
LDP X4, X5, [SP], #0x10 LDP X4, X5, [SP], #0x10
LDP X2, X3, [SP], #0x10 LDP X2, X3, [SP], #0x10
LDP X0, X1, [SP], #0x10 LDP X0, X1, [SP], #0x10
ERET ERET

View file

@ -30,7 +30,7 @@
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -44,13 +44,13 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE size_t #define portSTACK_TYPE size_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t; typedef portBASE_TYPE BaseType_t;
@ -66,10 +66,10 @@ not need to be guarded with a critical section. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 16 #define portBYTE_ALIGNMENT 16
#define portPOINTER_SIZE_TYPE uint64_t #define portPOINTER_SIZE_TYPE uint64_t
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -77,20 +77,20 @@ not need to be guarded with a critical section. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired )\ #define portEND_SWITCHING_ISR( xSwitchRequired )\
{ \ { \
extern uint64_t ullPortYieldRequired; \ extern uint64_t ullPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ullPortYieldRequired = pdTRUE; \ ullPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#if defined( GUEST ) #if defined( GUEST )
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" ) #define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
#else #else
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" ) #define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
@ -102,31 +102,31 @@ extern UBaseType_t uxPortSetInterruptMask( void );
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue ); extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void ); extern void vPortInstallFreeRTOSVectorTable( void );
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \ __asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \ __asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" ); __asm volatile ( "ISB SY" );
#define portENABLE_INTERRUPTS() \ #define portENABLE_INTERRUPTS() \
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \ __asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
__asm volatile ( "DSB SY" ); \ __asm volatile ( "DSB SY" ); \
__asm volatile ( "ISB SY" ); __asm volatile ( "ISB SY" );
/* These macros do not globally disable/enable interrupts. They do mask off /* These macros do not globally disable/enable interrupts. They do mask off
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
not required for this port but included in case common demo code that uses these not required for this port but included in case common demo code that uses these
macros is used. */ macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
handler for whichever peripheral is used to generate the RTOS tick. */ handler for whichever peripheral is used to generate the RTOS tick. */
@ -142,56 +142,55 @@ void vPortTaskUsesFPU( void );
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#define portINLINE __inline #define portINLINE __inline
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#endif #endif
/* The number of bits to shift for an interrupt priority is dependent on the /* The number of bits to shift for an interrupt priority is dependent on the
number of bits implemented by the interrupt controller. */ number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16 #if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else #else
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif #endif
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -35,123 +35,123 @@
#include "task.h" #include "task.h"
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET #ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configUNIQUE_INTERRUPT_PRIORITIES #ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0 #error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES #if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority #error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* In case security extensions are implemented. */ /* In case security extensions are implemented. */
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#endif #endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
portmacro.h. */ portmacro.h. */
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /* In all GICs 255 can be written to the priority mask register to unmask all
(but the lowest) interrupt priority. */ (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINTERRUPT_ENABLE_BIT ( 0x80UL ) #define portINTERRUPT_ENABLE_BIT ( 0x80UL )
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
point is zero. */ point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) #define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x1F ) #define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user /* The value of the mode bits in the APSR when the CPU is executing in user
mode. */ mode. */
#define portAPSR_USER_MODE ( 0x10 ) #define portAPSR_USER_MODE ( 0x10 )
/* The critical section macros only mask interrupts up to an application /* The critical section macros only mask interrupts up to an application
determined priority level. Sometimes it is necessary to turn interrupt off in determined priority level. Sometimes it is necessary to turn interrupt off in
the CPU itself before modifying certain hardware registers. */ the CPU itself before modifying certain hardware registers. */
#define portCPU_IRQ_DISABLE() \ #define portCPU_IRQ_DISABLE() \
__asm volatile ( "CPSID i" ::: "memory" ); \ __asm volatile ( "CPSID i" ::: "memory" ); \
__asm volatile ( "DSB" ); \ __asm volatile ( "DSB" ); \
__asm volatile ( "ISB" ); __asm volatile ( "ISB" );
#define portCPU_IRQ_ENABLE() \ #define portCPU_IRQ_ENABLE() \
__asm volatile ( "CPSIE i" ::: "memory" ); \ __asm volatile ( "CPSIE i" ::: "memory" ); \
__asm volatile ( "DSB" ); \ __asm volatile ( "DSB" ); \
__asm volatile ( "ISB" ); __asm volatile ( "ISB" );
/* Macro to unmask all interrupt priorities. */ /* Macro to unmask all interrupt priorities. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
portCPU_IRQ_DISABLE(); \ portCPU_IRQ_DISABLE(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm volatile ( "DSB \n" \ __asm volatile ( "DSB \n" \
"ISB \n" ); \ "ISB \n" ); \
portCPU_IRQ_ENABLE(); \ portCPU_IRQ_ENABLE(); \
} }
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL #define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portBIT_0_SET ( ( uint8_t ) 0x01 ) #define portBIT_0_SET ( ( uint8_t ) 0x01 )
/* Let the user override the pre-loading of the initial LR with the address of /* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */ debugger. */
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
#define portTASK_RETURN_ADDRESS prvTaskExitError #define portTASK_RETURN_ADDRESS prvTaskExitError
#endif #endif
/* The space on the stack required to hold the FPU registers. This is 32 64-bit /* The space on the stack required to hold the FPU registers. This is 32 64-bit
registers, plus a 32-bit status register. */ registers, plus a 32-bit status register. */
#define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 ) #define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -210,7 +210,7 @@ volatile uint32_t ulPortInterruptNesting = 0UL;
/* Used in the asm file. */ /* Used in the asm file. */
__attribute__(( used )) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS; __attribute__(( used )) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS; __attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS; __attribute__(( used )) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
__attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); __attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -220,106 +220,106 @@ __attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CA
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. expected by the portRESTORE_CONTEXT() macro.
The fist real value on the stack is the status register, which is set for The fist real value on the stack is the status register, which is set for
system mode, with interrupts enabled. A few NULLs are added first to ensure system mode, with interrupts enabled. A few NULLs are added first to ensure
GDB does not try decoding a non-existent return address. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{ {
/* The task will start in THUMB mode. */ /* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
pxTopOfStack--; pxTopOfStack--;
/* Next the return address, which in this case is the start of the task. */ /* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
/* Next all the registers other than the stack pointer. */ /* Next all the registers other than the stack pointer. */
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
#if( configUSE_TASK_FPU_SUPPORT == 1 ) #if( configUSE_TASK_FPU_SUPPORT == 1 )
{ {
/* The task will start without a floating point context. A task that /* The task will start without a floating point context. A task that
uses the floating point hardware must call vPortTaskUsesFPU() before uses the floating point hardware must call vPortTaskUsesFPU() before
executing any floating point instructions. */ executing any floating point instructions. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
} }
#elif( configUSE_TASK_FPU_SUPPORT == 2 ) #elif( configUSE_TASK_FPU_SUPPORT == 2 )
{ {
/* The task will start with a floating point context. Leave enough /* The task will start with a floating point context. Leave enough
space for the registers - and ensure they are initialised to 0. */ space for the registers - and ensure they are initialised to 0. */
pxTopOfStack -= portFPU_REGISTER_WORDS; pxTopOfStack -= portFPU_REGISTER_WORDS;
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) ); memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = pdTRUE; *pxTopOfStack = pdTRUE;
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
} }
#else #else
{ {
#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined. #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
} }
#endif #endif
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ). should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */ defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; ); for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -327,178 +327,178 @@ BaseType_t xPortStartScheduler( void )
{ {
uint32_t ulAPSR; uint32_t ulAPSR;
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
volatile uint32_t ulOriginalPriority; volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC. /* Determine how many priority bits are implemented in the GIC.
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to /* Determine the number of priority bits available. First write to
all possible bits. */ all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister; ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Shift to the least significant bits. */ /* Shift to the least significant bits. */
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET ) while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
{ {
ucMaxPriorityValue >>= ( uint8_t ) 0x01; ucMaxPriorityValue >>= ( uint8_t ) 0x01;
} }
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
value. */ value. */
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY ); configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Only continue if the CPU is not in User mode. The CPU must be in a /* Only continue if the CPU is not in User mode. The CPU must be in a
Privileged mode for the scheduler to start. */ Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
if( ulAPSR != portAPSR_USER_MODE ) if( ulAPSR != portAPSR_USER_MODE )
{ {
/* Only continue if the binary point value is set to its lowest possible /* Only continue if the binary point value is set to its lowest possible
setting. See the comments in vPortValidateInterruptPriority() below for setting. See the comments in vPortValidateInterruptPriority() below for
more information. */ more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Interrupts are turned off in the CPU itself to ensure tick does /* Interrupts are turned off in the CPU itself to ensure tick does
not execute while the scheduler is being started. Interrupts are not execute while the scheduler is being started. Interrupts are
automatically turned back on in the CPU when the first task starts automatically turned back on in the CPU when the first task starts
executing. */ executing. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Start the first task executing. */ /* Start the first task executing. */
vPortRestoreTaskContext(); vPortRestoreTaskContext();
} }
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /* Will only get here if vTaskStartScheduler() was called with the CPU in
a non-privileged mode or the binary point register was not set to its lowest a non-privileged mode or the binary point register was not set to its lowest
possible value. prvTaskExitError() is referenced to prevent a compiler possible value. prvTaskExitError() is referenced to prevent a compiler
warning about it being defined but not referenced in the case that the user warning about it being defined but not referenced in the case that the user
defines their own exit address. */ defines their own exit address. */
( void ) prvTaskExitError; ( void ) prvTaskExitError;
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Mask interrupts up to the max syscall interrupt priority. */ /* Mask interrupts up to the max syscall interrupt priority. */
ulPortSetInterruptMask(); ulPortSetInterruptMask();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
exited. */ exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */ priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */ should be unmasked. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
/* Set interrupt mask before altering scheduler structures. The tick /* Set interrupt mask before altering scheduler structures. The tick
handler runs at the lowest priority, so interrupts cannot already be masked, handler runs at the lowest priority, so interrupts cannot already be masked,
so there is no need to save and restore the current mask value. It is so there is no need to save and restore the current mask value. It is
necessary to turn off interrupts in the CPU itself while the ICCPMR is being necessary to turn off interrupts in the CPU itself while the ICCPMR is being
updated. */ updated. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
"isb \n" ::: "memory" ); "isb \n" ::: "memory" );
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ulPortYieldRequired = pdTRUE; ulPortYieldRequired = pdTRUE;
} }
/* Ensure all interrupt priorities are active again. */ /* Ensure all interrupt priorities are active again. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_FPU_SUPPORT != 2 ) #if( configUSE_TASK_FPU_SUPPORT != 2 )
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" ); __asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" );
} }
#endif /* configUSE_TASK_FPU_SUPPORT */ #endif /* configUSE_TASK_FPU_SUPPORT */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortClearInterruptMask( uint32_t ulNewMaskValue ) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{ {
if( ulNewMaskValue == pdFALSE ) if( ulNewMaskValue == pdFALSE )
{ {
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -506,65 +506,65 @@ uint32_t ulPortSetInterruptMask( void )
{ {
uint32_t ulReturn; uint32_t ulReturn;
/* 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. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
ulReturn = pdTRUE; ulReturn = pdTRUE;
} }
else else
{ {
ulReturn = pdFALSE; ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
"isb \n" ::: "memory" ); "isb \n" ::: "memory" );
} }
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();
return ulReturn; return ulReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
FreeRTOS maintains separate thread and ISR API functions to ensure FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible. */ interrupt entry is as fast and simple as possible. */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits /* Priority grouping: The interrupt controller (GIC) allows the bits
that define each interrupt's priority to be split between bits that that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
The priority grouping is configured by the GIC's binary point register The priority grouping is configured by the GIC's binary point register
(ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
possible value (which may be above 0). */ possible value (which may be above 0). */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
{ {
( void ) ulICCIAR; ( void ) ulICCIAR;
configASSERT( ( volatile void * ) NULL ); configASSERT( ( volatile void * ) NULL );
} }

View file

@ -25,114 +25,114 @@
* https://github.com/FreeRTOS * https://github.com/FreeRTOS
* *
*/ */
.eabi_attribute Tag_ABI_align_preserved, 1 .eabi_attribute Tag_ABI_align_preserved, 1
.text .text
.arm .arm
.set SYS_MODE, 0x1f .set SYS_MODE, 0x1f
.set SVC_MODE, 0x13 .set SVC_MODE, 0x13
.set IRQ_MODE, 0x12 .set IRQ_MODE, 0x12
/* Hardware registers. */ /* Hardware registers. */
.extern ulICCIAR .extern ulICCIAR
.extern ulICCEOIR .extern ulICCEOIR
.extern ulICCPMR .extern ulICCPMR
/* Variables and functions. */ /* Variables and functions. */
.extern ulMaxAPIPriorityMask .extern ulMaxAPIPriorityMask
.extern _freertos_vector_table .extern _freertos_vector_table
.extern pxCurrentTCB .extern pxCurrentTCB
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vApplicationIRQHandler .extern vApplicationIRQHandler
.extern ulPortInterruptNesting .extern ulPortInterruptNesting
.extern ulPortTaskHasFPUContext .extern ulPortTaskHasFPUContext
.global FreeRTOS_IRQ_Handler .global FreeRTOS_IRQ_Handler
.global FreeRTOS_SWI_Handler .global FreeRTOS_SWI_Handler
.global vPortRestoreTaskContext .global vPortRestoreTaskContext
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
/* Save the LR and SPSR onto the system mode stack before switching to /* Save the LR and SPSR onto the system mode stack before switching to
system mode to save the remaining system mode registers. */ system mode to save the remaining system mode registers. */
SRSDB sp!, #SYS_MODE SRSDB sp!, #SYS_MODE
CPS #SYS_MODE CPS #SYS_MODE
PUSH {R0-R12, R14} PUSH {R0-R12, R14}
/* Push the critical nesting count. */ /* Push the critical nesting count. */
LDR R2, ulCriticalNestingConst LDR R2, ulCriticalNestingConst
LDR R1, [R2] LDR R1, [R2]
PUSH {R1} PUSH {R1}
/* Does the task have a floating point context that needs saving? If /* Does the task have a floating point context that needs saving? If
ulPortTaskHasFPUContext is 0 then no. */ ulPortTaskHasFPUContext is 0 then no. */
LDR R2, ulPortTaskHasFPUContextConst LDR R2, ulPortTaskHasFPUContextConst
LDR R3, [R2] LDR R3, [R2]
CMP R3, #0 CMP R3, #0
/* Save the floating point context, if any. */ /* Save the floating point context, if any. */
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
VPUSHNE {D16-D31} VPUSHNE {D16-D31}
PUSHNE {R1} PUSHNE {R1}
/* Save ulPortTaskHasFPUContext itself. */ /* Save ulPortTaskHasFPUContext itself. */
PUSH {R3} PUSH {R3}
/* Save the stack pointer in the TCB. */ /* Save the stack pointer in the TCB. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R1, [R0] LDR R1, [R0]
STR SP, [R1] STR SP, [R1]
.endm .endm
; /**********************************************************************/ ; /**********************************************************************/
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
/* Set the SP to point to the stack of the task being restored. */ /* Set the SP to point to the stack of the task being restored. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R1, [R0] LDR R1, [R0]
LDR SP, [R1] LDR SP, [R1]
/* Is there a floating point context to restore? If the restored /* Is there a floating point context to restore? If the restored
ulPortTaskHasFPUContext is zero then no. */ ulPortTaskHasFPUContext is zero then no. */
LDR R0, ulPortTaskHasFPUContextConst LDR R0, ulPortTaskHasFPUContextConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
CMP R1, #0 CMP R1, #0
/* Restore the floating point context, if any. */ /* Restore the floating point context, if any. */
POPNE {R0} POPNE {R0}
VPOPNE {D16-D31} VPOPNE {D16-D31}
VPOPNE {D0-D15} VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
/* Restore the critical section nesting depth. */ /* Restore the critical section nesting depth. */
LDR R0, ulCriticalNestingConst LDR R0, ulCriticalNestingConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
/* Ensure the priority mask is correct for the critical nesting depth. */ /* Ensure the priority mask is correct for the critical nesting depth. */
LDR R2, ulICCPMRConst LDR R2, ulICCPMRConst
LDR R2, [R2] LDR R2, [R2]
CMP R1, #0 CMP R1, #0
MOVEQ R4, #255 MOVEQ R4, #255
LDRNE R4, ulMaxAPIPriorityMaskConst LDRNE R4, ulMaxAPIPriorityMaskConst
LDRNE R4, [R4] LDRNE R4, [R4]
STR R4, [R2] STR R4, [R2]
/* Restore all system mode registers other than the SP (which is already /* Restore all system mode registers other than the SP (which is already
being used). */ being used). */
POP {R0-R12, R14} POP {R0-R12, R14}
/* Return to the task code, loading CPSR on the way. */ /* Return to the task code, loading CPSR on the way. */
RFEIA sp! RFEIA sp!
.endm .endm
@ -143,11 +143,11 @@
.align 4 .align 4
.type FreeRTOS_SWI_Handler, %function .type FreeRTOS_SWI_Handler, %function
FreeRTOS_SWI_Handler: FreeRTOS_SWI_Handler:
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
@ -155,114 +155,114 @@ FreeRTOS_SWI_Handler:
*****************************************************************************/ *****************************************************************************/
.type vPortRestoreTaskContext, %function .type vPortRestoreTaskContext, %function
vPortRestoreTaskContext: vPortRestoreTaskContext:
/* Switch to system mode. */ /* Switch to system mode. */
CPS #SYS_MODE CPS #SYS_MODE
portRESTORE_CONTEXT portRESTORE_CONTEXT
.align 4 .align 4
.type FreeRTOS_IRQ_Handler, %function .type FreeRTOS_IRQ_Handler, %function
FreeRTOS_IRQ_Handler: FreeRTOS_IRQ_Handler:
/* Return to the interrupted instruction. */ /* Return to the interrupted instruction. */
SUB lr, lr, #4 SUB lr, lr, #4
/* Push the return address and SPSR. */ /* Push the return address and SPSR. */
PUSH {lr} PUSH {lr}
MRS lr, SPSR MRS lr, SPSR
PUSH {lr} PUSH {lr}
/* Change to supervisor mode to allow reentry. */ /* Change to supervisor mode to allow reentry. */
CPS #SVC_MODE CPS #SVC_MODE
/* Push used registers. */ /* Push used registers. */
PUSH {r0-r4, r12} PUSH {r0-r4, r12}
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting /* Increment nesting count. r3 holds the address of ulPortInterruptNesting
for future use. r1 holds the original ulPortInterruptNesting value for for future use. r1 holds the original ulPortInterruptNesting value for
future use. */ future use. */
LDR r3, ulPortInterruptNestingConst LDR r3, ulPortInterruptNestingConst
LDR r1, [r3] LDR r1, [r3]
ADD r4, r1, #1 ADD r4, r1, #1
STR r4, [r3] STR r4, [r3]
/* Read value from the interrupt acknowledge register, which is stored in r0 /* Read value from the interrupt acknowledge register, which is stored in r0
for future parameter and interrupt clearing use. */ for future parameter and interrupt clearing use. */
LDR r2, ulICCIARConst LDR r2, ulICCIARConst
LDR r2, [r2] LDR r2, [r2]
LDR r0, [r2] LDR r0, [r2]
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for /* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
future use. _RB_ Does this ever actually need to be done provided the start future use. _RB_ Does this ever actually need to be done provided the start
of the stack is 8-byte aligned? */ of the stack is 8-byte aligned? */
MOV r2, sp MOV r2, sp
AND r2, r2, #4 AND r2, r2, #4
SUB sp, sp, r2 SUB sp, sp, r2
/* Call the interrupt handler. r4 pushed to maintain alignment. */ /* Call the interrupt handler. r4 pushed to maintain alignment. */
PUSH {r0-r4, lr} PUSH {r0-r4, lr}
LDR r1, vApplicationIRQHandlerConst LDR r1, vApplicationIRQHandlerConst
BLX r1 BLX r1
POP {r0-r4, lr} POP {r0-r4, lr}
ADD sp, sp, r2 ADD sp, sp, r2
CPSID i CPSID i
DSB DSB
ISB ISB
/* Write the value read from ICCIAR to ICCEOIR. */ /* Write the value read from ICCIAR to ICCEOIR. */
LDR r4, ulICCEOIRConst LDR r4, ulICCEOIRConst
LDR r4, [r4] LDR r4, [r4]
STR r0, [r4] STR r0, [r4]
/* Restore the old nesting count. */ /* Restore the old nesting count. */
STR r1, [r3] STR r1, [r3]
/* A context switch is never performed if the nesting count is not 0. */ /* A context switch is never performed if the nesting count is not 0. */
CMP r1, #0 CMP r1, #0
BNE exit_without_switch BNE exit_without_switch
/* Did the interrupt request a context switch? r1 holds the address of /* Did the interrupt request a context switch? r1 holds the address of
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
use. */ use. */
LDR r1, =ulPortYieldRequired LDR r1, =ulPortYieldRequired
LDR r0, [r1] LDR r0, [r1]
CMP r0, #0 CMP r0, #0
BNE switch_before_exit BNE switch_before_exit
exit_without_switch: exit_without_switch:
/* No context switch. Restore used registers, LR_irq and SPSR before /* No context switch. Restore used registers, LR_irq and SPSR before
returning. */ returning. */
POP {r0-r4, r12} POP {r0-r4, r12}
CPS #IRQ_MODE CPS #IRQ_MODE
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
MOVS PC, LR MOVS PC, LR
switch_before_exit: switch_before_exit:
/* A context swtich is to be performed. Clear the context switch pending /* A context swtich is to be performed. Clear the context switch pending
flag. */ flag. */
MOV r0, #0 MOV r0, #0
STR r0, [r1] STR r0, [r1]
/* Restore used registers, LR-irq and SPSR before saving the context /* Restore used registers, LR-irq and SPSR before saving the context
to the task stack. */ to the task stack. */
POP {r0-r4, r12} POP {r0-r4, r12}
CPS #IRQ_MODE CPS #IRQ_MODE
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
portSAVE_CONTEXT portSAVE_CONTEXT
/* Call the function that selects the new task to execute. /* Call the function that selects the new task to execute.
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
instructions, or 8 byte aligned stack allocated data. LR does not need instructions, or 8 byte aligned stack allocated data. LR does not need
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */ saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
/* Restore the context of, and branch to, the task selected to execute /* Restore the context of, and branch to, the task selected to execute
next. */ next. */
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
@ -287,25 +287,25 @@ switch_before_exit:
.weak vApplicationIRQHandler .weak vApplicationIRQHandler
.type vApplicationIRQHandler, %function .type vApplicationIRQHandler, %function
vApplicationIRQHandler: vApplicationIRQHandler:
PUSH {LR} PUSH {LR}
FMRX R1, FPSCR FMRX R1, FPSCR
VPUSH {D0-D15} VPUSH {D0-D15}
VPUSH {D16-D31} VPUSH {D16-D31}
PUSH {R1} PUSH {R1}
LDR r1, vApplicationFPUSafeIRQHandlerConst LDR r1, vApplicationFPUSafeIRQHandlerConst
BLX r1 BLX r1
POP {R0} POP {R0}
VPOP {D16-D31} VPOP {D16-D31}
VPOP {D0-D15} VPOP {D0-D15}
VMSR FPSCR, R0 VMSR FPSCR, R0
POP {PC} POP {PC}
ulICCIARConst: .word ulICCIAR ulICCIARConst: .word ulICCIAR
ulICCEOIRConst: .word ulICCEOIR ulICCEOIRConst: .word ulICCEOIR
ulICCPMRConst: .word ulICCPMR ulICCPMRConst: .word ulICCPMR
pxCurrentTCBConst: .word pxCurrentTCB pxCurrentTCBConst: .word pxCurrentTCB
ulCriticalNestingConst: .word ulCriticalNesting ulCriticalNestingConst: .word ulCriticalNesting
@ -317,8 +317,3 @@ ulPortInterruptNestingConst: .word ulPortInterruptNesting
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
.end .end

View file

@ -30,7 +30,7 @@
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -44,13 +44,13 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
@ -66,9 +66,9 @@ not need to be guarded with a critical section. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -76,13 +76,13 @@ not need to be guarded with a critical section. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired )\ #define portEND_SWITCHING_ISR( xSwitchRequired )\
{ \ { \
extern uint32_t ulPortYieldRequired; \ extern uint32_t ulPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ulPortYieldRequired = pdTRUE; \ ulPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
@ -101,20 +101,20 @@ extern void vPortInstallFreeRTOSVectorTable( void );
/* These macros do not globally disable/enable interrupts. They do mask off /* These macros do not globally disable/enable interrupts. They do mask off
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
not required for this port but included in case common demo code that uses these not required for this port but included in case common demo code that uses these
macros is used. */ macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
handler for whichever peripheral is used to generate the RTOS tick. */ handler for whichever peripheral is used to generate the RTOS tick. */
@ -126,11 +126,11 @@ themselves an FPU context before using any FPU instructions. If
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
by default. */ by default. */
#if( configUSE_TASK_FPU_SUPPORT != 2 ) #if( configUSE_TASK_FPU_SUPPORT != 2 )
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#else #else
/* Each task has an FPU context already, so define this function away to /* Each task has an FPU context already, so define this function away to
nothing to prevent it being called accidentally. */ nothing to prevent it being called accidentally. */
#define vPortTaskUsesFPU() #define vPortTaskUsesFPU()
#endif #endif
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
@ -139,71 +139,70 @@ by default. */
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#define portINLINE __inline #define portINLINE __inline
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#endif #endif
/* The number of bits to shift for an interrupt priority is dependent on the /* The number of bits to shift for an interrupt priority is dependent on the
number of bits implemented by the interrupt controller. */ number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16 #if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else #else
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif #endif
/* Interrupt controller access addresses. */ /* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 ) #define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 ) #define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 ) #define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 ) #define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) ) #define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET ) #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -204,24 +204,24 @@ void vPortStartFirstTask( void )
* table offset register that can be used to locate the initial stack value. * 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. */ * Not all M0 parts have the application vector table at address 0. */
__asm volatile ( __asm volatile (
" .syntax unified \n" " .syntax unified \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Obtain location of pxCurrentTCB. */ " ldr r2, pxCurrentTCBConst2 \n"/* Obtain location of pxCurrentTCB. */
" ldr r3, [r2] \n" " ldr r3, [r2] \n"
" ldr r0, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" movs r0, #2 \n"/* Switch to the psp stack. */ " movs r0, #2 \n"/* Switch to the psp stack. */
" msr CONTROL, r0 \n" " msr CONTROL, r0 \n"
" isb \n" " isb \n"
" pop {r0-r5} \n"/* Pop the registers that are saved automatically. */ " pop {r0-r5} \n"/* Pop the registers that are saved automatically. */
" mov lr, r5 \n"/* lr is now in r5. */ " mov lr, r5 \n"/* lr is now in r5. */
" pop {r3} \n"/* Return address is now in r3. */ " pop {r3} \n"/* Return address is now in r3. */
" pop {r2} \n"/* Pop and discard XPSR. */ " pop {r2} \n"/* Pop and discard XPSR. */
" cpsie i \n"/* The first task has its context and interrupts can be enabled. */ " cpsie i \n"/* The first task has its context and interrupts can be enabled. */
" bx r3 \n"/* Finally, jump to the user defined task code. */ " bx r3 \n"/* Finally, jump to the user defined task code. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB " "pxCurrentTCBConst2: .word pxCurrentTCB "
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -303,9 +303,9 @@ void vPortExitCritical( void )
uint32_t ulSetInterruptMaskFromISR( void ) uint32_t ulSetInterruptMaskFromISR( void )
{ {
__asm volatile ( __asm volatile (
" mrs r0, PRIMASK \n" " mrs r0, PRIMASK \n"
" cpsid i \n" " cpsid i \n"
" bx lr " " bx lr "
::: "memory" ::: "memory"
); );
} }
@ -314,8 +314,8 @@ uint32_t ulSetInterruptMaskFromISR( void )
void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask )
{ {
__asm volatile ( __asm volatile (
" msr PRIMASK, r0 \n" " msr PRIMASK, r0 \n"
" bx lr " " bx lr "
::: "memory" ::: "memory"
); );
} }
@ -327,45 +327,45 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" mrs r0, psp \n" " mrs r0, psp \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" subs r0, r0, #32 \n"/* Make space for the remaining low registers. */ " subs r0, r0, #32 \n"/* Make space for the remaining low registers. */
" str r0, [r2] \n"/* Save the new top of stack. */ " str r0, [r2] \n"/* Save the new top of stack. */
" stmia r0!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
" mov r4, r8 \n"/* Store the high registers. */ " mov r4, r8 \n"/* Store the high registers. */
" mov r5, r9 \n" " mov r5, r9 \n"
" mov r6, r10 \n" " mov r6, r10 \n"
" mov r7, r11 \n" " mov r7, r11 \n"
" stmia r0!, {r4-r7} \n" " stmia r0!, {r4-r7} \n"
" \n" " \n"
" push {r3, r14} \n" " push {r3, r14} \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" pop {r2, r3} \n"/* lr goes in r3. r2 now holds tcb pointer. */ " pop {r2, r3} \n"/* lr goes in r3. r2 now holds tcb pointer. */
" \n" " \n"
" ldr r1, [r2] \n" " ldr r1, [r2] \n"
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, r0, #16 \n"/* Move to the high registers. */ " adds r0, r0, #16 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n"/* Pop the high registers. */ " ldmia r0!, {r4-r7} \n"/* Pop the high registers. */
" mov r8, r4 \n" " mov r8, r4 \n"
" mov r9, r5 \n" " mov r9, r5 \n"
" mov r10, r6 \n" " mov r10, r6 \n"
" mov r11, r7 \n" " mov r11, r7 \n"
" \n" " \n"
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" \n" " \n"
" subs r0, r0, #32 \n"/* Go back for the low registers that are not automatically restored. */ " subs r0, r0, #32 \n"/* Go back for the low registers that are not automatically restored. */
" ldmia r0!, {r4-r7} \n"/* Pop low registers. */ " ldmia r0!, {r4-r7} \n"/* Pop low registers. */
" \n" " \n"
" bx r3 \n" " bx r3 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB " "pxCurrentTCBConst: .word pxCurrentTCB "
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -48,86 +48,86 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */ " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" movs r5, #4 \n"/* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r2] \n"/* Program RNR = 4. */ " str r5, [r2] \n"/* Program RNR = 4. */
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n"/* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r2] \n"/* Program RNR = 5. */ " str r5, [r2] \n"/* Program RNR = 5. */
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n"/* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r2] \n"/* Program RNR = 6. */ " str r5, [r2] \n"/* Program RNR = 6. */
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n"/* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r2] \n"/* Program RNR = 7. */ " str r5, [r2] \n"/* Program RNR = 7. */
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n"/* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r4 \n"/* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -137,19 +137,19 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -159,13 +159,13 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n"/* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -175,13 +175,13 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n"/* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -191,20 +191,20 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -214,11 +214,11 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, PRIMASK \n" " mrs r0, PRIMASK \n"
" cpsid i \n" " cpsid i \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -228,10 +228,10 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr PRIMASK, r0 \n" " msr PRIMASK, r0 \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -241,181 +241,181 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ " ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/ " ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
" mrs r2, psp \n"/* Read PSP in r2. */ " mrs r2, psp \n"/* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n"/* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n"/* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n"/* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ " subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */ " adds r2, r2, #16 \n"/* r2 = r2 + 16. */
" stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */ " stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r2, r2, #48 \n"/* r2 = r2 - 48. */ " subs r2, r2, #48 \n"/* r2 = r2 - 48. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ " stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
" str r4, [r3] \n"/* Disable MPU. */ " str r4, [r3] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */ " ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r3] \n"/* Program MAIR0. */ " str r4, [r3] \n"/* Program MAIR0. */
" ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */ " ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r5, #4 \n"/* r5 = 4. */ " movs r5, #4 \n"/* r5 = 4. */
" str r5, [r4] \n"/* Program RNR = 4. */ " str r5, [r4] \n"/* Program RNR = 4. */
" ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
" movs r5, #5 \n"/* r5 = 5. */ " movs r5, #5 \n"/* r5 = 5. */
" str r5, [r4] \n"/* Program RNR = 5. */ " str r5, [r4] \n"/* Program RNR = 5. */
" ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
" movs r5, #6 \n"/* r5 = 6. */ " movs r5, #6 \n"/* r5 = 6. */
" str r5, [r4] \n"/* Program RNR = 6. */ " str r5, [r4] \n"/* Program RNR = 6. */
" ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
" movs r5, #7 \n"/* r5 = 7. */ " movs r5, #7 \n"/* r5 = 7. */
" str r5, [r4] \n"/* Program RNR = 7. */ " str r5, [r4] \n"/* Program RNR = 7. */
" ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" movs r5, #1 \n"/* r5 = 1. */ " movs r5, #1 \n"/* r5 = 1. */
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
" str r4, [r3] \n"/* Enable MPU. */ " str r4, [r3] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ " ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" adds r2, r2, #16 \n"/* Move to the high registers. */ " adds r2, r2, #16 \n"/* Move to the high registers. */
" ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ " ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n"/* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n"/* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n"/* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n"/* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" subs r2, r2, #32 \n"/* Go back to the low registers. */ " subs r2, r2, #32 \n"/* Go back to the low registers. */
" ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */ " ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -425,22 +425,22 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" movs r0, #4 \n" " movs r0, #4 \n"
" mov r1, lr \n" " mov r1, lr \n"
" tst r0, r1 \n" " tst r0, r1 \n"
" beq stacking_used_msp \n" " beq stacking_used_msp \n"
" mrs r0, psp \n" " mrs r0, psp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" stacking_used_msp: \n" " stacking_used_msp: \n"
" mrs r0, msp \n" " mrs r0, msp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -449,10 +449,10 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" svc %0 \n"/* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
@ -462,16 +462,16 @@ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PR
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */ " ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */ " ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ " cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" bne free_secure_context \n"/* Branch if r1 != 0. */ " bne free_secure_context \n"/* Branch if r1 != 0. */
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */ " bx lr \n"/* There is no secure context (xSecureContext is NULL). */
" free_secure_context: \n" " free_secure_context: \n"
" svc %0 \n"/* Secure context is freed in the supervisor call. */ " svc %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -48,81 +48,81 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n"/* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n"/* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n"/* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n"/* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n"/* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n"/* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" bx r2 \n"/* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -132,19 +132,19 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */ " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" running_privileged: \n" " running_privileged: \n"
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -154,13 +154,13 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" bics r0, r1 \n"/* Clear the bit 0. */ " bics r0, r1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -170,13 +170,13 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" movs r1, #1 \n"/* r1 = 1. */ " movs r1, #1 \n"/* r1 = 1. */
" orrs r0, r1 \n"/* r0 = r0 | r1. */ " orrs r0, r1 \n"/* r0 = r0 | r1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "r1", "memory" ::: "r0", "r1", "memory"
); );
} }
@ -186,20 +186,20 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -209,11 +209,11 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, PRIMASK \n" " mrs r0, PRIMASK \n"
" cpsid i \n" " cpsid i \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -223,10 +223,10 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr PRIMASK, r0 \n" " msr PRIMASK, r0 \n"
" bx lr \n" " bx lr \n"
::: "memory" ::: "memory"
); );
} }
@ -236,121 +236,121 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n"/* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ " stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */ " subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r2, psplim \n"/* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ " stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
" mov r4, r8 \n"/* r4 = r8. */ " mov r4, r8 \n"/* r4 = r8. */
" mov r5, r9 \n"/* r5 = r9. */ " mov r5, r9 \n"/* r5 = r9. */
" mov r6, r10 \n"/* r6 = r10. */ " mov r6, r10 \n"/* r6 = r10. */
" mov r7, r11 \n"/* r7 = r11. */ " mov r7, r11 \n"/* r7 = r11. */
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" cpsid i \n" " cpsid i \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" cpsie i \n" " cpsie i \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
" movs r4, #5 \n"/* r4 = 5. */ " movs r4, #5 \n"/* r4 = 5. */
" str r4, [r2] \n"/* Program RNR = 5. */ " str r4, [r2] \n"/* Program RNR = 5. */
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
" movs r4, #6 \n"/* r4 = 6. */ " movs r4, #6 \n"/* r4 = 6. */
" str r4, [r2] \n"/* Program RNR = 6. */ " str r4, [r2] \n"/* Program RNR = 6. */
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
" movs r4, #7 \n"/* r4 = 7. */ " movs r4, #7 \n"/* r4 = 7. */
" str r4, [r2] \n"/* Program RNR = 7. */ " str r4, [r2] \n"/* Program RNR = 7. */
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */ " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */ " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" movs r4, #1 \n"/* r4 = 1. */ " movs r4, #1 \n"/* r4 = 1. */
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" adds r0, r0, #28 \n"/* Move to the high registers. */ " adds r0, r0, #28 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n"/* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n"/* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n"/* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n"/* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #44 \n"/* Move to the starting of the saved context. */ " subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
" bx r3 \n" " bx r3 \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" adds r0, r0, #24 \n"/* Move to the high registers. */ " adds r0, r0, #24 \n"/* Move to the high registers. */
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
" mov r8, r4 \n"/* r8 = r4. */ " mov r8, r4 \n"/* r8 = r4. */
" mov r9, r5 \n"/* r9 = r5. */ " mov r9, r5 \n"/* r9 = r5. */
" mov r10, r6 \n"/* r10 = r6. */ " mov r10, r6 \n"/* r10 = r6. */
" mov r11, r7 \n"/* r11 = r7. */ " mov r11, r7 \n"/* r11 = r7. */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" subs r0, r0, #40 \n"/* Move to the starting of the saved context. */ " subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
" ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ " ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
" bx r3 \n" " bx r3 \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -360,22 +360,22 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" movs r0, #4 \n" " movs r0, #4 \n"
" mov r1, lr \n" " mov r1, lr \n"
" tst r0, r1 \n" " tst r0, r1 \n"
" beq stacking_used_msp \n" " beq stacking_used_msp \n"
" mrs r0, psp \n" " mrs r0, psp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" stacking_used_msp: \n" " stacking_used_msp: \n"
" mrs r0, msp \n" " mrs r0, msp \n"
" ldr r2, svchandler_address_const \n" " ldr r2, svchandler_address_const \n"
" bx r2 \n" " bx r2 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -225,19 +225,19 @@ static void prvTaskExitError( void )
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
" ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
" ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n"/* Restore the task stack pointer. */ " msr psp, r0 \n"/* Restore the task stack pointer. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" orr r14, #0xd \n" " orr r14, #0xd \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -245,17 +245,17 @@ void vPortSVCHandler( void )
static void prvPortStartFirstTask( void ) static void prvPortStartFirstTask( void )
{ {
__asm volatile ( __asm volatile (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc 0 \n"/* System call to start first task. */ " svc 0 \n"/* System call to start first task. */
" nop \n" " nop \n"
" .ltorg \n" " .ltorg \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -403,32 +403,32 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \n" " isb \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" stmdb r0!, {r4-r11} \n"/* Save the remaining registers. */ " stmdb r0!, {r4-r11} \n"/* Save the remaining registers. */
" str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
" \n" " \n"
" stmdb sp!, {r3, r14} \n" " stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n" " ldmia sp!, {r3, r14} \n"
" \n"/* Restore the context, including the critical nesting count. */ " \n"/* Restore the context, including the critical nesting count. */
" ldr r1, [r3] \n" " ldr r1, [r3] \n"
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n"/* Pop the registers. */ " ldmia r0!, {r4-r11} \n"/* Pop the registers. */
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n" " isb \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
@ -728,10 +728,10 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
* be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.

View file

@ -199,10 +199,10 @@
__asm volatile __asm volatile
( (
" mov %0, %1 \n"\ " mov %0, %1 \n"\
" msr basepri, %0 \n"\ " msr basepri, %0 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -215,11 +215,11 @@
__asm volatile __asm volatile
( (
" mrs %0, basepri \n"\ " mrs %0, basepri \n"\
" mov %1, %2 \n"\ " mov %1, %2 \n"\
" msr basepri, %1 \n"\ " msr basepri, %1 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
@ -233,7 +233,7 @@
{ {
__asm volatile __asm volatile
( (
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -44,88 +44,88 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */ " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r2] \n"/* Program RNR = 8. */ " str r4, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r2] \n"/* Program RNR = 12. */ " str r4, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n"/* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r4 \n"/* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -135,16 +135,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -154,12 +154,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -169,12 +169,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -184,21 +184,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -208,14 +208,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -225,12 +225,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -240,180 +240,180 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ " ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
" mrs r2, psp \n"/* Read PSP in r2. */ " mrs r2, psp \n"/* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n"/* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n"/* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n"/* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB.*/ " ldr r1, [r3] \n"/* Read pxCurrentTCB.*/
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ " subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */ " adds r2, r2, #16 \n"/* r2 = r2 + 16. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r2, r2, #16 \n"/* r2 = r2 - 16. */ " subs r2, r2, #16 \n"/* r2 = r2 - 16. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n"/* r2 = r2 + 12. */ " adds r2, r2, #12 \n"/* r2 = r2 + 12. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n"/* r2 = r2 - 12. */ " subs r2, r2, #12 \n"/* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r3] \n"/* Disable MPU. */ " str r4, [r3] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */ " ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r3] \n"/* Program MAIR0. */ " str r4, [r3] \n"/* Program MAIR0. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r3] \n"/* Program RNR = 4. */ " str r4, [r3] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r3] \n"/* Program RNR = 8. */ " str r4, [r3] \n"/* Program RNR = 8. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r3] \n"/* Program RNR = 12. */ " str r4, [r3] \n"/* Program RNR = 12. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r3] \n"/* Enable MPU. */ " str r4, [r3] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ " ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -424,17 +424,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -443,10 +443,10 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" svc %0 \n"/* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
@ -456,14 +456,14 @@ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PR
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */ " ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */ " ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ " cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" it ne \n" " it ne \n"
" svcne %0 \n"/* Secure context is freed in the supervisor call. */ " svcne %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -44,83 +44,83 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r2 \n"/* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -130,16 +130,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -149,12 +149,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -164,12 +164,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -179,21 +179,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -203,14 +203,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -220,12 +220,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -235,110 +235,110 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n"/* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ " stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" mrs r2, psplim \n"/* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" \n" " \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" bx r3 \n" " bx r3 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -349,17 +349,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -239,14 +239,14 @@ void vPortSVCHandler( void )
__asm volatile __asm volatile
( (
#ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
#else #else
" mrs r0, psp \n" " mrs r0, psp \n"
#endif #endif
" b %0 \n" " b %0 \n"
::"i" ( prvSVCHandler ) : "r0", "memory" ::"i" ( prvSVCHandler ) : "r0", "memory"
); );
} }
@ -306,9 +306,9 @@ static void prvSVCHandler( uint32_t * pulParam )
{ {
__asm volatile __asm volatile
( (
" mrs r1, control \n"/* Obtain current control value. */ " mrs r1, control \n"/* Obtain current control value. */
" bic r1, #1 \n"/* Set privilege bit. */ " bic r1, #1 \n"/* Set privilege bit. */
" msr control, r1 \n"/* Write back new control value. */ " msr control, r1 \n"/* Write back new control value. */
::: "r1", "memory" ::: "r1", "memory"
); );
} }
@ -318,9 +318,9 @@ static void prvSVCHandler( uint32_t * pulParam )
case portSVC_RAISE_PRIVILEGE: case portSVC_RAISE_PRIVILEGE:
__asm volatile __asm volatile
( (
" mrs r1, control \n"/* Obtain current control value. */ " mrs r1, control \n"/* Obtain current control value. */
" bic r1, #1 \n"/* Set privilege bit. */ " bic r1, #1 \n"/* Set privilege bit. */
" msr control, r1 \n"/* Write back new control value. */ " msr control, r1 \n"/* Write back new control value. */
::: "r1", "memory" ::: "r1", "memory"
); );
break; break;
@ -336,42 +336,42 @@ static void prvRestoreContextOfFirstTask( void )
{ {
__asm volatile __asm volatile
( (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
" ldr r1, [r3] \n" " ldr r1, [r3] \n"
" ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */
" \n" " \n"
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */
" stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */
" \n" " \n"
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
" \n" " \n"
" ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */
" msr control, r3 \n" " msr control, r3 \n"
" msr psp, r0 \n"/* Restore the task stack pointer. */ " msr psp, r0 \n"/* Restore the task stack pointer. */
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldr r14, =0xfffffffd \n"/* Load exec return code. */ " ldr r14, =0xfffffffd \n"/* Load exec return code. */
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -466,17 +466,17 @@ BaseType_t xPortStartScheduler( void )
/* Start the first task. */ /* Start the first task. */
__asm volatile ( __asm volatile (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start first task. */ " svc %0 \n"/* System call to start first task. */
" nop \n" " nop \n"
" .ltorg \n" " .ltorg \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ); ::"i" ( portSVC_START_SCHEDULER ) : "memory" );
/* Should not get here! */ /* Should not get here! */
@ -567,54 +567,54 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" mrs r1, control \n" " mrs r1, control \n"
" stmdb r0!, {r1, r4-r11} \n"/* Save the remaining registers. */ " stmdb r0!, {r1, r4-r11} \n"/* Save the remaining registers. */
" str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
" \n" " \n"
" stmdb sp!, {r3, r14} \n" " stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n" " ldmia sp!, {r3, r14} \n"
" \n"/* Restore the context. */ " \n"/* Restore the context. */
" ldr r1, [r3] \n" " ldr r1, [r3] \n"
" ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */
" \n" " \n"
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */
" stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */
" \n" " \n"
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
" \n" " \n"
" ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */
" msr control, r3 \n" " msr control, r3 \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
@ -745,14 +745,14 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -762,10 +762,10 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -887,10 +887,10 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
* be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.

View file

@ -120,7 +120,7 @@
/* Scheduler utilities. */ /* Scheduler utilities. */
#define portYIELD() __asm volatile ( " SVC %0 \n"::"i" ( portSVC_YIELD ) : "memory" ) #define portYIELD() __asm volatile ( " SVC %0 \n"::"i" ( portSVC_YIELD ) : "memory" )
#define portYIELD_WITHIN_API() \ #define portYIELD_WITHIN_API() \
{ \ { \
/* Set a PendSV to request a context switch. */ \ /* Set a PendSV to request a context switch. */ \
@ -256,10 +256,10 @@
__asm volatile __asm volatile
( (
" mov %0, %1 \n"\ " mov %0, %1 \n"\
" msr basepri, %0 \n"\ " msr basepri, %0 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -272,11 +272,11 @@
__asm volatile __asm volatile
( (
" mrs %0, basepri \n"\ " mrs %0, basepri \n"\
" mov %1, %2 \n"\ " mov %1, %2 \n"\
" msr basepri, %1 \n"\ " msr basepri, %1 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
@ -290,7 +290,7 @@
{ {
__asm volatile __asm volatile
( (
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -250,18 +250,18 @@ static void prvTaskExitError( void )
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
" ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
" ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n"/* Restore the task stack pointer. */ " msr psp, r0 \n"/* Restore the task stack pointer. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -273,19 +273,19 @@ static void prvPortStartFirstTask( void )
* would otherwise result in the unnecessary leaving of space in the SVC stack * would otherwise result in the unnecessary leaving of space in the SVC stack
* for lazy saving of FPU registers. */ * for lazy saving of FPU registers. */
__asm volatile ( __asm volatile (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */
" msr control, r0 \n" " msr control, r0 \n"
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc 0 \n"/* System call to start first task. */ " svc 0 \n"/* System call to start first task. */
" nop \n" " nop \n"
" .ltorg \n" " .ltorg \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -445,52 +445,52 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \n" " isb \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n" " vstmdbeq r0!, {s16-s31} \n"
" \n" " \n"
" stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */
" str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
" \n" " \n"
" stmdb sp!, {r0, r3} \n" " stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldmia sp!, {r0, r3} \n" " ldmia sp!, {r0, r3} \n"
" \n" " \n"
" ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n" " ldr r0, [r1] \n"
" \n" " \n"
" ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */
" \n" " \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n" " vldmiaeq r0!, {s16-s31} \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n" " isb \n"
" \n" " \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
#if WORKAROUND_PMU_CM001 == 1 #if WORKAROUND_PMU_CM001 == 1
" push { r14 } \n" " push { r14 } \n"
" pop { pc } \n" " pop { pc } \n"
#endif #endif
#endif #endif
" \n" " \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
@ -767,13 +767,13 @@ static void vPortEnableVFP( void )
{ {
__asm volatile __asm volatile
( (
" ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */
" ldr r1, [r0] \n" " ldr r1, [r0] \n"
" \n" " \n"
" orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */
" str r1, [r0] \n" " str r1, [r0] \n"
" bx r14 \n" " bx r14 \n"
" .ltorg \n" " .ltorg \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -806,10 +806,10 @@ static void vPortEnableVFP( void )
* be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.

View file

@ -197,10 +197,10 @@
__asm volatile __asm volatile
( (
" mov %0, %1 \n"\ " mov %0, %1 \n"\
" msr basepri, %0 \n"\ " msr basepri, %0 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -213,11 +213,11 @@
__asm volatile __asm volatile
( (
" mrs %0, basepri \n"\ " mrs %0, basepri \n"\
" mov %1, %2 \n"\ " mov %1, %2 \n"\
" msr basepri, %1 \n"\ " msr basepri, %1 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
@ -231,7 +231,7 @@
{ {
__asm volatile __asm volatile
( (
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -265,14 +265,14 @@ void vPortSVCHandler( void )
__asm volatile __asm volatile
( (
#ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
#else #else
" mrs r0, psp \n" " mrs r0, psp \n"
#endif #endif
" b %0 \n" " b %0 \n"
::"i" ( prvSVCHandler ) : "r0", "memory" ::"i" ( prvSVCHandler ) : "r0", "memory"
); );
} }
@ -331,9 +331,9 @@ static void prvSVCHandler( uint32_t * pulParam )
{ {
__asm volatile __asm volatile
( (
" mrs r1, control \n"/* Obtain current control value. */ " mrs r1, control \n"/* Obtain current control value. */
" bic r1, #1 \n"/* Set privilege bit. */ " bic r1, #1 \n"/* Set privilege bit. */
" msr control, r1 \n"/* Write back new control value. */ " msr control, r1 \n"/* Write back new control value. */
::: "r1", "memory" ::: "r1", "memory"
); );
} }
@ -343,9 +343,9 @@ static void prvSVCHandler( uint32_t * pulParam )
case portSVC_RAISE_PRIVILEGE: case portSVC_RAISE_PRIVILEGE:
__asm volatile __asm volatile
( (
" mrs r1, control \n"/* Obtain current control value. */ " mrs r1, control \n"/* Obtain current control value. */
" bic r1, #1 \n"/* Set privilege bit. */ " bic r1, #1 \n"/* Set privilege bit. */
" msr control, r1 \n"/* Write back new control value. */ " msr control, r1 \n"/* Write back new control value. */
::: "r1", "memory" ::: "r1", "memory"
); );
break; break;
@ -361,48 +361,48 @@ static void prvRestoreContextOfFirstTask( void )
{ {
__asm volatile __asm volatile
( (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
" ldr r1, [r3] \n" " ldr r1, [r3] \n"
" ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */
" \n" " \n"
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
#endif /* configTOTAL_MPU_REGIONS == 16. */ #endif /* configTOTAL_MPU_REGIONS == 16. */
" \n" " \n"
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
" \n" " \n"
" ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */
" msr control, r3 \n" " msr control, r3 \n"
" msr psp, r0 \n"/* Restore the task stack pointer. */ " msr psp, r0 \n"/* Restore the task stack pointer. */
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -518,19 +518,19 @@ BaseType_t xPortStartScheduler( void )
* would otherwise result in the unnecessary leaving of space in the SVC stack * would otherwise result in the unnecessary leaving of space in the SVC stack
* for lazy saving of FPU registers. */ * for lazy saving of FPU registers. */
__asm volatile ( __asm volatile (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */
" msr control, r0 \n" " msr control, r0 \n"
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start first task. */ " svc %0 \n"/* System call to start first task. */
" nop \n" " nop \n"
" .ltorg \n" " .ltorg \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ); ::"i" ( portSVC_START_SCHEDULER ) : "memory" );
/* Should not get here! */ /* Should not get here! */
@ -621,76 +621,76 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \n" " isb \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n" " vstmdbeq r0!, {s16-s31} \n"
" \n" " \n"
" mrs r1, control \n" " mrs r1, control \n"
" stmdb r0!, {r1, r4-r11, r14} \n"/* Save the remaining registers. */ " stmdb r0!, {r1, r4-r11, r14} \n"/* Save the remaining registers. */
" str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
" \n" " \n"
" stmdb sp!, {r0, r3} \n" " stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
" cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
#endif #endif
" msr basepri, r0 \n" " msr basepri, r0 \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
" cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
#endif #endif
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldmia sp!, {r0, r3} \n" " ldmia sp!, {r0, r3} \n"
" \n"/* Restore the context. */ " \n"/* Restore the context. */
" ldr r1, [r3] \n" " ldr r1, [r3] \n"
" ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */
" \n" " \n"
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
" str r3, [r2] \n"/* Disable MPU. */ " str r3, [r2] \n"/* Disable MPU. */
" \n" " \n"
" ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
" stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
#endif /* configTOTAL_MPU_REGIONS == 16. */ #endif /* configTOTAL_MPU_REGIONS == 16. */
" \n" " \n"
" ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
" str r3, [r2] \n"/* Enable MPU. */ " str r3, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
" \n" " \n"
" ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */
" msr control, r3 \n" " msr control, r3 \n"
" \n" " \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n" " vldmiaeq r0!, {s16-s31} \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .ltorg \n"/* Assemble the current literal pool to avoid offset-out-of-bound errors with lto. */ " .ltorg \n"/* Assemble the current literal pool to avoid offset-out-of-bound errors with lto. */
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
@ -734,13 +734,13 @@ static void vPortEnableVFP( void )
{ {
__asm volatile __asm volatile
( (
" ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */
" ldr r1, [r0] \n" " ldr r1, [r0] \n"
" \n" " \n"
" orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */
" str r1, [r0] \n" " str r1, [r0] \n"
" bx r14 \n" " bx r14 \n"
" .ltorg \n" " .ltorg \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -856,14 +856,14 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -873,10 +873,10 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }

View file

@ -210,7 +210,7 @@ typedef struct MPU_SETTINGS
/* Scheduler utilities. */ /* Scheduler utilities. */
#define portYIELD() __asm volatile ( " SVC %0 \n"::"i" ( portSVC_YIELD ) : "memory" ) #define portYIELD() __asm volatile ( " SVC %0 \n"::"i" ( portSVC_YIELD ) : "memory" )
#define portYIELD_WITHIN_API() \ #define portYIELD_WITHIN_API() \
{ \ { \
/* Set a PendSV to request a context switch. */ \ /* Set a PendSV to request a context switch. */ \
@ -346,15 +346,15 @@ portFORCE_INLINE static void vPortRaiseBASEPRI( void )
__asm volatile __asm volatile
( (
" mov %0, %1 \n" " mov %0, %1 \n"
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
" cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
#endif #endif
" msr basepri, %0 \n" " msr basepri, %0 \n"
" isb \n" " isb \n"
" dsb \n" " dsb \n"
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
" cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
#endif #endif
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
@ -368,16 +368,16 @@ portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
__asm volatile __asm volatile
( (
" mrs %0, basepri \n" " mrs %0, basepri \n"
" mov %1, %2 \n" " mov %1, %2 \n"
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
" cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
#endif #endif
" msr basepri, %1 \n" " msr basepri, %1 \n"
" isb \n" " isb \n"
" dsb \n" " dsb \n"
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
" cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
#endif #endif
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
@ -392,7 +392,7 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{ {
__asm volatile __asm volatile
( (
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -44,88 +44,88 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */ " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r2] \n"/* Program RNR = 8. */ " str r4, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r2] \n"/* Program RNR = 12. */ " str r4, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n"/* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r4 \n"/* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -135,16 +135,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -154,12 +154,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -169,12 +169,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -184,21 +184,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -208,14 +208,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -225,12 +225,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -240,180 +240,180 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ " ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
" mrs r2, psp \n"/* Read PSP in r2. */ " mrs r2, psp \n"/* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n"/* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n"/* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n"/* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB.*/ " ldr r1, [r3] \n"/* Read pxCurrentTCB.*/
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ " subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */ " adds r2, r2, #16 \n"/* r2 = r2 + 16. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r2, r2, #16 \n"/* r2 = r2 - 16. */ " subs r2, r2, #16 \n"/* r2 = r2 - 16. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n"/* r2 = r2 + 12. */ " adds r2, r2, #12 \n"/* r2 = r2 + 12. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n"/* r2 = r2 - 12. */ " subs r2, r2, #12 \n"/* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r3] \n"/* Disable MPU. */ " str r4, [r3] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */ " ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r3] \n"/* Program MAIR0. */ " str r4, [r3] \n"/* Program MAIR0. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r3] \n"/* Program RNR = 4. */ " str r4, [r3] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r3] \n"/* Program RNR = 8. */ " str r4, [r3] \n"/* Program RNR = 8. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r3] \n"/* Program RNR = 12. */ " str r4, [r3] \n"/* Program RNR = 12. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r3] \n"/* Enable MPU. */ " str r4, [r3] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ " ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -424,17 +424,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -443,10 +443,10 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" svc %0 \n"/* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
@ -456,14 +456,14 @@ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PR
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */ " ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */ " ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ " cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" it ne \n" " it ne \n"
" svcne %0 \n"/* Secure context is freed in the supervisor call. */ " svcne %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -44,83 +44,83 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r2 \n"/* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -130,16 +130,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -149,12 +149,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -164,12 +164,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -179,21 +179,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -203,14 +203,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -220,12 +220,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -235,110 +235,110 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n"/* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ " stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" mrs r2, psplim \n"/* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" \n" " \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" bx r3 \n" " bx r3 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -349,17 +349,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -244,18 +244,18 @@ static void prvTaskExitError( void )
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
" ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
" ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n"/* Restore the task stack pointer. */ " msr psp, r0 \n"/* Restore the task stack pointer. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -267,19 +267,19 @@ static void prvPortStartFirstTask( void )
* would otherwise result in the unnecessary leaving of space in the SVC stack * would otherwise result in the unnecessary leaving of space in the SVC stack
* for lazy saving of FPU registers. */ * for lazy saving of FPU registers. */
__asm volatile ( __asm volatile (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */
" msr control, r0 \n" " msr control, r0 \n"
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc 0 \n"/* System call to start first task. */ " svc 0 \n"/* System call to start first task. */
" nop \n" " nop \n"
" .ltorg \n" " .ltorg \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -433,54 +433,54 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \n" " isb \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
" \n" " \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n" " vstmdbeq r0!, {s16-s31} \n"
" \n" " \n"
" stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */
" str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
" \n" " \n"
" stmdb sp!, {r0, r3} \n" " stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
" cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
" msr basepri, r0 \n" " msr basepri, r0 \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" ldmia sp!, {r0, r3} \n" " ldmia sp!, {r0, r3} \n"
" \n" " \n"
" ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n" " ldr r0, [r1] \n"
" \n" " \n"
" ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */
" \n" " \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n" " vldmiaeq r0!, {s16-s31} \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n" " isb \n"
" \n" " \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
#if WORKAROUND_PMU_CM001 == 1 #if WORKAROUND_PMU_CM001 == 1
" push { r14 } \n" " push { r14 } \n"
" pop { pc } \n" " pop { pc } \n"
#endif #endif
#endif #endif
" \n" " \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
} }
@ -757,13 +757,13 @@ static void vPortEnableVFP( void )
{ {
__asm volatile __asm volatile
( (
" ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */
" ldr r1, [r0] \n" " ldr r1, [r0] \n"
" \n" " \n"
" orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */
" str r1, [r0] \n" " str r1, [r0] \n"
" bx r14 \n" " bx r14 \n"
" .ltorg \n" " .ltorg \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -796,10 +796,10 @@ static void vPortEnableVFP( void )
* be set to a value equal to or numerically *higher* than * be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* Interrupts that use the FreeRTOS API must not be left at their * Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority, * default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid. * and therefore also guaranteed to be invalid.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. * interrupt entry is as fast and simple as possible.

View file

@ -197,12 +197,12 @@
__asm volatile __asm volatile
( (
" mov %0, %1 \n"\ " mov %0, %1 \n"\
" cpsid i \n"\ " cpsid i \n"\
" msr basepri, %0 \n"\ " msr basepri, %0 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
" cpsie i \n"\ " cpsie i \n"\
: "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -215,13 +215,13 @@
__asm volatile __asm volatile
( (
" mrs %0, basepri \n"\ " mrs %0, basepri \n"\
" mov %1, %2 \n"\ " mov %1, %2 \n"\
" cpsid i \n"\ " cpsid i \n"\
" msr basepri, %1 \n"\ " msr basepri, %1 \n"\
" isb \n"\ " isb \n"\
" dsb \n"\ " dsb \n"\
" cpsie i \n"\ " cpsie i \n"\
: "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
@ -235,7 +235,7 @@
{ {
__asm volatile __asm volatile
( (
" msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -44,88 +44,88 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */ " ldr r3, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r2] \n"/* Program MAIR0. */ " str r4, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r2] \n"/* Program RNR = 4. */ " str r4, [r2] \n"/* Program RNR = 4. */
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r2] \n"/* Program RNR = 8. */ " str r4, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r2] \n"/* Program RNR = 12. */ " str r4, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
" ldr r5, xSecureContextConst2 \n" " ldr r5, xSecureContextConst2 \n"
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" msr control, r3 \n"/* Set this task's CONTROL value. */ " msr control, r3 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r4 \n"/* Finally, branch to EXC_RETURN. */ " bx r4 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, xSecureContextConst2 \n" " ldr r4, xSecureContextConst2 \n"
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */ " msr psplim, r2 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
"xSecureContextConst2: .word xSecureContext \n" "xSecureContextConst2: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -135,16 +135,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -154,12 +154,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -169,12 +169,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -184,21 +184,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -208,14 +208,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -225,12 +225,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -240,180 +240,180 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" .extern SecureContext_SaveContext \n" " .extern SecureContext_SaveContext \n"
" .extern SecureContext_LoadContext \n" " .extern SecureContext_LoadContext \n"
" \n" " \n"
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ " ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
" mrs r2, psp \n"/* Read PSP in r2. */ " mrs r2, psp \n"/* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n"/* No secure context to save. */ " cbz r0, save_ns_context \n"/* No secure context to save. */
" push {r0-r2, r14} \n" " push {r0-r2, r14} \n"
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n"/* LR is now in r3. */ " pop {r0-r3} \n"/* LR is now in r3. */
" mov lr, r3 \n"/* LR = r3. */ " mov lr, r3 \n"/* LR = r3. */
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB.*/ " ldr r1, [r3] \n"/* Read pxCurrentTCB.*/
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ " subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" b select_next_task \n" " b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ " subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */ " adds r2, r2, #16 \n"/* r2 = r2 + 16. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r3, control \n"/* r3 = CONTROL. */ " mrs r3, control \n"/* r3 = CONTROL. */
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
" subs r2, r2, #16 \n"/* r2 = r2 - 16. */ " subs r2, r2, #16 \n"/* r2 = r2 - 16. */
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ " stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
" str r2, [r1] \n"/* Save the new top of stack in TCB. */ " str r2, [r1] \n"/* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n"/* r2 = r2 + 12. */ " adds r2, r2, #12 \n"/* r2 = r2 + 12. */
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */ " stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n"/* r2 = r2 - 12. */ " subs r2, r2, #12 \n"/* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ " stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r3] \n"/* Disable MPU. */ " str r4, [r3] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */ " ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
" str r4, [r3] \n"/* Program MAIR0. */ " str r4, [r3] \n"/* Program MAIR0. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #4 \n"/* r4 = 4. */ " movs r4, #4 \n"/* r4 = 4. */
" str r4, [r3] \n"/* Program RNR = 4. */ " str r4, [r3] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #8 \n"/* r4 = 8. */ " movs r4, #8 \n"/* r4 = 8. */
" str r4, [r3] \n"/* Program RNR = 8. */ " str r4, [r3] \n"/* Program RNR = 8. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */ " ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
" movs r4, #12 \n"/* r4 = 12. */ " movs r4, #12 \n"/* r4 = 12. */
" str r4, [r3] \n"/* Program RNR = 12. */ " str r4, [r3] \n"/* Program RNR = 12. */
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r3] \n"/* Enable MPU. */ " str r4, [r3] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */ " ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */ " msr control, r3 \n"/* Restore the CONTROL register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n"/* Restore the task's xSecureContext. */ " str r0, [r3] \n"/* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */ " ldr r1, [r3] \n"/* Read pxCurrentTCB. */
" push {r2, r4} \n" " push {r2, r4} \n"
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r2, r4} \n"
" mov lr, r4 \n"/* LR = r4. */ " mov lr, r4 \n"/* LR = r4. */
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ " lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ " bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" msr psp, r2 \n"/* Remember the new top of stack for the task. */ " msr psp, r2 \n"/* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
"xSecureContextConst: .word xSecureContext \n" "xSecureContextConst: .word xSecureContext \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -424,17 +424,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -443,10 +443,10 @@ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" svc %0 \n"/* Secure context is allocated in the supervisor call. */ " svc %0 \n"/* Secure context is allocated in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
); );
} }
@ -456,14 +456,14 @@ void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PR
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */ " ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */ " ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ " cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
" it ne \n" " it ne \n"
" svcne %0 \n"/* Secure context is freed in the supervisor call. */ " svcne %0 \n"/* Secure context is freed in the supervisor call. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
); );
} }

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -44,83 +44,83 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" msr control, r2 \n"/* Set this task's CONTROL value. */ " msr control, r2 \n"/* Set this task's CONTROL value. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r3 \n"/* Finally, branch to EXC_RETURN. */ " bx r3 \n"/* Finally, branch to EXC_RETURN. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */ " msr psplim, r1 \n"/* Set this task's PSPLIM value. */
" movs r1, #2 \n"/* r1 = 2. */ " movs r1, #2 \n"/* r1 = 2. */
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
" adds r0, #32 \n"/* Discard everything up to r0. */ " adds r0, #32 \n"/* Discard everything up to r0. */
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
" isb \n" " isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */ " msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
" bx r2 \n"/* Finally, branch to EXC_RETURN. */ " bx r2 \n"/* Finally, branch to EXC_RETURN. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst2: .word 0xe000ed94 \n" "xMPUCTRLConst2: .word 0xe000ed94 \n"
"xMAIR0Const2: .word 0xe000edc0 \n" "xMAIR0Const2: .word 0xe000edc0 \n"
"xRNRConst2: .word 0xe000ed98 \n" "xRNRConst2: .word 0xe000ed98 \n"
"xRBARConst2: .word 0xe000ed9c \n" "xRBARConst2: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
); );
} }
@ -130,16 +130,16 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
" ite ne \n" " ite ne \n"
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
" \n" " \n"
" .align 4 \n" " .align 4 \n"
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -149,12 +149,12 @@ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* Read the CONTROL register. */ " mrs r0, control \n"/* Read the CONTROL register. */
" bic r0, #1 \n"/* Clear the bit 0. */ " bic r0, #1 \n"/* Clear the bit 0. */
" msr control, r0 \n"/* Write back the new CONTROL value. */ " msr control, r0 \n"/* Write back the new CONTROL value. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -164,12 +164,12 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, control \n"/* r0 = CONTROL. */ " mrs r0, control \n"/* r0 = CONTROL. */
" orr r0, #1 \n"/* r0 = r0 | 1. */ " orr r0, #1 \n"/* r0 = r0 | 1. */
" msr control, r0 \n"/* CONTROL = r0. */ " msr control, r0 \n"/* CONTROL = r0. */
" bx lr \n"/* Return to the caller. */ " bx lr \n"/* Return to the caller. */
::: "r0", "memory" ::: "r0", "memory"
); );
} }
@ -179,21 +179,21 @@ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
" cpsie i \n"/* Globally enable interrupts. */ " cpsie i \n"/* Globally enable interrupts. */
" cpsie f \n" " cpsie f \n"
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" svc %0 \n"/* System call to start the first task. */ " svc %0 \n"/* System call to start the first task. */
" nop \n" " nop \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"xVTORConst: .word 0xe000ed08 \n" "xVTORConst: .word 0xe000ed08 \n"
::"i" ( portSVC_START_SCHEDULER ) : "memory" ::"i" ( portSVC_START_SCHEDULER ) : "memory"
); );
} }
@ -203,14 +203,14 @@ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCT
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
); );
} }
@ -220,12 +220,12 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" msr basepri, r0 \n"/* basepri = ulMask. */ " msr basepri, r0 \n"/* basepri = ulMask. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bx lr \n"/* Return. */ " bx lr \n"/* Return. */
::: "memory" ::: "memory"
); );
} }
@ -235,110 +235,110 @@ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" mrs r0, psp \n"/* Read PSP in r0. */ " mrs r0, psp \n"/* Read PSP in r0. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" mrs r1, psplim \n"/* r1 = PSPLIM. */ " mrs r1, psplim \n"/* r1 = PSPLIM. */
" mrs r2, control \n"/* r2 = CONTROL. */ " mrs r2, control \n"/* r2 = CONTROL. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ " stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" mrs r2, psplim \n"/* r2 = PSPLIM. */ " mrs r2, psplim \n"/* r2 = PSPLIM. */
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" str r0, [r1] \n"/* Save the new top of stack in TCB. */ " str r0, [r1] \n"/* Save the new top of stack in TCB. */
" \n" " \n"
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
" dsb \n" " dsb \n"
" isb \n" " isb \n"
" bl vTaskSwitchContext \n" " bl vTaskSwitchContext \n"
" mov r0, #0 \n"/* r0 = 0. */ " mov r0, #0 \n"/* r0 = 0. */
" msr basepri, r0 \n"/* Enable interrupts. */ " msr basepri, r0 \n"/* Enable interrupts. */
" \n" " \n"
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */ " ldr r1, [r2] \n"/* Read pxCurrentTCB. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" dmb \n"/* Complete outstanding transfers before disabling MPU. */ " dmb \n"/* Complete outstanding transfers before disabling MPU. */
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
" str r4, [r2] \n"/* Disable MPU. */ " str r4, [r2] \n"/* Disable MPU. */
" \n" " \n"
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
" str r3, [r2] \n"/* Program MAIR0. */ " str r3, [r2] \n"/* Program MAIR0. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #4 \n"/* r3 = 4. */ " movs r3, #4 \n"/* r3 = 4. */
" str r3, [r2] \n"/* Program RNR = 4. */ " str r3, [r2] \n"/* Program RNR = 4. */
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" \n" " \n"
#if ( configTOTAL_MPU_REGIONS == 16 ) #if ( configTOTAL_MPU_REGIONS == 16 )
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #8 \n"/* r3 = 8. */ " movs r3, #8 \n"/* r3 = 8. */
" str r3, [r2] \n"/* Program RNR = 8. */ " str r3, [r2] \n"/* Program RNR = 8. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
" movs r3, #12 \n"/* r3 = 12. */ " movs r3, #12 \n"/* r3 = 12. */
" str r3, [r2] \n"/* Program RNR = 12. */ " str r3, [r2] \n"/* Program RNR = 12. */
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
#endif /* configTOTAL_MPU_REGIONS == 16 */ #endif /* configTOTAL_MPU_REGIONS == 16 */
" \n" " \n"
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
" str r4, [r2] \n"/* Enable MPU. */ " str r4, [r2] \n"/* Enable MPU. */
" dsb \n"/* Force memory writes before continuing. */ " dsb \n"/* Force memory writes before continuing. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n" " \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */ " msr control, r2 \n"/* Restore the CONTROL register value for the task. */
#else /* configENABLE_MPU */ #else /* configENABLE_MPU */
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
" msr psp, r0 \n"/* Remember the new top of stack for the task. */ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
" bx r3 \n" " bx r3 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n" "pxCurrentTCBConst: .word pxCurrentTCB \n"
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
"xMPUCTRLConst: .word 0xe000ed94 \n" "xMPUCTRLConst: .word 0xe000ed94 \n"
"xMAIR0Const: .word 0xe000edc0 \n" "xMAIR0Const: .word 0xe000edc0 \n"
"xRNRConst: .word 0xe000ed98 \n" "xRNRConst: .word 0xe000ed98 \n"
"xRBARConst: .word 0xe000ed9c \n" "xRBARConst: .word 0xe000ed9c \n"
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
); );
@ -349,17 +349,17 @@ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
{ {
__asm volatile __asm volatile
( (
" .syntax unified \n" " .syntax unified \n"
" \n" " \n"
" tst lr, #4 \n" " tst lr, #4 \n"
" ite eq \n" " ite eq \n"
" mrseq r0, msp \n" " mrseq r0, msp \n"
" mrsne r0, psp \n" " mrsne r0, psp \n"
" ldr r1, svchandler_address_const \n" " ldr r1, svchandler_address_const \n"
" bx r1 \n" " bx r1 \n"
" \n" " \n"
" .align 4 \n" " .align 4 \n"
"svchandler_address_const: .word vPortSVCHandler_C \n" "svchandler_address_const: .word vPortSVCHandler_C \n"
); );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -155,9 +155,9 @@
* 8-bit values encoded as follows: * 8-bit values encoded as follows:
* Bit[7:4] - 0000 - Device Memory * Bit[7:4] - 0000 - Device Memory
* Bit[3:2] - 00 --> Device-nGnRnE * Bit[3:2] - 00 --> Device-nGnRnE
* 01 --> Device-nGnRE * 01 --> Device-nGnRE
* 10 --> Device-nGRE * 10 --> Device-nGRE
* 11 --> Device-GRE * 11 --> Device-GRE
* Bit[1:0] - 00, Reserved. * Bit[1:0] - 00, Reserved.
*/ */
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */

View file

@ -131,8 +131,8 @@
{ \ { \
portCPU_IRQ_DISABLE(); \ portCPU_IRQ_DISABLE(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm volatile ( "DSB \n" \ __asm volatile ( "DSB \n" \
"ISB \n"); \ "ISB \n"); \
portCPU_IRQ_ENABLE(); \ portCPU_IRQ_ENABLE(); \
} }
@ -407,7 +407,7 @@ BaseType_t xPortStartScheduler( void )
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Interrupts are turned off in the CPU itself to ensure tick does /* Interrupts are turned off in the CPU itself to ensure tick does
* not execute while the scheduler is being started. Interrupts are * not execute while the scheduler is being started. Interrupts are
* automatically turned back on in the CPU when the first task starts * automatically turned back on in the CPU when the first task starts
* executing. */ * executing. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
@ -489,8 +489,8 @@ void FreeRTOS_Tick_Handler( void )
* updated. */ * updated. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
"isb \n"::: "memory" ); "isb \n"::: "memory" );
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
@ -516,7 +516,7 @@ void FreeRTOS_Tick_Handler( void )
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" ); __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
} }
#endif /* configUSE_TASK_FPU_SUPPORT */ #endif /* configUSE_TASK_FPU_SUPPORT */
@ -548,8 +548,8 @@ uint32_t ulPortSetInterruptMask( void )
{ {
ulReturn = pdFALSE; ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
"isb \n"::: "memory" ); "isb \n"::: "memory" );
} }
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();

View file

@ -26,110 +26,110 @@
* *
*/ */
.text .text
.arm .arm
.set SYS_MODE, 0x1f .set SYS_MODE, 0x1f
.set SVC_MODE, 0x13 .set SVC_MODE, 0x13
.set IRQ_MODE, 0x12 .set IRQ_MODE, 0x12
/* Hardware registers. */ /* Hardware registers. */
.extern ulICCIAR .extern ulICCIAR
.extern ulICCEOIR .extern ulICCEOIR
.extern ulICCPMR .extern ulICCPMR
/* Variables and functions. */ /* Variables and functions. */
.extern ulMaxAPIPriorityMask .extern ulMaxAPIPriorityMask
.extern _freertos_vector_table .extern _freertos_vector_table
.extern pxCurrentTCB .extern pxCurrentTCB
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vApplicationIRQHandler .extern vApplicationIRQHandler
.extern ulPortInterruptNesting .extern ulPortInterruptNesting
.extern ulPortTaskHasFPUContext .extern ulPortTaskHasFPUContext
.global FreeRTOS_IRQ_Handler .global FreeRTOS_IRQ_Handler
.global FreeRTOS_SWI_Handler .global FreeRTOS_SWI_Handler
.global vPortRestoreTaskContext .global vPortRestoreTaskContext
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
/* Save the LR and SPSR onto the system mode stack before switching to /* Save the LR and SPSR onto the system mode stack before switching to
system mode to save the remaining system mode registers. */ system mode to save the remaining system mode registers. */
SRSDB sp!, #SYS_MODE SRSDB sp!, #SYS_MODE
CPS #SYS_MODE CPS #SYS_MODE
PUSH {R0-R12, R14} PUSH {R0-R12, R14}
/* Push the critical nesting count. */ /* Push the critical nesting count. */
LDR R2, ulCriticalNestingConst LDR R2, ulCriticalNestingConst
LDR R1, [R2] LDR R1, [R2]
PUSH {R1} PUSH {R1}
/* Does the task have a floating point context that needs saving? If /* Does the task have a floating point context that needs saving? If
ulPortTaskHasFPUContext is 0 then no. */ ulPortTaskHasFPUContext is 0 then no. */
LDR R2, ulPortTaskHasFPUContextConst LDR R2, ulPortTaskHasFPUContextConst
LDR R3, [R2] LDR R3, [R2]
CMP R3, #0 CMP R3, #0
/* Save the floating point context, if any. */ /* Save the floating point context, if any. */
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
/*VPUSHNE {D16-D31}*/ /*VPUSHNE {D16-D31}*/
PUSHNE {R1} PUSHNE {R1}
/* Save ulPortTaskHasFPUContext itself. */ /* Save ulPortTaskHasFPUContext itself. */
PUSH {R3} PUSH {R3}
/* Save the stack pointer in the TCB. */ /* Save the stack pointer in the TCB. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R1, [R0] LDR R1, [R0]
STR SP, [R1] STR SP, [R1]
.endm .endm
; /**********************************************************************/ ; /**********************************************************************/
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
/* Set the SP to point to the stack of the task being restored. */ /* Set the SP to point to the stack of the task being restored. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R1, [R0] LDR R1, [R0]
LDR SP, [R1] LDR SP, [R1]
/* Is there a floating point context to restore? If the restored /* Is there a floating point context to restore? If the restored
ulPortTaskHasFPUContext is zero then no. */ ulPortTaskHasFPUContext is zero then no. */
LDR R0, ulPortTaskHasFPUContextConst LDR R0, ulPortTaskHasFPUContextConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
CMP R1, #0 CMP R1, #0
/* Restore the floating point context, if any. */ /* Restore the floating point context, if any. */
POPNE {R0} POPNE {R0}
/*VPOPNE {D16-D31}*/ /*VPOPNE {D16-D31}*/
VPOPNE {D0-D15} VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
/* Restore the critical section nesting depth. */ /* Restore the critical section nesting depth. */
LDR R0, ulCriticalNestingConst LDR R0, ulCriticalNestingConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
/* Ensure the priority mask is correct for the critical nesting depth. */ /* Ensure the priority mask is correct for the critical nesting depth. */
LDR R2, ulICCPMRConst LDR R2, ulICCPMRConst
LDR R2, [R2] LDR R2, [R2]
CMP R1, #0 CMP R1, #0
MOVEQ R4, #255 MOVEQ R4, #255
LDRNE R4, ulMaxAPIPriorityMaskConst LDRNE R4, ulMaxAPIPriorityMaskConst
LDRNE R4, [R4] LDRNE R4, [R4]
STR R4, [R2] STR R4, [R2]
/* Restore all system mode registers other than the SP (which is already /* Restore all system mode registers other than the SP (which is already
being used). */ being used). */
POP {R0-R12, R14} POP {R0-R12, R14}
/* Return to the task code, loading CPSR on the way. */ /* Return to the task code, loading CPSR on the way. */
RFEIA sp! RFEIA sp!
.endm .endm
@ -140,11 +140,11 @@
.align 4 .align 4
.type FreeRTOS_SWI_Handler, %function .type FreeRTOS_SWI_Handler, %function
FreeRTOS_SWI_Handler: FreeRTOS_SWI_Handler:
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
@ -152,115 +152,115 @@ FreeRTOS_SWI_Handler:
*****************************************************************************/ *****************************************************************************/
.type vPortRestoreTaskContext, %function .type vPortRestoreTaskContext, %function
vPortRestoreTaskContext: vPortRestoreTaskContext:
/* Switch to system mode. */ /* Switch to system mode. */
CPS #SYS_MODE CPS #SYS_MODE
portRESTORE_CONTEXT portRESTORE_CONTEXT
.align 4 .align 4
.type FreeRTOS_IRQ_Handler, %function .type FreeRTOS_IRQ_Handler, %function
FreeRTOS_IRQ_Handler: FreeRTOS_IRQ_Handler:
/* Return to the interrupted instruction. */ /* Return to the interrupted instruction. */
SUB lr, lr, #4 SUB lr, lr, #4
/* Push the return address and SPSR. */ /* Push the return address and SPSR. */
PUSH {lr} PUSH {lr}
MRS lr, SPSR MRS lr, SPSR
PUSH {lr} PUSH {lr}
/* Change to supervisor mode to allow reentry. */ /* Change to supervisor mode to allow reentry. */
CPS #SVC_MODE CPS #SVC_MODE
/* Push used registers. */ /* Push used registers. */
PUSH {r0-r4, r12} PUSH {r0-r4, r12}
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting /* Increment nesting count. r3 holds the address of ulPortInterruptNesting
for future use. r1 holds the original ulPortInterruptNesting value for for future use. r1 holds the original ulPortInterruptNesting value for
future use. */ future use. */
LDR r3, ulPortInterruptNestingConst LDR r3, ulPortInterruptNestingConst
LDR r1, [r3] LDR r1, [r3]
ADD r4, r1, #1 ADD r4, r1, #1
STR r4, [r3] STR r4, [r3]
/* Read value from the interrupt acknowledge register, which is stored in r0 /* Read value from the interrupt acknowledge register, which is stored in r0
for future parameter and interrupt clearing use. */ for future parameter and interrupt clearing use. */
LDR r2, ulICCIARConst LDR r2, ulICCIARConst
LDR r2, [r2] LDR r2, [r2]
LDR r0, [r2] LDR r0, [r2]
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for /* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
future use. _RB_ Is this ever needed provided the start of the stack is future use. _RB_ Is this ever needed provided the start of the stack is
alligned on an 8-byte boundary? */ alligned on an 8-byte boundary? */
MOV r2, sp MOV r2, sp
AND r2, r2, #4 AND r2, r2, #4
SUB sp, sp, r2 SUB sp, sp, r2
/* Call the interrupt handler. */ /* Call the interrupt handler. */
PUSH {r0-r4, lr} PUSH {r0-r4, lr}
LDR r1, vApplicationIRQHandlerConst LDR r1, vApplicationIRQHandlerConst
BLX r1 BLX r1
POP {r0-r4, lr} POP {r0-r4, lr}
ADD sp, sp, r2 ADD sp, sp, r2
CPSID i CPSID i
DSB DSB
ISB ISB
/* Write the value read from ICCIAR to ICCEOIR. */ /* Write the value read from ICCIAR to ICCEOIR. */
LDR r4, ulICCEOIRConst LDR r4, ulICCEOIRConst
LDR r4, [r4] LDR r4, [r4]
STR r0, [r4] STR r0, [r4]
/* Restore the old nesting count. */ /* Restore the old nesting count. */
STR r1, [r3] STR r1, [r3]
/* A context switch is never performed if the nesting count is not 0. */ /* A context switch is never performed if the nesting count is not 0. */
CMP r1, #0 CMP r1, #0
BNE exit_without_switch BNE exit_without_switch
/* Did the interrupt request a context switch? r1 holds the address of /* Did the interrupt request a context switch? r1 holds the address of
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
use. */ use. */
LDR r1, =ulPortYieldRequired LDR r1, =ulPortYieldRequired
LDR r0, [r1] LDR r0, [r1]
CMP r0, #0 CMP r0, #0
BNE switch_before_exit BNE switch_before_exit
exit_without_switch: exit_without_switch:
/* No context switch. Restore used registers, LR_irq and SPSR before /* No context switch. Restore used registers, LR_irq and SPSR before
returning. */ returning. */
POP {r0-r4, r12} POP {r0-r4, r12}
CPS #IRQ_MODE CPS #IRQ_MODE
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
MOVS PC, LR MOVS PC, LR
switch_before_exit: switch_before_exit:
/* A context swtich is to be performed. Clear the context switch pending /* A context swtich is to be performed. Clear the context switch pending
flag. */ flag. */
MOV r0, #0 MOV r0, #0
STR r0, [r1] STR r0, [r1]
/* Restore used registers, LR-irq and SPSR before saving the context /* Restore used registers, LR-irq and SPSR before saving the context
to the task stack. */ to the task stack. */
POP {r0-r4, r12} POP {r0-r4, r12}
CPS #IRQ_MODE CPS #IRQ_MODE
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
portSAVE_CONTEXT portSAVE_CONTEXT
/* Call the function that selects the new task to execute. /* Call the function that selects the new task to execute.
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
instructions, or 8 byte aligned stack allocated data. LR does not need instructions, or 8 byte aligned stack allocated data. LR does not need
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */ saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
/* Restore the context of, and branch to, the task selected to execute /* Restore the context of, and branch to, the task selected to execute
next. */ next. */
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
* If the application provides an implementation of vApplicationIRQHandler(), * If the application provides an implementation of vApplicationIRQHandler(),
@ -284,22 +284,22 @@ switch_before_exit:
.weak vApplicationIRQHandler .weak vApplicationIRQHandler
.type vApplicationIRQHandler, %function .type vApplicationIRQHandler, %function
vApplicationIRQHandler: vApplicationIRQHandler:
PUSH {LR} PUSH {LR}
FMRX R1, FPSCR FMRX R1, FPSCR
VPUSH {D0-D15} VPUSH {D0-D15}
PUSH {R1} PUSH {R1}
LDR r1, vApplicationFPUSafeIRQHandlerConst LDR r1, vApplicationFPUSafeIRQHandlerConst
BLX r1 BLX r1
POP {R0} POP {R0}
VPOP {D0-D15} VPOP {D0-D15}
VMSR FPSCR, R0 VMSR FPSCR, R0
POP {PC} POP {PC}
ulICCIARConst: .word ulICCIAR ulICCIARConst: .word ulICCIAR
ulICCEOIRConst: .word ulICCEOIR ulICCEOIRConst: .word ulICCEOIR
ulICCPMRConst: .word ulICCPMR ulICCPMRConst: .word ulICCPMR
pxCurrentTCBConst: .word pxCurrentTCB pxCurrentTCBConst: .word pxCurrentTCB
ulCriticalNestingConst: .word ulCriticalNesting ulCriticalNestingConst: .word ulCriticalNesting
@ -311,8 +311,3 @@ ulPortInterruptNestingConst: .word ulPortInterruptNesting
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
.end .end

View file

@ -34,50 +34,50 @@
#include "task.h" #include "task.h"
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt. #error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.
#endif #endif
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt. #error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x1F ) #define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user /* The value of the mode bits in the APSR when the CPU is executing in user
mode. */ mode. */
#define portAPSR_USER_MODE ( 0x10 ) #define portAPSR_USER_MODE ( 0x10 )
/* Let the user override the pre-loading of the initial LR with the address of /* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */ debugger. */
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
#define portTASK_RETURN_ADDRESS prvTaskExitError #define portTASK_RETURN_ADDRESS prvTaskExitError
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -123,87 +123,87 @@ __attribute__(( used )) const uint32_t ulICCEOIR = configEOI_ADDRESS;
*/ */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. expected by the portRESTORE_CONTEXT() macro.
The fist real value on the stack is the status register, which is set for The fist real value on the stack is the status register, which is set for
system mode, with interrupts enabled. A few NULLs are added first to ensure system mode, with interrupts enabled. A few NULLs are added first to ensure
GDB does not try decoding a non-existent return address. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{ {
/* The task will start in THUMB mode. */ /* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack |= portTHUMB_MODE_BIT;
} }
pxTopOfStack--; pxTopOfStack--;
/* Next the return address, which in this case is the start of the task. */ /* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
/* Next all the registers other than the stack pointer. */ /* Next all the registers other than the stack pointer. */
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */ any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ). should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */ defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; ); for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -211,78 +211,78 @@ BaseType_t xPortStartScheduler( void )
{ {
uint32_t ulAPSR; uint32_t ulAPSR;
/* Only continue if the CPU is not in User mode. The CPU must be in a /* Only continue if the CPU is not in User mode. The CPU must be in a
Privileged mode for the scheduler to start. */ Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) :: "memory" );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
if( ulAPSR != portAPSR_USER_MODE ) if( ulAPSR != portAPSR_USER_MODE )
{ {
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Start the first task executing. */ /* Start the first task executing. */
vPortRestoreTaskContext(); vPortRestoreTaskContext();
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /* Will only get here if vTaskStartScheduler() was called with the CPU in
a non-privileged mode or the binary point register was not set to its lowest a non-privileged mode or the binary point register was not set to its lowest
possible value. prvTaskExitError() is referenced to prevent a compiler possible value. prvTaskExitError() is referenced to prevent a compiler
warning about it being defined but not referenced in the case that the user warning about it being defined but not referenced in the case that the user
defines their own exit address. */ defines their own exit address. */
( void ) prvTaskExitError; ( void ) prvTaskExitError;
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */ Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */ assert function also uses a critical section. */
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
exited. */ exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */ priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */ should be unmasked. */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -290,17 +290,17 @@ void FreeRTOS_Tick_Handler( void )
{ {
uint32_t ulInterruptStatus; uint32_t ulInterruptStatus;
ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ulPortYieldRequired = pdTRUE; ulPortYieldRequired = pdTRUE;
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus );
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -308,13 +308,11 @@ void vPortTaskUsesFPU( void )
{ {
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" ); __asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) : "memory" );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,103 +26,103 @@
* *
*/ */
.text .text
.arm .arm
.set SYS_MODE, 0x1f .set SYS_MODE, 0x1f
.set SVC_MODE, 0x13 .set SVC_MODE, 0x13
.set IRQ_MODE, 0x12 .set IRQ_MODE, 0x12
/* Variables and functions. */ /* Variables and functions. */
.extern ulMaxAPIPriorityMask .extern ulMaxAPIPriorityMask
.extern _freertos_vector_table .extern _freertos_vector_table
.extern pxCurrentTCB .extern pxCurrentTCB
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vApplicationIRQHandler .extern vApplicationIRQHandler
.extern ulPortInterruptNesting .extern ulPortInterruptNesting
.extern ulPortTaskHasFPUContext .extern ulPortTaskHasFPUContext
.extern ulICCEOIR .extern ulICCEOIR
.extern ulPortYieldRequired .extern ulPortYieldRequired
.global FreeRTOS_IRQ_Handler .global FreeRTOS_IRQ_Handler
.global FreeRTOS_SVC_Handler .global FreeRTOS_SVC_Handler
.global vPortRestoreTaskContext .global vPortRestoreTaskContext
.macro portSAVE_CONTEXT .macro portSAVE_CONTEXT
/* Save the LR and SPSR onto the system mode stack before switching to /* Save the LR and SPSR onto the system mode stack before switching to
system mode to save the remaining system mode registers. */ system mode to save the remaining system mode registers. */
SRSDB sp!, #SYS_MODE SRSDB sp!, #SYS_MODE
CPS #SYS_MODE CPS #SYS_MODE
PUSH {R0-R12, R14} PUSH {R0-R12, R14}
/* Push the critical nesting count. */ /* Push the critical nesting count. */
LDR R2, ulCriticalNestingConst LDR R2, ulCriticalNestingConst
LDR R1, [R2] LDR R1, [R2]
PUSH {R1} PUSH {R1}
/* Does the task have a floating point context that needs saving? If /* Does the task have a floating point context that needs saving? If
ulPortTaskHasFPUContext is 0 then no. */ ulPortTaskHasFPUContext is 0 then no. */
LDR R2, ulPortTaskHasFPUContextConst LDR R2, ulPortTaskHasFPUContextConst
LDR R3, [R2] LDR R3, [R2]
CMP R3, #0 CMP R3, #0
/* Save the floating point context, if any. */ /* Save the floating point context, if any. */
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
#if configFPU_D32 == 1 #if configFPU_D32 == 1
VPUSHNE {D16-D31} VPUSHNE {D16-D31}
#endif /* configFPU_D32 */ #endif /* configFPU_D32 */
PUSHNE {R1} PUSHNE {R1}
/* Save ulPortTaskHasFPUContext itself. */ /* Save ulPortTaskHasFPUContext itself. */
PUSH {R3} PUSH {R3}
/* Save the stack pointer in the TCB. */ /* Save the stack pointer in the TCB. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R1, [R0] LDR R1, [R0]
STR SP, [R1] STR SP, [R1]
.endm .endm
; /**********************************************************************/ ; /**********************************************************************/
.macro portRESTORE_CONTEXT .macro portRESTORE_CONTEXT
/* Set the SP to point to the stack of the task being restored. */ /* Set the SP to point to the stack of the task being restored. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
LDR R1, [R0] LDR R1, [R0]
LDR SP, [R1] LDR SP, [R1]
/* Is there a floating point context to restore? If the restored /* Is there a floating point context to restore? If the restored
ulPortTaskHasFPUContext is zero then no. */ ulPortTaskHasFPUContext is zero then no. */
LDR R0, ulPortTaskHasFPUContextConst LDR R0, ulPortTaskHasFPUContextConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
CMP R1, #0 CMP R1, #0
/* Restore the floating point context, if any. */ /* Restore the floating point context, if any. */
POPNE {R0} POPNE {R0}
#if configFPU_D32 == 1 #if configFPU_D32 == 1
VPOPNE {D16-D31} VPOPNE {D16-D31}
#endif /* configFPU_D32 */ #endif /* configFPU_D32 */
VPOPNE {D0-D15} VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
/* Restore the critical section nesting depth. */ /* Restore the critical section nesting depth. */
LDR R0, ulCriticalNestingConst LDR R0, ulCriticalNestingConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
/* Restore all system mode registers other than the SP (which is already /* Restore all system mode registers other than the SP (which is already
being used). */ being used). */
POP {R0-R12, R14} POP {R0-R12, R14}
/* Return to the task code, loading CPSR on the way. */ /* Return to the task code, loading CPSR on the way. */
RFEIA sp! RFEIA sp!
.endm .endm
@ -133,11 +133,11 @@
.align 4 .align 4
.type FreeRTOS_SVC_Handler, %function .type FreeRTOS_SVC_Handler, %function
FreeRTOS_SVC_Handler: FreeRTOS_SVC_Handler:
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
portRESTORE_CONTEXT portRESTORE_CONTEXT
/****************************************************************************** /******************************************************************************
@ -146,109 +146,109 @@ FreeRTOS_SVC_Handler:
.align 4 .align 4
.type vPortRestoreTaskContext, %function .type vPortRestoreTaskContext, %function
vPortRestoreTaskContext: vPortRestoreTaskContext:
/* Switch to system mode. */ /* Switch to system mode. */
CPS #SYS_MODE CPS #SYS_MODE
portRESTORE_CONTEXT portRESTORE_CONTEXT
.align 4 .align 4
.type FreeRTOS_IRQ_Handler, %function .type FreeRTOS_IRQ_Handler, %function
FreeRTOS_IRQ_Handler: FreeRTOS_IRQ_Handler:
/* Return to the interrupted instruction. */ /* Return to the interrupted instruction. */
SUB lr, lr, #4 SUB lr, lr, #4
/* Push the return address and SPSR. */ /* Push the return address and SPSR. */
PUSH {lr} PUSH {lr}
MRS lr, SPSR MRS lr, SPSR
PUSH {lr} PUSH {lr}
/* Change to supervisor mode to allow reentry. */ /* Change to supervisor mode to allow reentry. */
CPS #0x13 CPS #0x13
/* Push used registers. */ /* Push used registers. */
PUSH {r0-r3, r12} PUSH {r0-r3, r12}
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting /* Increment nesting count. r3 holds the address of ulPortInterruptNesting
for future use. r1 holds the original ulPortInterruptNesting value for for future use. r1 holds the original ulPortInterruptNesting value for
future use. */ future use. */
LDR r3, ulPortInterruptNestingConst LDR r3, ulPortInterruptNestingConst
LDR r1, [r3] LDR r1, [r3]
ADD r0, r1, #1 ADD r0, r1, #1
STR r0, [r3] STR r0, [r3]
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for /* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
future use. */ future use. */
MOV r0, sp MOV r0, sp
AND r2, r0, #4 AND r2, r0, #4
SUB sp, sp, r2 SUB sp, sp, r2
/* Call the interrupt handler. */ /* Call the interrupt handler. */
PUSH {r0-r3, lr} PUSH {r0-r3, lr}
LDR r1, vApplicationIRQHandlerConst LDR r1, vApplicationIRQHandlerConst
BLX r1 BLX r1
POP {r0-r3, lr} POP {r0-r3, lr}
ADD sp, sp, r2 ADD sp, sp, r2
CPSID i CPSID i
DSB DSB
ISB ISB
/* Write to the EOI register. */ /* Write to the EOI register. */
LDR r0, ulICCEOIRConst LDR r0, ulICCEOIRConst
LDR r2, [r0] LDR r2, [r0]
STR r0, [r2] STR r0, [r2]
/* Restore the old nesting count. */ /* Restore the old nesting count. */
STR r1, [r3] STR r1, [r3]
/* A context switch is never performed if the nesting count is not 0. */ /* A context switch is never performed if the nesting count is not 0. */
CMP r1, #0 CMP r1, #0
BNE exit_without_switch BNE exit_without_switch
/* Did the interrupt request a context switch? r1 holds the address of /* Did the interrupt request a context switch? r1 holds the address of
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
use. */ use. */
LDR r1, ulPortYieldRequiredConst LDR r1, ulPortYieldRequiredConst
LDR r0, [r1] LDR r0, [r1]
CMP r0, #0 CMP r0, #0
BNE switch_before_exit BNE switch_before_exit
exit_without_switch: exit_without_switch:
/* No context switch. Restore used registers, LR_irq and SPSR before /* No context switch. Restore used registers, LR_irq and SPSR before
returning. */ returning. */
POP {r0-r3, r12} POP {r0-r3, r12}
CPS #IRQ_MODE CPS #IRQ_MODE
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
MOVS PC, LR MOVS PC, LR
switch_before_exit: switch_before_exit:
/* A context swtich is to be performed. Clear the context switch pending /* A context swtich is to be performed. Clear the context switch pending
flag. */ flag. */
MOV r0, #0 MOV r0, #0
STR r0, [r1] STR r0, [r1]
/* Restore used registers, LR-irq and SPSR before saving the context /* Restore used registers, LR-irq and SPSR before saving the context
to the task stack. */ to the task stack. */
POP {r0-r3, r12} POP {r0-r3, r12}
CPS #IRQ_MODE CPS #IRQ_MODE
POP {LR} POP {LR}
MSR SPSR_cxsf, LR MSR SPSR_cxsf, LR
POP {LR} POP {LR}
portSAVE_CONTEXT portSAVE_CONTEXT
/* Call the function that selects the new task to execute. /* Call the function that selects the new task to execute.
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
instructions, or 8 byte aligned stack allocated data. LR does not need instructions, or 8 byte aligned stack allocated data. LR does not need
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */ saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
/* Restore the context of, and branch to, the task selected to execute /* Restore the context of, and branch to, the task selected to execute
next. */ next. */
portRESTORE_CONTEXT portRESTORE_CONTEXT
ulICCEOIRConst: .word ulICCEOIR ulICCEOIRConst: .word ulICCEOIR
pxCurrentTCBConst: .word pxCurrentTCB pxCurrentTCBConst: .word pxCurrentTCB
ulCriticalNestingConst: .word ulCriticalNesting ulCriticalNestingConst: .word ulCriticalNesting
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
@ -258,8 +258,3 @@ ulPortInterruptNestingConst: .word ulPortInterruptNesting
ulPortYieldRequiredConst: .word ulPortYieldRequired ulPortYieldRequiredConst: .word ulPortYieldRequired
.end .end

Some files were not shown because too many files have changed in this diff Show more