/**************************************************************************//**
 * @item     CosyOS-III Port
 * @file     port_cmx_s.c
 * @brief    CMSIS Cortex-M Core Port File for Arm / GNU / IAR Compiler
 * @author   迟凯峰
 * @version  v3.0.7
 * @date     2026.08.14
 ******************************************************************************/

#include "os_var.h"
#ifdef __PORT_CMX_H

#if ((defined (__ARM_ARCH_7M__       ) && (__ARM_ARCH_7M__        == 1)) \
 ||  (defined (__ARM_ARCH_7EM__      ) && (__ARM_ARCH_7EM__       == 1)) \
 ||  (defined (__ARM_ARCH_8M_BASE__  ) && (__ARM_ARCH_8M_BASE__   == 1)) \
 ||  (defined (__ARM_ARCH_8M_MAIN__  ) && (__ARM_ARCH_8M_MAIN__   == 1)) \
 ||  (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)))
#define __CMX_ISA 7
#else
#define __CMX_ISA 6
#endif


/*
 * Arm Compiler 4/5
 */
#if (defined ( __CC_ARM ))

/* PendSV软中断 */
__ASM void OS_PendSV_Handler(void)
{
                IMPORT  sPendSV_Handler
                IMPORT  s_task_current
                IMPORT	s_task_news
                PRESERVE8
                THUMB

                push    {lr}
                bl      sPendSV_Handler
/* 直接返回吗？*/
                #if (__CMX_ISA == 6)
                cmp     r0, #0
                beq     __RETURN
                #else
                cbz     r0, __RETURN
                #endif
/* 保护现场吗？*/
                ldr     r1, =s_task_current
                subs    r0, #1
                #if (__CMX_ISA == 6)
                cmp     r0, #0
                beq     __RESTORE
                #else
                cbz     r0, __RESTORE
                #endif
                mrs     r0, psp
                isb
/* 任务PC监控 */
                #if (SYSCFG_TASKPC_MONITOR == 1)
                IMPORT  s_pc
                ldr     r2, [r0,#24]
                ldr     r3, =s_pc
                str     r2, [r3]
                #endif
/* 保护现场 */
                #if (MCUCFG_ASPEN_LSPEN == 1)
                vstmdb  r0!, {s16-s31}
                #endif
                #if (__CMX_ISA == 6)
                subs    r0, #32
                ldr     r2, [r1]
                str     r0, [r2]
                stmia   r0!, {r4-r7}
                mov     r4, r8
                mov     r5, r9
                mov     r6, r10
                mov     r7, r11
                stmia   r0!, {r4-r7}
                #else
                stmdb   r0!, {r4-r11}
                ldr     r2, [r1]
                str     r0, [r2]
                #endif
                dsb
/* 恢复现场 */
__RESTORE       ldr     r3, =s_task_news
                ldr     r3, [r3]
                str     r3, [r1]
                ldr     r0, [r3]
                #if (__CMX_ISA == 6)
                adds    r0, #16
                ldmia   r0!, {r4-r7}
                mov     r11, r7
                mov     r10, r6
                mov     r9, r5
                mov     r8, r4
                mov     r1, r0
                subs    r1, #32
                ldmia   r1!, {r4-r7}
                #else
                ldmia   r0!, {r4-r11}
                #endif
                #if (MCUCFG_ASPEN_LSPEN == 1)
                vldmia  r0!, {s16-s31}
                #endif
                msr     psp, r0
/* 返回 */
__RETURN        pop     {pc}

                ALIGN
}


/* 中断FIFO服务装载器 */
#if (SYSCFG_PENDSVFIFO_DEPTH > 0)
__ASM void mPendSV_FIFOLoader(void *sv)
{
                IMPORT  mPendSV_FIFO_0
                IMPORT  mPendSV_FIFO_1
                IMPORT  m_fifo_lock
                THUMB
/* FIFO选择 */
                ldr     r2, =m_fifo_lock
                ldrb    r3, [r2]
                #if (__CMX_ISA == 6)
                cmp     r3, #0
                beq     __FIFO1
                #else
                cbz     r3, __FIFO1
                #endif
__FIFO0         ldr     r1, =mPendSV_FIFO_0
                b       __OVERFLOW1
__FIFO1         ldr     r1, =mPendSV_FIFO_1
/* 计数溢出 */
__OVERFLOW1
                #if (0) // 正常情况下计数器难以溢出，默认关闭防护以提高装载效率。
                #if (MCUCFG_PENDSVFIFO_MUTEX == 0xFF)
                ldrh    r2, [r1]
                ldr     r3, =0x8000
                #else
                ldr     r2, [r1]
                ldr     r3, =0x80000000
                #endif
                cmp     r2, r3
                bhi     __OVER
                #endif
/* FIFO计数 */
                /* 关闭总中断 */
                #if (MCUCFG_PENDSVFIFO_MUTEX == 0)
                #if (MCUCFG_PENDSVFIFO_XXXXX == 1)
                mrs     r3, primask // cycle:4
                #endif
                cpsid   i           // cycle:1
                ldr     r2, [r1]    // cycle:2
                adds    r2, #1      // cycle:1
                str     r2, [r1]    // cycle:2
                #if (MCUCFG_PENDSVFIFO_XXXXX == 1)
                msr     primask, r3 // cycle:4
                #else
                cpsie   i           // cycle:1
                #endif

                /* 互斥访问指令 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 1)
__LOOP          ldrex   r2, [r1]
                adds    r2, #1
                strex   r3, r2, [r1]
                cmp     r3, #0
                bne     __LOOP

                /* 互斥访问机制 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 0xFF)
                IMPORT  mPendSV_FIFO_X
                #define rx  mPendSV_FIFO_rx
                ldrh    r3, [r1, #2] // 查询独占访问标志
                cmp     r3, #0
                beq     __WHOLE
/* 已打断 *///不会被打断：8
                ldrh    r2, [r1]
                adds    r2, #1
                strh    r2, [r1]
                ldr     rx, =mPendSV_FIFO_X // 重设 rx
                b       __OVERFLOW2
/* 未打断 *///可能被打断：14
__WHOLE         push    {rx} // 保护 rx
                movs    r2, #1
                strh    r2, [r1, #2] // 设置独占访问标志
__LOOP          mov     rx, r1
                ldrh    r2, [rx]
                adds    r2, #1
                strh    r2, [rx]
                cmp     rx, r1
                bne     __LOOP
                strh    r3, [r1, #2] // 清除独占访问标志
                pop     {rx} // 恢复 rx
                #undef  rx
                #endif
/* FIFO溢出 */
__OVERFLOW2     cmp     r2, #SYSCFG_PENDSVFIFO_DEPTH
                bhi     __OVER
/* FIFO装载 */
                lsls    r2, r2, #2
                str     r0, [r1, r2]

__OVER          bx      lr

                ALIGN
}
#endif


/*
 * IAR Compiler
 * GNU Compiler
 * Arm Compiler 6.6 LTM / above 6.10.1 (armclang)
 */
#elif ((defined ( __GNUC__   )) \
   ||  (defined ( __ICCARM__ )) \
   ||  (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))

#if !defined (__ICCARM__)
s_u8_t sPendSV_Handler(void);
extern s_taskctrl_tsp s_task_news;
#else
#include "os_handler.c"
#endif

/* PendSV软中断 */
void OS_PendSV_Handler(void)
{
        #if  defined (__GNUC__)
        __ASM volatile(".syntax unified");
        #endif
        #if !defined (__ICCARM__)
        __ASM volatile(".THUMB");
        #endif
        __ASM volatile(
               "push    {lr} \n"
               "bl      sPendSV_Handler \n"
/* 直接返回吗？*/
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
               "cmp     r0, #0 \n"
               "beq     __RETURN \n"
                #else
               "cbz     r0, __RETURN \n"
                #endif
/* 保护现场吗？*/
               "ldr     r1, =s_task_current \n"
               "subs    r0, #1 \n"
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
               "cmp     r0, #0 \n"
               "beq     __RESTORE \n"
                #else
               "cbz     r0, __RESTORE \n"
                #endif
               "mrs     r0, psp \n"
               "isb \n"
/* 任务PC监控 */
                #if (SYSCFG_TASKPC_MONITOR == 1)
               "ldr     r2, [r0,#24] \n"
               "ldr     r3, =s_pc \n"
               "str     r2, [r3] \n"
                #endif
/* 保护现场 */
                #if (MCUCFG_ASPEN_LSPEN == 1)
               "vstmdb  r0!, {s16-s31} \n"
                #endif
                #if (__CMX_ISA == 6)
               "subs    r0, #32 \n"
               "ldr     r2, [r1] \n"
               "str     r0, [r2] \n"
               "stmia   r0!, {r4-r7} \n"
               "mov     r4, r8 \n"
               "mov     r5, r9 \n"
               "mov     r6, r10 \n"
               "mov     r7, r11 \n"
               "stmia   r0!, {r4-r7} \n"
                #else
               "stmdb   r0!, {r4-r11} \n"
               "ldr     r2, [r1] \n"
               "str     r0, [r2] \n"
                #endif
               "dsb \n"
/* 恢复现场 */
"__RESTORE:     ldr     r3, =s_task_news \n"
               "ldr     r3, [r3] \n"
               "str     r3, [r1] \n"
               "ldr     r0, [r3] \n"
                #if (__CMX_ISA == 6)
               "adds    r0, #16 \n"
               "ldmia   r0!, {r4-r7} \n"
               "mov     r11, r7 \n"
               "mov     r10, r6 \n"
               "mov     r9, r5 \n"
               "mov     r8, r4 \n"
               "mov     r1, r0 \n"
               "subs    r1, #32 \n"
               "ldmia   r1!, {r4-r7} \n"
                #else
               "ldmia   r0!, {r4-r11} \n"
                #endif
                #if (MCUCFG_ASPEN_LSPEN == 1)
               "vldmia  r0!, {s16-s31} \n"
                #endif
               "msr     psp, r0 \n"
/* 返回 */
"__RETURN:      pop     {pc}"
        );
        #if !defined (__ICCARM__)
        __ASM volatile(".ALIGN");
        #endif
}


/* 中断FIFO服务装载器 */
#if (SYSCFG_PENDSVFIFO_DEPTH > 0)
void mPendSV_FIFOLoader(void *sv)
{
        #if  defined (__GNUC__)
        __ASM volatile(".syntax unified");
        #endif
        #if !defined (__ICCARM__)
        __ASM volatile(".THUMB");
        #endif
        __ASM volatile(
/* FIFO选择 */
               "ldr     r2, =m_fifo_lock \n"
               "ldrb    r3, [r2] \n"
                #if ((__CMX_ISA == 6) || defined (__ICCARM__))
               "cmp     r3, #0 \n"
               "beq     __FIFO1 \n"
                #else
               "cbz     r3, __FIFO1 \n"
                #endif
"__FIFO0:       ldr     r1, =mPendSV_FIFO_0 \n"
               "b       __OVERFLOW1 \n"
"__FIFO1:       ldr     r1, =mPendSV_FIFO_1 \n"
/* 计数溢出 */
"__OVERFLOW1: \n"
                #if (0) // 正常情况下计数器难以溢出，默认关闭防护以提高装载效率。
                #if (MCUCFG_PENDSVFIFO_MUTEX == 0xFF)
               "ldrh    r2, [r1] \n"
               "ldr     r3, =0x8000 \n"
                #else
               "ldr     r2, [r1] \n"
               "ldr     r3, =0x80000000 \n"
                #endif
               "cmp     r2, r3 \n"
               "bhi     __OVER \n"
                #endif
/* FIFO计数 */
                /* 关闭总中断 */
                #if (MCUCFG_PENDSVFIFO_MUTEX == 0)
                #if (MCUCFG_PENDSVFIFO_XXXXX == 1)
               "mrs     r3, primask \n" // cycle:4
                #endif
               "cpsid   i \n"           // cycle:1
               "ldr     r2, [r1] \n"    // cycle:2
               "adds    r2, #1 \n"      // cycle:1
               "str     r2, [r1] \n"    // cycle:2
                #if (MCUCFG_PENDSVFIFO_XXXXX == 1)
               "msr     primask, r3 \n" // cycle:4
                #else
               "cpsie   i \n"           // cycle:1
                #endif

                /* 互斥访问指令 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 1)
"__LOOP:        ldrex   r2, [r1] \n"
               "adds    r2, #1 \n"
               "strex   r3, r2, [r1] \n"
               "cmp     r3, #0 \n"
               "bne     __LOOP \n"

                /* 互斥访问机制 */
                #elif (MCUCFG_PENDSVFIFO_MUTEX == 0xFF)
                #define rx  mPendSV_FIFO_rx
               "ldrh    r3, [r1, #2] \n"
               "cmp     r3, #0 \n"
               "beq     __WHOLE \n"

               "ldrh    r2, "sDefStr([r1] \n)
               "adds    r2, #1 \n"
               "strh    r2, "sDefStr([r1] \n)
               "ldr     "sDefStr(rx)", =mPendSV_FIFO_X \n"
               "b       __OVERFLOW2 \n"

"__WHOLE:       push    "sDefStr({rx} \n)
               "movs    r2, #1 \n"
               "strh    r2, [r1, #2] \n"
"__LOOP:        mov     "sDefStr(rx)", r1 \n"
               "ldrh    r2, "sDefStr([rx] \n)
               "adds    r2, #1 \n"
               "strh    r2, "sDefStr([rx] \n)
               "cmp     "sDefStr(rx)", r1 \n"
               "bne     __LOOP \n"
               "strh    r3, [r1, #2] \n"
               "pop     "sDefStr({rx} \n)
                #undef  rx
                #endif
/* FIFO溢出 */
"__OVERFLOW2:   cmp r2, #"sDefStr(SYSCFG_PENDSVFIFO_DEPTH \n)
               "bhi     __OVER \n"
/* FIFO装载 */
               "lsls    r2, r2, #2 \n"
               "str     r0, [r1, r2] \n"

"__OVER:        bx      lr"
        );
        #if !defined (__ICCARM__)
        __ASM volatile(".ALIGN");
        #endif
}
#endif


/*
 * Unknown Compiler
 */
#else

    #error Unknown compiler.
#endif

#endif
