예제 #1
0
int up_svcall(int irq, FAR void *context)
{
    uint32_t *regs = (uint32_t*)context;

    DEBUGASSERT(regs && regs == current_regs);

    /* The SVCall software interrupt is called with R0 = system call command
     * and R1..R7 =  variable number of arguments depending on the system call.
     */

    svcdbg("SVCALL Entry: regs: %p cmd: %d\n", regs, regs[REG_R0]);
    svcdbg("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
           regs[REG_R0],  regs[REG_R1],  regs[REG_R2],  regs[REG_R3],
           regs[REG_R4],  regs[REG_R5],  regs[REG_R6],  regs[REG_R7]);
    svcdbg("  R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
           regs[REG_R8],  regs[REG_R9],  regs[REG_R10], regs[REG_R11],
           regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
    svcdbg("  PSR=%08x\n", regs[REG_XPSR]);

    /* Handle the SVCall according to the command in R0 */

    switch (regs[REG_R0])
    {
    /* R0=SYS_save_context:  This is a save context command:
     *
     *   int up_saveusercontext(uint32_t *saveregs);
     *
     * At this point, the following values are saved in context:
     *
     *   R0 = SYS_save_context
     *   R1 = saveregs
     *
     * In this case, we simply need to copy the current regsters to the
     * save register space references in the saved R1 and return.
     */

    case SYS_save_context:
    {
        DEBUGASSERT(regs[REG_R1] != 0);
        memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE);
    }
    break;

    /* R0=SYS_restore_context: This a restore context command:
     *
     *   void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn));
     *
     * At this point, the following values are saved in context:
     *
     *   R0 = SYS_restore_context
     *   R1 = restoreregs
     *
     * In this case, we simply need to set current_regs to restore register
     * area referenced in the saved R1. context == current_regs is the normal
     * exception return.  By setting current_regs = context[R1], we force
     * the return to the saved context referenced in R1.
     */

    case SYS_restore_context:
    {
        DEBUGASSERT(regs[REG_R1] != 0);
        current_regs = (uint32_t*)regs[REG_R1];
    }
    break;

    /* R0=SYS_switch_context: This a switch context command:
     *
     *   void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
     *
     * At this point, the following values are saved in context:
     *
     *   R0 = 1
     *   R1 = saveregs
     *   R2 = restoreregs
     *
     * In this case, we do both: We save the context registers to the save
     * register area reference by the saved contents of R1 and then set
     * current_regs to to the save register area referenced by the saved
     * contents of R2.
     */

    case SYS_switch_context:
    {
        DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
        memcpy((uint32_t*)regs[REG_R1], regs, XCPTCONTEXT_SIZE);
        current_regs = (uint32_t*)regs[REG_R2];
    }
    break;

    /* This is not an architecture-specific system call.  If NuttX is built
     * as a standalone kernel with a system call interface, then all of the
     * additional system calls must be handled as in the default case.
     */

    default:
#ifdef CONFIG_NUTTX_KERNEL
        dispatch_syscall(regs);
#else
        slldbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
#endif
        break;
    }

    /* Report what happened.  That might difficult in the case of a context switch */

    if (regs != current_regs)
    {
        svcdbg("SVCall Return: Context switch!\n");
        svcdbg("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
               current_regs[REG_R0],  current_regs[REG_R1],  current_regs[REG_R2],  current_regs[REG_R3],
               current_regs[REG_R4],  current_regs[REG_R5],  current_regs[REG_R6],  current_regs[REG_R7]);
        svcdbg("  R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
               current_regs[REG_R8],  current_regs[REG_R9],  current_regs[REG_R10], current_regs[REG_R11],
               current_regs[REG_R12], current_regs[REG_R13], current_regs[REG_R14], current_regs[REG_R15]);
        svcdbg("  PSR=%08x\n", current_regs[REG_XPSR]);
    }
    else
    {
        svcdbg("SVCall Return: %d\n", regs[REG_R0]);
    }

    return OK;
}
예제 #2
0
int up_swint0(int irq, FAR void *context)
{
  uint32_t *regs = (uint32_t*)context;

  DEBUGASSERT(regs && regs == current_regs);

  /* Software interrupt 0 is invoked with REG_A0 (REG_R4) = system call
   * command and REG_A1-3 and REG_T0-2 (REG_R5-10) = variable number of
   * arguments depending on the system call.
   */

#ifdef DEBUG_SWINT0
  swidbg("Entry: regs: %p cmd: %d\n", regs, regs[REG_R4]);
  up_registerdump(regs);
#endif

  /* Handle the SWInt according to the command in $4 */

  switch (regs[REG_R4])
    {
      /* R4=SYS_restore_context: This a restore context command:
       *
       *   void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn));
       *
       * At this point, the following values are saved in context:
       *
       *   R4 = SYS_restore_context
       *   R5 = restoreregs
       *
       * In this case, we simply need to set current_regs to restore register
       * area referenced in the saved R1. context == current_regs is the normal
       * exception return.  By setting current_regs = context[R1], we force
       * the return to the saved context referenced in R1.
       */

      case SYS_restore_context:
        {
          DEBUGASSERT(regs[REG_A1] != 0);
          current_regs = (uint32_t*)regs[REG_A1];
        }
        break;

      /* R4=SYS_switch_context: This a switch context command:
       *
       *   void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
       *
       * At this point, the following values are saved in context:
       *
       *   R4 = SYS_switch_context
       *   R5 = saveregs
       *   R6 = restoreregs
       *
       * In this case, we save the context registers to the save register
       * area reference by the saved contents of R5 and then set
       * current_regs to to the save register area referenced by the saved
       * contents of R6.
       */

      case SYS_switch_context:
        {
          DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0);
          up_copystate((uint32_t*)regs[REG_A1], regs);
          current_regs = (uint32_t*)regs[REG_A2];
        }
        break;

      /* This is not an architecture-specify system call.  If NuttX is built
       * as a standalone kernel with a system call interface, then all of the
       * additional system calls must be handled as in the default case.
       */

      default:
#ifdef CONFIG_NUTTX_KERNEL
        dispatch_syscall(regs);
#else
        slldbg("ERROR: Bad SYS call: %d\n", regs[REG_A0]);
#endif
        break;
    }

  /* Report what happened.  That might difficult in the case of a context switch */

#ifdef DEBUG_SWINT0
  if (regs != current_regs)
    {
      swidbg("SWInt Return: Context switch!\n");
      up_registerdump(current_regs);
    }
  else
    {
      swidbg("SWInt Return: %d\n", regs[REG_V0]);
    }
#endif

  /* Clear the pending software interrupt 0 */
 
  up_clrpend_irq(PIC32MX_IRQSRC_CS0);
  
  return OK;
}