]> git.sur5r.net Git - freertos/commitdiff
Add nesting support.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 4 May 2008 17:36:23 +0000 (17:36 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sun, 4 May 2008 17:36:23 +0000 (17:36 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@334 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Source/portable/MPLAB/PIC32MX/ISR_Support.h
Source/portable/MPLAB/PIC32MX/port.c

index 2ea3d4de37bac56f49dab09e09eebbb79fcd5e9c..62d5ef1e197fef4b12494d1d5fd30c0e373d478e 100644 (file)
 /******************************************************************/   \r
 .macro portSAVE_CONTEXT\r
 \r
-       /* Make room for the context. */        \r
-\r
-       /* Get interrupts above the kernel priority enabled again ASAP.  First\r
-       save the current status so we can manipulate it, and the cause and EPC\r
-       registers so we capture their original values in case of interrupt nesting. */\r
-\r
+       /* Make room for the context. First save the current status so we can \r
+       manipulate it, and the cause and EPC registers so we capture their \r
+       original values in case of interrupt nesting. */\r
        mfc0            k0, _CP0_CAUSE\r
        addiu           sp,     sp, -portCONTEXT_SIZE\r
        sw                      k0, portCAUSE_STACK_LOCATION(sp)\r
        mfc0            k1, _CP0_STATUS\r
-       /* Also save s6 so we can use it during this interrupt.  Any\r
-       nesting interrupts should maintain the values of this register\r
+\r
+       /* Also save s6 and s5 so we can use them during this interrupt.  Any\r
+       nesting interrupts should maintain the values of these registers\r
        accross the ISR. */\r
        sw                      s6, 44(sp)\r
+       sw                      s5, 40(sp)\r
        sw                      k1, portSTATUS_STACK_LOCATION(sp)\r
 \r
+       /* Enable interrupts above the current priority.  SysCall interrupts\r
+       enable priorities above configKERNEL_INTERRUPT_PRIORITY, so first \r
+       check if the interrupt was a system call (32). */\r
+       add                     s6, zero, k0\r
+       and                     s6, s6, 32\r
+       beq                     s6, zero, .+20 /* Not a system call, mask up to the current interrupt priority. */\r
+       nop\r
+       addiu           k0, zero, configKERNEL_INTERRUPT_PRIORITY /* Was a system call, mask only to kernel priority. */\r
+       beq                     zero, zero, .+12\r
+       nop\r
+       srl                     k0, k0, 0xa\r
+       ins             k1, k0, 10, 6\r
+       ins                     k1, zero, 1, 4\r
+\r
+       /* Load, incrmement, then save the interrupt nesting count. */\r
+       la                      k0, uxInterruptNesting\r
+       lw                      s6, (k0)\r
+       addiu           s6, s6, 1\r
+       sw                      s6, 0(k0)\r
+\r
+       /* If it was zero, switch to the system stack.  If it was not zero then\r
+       we are already using the system stack.  s5 holds the old stack value -\r
+       this might be used to determine the cause of a general exception. */\r
+       add                     s5, zero, sp\r
+       addiu           s6, s6, -1\r
+       bne                     zero, s6, .+20\r
+       nop\r
+       la                      s6, xISRStackTop\r
+       lw                      sp, (s6)\r
 \r
        /* s6 holds the EPC value, we may want this during the context switch. */\r
        mfc0            s6, _CP0_EPC\r
 \r
-       /* Enable interrupts above the kernel priority. */\r
-       addiu           k0, zero, configKERNEL_INTERRUPT_PRIORITY\r
-       ins             k1, k0, 10, 6\r
-       ins                     k1, zero, 1, 4\r
+       /* Re-enable interrupts. */\r
        mtc0            k1, _CP0_STATUS\r
 \r
        /* Save the context into the space just created.  s6 is saved again\r
        here as it now contains the EPC value. */\r
-       sw                      ra,     120(sp)\r
-       sw                      s8, 116(sp)\r
-       sw                      t9, 112(sp)\r
-       sw                      t8,     108(sp)\r
-       sw                      t7,     104(sp)\r
-       sw                      t6, 100(sp)\r
-       sw                      t5, 96(sp)\r
-       sw                      t4, 92(sp)\r
-       sw                      t3, 88(sp)\r
-       sw                      t2, 84(sp)\r
-       sw                      t1, 80(sp)\r
-       sw                      t0, 76(sp)\r
-       sw                      a3, 72(sp)\r
-       sw                      a2, 68(sp)\r
-       sw                      a1, 64(sp)\r
-       sw                      a0, 60(sp)\r
-       sw                      v1, 56(sp)\r
-       sw                      v0, 52(sp)\r
-       sw                      s7, 48(sp)\r
-       sw                      s6, portEPC_STACK_LOCATION(sp)\r
-       sw                      s5, 40(sp)\r
-       sw                      s4,     36(sp)\r
-       sw                      s3, 32(sp)\r
-       sw                      s2, 28(sp)\r
-       sw                      s1, 24(sp)\r
-       sw                      s0, 20(sp)\r
-       sw                      $1, 16(sp)\r
+       sw                      ra,     120(s5)\r
+       sw                      s8, 116(s5)\r
+       sw                      t9, 112(s5)\r
+       sw                      t8,     108(s5)\r
+       sw                      t7,     104(s5)\r
+       sw                      t6, 100(s5)\r
+       sw                      t5, 96(s5)\r
+       sw                      t4, 92(s5)\r
+       sw                      t3, 88(s5)\r
+       sw                      t2, 84(s5)\r
+       sw                      t1, 80(s5)\r
+       sw                      t0, 76(s5)\r
+       sw                      a3, 72(s5)\r
+       sw                      a2, 68(s5)\r
+       sw                      a1, 64(s5)\r
+       sw                      a0, 60(s5)\r
+       sw                      v1, 56(s5)\r
+       sw                      v0, 52(s5)\r
+       sw                      s7, 48(s5)\r
+       sw                      s6, portEPC_STACK_LOCATION(s5)\r
+       /* s5 has already been saved. */\r
+       sw                      s4,     36(s5)\r
+       sw                      s3, 32(s5)\r
+       sw                      s2, 28(s5)\r
+       sw                      s1, 24(s5)\r
+       sw                      s0, 20(s5)\r
+       sw                      $1, 16(s5)\r
 \r
        /* s7 is used as a scratch register. */\r
        mfhi            s7\r
-       sw                      s7, 12(sp)\r
+       sw                      s7, 12(s5)\r
        mflo            s7\r
-       sw                      s7, 8(sp)\r
+       sw                      s7, 8(s5)\r
 \r
        /* Each task maintains its own nesting count. */\r
        la                      s7, uxCriticalNesting\r
        lw                      s7, (s7)\r
-       sw                      s7, 4(sp)\r
-       \r
-       /* Update the TCB stack pointer value */\r
-       la                      s7, pxCurrentTCB\r
+       sw                      s7, 4(s5)\r
+\r
+       /* Update the TCB stack pointer value if the nesting count is 1. */\r
+       la                      s7, uxInterruptNesting\r
        lw                      s7, (s7)\r
-       sw                      sp, (s7)\r
+       addiu           s7, s7, -1\r
+       bne                     s7, zero, .+24 /* Dont save the stack pointer to the task or swap stacks. */\r
+       nop\r
 \r
-       /* Switch to the ISR stack, saving the current stack in s5.  This might\r
-       be used to determine the cause of a general exception. */\r
-       add                     s5, zero, sp\r
-       la                      s7, xISRStackTop\r
-       lw                      sp, (s7)\r
+       /* Save the stack pointer to the task. */\r
+       la                      s7, pxCurrentTCB\r
+       lw                      s7, (s7)\r
+       sw                      s5, (s7)\r
 \r
        .endm\r
        \r
 /******************************************************************/   \r
 .macro portRESTORE_CONTEXT\r
 \r
-       /* Restore the stack pointer from the TCB */\r
+       /* Restore the stack pointer from the TCB.  This is only done if the\r
+       nesting count is 1. */\r
+       la                      s7, uxInterruptNesting\r
+       lw                      s7, (s7)\r
+       addiu           s7, s7, -1\r
+       bne                     s7, zero, .+24 /* Dont load the stack pointer. */\r
+       nop\r
        la                      s0, pxCurrentTCB\r
-       lw                      s1, (s0)\r
-       lw                      sp, (s1)\r
+       lw                      s0, (s0)\r
+       lw                      s5, (s0)\r
        \r
        /* Restore the context, the first item of which is the critical nesting\r
        depth. */\r
        la                      s0, uxCriticalNesting\r
-       lw                      s1, 4(sp)\r
+       lw                      s1, 4(s5)\r
        sw                      s1, (s0)\r
 \r
        /* Restore the rest of the context. */\r
-       lw                      s0, 8(sp)\r
+       lw                      s0, 8(s5)\r
        mtlo            s0\r
-       lw                      s0, 12(sp)\r
+       lw                      s0, 12(s5)\r
        mthi            s0\r
-       lw                      $1, 16(sp)\r
-       lw                      s0, 20(sp)\r
-       lw                      s1, 24(sp)\r
-       lw                      s2, 28(sp)\r
-       lw                      s3, 32(sp)\r
-       lw                      s4, 36(sp)\r
-       lw                      s5, 40(sp)\r
-       lw                      s6, 44(sp)\r
-       lw                      s7, 48(sp)\r
-       lw                      v0, 52(sp)\r
-       lw                      v1, 56(sp)\r
-       lw                      a0, 60(sp)\r
-       lw                      a1, 64(sp)\r
-       lw                      a2, 68(sp)\r
-       lw                      a3, 72(sp)\r
-       lw                      t0, 76(sp)\r
-       lw                      t1, 80(sp)\r
-       lw                      t2, 84(sp)\r
-       lw                      t3, 88(sp)\r
-       lw                      t4, 92(sp)\r
-       lw                      t5, 96(sp)\r
-       lw                      t6, 100(sp)\r
-       lw                      t7, 104(sp)\r
-       lw                      t8, 108(sp)\r
-       lw                      t9, 112(sp)\r
-       lw                      s8, 116(sp)\r
-       lw                      ra, 120(sp)\r
-\r
-       /* Protect access to the k registers. */\r
+       lw                      $1, 16(s5)\r
+       lw                      s0, 20(s5)\r
+       lw                      s1, 24(s5)\r
+       lw                      s2, 28(s5)\r
+       lw                      s3, 32(s5)\r
+       lw                      s4, 36(s5)\r
+       /* s5 is loaded later. */\r
+       lw                      s6, 44(s5)\r
+       lw                      s7, 48(s5)\r
+       lw                      v0, 52(s5)\r
+       lw                      v1, 56(s5)\r
+       lw                      a0, 60(s5)\r
+       lw                      a1, 64(s5)\r
+       lw                      a2, 68(s5)\r
+       lw                      a3, 72(s5)\r
+       lw                      t0, 76(s5)\r
+       lw                      t1, 80(s5)\r
+       lw                      t2, 84(s5)\r
+       lw                      t3, 88(s5)\r
+       lw                      t4, 92(s5)\r
+       lw                      t5, 96(s5)\r
+       lw                      t6, 100(s5)\r
+       lw                      t7, 104(s5)\r
+       lw                      t8, 108(s5)\r
+       lw                      t9, 112(s5)\r
+       lw                      s8, 116(s5)\r
+       lw                      ra, 120(s5)\r
+\r
+       /* Protect access to the k registers, and others. */\r
        di\r
-       lw                      k1, portSTATUS_STACK_LOCATION(sp)\r
-       lw                      k0, portEPC_STACK_LOCATION(sp)\r
 \r
-       /* Leave the stack how we found it. */\r
+       /* Decrement the nesting count. */\r
+       la                      k0, uxInterruptNesting\r
+       lw                      k1, (k0)\r
+       addiu           k1, k1, -1\r
+       sw                      k1, 0(k0)\r
+\r
+       lw                      k1, portSTATUS_STACK_LOCATION(s5)\r
+       lw                      k0, portEPC_STACK_LOCATION(s5)\r
+\r
+       /* Leave the stack how we found it.  First load sp from s5, then restore\r
+       s5 from the stack. */\r
+       add                     sp, zero, s5\r
+       lw                      s5, 40(sp)\r
        addiu           sp,     sp,     portCONTEXT_SIZE\r
 \r
        mtc0            k1, _CP0_STATUS\r
index f3346b36b9f1d0c3ddb436dbec5a070e1e88d508..7e021d4c27949f81658c22e102358a7eb9a751f6 100644 (file)
@@ -51,6 +51,9 @@
  * Implementation of functions defined in portable.h for the PIC32MX port.\r
   *----------------------------------------------------------*/\r
 \r
+/* Library includes. */\r
+#include <string.h>\r
+\r
 /* Scheduler include files. */\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
@@ -71,6 +74,10 @@ the first task is being restored. */
 /* Records the nesting depth of calls to portENTER_CRITICAL(). */\r
 unsigned portBASE_TYPE uxCriticalNesting = 0x55555555;\r
 \r
+/* Records the interrupt nesting depth.  This starts at one as it will be\r
+decremented to 0 when the first task starts. */\r
+volatile unsigned portBASE_TYPE uxInterruptNesting = 0x01;\r
+\r
 /* The stack used by interrupt service routines that cause a context switch. */\r
 portSTACK_TYPE xISRStack[ configISR_STACK_SIZE ] = { 0 };\r
 \r
@@ -180,6 +187,8 @@ portBASE_TYPE xPortStartScheduler( void )
 {\r
 extern void vPortStartFirstTask( void );\r
 \r
+       memset( xISRStack, 0x5a, configISR_STACK_SIZE * sizeof( portSTACK_TYPE ) );\r
+\r
        /* Setup the timer to generate the tick.  Interrupts will have been \r
        disabled by the time we get here. */\r
        prvSetupTimerInterrupt();\r