TencentOS tiny 中断嵌套

 

 

 

tos_knl_irq_enter和tos_knl_irq_leave

__API__ void tos_knl_irq_enter(void)
{
    if (!tos_knl_is_running()) {
        return;
    }

    if (unlikely(k_irq_nest_cnt >= K_NESTING_LIMIT_IRQ)) {
        return;
    }

    ++k_irq_nest_cnt;
}

__API__ void tos_knl_irq_leave(void)
{
    TOS_CPU_CPSR_ALLOC();

    if (!tos_knl_is_running()) {
        return;
    }

    TOS_CPU_INT_DISABLE();
    if (!knl_is_inirq()) {
        TOS_CPU_INT_ENABLE();
        return;
    }

    --k_irq_nest_cnt;

    if (knl_is_inirq()) {
        TOS_CPU_INT_ENABLE();
        return;
    }

    if (knl_is_sched_locked()) {
        TOS_CPU_INT_ENABLE();
        return;
    }

    k_next_task = readyqueue_highest_ready_task_get();
    if (knl_is_self(k_next_task)) {
        TOS_CPU_INT_ENABLE();
        return;
    }

    cpu_irq_context_switch();
    TOS_CPU_INT_ENABLE();
}

 

SysTick_Handler(void)

{
    if (tos_knl_is_running()) {
        tos_knl_irq_enter();
        tos_tick_handler();
        tos_knl_irq_leave();
    }
}

/* LPUART2_IRQn interrupt handler */
void LPUART2_IRQHandler(void) {
    uint8_t data;
    
    tos_knl_irq_enter();

    /* If new data arrived. */
    if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(LPUART2))
    {
        data = LPUART_ReadByte(LPUART2);
        tos_at_uart_input_byte(data);
    }
    
    tos_knl_irq_leave();
}

/* LPUART4_IRQn interrupt handler */
void LPUART4_IRQHandler(void) {
    uint8_t data;
    
    tos_knl_irq_enter();

    /* If new data arrived. */
    if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(LPUART4))
    {
        data = LPUART_ReadByte(LPUART4);
        tos_at_uart_input_byte(data);
    }
    
    tos_knl_irq_leave();
}

 

/* Fuchsia's code is nice here, so I learn from it(fine, almost copy). thanks */

#include "exceptions.h"

    .global arm_undefined
    .global arm_syscall
    .global arm_prefetch_abort
    .global arm_data_abort
    .global arm_reserved
    .global arm_irq
    .global arm_fiq

    .extern tos_knl_irq_enter
    .extern tos_knl_irq_leave
    .extern interrupt_irq

    .syntax unified
    .text

.type arm_undefined, %function
arm_undefined:
    save
    /* r0 now holds pointer to iframe */

    bl      arm_undefined_handler

    restore


.type arm_syscall, %function
arm_syscall:
    b       .


.type arm_prefetch_abort, %function
arm_prefetch_abort:
    saveall_offset #4
    /* r0 now holds pointer to iframe */

    bl      arm_prefetch_abort_handler

    restoreall


.type arm_data_abort, %function
arm_data_abort:
    saveall_offset #8
    /* r0 now holds pointer to iframe */

    bl      arm_data_abort_handler

    restoreall


.type arm_reserved, %function
arm_reserved:
    b       .


.type arm_irq, %function
arm_irq:
    saveall_offset  #4

    /* r0 now holds pointer to iframe */
    bl      tos_knl_irq_enter

    /* call into higher level code */
    bl      interrupt_irq

    bl      tos_knl_irq_leave

    restoreall


.type arm_fiq, %function
arm_fiq:
    b       .

.end

 

saveall_offset restoreall

/* macros to align and unalign the stack on 8 byte boundary for ABI compliance */
.macro stack_align, tempreg
    /* make sure the stack is aligned */
    mov     \tempreg, sp
    tst     sp, #4
    subeq   sp, #4
    push    { \tempreg }

    /* tempreg holds the original stack */
.endm

.macro stack_restore, tempreg
    /* restore the potentially unaligned stack */
    pop     { \tempreg }
    mov     sp, \tempreg
.endm

/* save and disable the vfp unit */
.macro vfp_save, temp1
    /* save old fpexc */
    vmrs    \temp1, fpexc

    push    { \temp1 }

    /* hard disable the vfp unit */
    bic     \temp1, #(1<<30)
    vmsr    fpexc, \temp1
.endm

/* restore the vfp enable/disable state */
.macro vfp_restore, temp1
    /* restore fpexc */
    pop     { \temp1 }

    vmsr    fpexc, \temp1
.endm

/* Save callee trashed registers.
 * At exit r0 contains a pointer to the register frame.
 */
.macro save
    /* save spsr and r14 onto the svc stack */
    srsdb   #0x13!

    /* switch to svc mode, interrupts disabled */
    cpsid   i, #0x13

    /* save callee trashed regs and lr */
    push    { r0-r3, r12, lr }

#if 0
    #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
    /* save and disable the vfp unit */
    vfp_save    r0
    #endif
#endif

    /* make sure the stack is 8 byte aligned */
    stack_align r0

    /* r0 now holds the pointer to the original iframe (before alignment) */
.endm

.macro save_offset, offset
    sub     lr, \offset
    save
.endm

.macro restore
    /* undo the stack alignment we did before */
    stack_restore r0

#if 0
    #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
    /* restore the old state of the vfp unit */
    vfp_restore r0
    #endif
#endif

    pop     { r0-r3, r12, lr }

    /* return to whence we came from */
    rfeia   sp!
.endm

/* Save all registers.
 * At exit r0 contains a pointer to the register frame.
 */
.macro saveall
    /* save spsr and r14 onto the svc stack */
    srsdb   #0x13!

    /* switch to svc mode, interrupts disabled */
    cpsid   i,#0x13

    /* save all regs */
    push    { r0-r12, lr }

    #if 0
    #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
    /* save and disable the vfp unit */
    vfp_save    r0
    #endif
    #endif

    /* make sure the stack is 8 byte aligned */
    stack_align r0

    /* r0 now holds the pointer to the original iframe (before alignment) */
.endm

.macro saveall_offset, offset
    sub     lr, \offset
    saveall
.endm

.macro restoreall
    /* undo the stack alignment we did before */
    stack_restore r0

    #if 0
    #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
    /* restore the old state of the vfp unit */
    vfp_restore r0
    #endif
    #endif

    pop     { r0-r12, r14 }

    /* return to whence we came from */
    rfeia   sp!
.endm

 

interrupt_irq

__STATIC__ int_handle_t int_handle_table[INTERRUPT_MAX];

__KNL__ void interrupt_irq(int_frame_t *int_frame)
{
    uint32_t vector;
    int_handle_t *handle;

    vector = gic_interrupt_id_get(0u);

    if (vector > INTERRUPT_MAX || vector == (uint32_t)-1) {
        return;
    }

    handle = &int_handle_table[vector];
    if (handle->handler) {
        handle->handler(handle->arg);
    }

    gic_interrupt_end(0u, vector);
}

 

posted on 2022-02-24 11:39  tycoon3  阅读(124)  评论(0)    收藏  举报

导航