1 /*
2 * FreeRTOS Kernel V11.1.0
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
26 *
27 */
28
29
30 /*-----------------------------------------------------------
31 * Components that can be compiled to either ARM or THUMB mode are
32 * contained in port.c The ISR routines, which can only be compiled
33 * to ARM mode, are contained in this file.
34 *----------------------------------------------------------*/
35
36 /*
37 */
38
39 /* Scheduler includes. */
40 #include "FreeRTOS.h"
41 #include "task.h"
42
43 /* Constants required to handle critical sections. */
44 #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
45
46 volatile uint32_t ulCriticalNesting = 9999UL;
47
48 /*-----------------------------------------------------------*/
49
50 /*
51 * The scheduler can only be started from ARM mode, hence the inclusion of this
52 * function here.
53 */
54 void vPortISRStartFirstTask( void );
55 /*-----------------------------------------------------------*/
56
vPortISRStartFirstTask(void)57 void vPortISRStartFirstTask( void )
58 {
59 /* Simply start the scheduler. This is included here as it can only be
60 * called from ARM mode. */
61 asm volatile ( \
62 "LDR R0, =pxCurrentTCB \n\t" \
63 "LDR R0, [R0] \n\t" \
64 "LDR LR, [R0] \n\t" \
65 \
66 /* The critical nesting depth is the first item on the stack. */ \
67 /* Load it into the ulCriticalNesting variable. */ \
68 "LDR R0, =ulCriticalNesting \n\t" \
69 "LDMFD LR!, {R1} \n\t" \
70 "STR R1, [R0] \n\t" \
71 \
72 /* Get the SPSR from the stack. */ \
73 "LDMFD LR!, {R0} \n\t" \
74 "MSR SPSR, R0 \n\t" \
75 \
76 /* Restore all system mode registers for the task. */ \
77 "LDMFD LR, {R0-R14}^ \n\t" \
78 "NOP \n\t" \
79 \
80 /* Restore the return address. */ \
81 "LDR LR, [LR, #+60] \n\t" \
82 \
83 /* And return - correcting the offset in the LR to obtain the */ \
84 /* correct address. */ \
85 "SUBS PC, LR, #4 \n\t" \
86 );
87 }
88 /*-----------------------------------------------------------*/
89
vPortTickISR(void)90 void vPortTickISR( void )
91 {
92 /* Increment the RTOS tick count, then look for the highest priority
93 * task that is ready to run. */
94 if( xTaskIncrementTick() != pdFALSE )
95 {
96 vTaskSwitchContext();
97 }
98
99 /* Ready for the next interrupt. */
100 TB_ClearITPendingBit( TB_IT_Update );
101 }
102
103 /*-----------------------------------------------------------*/
104
105 /*
106 * The interrupt management utilities can only be called from ARM mode. When
107 * THUMB_INTERWORK is defined the utilities are defined as functions here to
108 * ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
109 * the utilities are defined as macros in portmacro.h - as per other ports.
110 */
111 #ifdef THUMB_INTERWORK
112
113 void vPortDisableInterruptsFromThumb( void ) __attribute__( ( naked ) );
114 void vPortEnableInterruptsFromThumb( void ) __attribute__( ( naked ) );
115
vPortDisableInterruptsFromThumb(void)116 void vPortDisableInterruptsFromThumb( void )
117 {
118 asm volatile (
119 "STMDB SP!, {R0} \n\t" /* Push R0. */
120 "MRS R0, CPSR \n\t" /* Get CPSR. */
121 "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
122 "MSR CPSR, R0 \n\t" /* Write back modified value. */
123 "LDMIA SP!, {R0} \n\t" /* Pop R0. */
124 "BX R14" ); /* Return back to thumb. */
125 }
126
vPortEnableInterruptsFromThumb(void)127 void vPortEnableInterruptsFromThumb( void )
128 {
129 asm volatile (
130 "STMDB SP!, {R0} \n\t" /* Push R0. */
131 "MRS R0, CPSR \n\t" /* Get CPSR. */
132 "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
133 "MSR CPSR, R0 \n\t" /* Write back modified value. */
134 "LDMIA SP!, {R0} \n\t" /* Pop R0. */
135 "BX R14" ); /* Return back to thumb. */
136 }
137
138 #endif /* THUMB_INTERWORK */
139 /*-----------------------------------------------------------*/
140
vPortEnterCritical(void)141 void vPortEnterCritical( void )
142 {
143 /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
144 asm volatile (
145 "STMDB SP!, {R0} \n\t" /* Push R0. */
146 "MRS R0, CPSR \n\t" /* Get CPSR. */
147 "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
148 "MSR CPSR, R0 \n\t" /* Write back modified value. */
149 "LDMIA SP!, {R0}" ); /* Pop R0. */
150
151 /* Now that interrupts are disabled, ulCriticalNesting can be accessed
152 * directly. Increment ulCriticalNesting to keep a count of how many times
153 * portENTER_CRITICAL() has been called. */
154 ulCriticalNesting++;
155 }
156 /*-----------------------------------------------------------*/
157
vPortExitCritical(void)158 void vPortExitCritical( void )
159 {
160 if( ulCriticalNesting > portNO_CRITICAL_NESTING )
161 {
162 /* Decrement the nesting count as we are leaving a critical section. */
163 ulCriticalNesting--;
164
165 /* If the nesting level has reached zero then interrupts should be
166 * re-enabled. */
167 if( ulCriticalNesting == portNO_CRITICAL_NESTING )
168 {
169 /* Enable interrupts as per portEXIT_CRITICAL(). */
170 asm volatile (
171 "STMDB SP!, {R0} \n\t" /* Push R0. */
172 "MRS R0, CPSR \n\t" /* Get CPSR. */
173 "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
174 "MSR CPSR, R0 \n\t" /* Write back modified value. */
175 "LDMIA SP!, {R0}" ); /* Pop R0. */
176 }
177 }
178 }
179