/**************************************************************************//**
 * @item     CosyOS-III Port
 * @file     port_cmx_iar.s
 * @brief    CMSIS Cortex-M Core Port File for IAR Compiler
 * @author   迟凯峰
 * @version  v3.0.0
 * @date     2026.07.21
 ******************************************************************************/

                                    用户须知

;     该文件是专门为 IAR-EWARM 适配的高性能移植版本，原因是 port_cmx_s.c 文件
; 虽然支持 EWARM，但对于 ARMv7-M 及以上架构来说，性能上是有少许损失的，这源于
; EWARM 内联汇编的局限性。
;     如果您的处理器架构是 ARMv7-M 或以上，并采用 EWARM 来编译您的项目，同时
; 又追求卓越性能，可移除 port_cmx_s.c 文件，并替换为该文件进行编译。
;     注意，该文件仅支持 ARMv7-M 及以上架构，mcucfg_cmx.h 中，互斥访问方案 也
; 必须选择为高性能的 互斥访问指令。

////////////////////////////////////////////////////////////////////////////////

                INCLUDE syscfg.h
                INCLUDE mcucfg_cm0.h
                INCLUDE mcucfg_cm3.h

                SECTION .text:CODE:REORDER:NOROOT(2)
                THUMB

////////////////////////////////////////////////////////////////////////////////

; PendSV软中断

                PUBLIC  OS_PendSV_Handler
OS_PendSV_Handler:
                EXTERN  sPendSV_Handler
                EXTERN  s_task_current
                EXTERN  s_task_news
                PRESERVE8

                push    {lr}
                bl      sPendSV_Handler
; 直接返回吗？
                cbz     r0, __RETURN
; 保护现场吗？
                ldr     r1, =s_task_current
                IF (SYSCFG_DEBUGGING == 1)
                subs    r0, #1
                cbz     r0, __RESTORE
                ENDIF
                mrs     r0, psp
                isb
; 任务PC监控
                IF (SYSCFG_TASKPC_MONITOR == 1)
                EXTERN  s_pc
                ldr     r2, [r0,#24]
                ldr     r3, =s_pc
                str     r2, [r3]
                ENDIF
; 保护现场
                IF (MCUCFG_ASPEN_LSPEN == 1)
                vstmdb  r0!, {s16-s31}
                ENDIF
                stmdb   r0!, {r4-r11}
                ldr     r2, [r1]
                str     r0, [r2]
                dsb
; 恢复现场
__RESTORE       ldr     r3, =s_task_news
                ldr     r3, [r3]
                str     r3, [r1]
                ldr     r0, [r3]
                ldmia   r0!, {r4-r11}
                IF (MCUCFG_ASPEN_LSPEN == 1)
                vldmia  r0!, {s16-s31}
                ENDIF
                msr     psp, r0
; 返回
__RETURN        pop     {pc}

////////////////////////////////////////////////////////////////////////////////

; 中断FIFO服务装载器

                IF (SYSCFG_PENDSVFIFO_DEPTH > 0)

                PUBLIC  mPendSV_FIFOLoader
mPendSV_FIFOLoader:
                EXTERN  mPendSV_FIFO_0
                EXTERN  mPendSV_FIFO_1
                EXTERN  m_fifo_lock
; FIFO选择
                ldr     r2, =m_fifo_lock
                ldrb    r3, [r2]
                cbz     r3, __FIFO1
__FIFO0         ldr     r1, =mPendSV_FIFO_0
                b       __OVERFLOW1
__FIFO1         ldr     r1, =mPendSV_FIFO_1
; 计数溢出
__OVERFLOW1     IF (0) ; 正常情况下计数器难以溢出，默认关闭防护以提高装载效率。
                ldr     r2, [r1]
                ldr     r3, =0x80000000
                cmp     r2, r3
                bhi     __OVER
                ENDIF
; FIFO计数
                /* 互斥访问指令 */
                #if (MCUCFG_PENDSVFIFO_MUTEX == 1)
__LOOP          ldrex   r2, [r1]
                adds    r2, #1
                strex   r3, r2, [r1]
                cmp     r3, #0
                bne     __LOOP
                #else
                #error 互斥访问方案 未选择 互斥访问指令！
                #endif
; FIFO溢出
                cmp     r2, #SYSCFG_PENDSVFIFO_DEPTH
                bhi     __OVER
; FIFO装载
                lsls    r2, r2, #2
                str     r0, [r1, r2]

__OVER          bx      lr

                ENDIF

////////////////////////////////////////////////////////////////////////////////
ALIGN
                END
