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