]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/MCF5235/port.c
Add xEventGroupClearBitsFromISR() and xEventGroupGetBitsFromISR() functions.
[freertos] / FreeRTOS / Source / portable / GCC / MCF5235 / port.c
1 /*\r
2     FreeRTOS V4.1.1 - Copyright (C) 2003-2006 Richard Barry.\r
3     MCF5235 Port - Copyright (C) 2006 Christian Walter.\r
4 \r
5     This file is part of the FreeRTOS distribution.\r
6 \r
7     FreeRTOS is free software; you can redistribute it and/or modify\r
8     it under the terms of the GNU General Public License** as published by\r
9     the Free Software Foundation; either version 2 of the License, or\r
10     (at your option) any later version.\r
11 \r
12     FreeRTOS is distributed in the hope that it will be useful,\r
13     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15     GNU General Public License for more details.\r
16 \r
17     You should have received a copy of the GNU General Public License\r
18     along with FreeRTOS; if not, write to the Free Software\r
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
20 \r
21     A special exception to the GPL can be applied should you wish to distribute\r
22     a combined work that includes FreeRTOS, without being obliged to provide\r
23     the source code for any proprietary components.  See the licensing section\r
24     of http://www.FreeRTOS.org for full details of how and when the exception\r
25     can be applied.\r
26 \r
27     ***************************************************************************\r
28     ***************************************************************************\r
29     *                                                                         *\r
30     * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
31         *                                                                         *\r
32         * This is a concise, step by step, 'hands on' guide that describes both   *\r
33         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
34         * explains numerous examples that are written using the FreeRTOS API.     *\r
35         * Full source code for all the examples is provided in an accompanying    *\r
36         * .zip file.                                                              *\r
37     *                                                                         *\r
38     ***************************************************************************\r
39     ***************************************************************************\r
40 \r
41         Please ensure to read the configuration and relevant port sections of the\r
42         online documentation.\r
43 \r
44         http://www.FreeRTOS.org - Documentation, latest information, license and \r
45         contact details.\r
46 \r
47         http://www.SafeRTOS.com - A version that is certified for use in safety \r
48         critical systems.\r
49 \r
50         http://www.OpenRTOS.com - Commercial support, development, porting, \r
51         licensing and training services.\r
52 */\r
53 \r
54 #include <stdlib.h>\r
55 \r
56 #include "FreeRTOS.h"\r
57 #include "FreeRTOSConfig.h"\r
58 #include "task.h"\r
59 \r
60 /* ------------------------ Types ----------------------------------------- */\r
61 typedef volatile uint32_t vuint32;\r
62 typedef volatile uint16_t vuint16;\r
63 typedef volatile uint8_t vuint8;\r
64 \r
65 /* ------------------------ Defines --------------------------------------- */\r
66 #define portVECTOR_TABLE                __RAMVEC\r
67 #define portVECTOR_SYSCALL              ( 32 + portTRAP_YIELD )\r
68 #define portVECTOR_TIMER                ( 64 + 36 )\r
69 \r
70 #define MCF_PIT_PRESCALER               512UL\r
71 #define MCF_PIT_TIMER_TICKS             ( FSYS_2 / MCF_PIT_PRESCALER )\r
72 #define MCF_PIT_MODULUS_REGISTER(freq)  ( MCF_PIT_TIMER_TICKS / ( freq ) - 1UL)\r
73 \r
74 #define MCF_PIT_PMR0                    ( *( vuint16 * )( void * )( &__IPSBAR[ 0x150002 ] ) )\r
75 #define MCF_PIT_PCSR0                   ( *( vuint16 * )( void * )( &__IPSBAR[ 0x150000 ] ) )\r
76 #define MCF_PIT_PCSR_PRE(x)             ( ( ( x ) & 0x000F ) << 8 )\r
77 #define MCF_PIT_PCSR_EN                 ( 0x0001 )\r
78 #define MCF_PIT_PCSR_RLD                ( 0x0002 )\r
79 #define MCF_PIT_PCSR_PIF                ( 0x0004 )\r
80 #define MCF_PIT_PCSR_PIE                ( 0x0008 )\r
81 #define MCF_PIT_PCSR_OVW                ( 0x0010 )\r
82 #define MCF_INTC0_ICR36                 ( *( vuint8 * )( void * )( &__IPSBAR[ 0x000C64 ] ) )\r
83 #define MCF_INTC0_IMRH                  ( *( vuint32 * )( void * )( &__IPSBAR[ 0x000C08 ] ) )\r
84 #define MCF_INTC0_IMRH_INT_MASK36       ( 0x00000010 )\r
85 #define MCF_INTC0_IMRH_MASKALL          ( 0x00000001 )\r
86 #define MCF_INTC0_ICRn_IP(x)            ( ( ( x ) & 0x07 ) << 0 )\r
87 #define MCF_INTC0_ICRn_IL(x)            ( ( ( x ) & 0x07 ) << 3 )\r
88 \r
89 #define portNO_CRITICAL_NESTING         ( ( uint32_t ) 0 )\r
90 #define portINITIAL_CRITICAL_NESTING    ( ( uint32_t ) 10 )\r
91 \r
92 /* ------------------------ Static variables ------------------------------ */\r
93 volatile uint32_t              ulCriticalNesting = portINITIAL_CRITICAL_NESTING;\r
94 \r
95 /* ------------------------ Static functions ------------------------------ */\r
96 #if configUSE_PREEMPTION == 0\r
97 static void prvPortPreemptiveTick ( void ) __attribute__ ((interrupt_handler));\r
98 #else\r
99 static void prvPortPreemptiveTick ( void );\r
100 #endif\r
101 \r
102 /* ------------------------ Start implementation -------------------------- */\r
103 \r
104 StackType_t *\r
105 pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode,\r
106                        void *pvParameters )\r
107 {\r
108     /* Place the parameter on the stack in the expected location. */\r
109     *pxTopOfStack = ( StackType_t ) pvParameters;\r
110     pxTopOfStack--;\r
111 \r
112     /* Place dummy return address on stack. Tasks should never terminate so\r
113      * we can set this to anything. */\r
114     *pxTopOfStack = ( StackType_t ) 0;\r
115     pxTopOfStack--;\r
116 \r
117     /* Create a Motorola Coldfire exception stack frame. First comes the return\r
118      * address. */\r
119     *pxTopOfStack = ( StackType_t ) pxCode;\r
120     pxTopOfStack--;\r
121 \r
122     /* Format, fault-status, vector number for exception stack frame. Task\r
123      * run in supervisor mode. */\r
124     *pxTopOfStack = 0x40002000UL | ( portVECTOR_SYSCALL + 32 ) << 18;\r
125     pxTopOfStack--;\r
126 \r
127     /* Set the initial critical section nesting counter to zero. This value\r
128      * is used to restore the value of ulCriticalNesting. */\r
129     *pxTopOfStack = 0;\r
130     *pxTopOfStack--;\r
131 \r
132     *pxTopOfStack = ( StackType_t ) 0xA6;    /* A6 / FP */\r
133     pxTopOfStack--;\r
134     *pxTopOfStack = ( StackType_t ) 0xA5;    /* A5 */\r
135     pxTopOfStack--;\r
136     *pxTopOfStack = ( StackType_t ) 0xA4;    /* A4 */\r
137     pxTopOfStack--;\r
138     *pxTopOfStack = ( StackType_t ) 0xA3;    /* A3 */\r
139     pxTopOfStack--;\r
140     *pxTopOfStack = ( StackType_t ) 0xA2;    /* A2 */\r
141     pxTopOfStack--;\r
142     *pxTopOfStack = ( StackType_t ) 0xA1;    /* A1 */\r
143     pxTopOfStack--;\r
144     *pxTopOfStack = ( StackType_t ) 0xA0;    /* A0 */\r
145     pxTopOfStack--;\r
146     *pxTopOfStack = ( StackType_t ) 0xD7;    /* D7 */\r
147     pxTopOfStack--;\r
148     *pxTopOfStack = ( StackType_t ) 0xD6;    /* D6 */\r
149     pxTopOfStack--;\r
150     *pxTopOfStack = ( StackType_t ) 0xD5;    /* D5 */\r
151     pxTopOfStack--;\r
152     *pxTopOfStack = ( StackType_t ) 0xD4;    /* D4 */\r
153     pxTopOfStack--;\r
154     *pxTopOfStack = ( StackType_t ) 0xD3;    /* D3 */\r
155     pxTopOfStack--;\r
156     *pxTopOfStack = ( StackType_t ) 0xD2;    /* D2 */\r
157     pxTopOfStack--;\r
158     *pxTopOfStack = ( StackType_t ) 0xD1;    /* D1 */\r
159     pxTopOfStack--;\r
160     *pxTopOfStack = ( StackType_t ) 0xD0;    /* D0 */\r
161 \r
162     return pxTopOfStack;\r
163 }\r
164 \r
165 /*\r
166  * Called by portYIELD() or taskYIELD() to manually force a context switch.\r
167  */\r
168 static void\r
169 prvPortYield( void )\r
170 {\r
171     asm volatile ( "move.w  #0x2700, %sr\n\t" );\r
172 #if _GCC_USES_FP == 1\r
173     asm volatile ( "unlk %fp\n\t" );\r
174 #endif\r
175      /* Perform the context switch.  First save the context of the current task. */\r
176     portSAVE_CONTEXT(  );\r
177 \r
178     /* Find the highest priority task that is ready to run. */\r
179     vTaskSwitchContext(  );\r
180 \r
181     /* Restore the context of the new task. */\r
182     portRESTORE_CONTEXT(  );\r
183 }\r
184 \r
185 #if configUSE_PREEMPTION == 0\r
186 /*\r
187  * The ISR used for the scheduler tick depends on whether the cooperative or\r
188  * the preemptive scheduler is being used.\r
189  */\r
190 static void\r
191 prvPortPreemptiveTick ( void )\r
192 {\r
193     /* The cooperative scheduler requires a normal IRQ service routine to\r
194      * simply increment the system tick.\r
195      */\r
196 \r
197     xTaskIncrementTick();\r
198     MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;\r
199 }\r
200 \r
201 #else\r
202 \r
203 static void\r
204 prvPortPreemptiveTick( void )\r
205 {\r
206     asm volatile ( "move.w  #0x2700, %sr\n\t" );\r
207 #if _GCC_USES_FP == 1\r
208     asm volatile ( "unlk %fp\n\t" );\r
209 #endif\r
210     portSAVE_CONTEXT(  );\r
211     MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIF;\r
212     if( xTaskIncrementTick() != pdFALSE )\r
213         {\r
214                 vTaskSwitchContext(  );\r
215         }\r
216     portRESTORE_CONTEXT(  );\r
217 }\r
218 #endif\r
219 \r
220 void\r
221 vPortEnterCritical()\r
222 {\r
223     /* FIXME: We should store the old IPL here - How are we supposed to do\r
224      * this.\r
225      */\r
226     ( void )portSET_IPL( portIPL_MAX );\r
227 \r
228     /* Now interrupts are disabled ulCriticalNesting can be accessed\r
229      * directly.  Increment ulCriticalNesting to keep a count of how many times\r
230      * portENTER_CRITICAL() has been called. */\r
231     ulCriticalNesting++;\r
232 }\r
233 \r
234 void\r
235 vPortExitCritical()\r
236 {\r
237     if( ulCriticalNesting > portNO_CRITICAL_NESTING )\r
238     {\r
239         /* Decrement the nesting count as we are leaving a critical section. */\r
240         ulCriticalNesting--;\r
241 \r
242         /* If the nesting level has reached zero then interrupts should be\r
243         re-enabled. */\r
244         if( ulCriticalNesting == portNO_CRITICAL_NESTING )\r
245         {\r
246             ( void )portSET_IPL( 0 );\r
247         }\r
248     }\r
249 }\r
250 \r
251 BaseType_t\r
252 xPortStartScheduler( void )\r
253 {\r
254     extern void     ( *portVECTOR_TABLE[  ] ) (  );\r
255 \r
256     /* Add entry in vector table for yield system call. */\r
257     portVECTOR_TABLE[ portVECTOR_SYSCALL ] = prvPortYield;\r
258     /* Add entry in vector table for periodic timer. */\r
259     portVECTOR_TABLE[ portVECTOR_TIMER ] = prvPortPreemptiveTick;\r
260 \r
261     /* Configure the timer for the system clock. */\r
262     if ( configTICK_RATE_HZ > 0)\r
263     {\r
264         /* Configure prescaler */\r
265         MCF_PIT_PCSR0 = MCF_PIT_PCSR_PRE( 0x9 ) | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_OVW;\r
266         /* Initialize the periodic timer interrupt. */\r
267         MCF_PIT_PMR0 = MCF_PIT_MODULUS_REGISTER( configTICK_RATE_HZ );\r
268         /* Configure interrupt priority and level and unmask interrupt. */\r
269         MCF_INTC0_ICR36 = MCF_INTC0_ICRn_IL( 0x1 ) | MCF_INTC0_ICRn_IP( 0x1 );\r
270         MCF_INTC0_IMRH &= ~( MCF_INTC0_IMRH_INT_MASK36 | MCF_INTC0_IMRH_MASKALL );\r
271         /* Enable interrupts */\r
272         MCF_PIT_PCSR0 |= MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_EN | MCF_PIT_PCSR_PIF;\r
273     }\r
274 \r
275     /* Restore the context of the first task that is going to run. */\r
276     portRESTORE_CONTEXT(  );\r
277 \r
278     /* Should not get here. */\r
279     return pdTRUE;\r
280 }\r
281 \r
282 void\r
283 vPortEndScheduler( void )\r
284 {\r
285 }\r