1
.macro      SAVE_CONTEXT      SWI_F
    ldr     sp,=current_p               /* switch to pcb */
    ldr     sp,[sp]                     /* get pcb ptr */
    add     sp,sp,#68                   /* point to top of stack */
.if (\SWI_F == 0)                       /* if it is not swi macro */
    sub     lr,lr,#0x04                 /* return addr */
.endif                                  /* lr -= 4 if not swi */
    stmdb   sp!,{lr}
    stmdb   sp!,{r0-r12,lr}             /* prepare to return */ 
    mrs     r1,spsr                     /* r1 <- spsr_usr */
    mrs     r2,cpsr                     /* r2 <- cpsr */
    push    {r1}                        /* save spsr_usr */
    msr     cpsr_c,#SYS_MODE|NO_INTR    /* switch to sys mode */
    mov     r3,sp                       /* r3 <- sp_usr */
    msr     cpsr,r2                     /* switch back */
    push    {r3}                        /* save sp_usr */
    mov     r0,lr                       /* r0 <-- lr */
    msr     cpsr_c,#SVC_MODE|NO_INTR    /* switch back to SVC mode */
    ldr     sp,=KERNEL_STACK            /* switch to SVC stack */
.endm

.macro      SET_ISR_PROC     ISR_PROC   /* */
    ldr     lr,=__restart               /* set return address */
    ldr     pc,=\ISR_PROC               /* call ISR */
.endm

__restart:                              /* restore context */
    ldr     sp,=current_p               /* get pcb */
    ldr     sp,[sp]                     /* adjust back to pcb */
re_restart:                             /* ret from kernel */
    pop     {r3}                        /* r3 <- sp_usr */
    mrs     r2,cpsr                     /* r2 <- cpsr */
    msr     cpsr_c,SYS_MODE|NO_INTR     /* switch to sys mode*/
    mov     sp,r3                       /* sp_usr <-- r3 */
    msr     cpsr,r2                     /* switch back */
    pop     {r1}                        /* r1 <- spsr_usr */
    msr     spsr,r1                     /* restore spsr */
    ldmia   sp!,{r0-r12,lr,pc}^         /* intr ret */

_do_irq:
    SAVE_CONTEXT    0                   /* not swi */
    SET_ISR_PROC    do_irq

this task switching code works well ON my s3c2440 board when I got just one task but when two or more tasks are created ,task0 will go to execute task1 code or task 1 execute the task0 code ,I do't know why ,any help is need !

Shruti
  • 1
  • 13
  • 55
  • 95
true_casey
  • 79
  • 1
  • 11
  • The code looks ok to me, but it all depends what's stored in `current_p`, so I'd look there. – ams May 03 '13 at 12:57
  • You have a global `current_p` and use an `ldr sp,=KERNEL_STACK`, so the code is not re-entrant. A more *normal* way is to switch the SVC stack on context switches. Then `sp_svc & 0xfffffc00` can be used to get a *current_p*. Ie, the supervisor stack is separate per process and it also hold task restore info. The *stack* plus task struct are held at 4k for standard ARM MMU page sizes; if you run without the MMU, you can use any size. You also have small pages, multiple pages, etc. You can use the `sp_irq` as a scratch register. On all entry exceptions switch to `svc` mode . – artless noise May 03 '13 at 13:21
  • +1 I see someone down voted. However, at least you tagged an ARM question that is actually ARM code. I guess someone expected a little more work to say what you have/haven't done. You should look at [entry-armv.S](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/entry-armv.S) and/or many other *open source* projects to get some ideas. **Ch 9.6.5 Context Switch** in the ARM reference manuals may also be helpful. Definitely reloading the stacks with constants defeats the purpose of the stack. Eventually you have multiple-exception needing several frames. – artless noise May 03 '13 at 13:31
  • the code is ok now atfer I saved the lr_usr at IRQ mode (restore usr_ lr when return also).the code i posted before will not work out when task call some func ,if the func is interrupted with the func not finished yet ,and clock interrupt change the current_p,the LR is not the right lr after interrupt return thanks for giving me such good advises ^_^ – true_casey May 03 '13 at 14:22

1 Answers1

1

the code is ok now atfer I saved the lr_usr at IRQ mode (restore usr_ lr when return also).the code i posted before will not work out when task call some func ,if the func is interrupted with the func not finished yet ,and clock interrupt change the current_p,the LR is not the right lr after interrupt return

true_casey
  • 79
  • 1
  • 11