⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arch_a.s

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 S
📖 第 1 页 / 共 2 页
字号:
    mtspr   DEC,r3

    /* enable auto-reload */
    oris    r4,r4,TCR_ARE
    mtspr   TCR,r4

    /* reenable global interrupts */
    mtmsr   r7

    blr

    ENDFUNC(p_asm_setupTimerIrq)



/*----------------------------------------------------------------------------
 |
 |  FUNCTION:
 |
 |    UVAR_t p_pos_findbit(const UVAR_t bitfield, UVAR_t rrOffset);
 |
 |    Returns the number of the first set bit.
 |
 |    Note:
 |      This code is optimized, it fits into 3 cache lines.
 |
 *--------------------------------------------------------------------------*/

    .align 5     /* align to even 32 byte boundary */
p_pos_findbit:   /* input:  r3 = bitmask, r4 = offset */

    /* rotate r3 right by r4, store result in r6 */
    subfic      r5,r4,32
    rlwnm       r6,r3,r5,0,31

    /* r5 = 1 */
    addi        r5,0,1

    /* if (r6 & 0x0000FFFF == 0) { r5 |= 16; r6 >>= 16 } */
    rlwinm.     r3,r6,0,16,31
    bne         ..nzero0
    rlwinm      r6,r6,16,16,31
    ori         r5,r5,16
..nzero0:

    /* if (r6 & 0x000000FF == 0) { r5 |= 8; r6 >>= 8 } */
    rlwinm.     r3,r6,0,24,31
    bne         ..nzero1
    rlwinm      r6,r6,24,24,31
    ori         r5,r5,8
..nzero1:

    /* if (r6 & 0x0000000F == 0) { r5 |= 4; r6 >>= 4 } */
    rlwinm.     r3,r6,0,28,31
    bne         ..nzero2
    rlwinm      r6,r6,28,28,31
    ori         r5,r5,4
..nzero2:

    /* if (r6 & 0x00000003 == 0) { r5 |= 2; r6 >>= 2 } */
    rlwinm.     r3,r6,0,30,31
    bne         ..nzero3
    rlwinm      r6,r6,30,30,31
    ori         r5,r5,2
..nzero3:

    /* if (r6 & 0x00000001 != 0) { r5 &= ~1; } */
    rlwinm      r3,r6,0,31,31
    xor         r5,r5,r3

    /* return (r5 + r4) & 31; */
    add         r6,r5,r4
    rlwinm      r3,r6,0,27,31

    blr

    ENDFUNC(p_pos_findbit)




/*----------------------------------------------------------------------------
 |
 |  FUNCTION:
 |
 |    void p_pos_startFirstContext(void);
 |
 |    Starts the first task.
 |
 *--------------------------------------------------------------------------*/

    .align  2
p_pos_startFirstContext:

    /* start decrementer timer interrupt: */

    /* 1) clear decrementer interrupt status */
    addis   r3,0,TSR_DIS
    mtspr   TSR,r3

    /* 2) enable decrementer interrupt */
    mfspr   r4,TCR
    oris    r4,r4,TCR_DIE
	mtspr	TCR,r4 

    /* get stackptr:  r1 = posCurrentTask_g->stackptr */
    addis   r3,0,posCurrentTask_g@h
    ori     r3,r3,posCurrentTask_g@l
    lwzx    r4,0,r3
    lwzx    r1,0,r4

    /* pop SPRs and GPRs from stack and return from interrupt */
    ISR_EXIT

    ENDFUNC(p_pos_startFirstContext)

    /* align following code to cache line boundary,
       since the last function is used seldom */
    .align  5




/*----------------------------------------------------------------------------
 |
 |  FUNCTION:
 |
 |    void p_pos_softContextSwitch(void);
 |
 |    Does a context switch from application level.
 |
 *--------------------------------------------------------------------------*/

    .align  2
