]> git.sur5r.net Git - freertos/blob - Source/portable/Keil/ARM7/portmacro.h
First version under SVN is V4.0.1
[freertos] / Source / portable / Keil / ARM7 / portmacro.h
1 /*\r
2         FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS distribution.\r
5 \r
6         FreeRTOS is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27         See http://www.FreeRTOS.org for documentation, latest information, license \r
28         and contact details.  Please ensure to read the configuration and relevant \r
29         port sections of the online documentation.\r
30         ***************************************************************************\r
31 */\r
32 \r
33 \r
34 #ifndef PORTMACRO_H\r
35 #define PORTMACRO_H\r
36 \r
37 /*-----------------------------------------------------------\r
38  * Port specific definitions.  \r
39  *\r
40  * The settings in this file configure FreeRTOS correctly for the\r
41  * given hardware and compiler.\r
42  *\r
43  * These settings should not be altered.\r
44  *-----------------------------------------------------------\r
45  */\r
46 \r
47 /* Type definitions. */\r
48 #define portCHAR                char\r
49 #define portFLOAT               float\r
50 #define portDOUBLE              double\r
51 #define portLONG                long\r
52 #define portSHORT               short\r
53 #define portSTACK_TYPE  unsigned portLONG\r
54 #define portBASE_TYPE   portLONG\r
55 \r
56 #if( configUSE_16_BIT_TICKS == 1 )\r
57         typedef unsigned portSHORT portTickType;\r
58         #define portMAX_DELAY ( portTickType ) 0xffff\r
59 #else\r
60         typedef unsigned portLONG portTickType;\r
61         #define portMAX_DELAY ( portTickType ) 0xffffffff\r
62 #endif\r
63 /*-----------------------------------------------------------*/ \r
64 \r
65 /* Hardware specifics. */\r
66 #define portSTACK_GROWTH                        ( -1 )\r
67 #define portTICK_RATE_MS                        ( ( portTickType ) 1000 / configTICK_RATE_HZ )          \r
68 #define portBYTE_ALIGNMENT                      4\r
69 /*-----------------------------------------------------------*/ \r
70 \r
71 /* Task utilities. */\r
72 #define portRESTORE_CONTEXT()                                                                                                                                                   \\r
73 {                                                                                                                                                                                                               \\r
74 extern volatile unsigned portLONG ulCriticalNesting;                                                                                                    \\r
75 extern volatile void * volatile pxCurrentTCB;                                                                                                                   \\r
76                                                                                                                                                                                                                 \\r
77         __asm{ LDR              R1, =pxCurrentTCB };/* Set the LR to the task stack.  The location was ... */           \\r
78         __asm{ LDR              R0, [R1]                };      /* ... stored in pxCurrentTCB. */                                                               \\r
79         __asm{ LDR              LR, [R0]                };                                                                                                                                      \\r
80                                                                                                                                                                                                                 \\r
81         __asm{ LDR              R0, =ulCriticalNesting }; /* The critical nesting depth is the first item on ... */     \\r
82         __asm{ LDMFD    LR!, {R1 }              }  /* ... the stack.  Load it into the ulCriticalNesting var. */        \\r
83         __asm{ STR              R1, [R0]                }                                                                                                                                       \\r
84                                                                                                                                                                                                                 \\r
85         __asm{ LDMFD    LR!, {R0}               }; /* Get the SPSR from the stack. */                                                           \\r
86         __asm{ MSR              SPSR_CXSF, R0   };                                                                                                                                      \\r
87                                                                                                                                                                                                                 \\r
88         __asm{ LDMFD    LR, {R0-R14}^   }; /* Restore all system mode registers for the task. */                        \\r
89         __asm{ NOP                                              };                                                                                                                                      \\r
90                                                                                                                                                                                                                 \\r
91         __asm{ LDR              LR, [LR, #+60]  }; /* Restore the return address. */                                                            \\r
92                                                                                                                                                                                                                 \\r
93                                                                            /* And return - correcting the offset in the LR to obtain ... */ \\r
94         __asm{ SUBS     PC, LR, #4                      }; /* ... the correct address. */                                                                       \\r
95 }\r
96 /*----------------------------------------------------------*/\r
97 \r
98 #define portSAVE_CONTEXT()                                                                                                                                                              \\r
99 {                                                                                                                                                                                                               \\r
100 extern volatile unsigned portLONG ulCriticalNesting;                                                                                                    \\r
101 extern volatile void * volatile pxCurrentTCB;                                                                                                                   \\r
102                                                                                                                                                                                                                 \\r
103         __asm{ STMDB    SP!, {R0}               };      /* Store R0 first as we need to use it.                                         */      \\r
104                                                                                                                                                                                                                 \\r
105         __asm{ STMDB    SP,{SP}^                }; /* Set R0 to point to the task stack pointer.                                */      \\r
106         __asm{ NOP                                              };                                                                                                                                      \\r
107         __asm{ SUB              SP, SP, #4              };                                                                                                                                      \\r
108         __asm{ LDMIA    SP!,{R0}                };                                                                                                                                      \\r
109                                                                                                                                                                                                                 \                                                                                                                                       \r
110         __asm{ STMDB    R0!, {LR}               }; /* Push the return address onto the stack.                                   */      \\r
111         __asm{ MOV              LR, R0                  }; /* Now we have saved LR we can use it instead of R0.                 */      \\r
112         __asm{ LDMIA    SP!, {R0}               }; /* Pop R0 so we can save it onto the system mode stack.              */      \\r
113                                                                                                                                                                                                                 \\r
114         __asm{ STMDB    LR,{R0-LR}^             }; /* Push all the system mode registers onto the task stack.   */      \\r
115         __asm{ NOP                                              };                                                                                                                                      \\r
116         __asm{ SUB              LR, LR, #60             };                                                                                                                                      \\r
117                                                                                                                                                                                                                 \\r
118         __asm{ MRS              R0, SPSR                }; /* Push the SPSR onto the task stack.                                                */      \\r
119         __asm{ STMDB    LR!, {R0}               };                                                                                                                                      \\r
120                                                                                                                                                                                                                 \\r
121         __asm{ LDR              R0, =ulCriticalNesting };                                                                                                                       \\r
122         __asm{ LDR              R0, [R0]                };                                                                                                                                      \\r
123         __asm{ STMDB    LR!, {R0}               };                                                                                                                                      \\r
124                                                                                                                                                                                                                 \\r
125         __asm{ LDR              R0, =pxCurrentTCB };/* Store the new top of stack for the task.                                 */      \\r
126         __asm{ LDR              R1, [R0]                };                                                                                                                                      \\r
127         __asm{ STR              LR, [R1]                };                                                                                                                                      \\r
128 }\r
129 \r
130 /*-----------------------------------------------------------\r
131  * ISR entry and exit macros.  These are only required if a task switch\r
132  * is required from an ISR.\r
133  *----------------------------------------------------------*/\r
134 \r
135 #define portENTER_SWITCHING_ISR()                                                                               \\r
136                 portSAVE_CONTEXT();                                                                                             \\r
137                 {\r
138 \r
139 #define portEXIT_SWITCHING_ISR( SwitchRequired )                                                \\r
140                 /* If a switch is required then we just need to call */                 \\r
141                 /* vTaskSwitchContext() as the context has already been */              \\r
142                 /* saved. */                                                                                                    \\r
143                 if( SwitchRequired )                                                                                    \\r
144                 {                                                                                                                               \\r
145                         vTaskSwitchContext();                                                                           \\r
146                 }                                                                                                                               \\r
147         }                                                                                                                                       \\r
148         /* Restore the context of which ever task is now the highest */         \\r
149         /* priority that is ready to run. */                                                            \\r
150         portRESTORE_CONTEXT();\r
151 \r
152 \r
153 /* Yield the processor - force a context switch. */\r
154 #define portYIELD()                                     __asm{ SWI 0 }; \r
155 /*-----------------------------------------------------------*/ \r
156 \r
157 /* Critical section management. */\r
158 \r
159 /*-----------------------------------------------------------\r
160  * Interrupt control macros.\r
161  *\r
162  * The interrupt management utilities can only be called from ARM mode.  When\r
163  * KEIL_THUMB_INTERWORK is defined the utilities are defined as functions in \r
164  * portISR.c to ensure a switch to ARM mode.  When KEIL_THUMB_INTERWORK is not \r
165  * defined then the utilities are defined as macros here - as per other ports.\r
166  *----------------------------------------------------------*/\r
167 \r
168 #ifdef KEIL_THUMB_INTERWORK\r
169 \r
170         extern void vPortDisableInterruptsFromThumb( void ) __task;\r
171         extern void vPortEnableInterruptsFromThumb( void ) __task;\r
172 \r
173         #define portDISABLE_INTERRUPTS()        vPortDisableInterruptsFromThumb()\r
174         #define portENABLE_INTERRUPTS()         vPortEnableInterruptsFromThumb()\r
175 \r
176 #else\r
177 \r
178         /*-----------------------------------------------------------*/\r
179 \r
180         #define portDISABLE_INTERRUPTS()                                                                                                                \\r
181                 __asm{ STMDB    SP!, {R0}               };      /* Push R0.                                                                     */      \\r
182                 __asm{ MRS              R0, CPSR                };      /* Get CPSR.                                                            */      \\r
183                 __asm{ ORR              R0, R0, #0xC0   };      /* Disable IRQ, FIQ.                                            */      \\r
184                 __asm{ MSR              CPSR_CXSF, R0   };      /* Write back modified value.                           */      \\r
185                 __asm{ LDMIA    SP!, {R0}               }       /* Pop R0.                                                                      */\r
186                         \r
187         #define portENABLE_INTERRUPTS()                                                                                                                 \\r
188                 __asm{ STMDB    SP!, {R0}               };      /* Push R0.                                                                     */      \\r
189                 __asm{ MRS              R0, CPSR                };      /* Get CPSR.                                                            */      \\r
190                 __asm{ BIC              R0, R0, #0xC0   };      /* Enable IRQ, FIQ.                                                     */      \\r
191                 __asm{ MSR              CPSR_CXSF, R0   };      /* Write back modified value.                           */      \\r
192                 __asm{ LDMIA    SP!, {R0}               }       /* Pop R0. */\r
193 \r
194 #endif /* KEIL_THUMB_INTERWORK */\r
195 \r
196 /*-----------------------------------------------------------\r
197  * Critical section control\r
198  *\r
199  * The code generated by the Keil compiler does not maintain separate\r
200  * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore\r
201  * use the stack as per other ports.  Instead a variable is used to keep\r
202  * track of the critical section nesting.  This necessitates the use of a \r
203  * function in place of the macro.\r
204  *----------------------------------------------------------*/\r
205 \r
206 extern void vPortEnterCritical( void );\r
207 extern void vPortExitCritical( void );\r
208 \r
209 #define portENTER_CRITICAL()            vPortEnterCritical();\r
210 #define portEXIT_CRITICAL()                     vPortExitCritical();\r
211 /*-----------------------------------------------------------*/ \r
212 \r
213 /* Compiler specifics. */\r
214 #define inline\r
215 #define register\r
216 #define portNOP()       __asm{ NOP }\r
217 /*-----------------------------------------------------------*/ \r
218 \r
219 /* Task function macros as described on the FreeRTOS.org WEB site. */\r
220 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )      void vFunction( void *pvParameters ) __task\r
221 #define portTASK_FUNCTION( vFunction, pvParameters )    void vFunction( void *pvParameters )\r
222 \r
223 #endif /* PORTMACRO_H */\r
224 \r