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 #ifndef PORTMACRO_H
30 #define PORTMACRO_H
31 
32 /* *INDENT-OFF* */
33 #ifdef __cplusplus
34     extern "C" {
35 #endif
36 /* *INDENT-ON* */
37 
38 /* BSP includes. */
39 #include <mb_interface.h>
40 #include <xparameters.h>
41 
42 /*-----------------------------------------------------------
43  * Port specific definitions.
44  *
45  * The settings in this file configure FreeRTOS correctly for the
46  * given hardware and compiler.
47  *
48  * These settings should not be altered.
49  *-----------------------------------------------------------
50  */
51 
52 /* Type definitions. */
53 #define portCHAR              char
54 #define portFLOAT             float
55 #define portDOUBLE            double
56 #define portLONG              long
57 #define portSHORT             short
58 #ifdef __arch64__
59     #define portSTACK_TYPE    size_t
60     typedef uint64_t        UBaseType_t;
61 #else
62     #define portSTACK_TYPE    uint32_t
63     typedef unsigned long   UBaseType_t;
64 #endif
65 #define portBASE_TYPE         long
66 
67 typedef portSTACK_TYPE      StackType_t;
68 typedef long                BaseType_t;
69 
70 
71 #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
72     typedef uint16_t        TickType_t;
73     #define portMAX_DELAY              ( TickType_t ) 0xffff
74 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
75     typedef uint32_t     TickType_t;
76     #define portMAX_DELAY              ( TickType_t ) 0xffffffffUL
77 
78 /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
79  * not need to be guarded with a critical section. */
80     #define portTICK_TYPE_IS_ATOMIC    1
81 #else
82     #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
83 #endif
84 /*-----------------------------------------------------------*/
85 
86 /* Interrupt control macros and functions. */
87 void microblaze_disable_interrupts( void );
88 void microblaze_enable_interrupts( void );
89 #define portDISABLE_INTERRUPTS()    microblaze_disable_interrupts()
90 #define portENABLE_INTERRUPTS()     microblaze_enable_interrupts()
91 /*-----------------------------------------------------------*/
92 
93 /* Critical section macros. */
94 void vPortEnterCritical( void );
95 void vPortExitCritical( void );
96 #define portENTER_CRITICAL()                           \
97     {                                                  \
98         extern volatile UBaseType_t uxCriticalNesting; \
99         microblaze_disable_interrupts();               \
100         uxCriticalNesting++;                           \
101     }
102 
103 #define portEXIT_CRITICAL()                            \
104     {                                                  \
105         extern volatile UBaseType_t uxCriticalNesting; \
106         /* Interrupts are disabled, so we can */       \
107         /* access the variable directly. */            \
108         uxCriticalNesting--;                           \
109         if( uxCriticalNesting == 0 )                   \
110         {                                              \
111             /* The nesting has unwound and we \
112              * can enable interrupts again. */ \
113             portENABLE_INTERRUPTS();           \
114         }                                      \
115     }
116 
117 /*-----------------------------------------------------------*/
118 
119 /* The yield macro maps directly to the vPortYield() function. */
120 void vPortYield( void );
121 #define portYIELD()    vPortYield()
122 
123 /* portYIELD_FROM_ISR() does not directly call vTaskSwitchContext(), but instead
124  * sets a flag to say that a yield has been requested.  The interrupt exit code
125  * then checks this flag, and calls vTaskSwitchContext() before restoring a task
126  * context, if the flag is not false.  This is done to prevent multiple calls to
127  * vTaskSwitchContext() being made from a single interrupt, as a single interrupt
128  * can result in multiple peripherals being serviced. */
129 extern volatile uint32_t ulTaskSwitchRequested;
130 #define portYIELD_FROM_ISR( x )                              \
131     do { if( ( x ) != pdFALSE ) ulTaskSwitchRequested = 1; } \
132     while( 0 )
133 
134 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
135 
136 /* Generic helper function. */
ucPortCountLeadingZeros(uint32_t ulBitmap)137     __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
138     {
139         uint8_t ucReturn;
140 
141         __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
142 
143         return ucReturn;
144     }
145 
146 /* Check the configuration. */
147     #if ( configMAX_PRIORITIES > 32 )
148         #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
149     #endif
150 
151 /* Store/clear the ready priorities in a bit map. */
152     #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )    ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
153     #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )     ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
154 
155 /*-----------------------------------------------------------*/
156 
157     #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
158 
159 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
160 
161 /*-----------------------------------------------------------*/
162 
163 /* Hardware specifics. */
164 #ifdef __arch64__
165     #define portBYTE_ALIGNMENT    8
166 #else
167     #define portBYTE_ALIGNMENT    4
168 #endif
169 #define portSTACK_GROWTH          ( -1 )
170 #define portTICK_PERIOD_MS        ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
171 #define portNOP()    asm volatile ( "NOP" )
172 #define portMEMORY_BARRIER()    asm volatile ( "" ::: "memory" )
173 /*-----------------------------------------------------------*/
174 
175 #if ( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
176     #define portHAS_STACK_OVERFLOW_CHECKING    1
177 #endif
178 /*-----------------------------------------------------------*/
179 
180 /* Task function macros as described on the FreeRTOS.org WEB site. */
181 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
182 #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
183 /*-----------------------------------------------------------*/
184 
185 /* The following structure is used by the FreeRTOS exception handler.  It is
186  * filled with the MicroBlaze context as it was at the time the exception occurred.
187  * This is done as an aid to debugging exception occurrences. */
188 typedef struct PORT_REGISTER_DUMP
189 {
190     /* The following structure members hold the values of the MicroBlaze
191      * registers at the time the exception was raised. */
192     UINTPTR ulR1_SP;
193     UINTPTR ulR2_small_data_area;
194     UINTPTR ulR3;
195     UINTPTR ulR4;
196     UINTPTR ulR5;
197     UINTPTR ulR6;
198     UINTPTR ulR7;
199     UINTPTR ulR8;
200     UINTPTR ulR9;
201     UINTPTR ulR10;
202     UINTPTR ulR11;
203     UINTPTR ulR12;
204     UINTPTR ulR13_read_write_small_data_area;
205     UINTPTR ulR14_return_address_from_interrupt;
206     UINTPTR ulR15_return_address_from_subroutine;
207     UINTPTR ulR16_return_address_from_trap;
208     UINTPTR ulR17_return_address_from_exceptions; /* The exception entry code will copy the BTR into R17 if the exception occurred in the delay slot of a branch instruction. */
209     UINTPTR ulR18;
210     UINTPTR ulR19;
211     UINTPTR ulR20;
212     UINTPTR ulR21;
213     UINTPTR ulR22;
214     UINTPTR ulR23;
215     UINTPTR ulR24;
216     UINTPTR ulR25;
217     UINTPTR ulR26;
218     UINTPTR ulR27;
219     UINTPTR ulR28;
220     UINTPTR ulR29;
221     UINTPTR ulR30;
222     UINTPTR ulR31;
223     UINTPTR ulPC;
224     UINTPTR ulESR;
225     UINTPTR ulMSR;
226     UINTPTR ulEAR;
227     UINTPTR ulFSR;
228     UINTPTR ulEDR;
229 
230     /* A human readable description of the exception cause.  The strings used
231      * are the same as the #define constant names found in the
232      * microblaze_exceptions_i.h header file */
233     int8_t * pcExceptionCause;
234 
235     /* The human readable name of the task that was running at the time the
236      * exception occurred.  This is the name that was given to the task when the
237      * task was created using the FreeRTOS xTaskCreate() API function. */
238     char * pcCurrentTaskName;
239 
240     /* The handle of the task that was running a the time the exception
241      * occurred. */
242     void * xCurrentTaskHandle;
243 } xPortRegisterDump;
244 
245 
246 /*
247  * Installs pxHandler as the interrupt handler for the peripheral specified by
248  * the ucInterruptID parameter.
249  *
250  * ucInterruptID:
251  *
252  * The ID of the peripheral that will have pxHandler assigned as its interrupt
253  * handler.  Peripheral IDs are defined in the xparameters.h header file, which
254  * is itself part of the BSP project.  For example, in the official demo
255  * application for this port, xparameters.h defines the following IDs for the
256  * four possible interrupt sources:
257  *
258  * XPAR_INTC_0_UARTLITE_1_VEC_ID  -  for the UARTlite peripheral.
259  * XPAR_INTC_0_TMRCTR_0_VEC_ID    -  for the AXI Timer 0 peripheral.
260  * XPAR_INTC_0_EMACLITE_0_VEC_ID  -  for the Ethernet lite peripheral.
261  * XPAR_INTC_0_GPIO_1_VEC_ID      -  for the button inputs.
262  *
263  *
264  * pxHandler:
265  *
266  * A pointer to the interrupt handler function itself.  This must be a void
267  * function that takes a (void *) parameter.
268  *
269  *
270  * pvCallBackRef:
271  *
272  * The parameter passed into the handler function.  In many cases this will not
273  * be used and can be NULL.  Some times it is used to pass in a reference to
274  * the peripheral instance variable, so it can be accessed from inside the
275  * handler function.
276  *
277  *
278  * pdPASS is returned if the function executes successfully.  Any other value
279  * being returned indicates that the function did not execute correctly.
280  */
281 BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID,
282                                          XInterruptHandler pxHandler,
283                                          void * pvCallBackRef );
284 
285 
286 /*
287  * Enables the interrupt, within the interrupt controller, for the peripheral
288  * specified by the ucInterruptID parameter.
289  *
290  * ucInterruptID:
291  *
292  * The ID of the peripheral that will have its interrupt enabled in the
293  * interrupt controller.  Peripheral IDs are defined in the xparameters.h header
294  * file, which is itself part of the BSP project.  For example, in the official
295  * demo application for this port, xparameters.h defines the following IDs for
296  * the four possible interrupt sources:
297  *
298  * XPAR_INTC_0_UARTLITE_1_VEC_ID  -  for the UARTlite peripheral.
299  * XPAR_INTC_0_TMRCTR_0_VEC_ID    -  for the AXI Timer 0 peripheral.
300  * XPAR_INTC_0_EMACLITE_0_VEC_ID  -  for the Ethernet lite peripheral.
301  * XPAR_INTC_0_GPIO_1_VEC_ID      -  for the button inputs.
302  *
303  */
304 void vPortEnableInterrupt( uint8_t ucInterruptID );
305 
306 /*
307  * Disables the interrupt, within the interrupt controller, for the peripheral
308  * specified by the ucInterruptID parameter.
309  *
310  * ucInterruptID:
311  *
312  * The ID of the peripheral that will have its interrupt disabled in the
313  * interrupt controller.  Peripheral IDs are defined in the xparameters.h header
314  * file, which is itself part of the BSP project.  For example, in the official
315  * demo application for this port, xparameters.h defines the following IDs for
316  * the four possible interrupt sources:
317  *
318  * XPAR_INTC_0_UARTLITE_1_VEC_ID  -  for the UARTlite peripheral.
319  * XPAR_INTC_0_TMRCTR_0_VEC_ID    -  for the AXI Timer 0 peripheral.
320  * XPAR_INTC_0_EMACLITE_0_VEC_ID  -  for the Ethernet lite peripheral.
321  * XPAR_INTC_0_GPIO_1_VEC_ID      -  for the button inputs.
322  *
323  */
324 void vPortDisableInterrupt( uint8_t ucInterruptID );
325 
326 /*
327  * This is an application defined callback function used to install the tick
328  * interrupt handler.  It is provided as an application callback because the
329  * kernel will run on lots of different MicroBlaze and FPGA configurations - not
330  * all of which will have the same timer peripherals defined or available.  This
331  * example uses the AXI Timer 0.  If that is available on your hardware platform
332  * then this example callback implementation should not require modification.
333  * The name of the interrupt handler that should be installed is vPortTickISR(),
334  * which the function below declares as an extern.
335  */
336 void vApplicationSetupTimerInterrupt( void );
337 
338 /*
339  * This is an application defined callback function used to clear whichever
340  * interrupt was installed by the the vApplicationSetupTimerInterrupt() callback
341  * function - in this case the interrupt generated by the AXI timer.  It is
342  * provided as an application callback because the kernel will run on lots of
343  * different MicroBlaze and FPGA configurations - not all of which will have the
344  * same timer peripherals defined or available.  This example uses the AXI Timer 0.
345  * If that is available on your hardware platform then this example callback
346  * implementation should not require modification provided the example definition
347  * of vApplicationSetupTimerInterrupt() is also not modified.
348  */
349 void vApplicationClearTimerInterrupt( void );
350 
351 /*
352  * vPortExceptionsInstallHandlers() is only available when the MicroBlaze
353  * is configured to include exception functionality, and
354  * configINSTALL_EXCEPTION_HANDLERS is set to 1 in FreeRTOSConfig.h.
355  *
356  * vPortExceptionsInstallHandlers() installs the FreeRTOS exception handler
357  * for every possible exception cause.
358  *
359  * vPortExceptionsInstallHandlers() can be called explicitly from application
360  * code.  After that is done, the default FreeRTOS exception handler that will
361  * have been installed can be replaced for any specific exception cause by using
362  * the standard Xilinx library function microblaze_register_exception_handler().
363  *
364  * If vPortExceptionsInstallHandlers() is not called explicitly by the
365  * application, it will be called automatically by the kernel the first time
366  * xPortInstallInterruptHandler() is called.  At that time, any exception
367  * handlers that may have already been installed will be replaced.
368  *
369  * See the description of vApplicationExceptionRegisterDump() for information
370  * on the processing performed by the FreeRTOS exception handler.
371  */
372 void vPortExceptionsInstallHandlers( void );
373 
374 /*
375  * The FreeRTOS exception handler fills an xPortRegisterDump structure (defined
376  * in portmacro.h) with the MicroBlaze context, as it was at the time the
377  * exception occurred.  The exception handler then calls
378  * vApplicationExceptionRegisterDump(), passing in the completed
379  * xPortRegisterDump structure as its parameter.
380  *
381  * The FreeRTOS kernel provides its own implementation of
382  * vApplicationExceptionRegisterDump(), but the kernel provided implementation
383  * is declared as being 'weak'.  The weak definition allows the application
384  * writer to provide their own implementation, should they wish to use the
385  * register dump information.  For example, an implementation could be provided
386  * that wrote the register dump data to a display, or a UART port.
387  */
388 void vApplicationExceptionRegisterDump( xPortRegisterDump * xRegisterDump );
389 
390 
391 /* *INDENT-OFF* */
392 #ifdef __cplusplus
393     }
394 #endif
395 /* *INDENT-ON* */
396 
397 #endif /* PORTMACRO_H */