p_pos_softContextSwitch:

    /* open new stack frame, and store R0 */
    OPEN_STACKFRAME

    /* push SPRs to the stack, simulate an interrupt */
    mfspr   r0,LR
    stw	    r0,SF_SRR0(r1)
    mfmsr   r0
    stw	    r0,SF_SRR1(r1)
    mfspr   r0,CTR
    stw	    r0,SF_CTR(r1)
    mfspr   r0,XER
    stw	    r0,SF_XER(r1)
    mfcr    r0
    stw	    r0,SF_CR(r1)

    /* push GPRs to the stack */
    PUSH_GPRS

    /* swap task environment and stack */

    /* r3 = &posCurrentTask_g; r4 = posCurrentTask_g */
    addis   r3,0,posCurrentTask_g@h
    ori     r3,r3,posCurrentTask_g@l
    lwzx    r4,0,r3

    /* store stackptr:  posCurrentTask_g->stackptr = r1 */
    stwx    r1,0,r4

    /* r5 = &posNextTask_g; r6 = posNextTask_g */
    addis   r5,0,posNextTask_g@h
    ori     r5,r5,posNextTask_g@l
    lwzx    r6,0,r5

    /* posCurrentTask_g = r6 */
    stwx    r6,0,r3

    /* get stackptr:  r1 = posNextTask_g->stackptr */
    lwzx    r1,0,r6

    /* pop SPRs and GPRs from stack and return from interrupt */
    ISR_EXIT

    ENDFUNC(p_pos_softContextSwitch)




/*----------------------------------------------------------------------------
 |
 |  FUNCTION:
 |
 |    void p_pos_intContextSwitch(void);
 |
 |    Does a context switch from interrupt level.
 |
 *--------------------------------------------------------------------------*/

    .align  2
p_pos_intContextSwitch:

    /* r6 = posNextTask_g */
    addis   r5,0,posNextTask_g@h
    ori     r5,r5,posNextTask_g@l
    lwzx    r6,0,r5

    /* posCurrentTask_g = r6 */
    addis   r4,0,posCurrentTask_g@h
    ori     r4,r4,posCurrentTask_g@l
    stwx    r6,0,r4

    /* get stackptr:  r1 = posNextTask_g->stackptr */
    lwzx    r1,0,r6

    /* pop SPRs and GPRs from stack and return from interrupt */
    ISR_EXIT

    ENDFUNC(p_pos_intContextSwitch)




/*----------------------------------------------------------------------------
 |
 |  FUNCTION:
 |
 |    void p_asm_timerISR(void);
 |
 |    Timer interrupt service routine.
 |    You must set up a decrementer timer interrupt with a tick rate
 |    of 1000 Hz. This function must be called (via direct jump)
 |    when the decrementer signals an interrupt.
 |
 *--------------------------------------------------------------------------*/

    .align      2
p_asm_timerISR:

    /* open new stack frame, push SPRs and GPRs to the stack */
    ISR_ENTER

    /* clear interrupting device */
    addis   r3,0,TSR_DIS
    mtspr   TSR,r3
      
    /* test if pico]OS is ready to accept timer ticks */
#if (TIMERISR_TEST_OSRUNNING != 0)
    addis   r4,0,posRunning_g@h
    ori     r4,r4,posRunning_g@l
    lwzx    r3,0,r4
    cmpi    CR0,0,r3,0
    beq     ..osnotrdy1
#endif

    /* store stack pointer when posInInterrupt_g == 0 */
#if (POSCFG_ISR_INTERRUPTABLE != 0)
    addis   r5,0,posInInterrupt_g@h
    ori     r5,r5,posInInterrupt_g@l
    lwzx    r3,0,r5
    cmpi    CR0,0,r3,0
    bne     ..iinoz1
#endif

    /* store stackptr:  posCurrentTask_g->stackptr = r1 */
    addis   r4,0,posCurrentTask_g@h
    ori     r4,r4,posCurrentTask_g@l
    lwzx    r5,0,r4
    stwx    r1,0,r5

    /* set stack pointer to dedicated ISR stack memory */
#if (DEDICATED_ISR_STACK != 0)
    .extern  isrstack_g
    addis   r3,0,isrstack_g@h
    ori     r3,r3,isrstack_g@l
    lwzx    r1,0,r3
#endif

..iinoz1:

    /* call pico]OS timer interrupt handler */
    bl      c_pos_intEnter
    bl      c_pos_timerInterrupt
    bl      c_pos_intExit  /* Note: This funcion call may not return. */

    /* get old stack pointer back */
#if (DEDICATED_ISR_STACK != 0)
    addis   r4,0,posCurrentTask_g@h
    ori     r4,r4,posCurrentTask_g@l
    lwzx    r5,0,r4
    lwzx    r1,0,r5
#endif

..osnotrdy1:

    /* pop SPRs and GPRs from stack and return from interrupt */
    ISR_EXIT

    ENDFUNC(p_asm_timerISR)




