1#include <k_config.h>
2
3;******************************************************************************
4;                            EXTERN PARAMETERS
5;******************************************************************************
6    EXTERN g_active_task
7    EXTERN g_preferred_ready_task
8    EXTERN krhino_stack_ovf_check
9    EXTERN krhino_task_sched_stats_get
10
11;******************************************************************************
12;                            EXPORT FUNCTIONS
13;******************************************************************************
14    PUBLIC cpu_intrpt_save
15    PUBLIC cpu_intrpt_restore
16    PUBLIC cpu_task_switch
17    PUBLIC cpu_intrpt_switch
18    PUBLIC cpu_first_task_start
19    PUBLIC _first_task_restore
20
21    PUBLIC PendSV_Handler
22
23;******************************************************************************
24;                                 EQUATES
25;******************************************************************************
26SCB_ICSR              EQU      0xE000ED04 ; Interrupt Control and State Register.
27SCB_VTOR              EQU      0xE000ED08 ; Vector Table Offset Register.
28ICSR_PENDSVSET        EQU      0x10000000 ; Value to trigger PendSV exception.
29
30SHPR3_PRI_14          EQU      0xE000ED22 ; System Handler Priority Register 3 (PendSV).
31PRI_LVL_PENDSV        EQU      0xFF       ; PendSV priority level (lowest).
32SHPR3_PRI_15          EQU      0xE000ED23 ; System Handler Priority Register 3 (SysTick).
33PRI_LVL_SYSTICK       EQU      0xFF       ; SYstick priority level (lowest).
34
35;******************************************************************************
36;                        CODE GENERATION DIRECTIVES
37;******************************************************************************
38    SECTION   .text:CODE(2)
39    THUMB
40    REQUIRE8
41    PRESERVE8
42
43;******************************************************************************
44; Functions:
45;     size_t cpu_intrpt_save(void);
46;     void cpu_intrpt_restore(size_t cpsr);
47;******************************************************************************
48cpu_intrpt_save:
49    MRS     R0, PRIMASK
50    CPSID   I
51    BX      LR
52
53cpu_intrpt_restore:
54    MSR     PRIMASK, R0
55    BX      LR
56
57;******************************************************************************
58; Functions:
59;     void cpu_intrpt_switch(void);
60;     void cpu_task_switch(void);
61;******************************************************************************
62cpu_task_switch:
63    LDR     R0, =SCB_ICSR
64    LDR     R1, =ICSR_PENDSVSET
65    STR     R1, [R0]
66    BX      LR
67
68cpu_intrpt_switch:
69    LDR     R0, =SCB_ICSR
70    LDR     R1, =ICSR_PENDSVSET
71    STR     R1, [R0]
72    BX      LR
73
74;******************************************************************************
75; Functions:
76;     void cpu_first_task_start(void);
77;******************************************************************************
78cpu_first_task_start:
79    ;set PendSV prority to the lowest
80    LDR     R0, =SHPR3_PRI_14
81    LDR     R1, =PRI_LVL_PENDSV
82    STRB    R1, [R0]
83
84    ;set Systick prority to the lowest
85    LDR     R0, =SHPR3_PRI_15
86    LDR     R1, =PRI_LVL_SYSTICK
87    STRB    R1, [R0]
88
89    ;indicate PendSV_Handler branch to _pendsv_handler_nosave
90    MOVS    R0, #0
91    MSR     PSP, R0
92
93    ;make PendSV exception pending
94    LDR     R0, =SCB_ICSR
95    LDR     R1, =ICSR_PENDSVSET
96    STR     R1, [R0]
97
98    ;goto PendSV_Handler
99    CPSIE   I
100    B       .
101
102;******************************************************************************
103; Functions:
104;     void krhino_pendsv_handler(void);
105;******************************************************************************
106PendSV_Handler:
107    CPSID   I
108    MRS     R0, PSP
109    ;branch if cpu_first_task_start
110    CMP     R0, #0
111    BEQ     _first_task_restore
112
113    ;hardware saved R0~R3,R12,LR,PC,xPSR
114
115    ;save context
116    SUBS    R0, R0, #0x24
117    STM     R0, {R4-R11, LR}
118
119    ;g_active_task->task_stack = context region
120    LDR     R1, =g_active_task
121    LDR     R1, [R1]
122    STR     R0, [R1]
123
124#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
125    BL      krhino_stack_ovf_check
126#endif
127#if (RHINO_CONFIG_SYS_STATS > 0)
128    BL      krhino_task_sched_stats_get
129#endif
130
131_pendsv_handler_nosave:
132    LDR     R0, =g_active_task
133    LDR     R1, =g_preferred_ready_task
134    LDR     R2, [R1]
135    STR     R2, [R0]
136    ;R0 = g_active_task->task_stack = context region
137    LDR     R0, [R2]
138
139    ;restore context
140    LDM     R0, {R4-R11, LR}
141    ADDS    R0, R0, #0x24
142
143    ;return stack = PSP
144    MSR     PSP, R0
145
146    CPSIE   I
147    ;hardware restore R0~R3,R12,LR,PC,xPSR
148    BX      LR
149
150_first_task_restore:
151    ;set MSP to the base of system stack
152    LDR     R0, =SCB_VTOR
153    LDR     R0, [R0]
154    LDR     R0, [R0]
155    MSR     MSP, R0
156
157    B       _pendsv_handler_nosave
158
159    END
160
161