#define portINITIAL_XPSR ( 0x01000000 )\r
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )\r
\r
+/* Let the user override the pre-loading of the initial LR with the address of\r
+prvTaskExitError() in case is messes up unwinding of the stack in the\r
+debugger. */\r
+#ifdef configTASK_RETURN_ADDRESS\r
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS\r
+#else\r
+ #define portTASK_RETURN_ADDRESS prvTaskExitError\r
+#endif\r
+\r
/* The priority used by the kernel is assigned to a variable to make access\r
from inline assembler easier. */\r
const unsigned long ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY;\r
extern void vPortEnableVFP( void );\r
extern void vPortStartFirstTask( void );\r
\r
+/*\r
+ * Used to catch tasks that attempt to return from their implementing function.\r
+ */\r
+static void prvTaskExitError( void );\r
+\r
/* This exists purely to allow the const to be used from within the\r
port_asm.asm assembly file. */\r
const unsigned long ulMaxSyscallInterruptPriorityConst = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */\r
pxTopOfStack--;\r
- *pxTopOfStack = 0; /* LR */\r
+ *pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */\r
\r
/* Save code space by skipping register initialisation. */\r
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvTaskExitError( void )\r
+{\r
+ /* A function that implements a task must not exit or attempt to return to\r
+ its caller as there is nothing to return to. If a task wants to exit it \r
+ should instead call vTaskDelete( NULL ).\r
+ \r
+ Artificially force an assert() to be triggered if configASSERT() is \r
+ defined, then stop here so application writers can catch the error. */\r
+ configASSERT( ulCriticalNesting == ~0UL );\r
+ portDISABLE_INTERRUPTS(); \r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
/*\r
* See header file for description.\r
*/\r
; licensing and training services.\r
;*/\r
\r
+\r
.extern pxCurrentTCB\r
.extern vTaskSwitchContext\r
.extern ulMaxSyscallInterruptPriorityConst\r
\r
- .global PendSV_Handler\r
+ .global _vector_14\r
+ .global _lc_ref__vector_pp_14\r
.global SVC_Handler\r
.global vPortStartFirstTask\r
.global vPortEnableVFP\r
+ .global ulPortSetInterruptMask\r
+ .global vPortClearInterruptMask\r
\r
;-----------------------------------------------------------\r
\r
.section .text\r
.thumb\r
.align 4\r
-PendSV_Handler: .type func\r
+_vector_14: .type func\r
+\r
mrs r0, psp\r
\r
;Get the location of the current TCB.\r
msr psp, r0\r
bx r14\r
\r
- .size PendSV_Handler, $-PendSV_Handler\r
+ .size _vector_14, $-_vector_14\r
+ .endsec\r
+\r
+;-----------------------------------------------------------\r
+\r
+; This function is an XMC4000 silicon errata workaround. It will get used when\r
+; the SILICON_BUG_PMC_CM_001 linker macro is defined.\r
+ .section .text\r
+ .thumb\r
+ .align 4\r
+_lc_ref__vector_pp_14: .type func\r
+\r
+ mrs r0, psp\r
+\r
+ ;Get the location of the current TCB.\r
+ ldr.w r3, =pxCurrentTCB\r
+ ldr r2, [r3]\r
+\r
+ ;Is the task using the FPU context? If so, push high vfp registers.\r
+ tst r14, #0x10\r
+ it eq\r
+ vstmdbeq r0!, {s16-s31}\r
+\r
+ ;Save the core registers.\r
+ stmdb r0!, {r4-r11, r14}\r
+\r
+ ;Save the new top of stack into the first member of the TCB.\r
+ str r0, [r2]\r
+\r
+ stmdb sp!, {r3, r14}\r
+ ldr.w r0, =ulMaxSyscallInterruptPriorityConst\r
+ msr basepri, r0\r
+ bl vTaskSwitchContext\r
+ mov r0, #0\r
+ msr basepri, r0\r
+ ldmia sp!, {r3, r14}\r
+\r
+ ;The first item in pxCurrentTCB is the task top of stack.\r
+ ldr r1, [r3]\r
+ ldr r0, [r1]\r
+\r
+ ;Pop the core registers.\r
+ ldmia r0!, {r4-r11, r14}\r
+\r
+ ;Is the task using the FPU context? If so, pop the high vfp registers too.\r
+ tst r14, #0x10\r
+ it eq\r
+ vldmiaeq r0!, {s16-s31}\r
+\r
+ msr psp, r0\r
+ push { lr }\r
+ pop { pc } ; XMC4000 specific errata workaround. Do not used "bx lr" here.\r
+\r
+ .size _lc_ref__vector_pp_14, $-_lc_ref__vector_pp_14\r
.endsec\r
\r
;-----------------------------------------------------------\r
.size vPortEnableVFP, $-vPortEnableVFP\r
.endsec\r
\r
+;-----------------------------------------------------------\r
+\r
+ .section .text\r
+ .thumb\r
+ .align 4\r
+ulPortSetInterruptMask:\r
+ mrs r0, basepri\r
+ ldr.w r1, =ulMaxSyscallInterruptPriorityConst\r
+ msr basepri, r1\r
+ bx r14\r
+ .size ulPortSetInterruptMask, $-ulPortSetInterruptMask\r
+ .endsec\r
+\r
+;-----------------------------------------------------------\r
+\r
+ .section .text\r
+ .thumb\r
+ .align 4\r
+vPortClearInterruptMask:\r
+ msr basepri, r0\r
+ bx r14\r
+ .size vPortClearInterruptMask, $-vPortClearInterruptMask\r
+ .endsec\r
+\r
+;-----------------------------------------------------------\r
\r
.end\r
\r
*/\r
#define portCLEAR_INTERRUPT_MASK() __set_BASEPRI( 0 )\r
\r
-/* FAQ: Setting BASEPRI to 0 is not a bug. Please see\r
-http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMask );\r
+#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )\r
\r
\r
extern void vPortEnterCritical( void );\r