/*----------------------------------------------------------------------------
 |
 |  FUNCTION:
 |
 |    void p_asm_extISR(void);
 |
 |    External interrupt service routine, must be called by a direct jump.
 |    This function handles level and edge triggered external interrupts.
 |    When an interrupt happens, this function does a call to the C-function
 |    c_extIntHandler.   (Note that a default handler is in arch_c.c)
 |
 |      void c_extIntHandler(unsigned int uic0s, unsigned int uics1s);
 |
 |      Parameters: uic0s and uic1s contain the status bits of the UICs.
 |
 *--------------------------------------------------------------------------*/

    .align      2
p_asm_extISR:

    /* open new stack frame, push SPRs and GPRs to the stack */
    ISR_ENTER

    /* test if pico]OS is ready to accept interrupts */
#if (EXTISR_TEST_OSRUNNING != 0)
    addis   r4,0,posRunning_g@h
    ori     r4,r4,posRunning_g@l
    lwzx    r3,0,r4
    cmpi    CR0,0,r3,0
    beq     ..osnotrdy2
#endif

    /* store stack pointer when posInInterrupt_g == 0 */
#if (POSCFG_ISR_INTERRUPTABLE != 0)
    addis   r5,0,posInInterrupt_g@h
    ori     r5,r5,posInInterrupt_g@l
    lwzx    r3,0,r5
    cmpi    CR0,0,r3,0
    bne     ..iinoz2
#endif

    /* store stackptr:  posCurrentTask_g->stackptr = r1 */
    addis   r4,0,posCurrentTask_g@h
    ori     r4,r4,posCurrentTask_g@l
    lwzx    r5,0,r4
    stwx    r1,0,r5

    /* set stack pointer to dedicated ISR stack memory */
#if (DEDICATED_ISR_STACK != 0)
    addis   r3,0,isrstack_g@h
    ori     r3,r3,isrstack_g@l
    lwzx    r1,0,r3
#endif

..iinoz2:

    /* set old MSR with external interrupts disabled */
    mfspr   r4,SRR1
    rlwinm  r4,r4,0,17,15
    mtmsr   r4

    /* enter pico]OS interrupt level */
    bl      c_pos_intEnter

    /* load interrupt trigger type masks to regs r25 (UIC0) and r26 (UIC1) */
	mfdcr   r25,0xC5  /* UIC0_TR */
	mfdcr   r26,0xD5  /* UIC1_TR */

    /* get signaled interrupts from UIC0 and UIC1: r3 (UIC0) and r4 (UIC1) */
	mfdcr   r3,0xC6   /* UIC0_MSR */
    mfdcr   r4,0xD6   /* UIC1_MSR */

    /* clear edge-triggered interrupts from UIC1, then from UIC0 */
    and     r27,r26,r4
    mtdcr   0xD0,r27  /* UIC1_SR */
    and     r28,r25,r3
    mtdcr   0xC0,r28  /* UIC0_SR */

    /* get masks of level-triggered interrupts: r27 (UIC0) and r28 (UIC1) */
    andc    r27,r3,r25
    andc    r28,r4,r26
    /* Note: registers r27 and r28 are volatile, that means,
       C functions that need this registers by itself will save
       the old register content to the stack. */

    /* Call external interrupt handler. The parameters
       uic0s (=r3) and uic1s (=r4) are passed to the function. */
    bl      c_extIntHandler

    /* clear level-triggered interrupts from UIC1 and UIC0 */
    mtdcr   0xD0,r28  /* UIC1_SR */
    mtdcr   0xC0,r27  /* UIC0_SR */

    /* exit pico]OS interrupt level */
    bl      c_pos_intExit  /* Note: This funcion call may not return. */

    /* get old stack pointer back */
#if (DEDICATED_ISR_STACK != 0)
    addis   r4,0,posCurrentTask_g@h
    ori     r4,r4,posCurrentTask_g@l
    lwzx    r5,0,r4
    lwzx    r1,0,r5
#endif

..intex2:

    /* pop SPRs and GPRs from stack and return from interrupt */
    ISR_EXIT

..osnotrdy2:

    /* clear pending  interrupts from UIC1 and UIC0 */
    mfdcr   r4,0xD6   /* r4 = UIC1_MSR */
    mtdcr   0xD0,r4   /* UIC1_SR = r4  */
	mfdcr   r3,0xC6   /* r3 = UIC0_MSR */
    mtdcr   0xC0,r3   /* UIC0_SR = r3  */

    b       ..intex2

    ENDFUNC(p_asm_extISR)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -