| Latest: FreeRTOS V7.1.1 was released May 1, 2012. View the change history. |
|
|||||||||||||||
|
Xilinx MicroBlaze Port
|
||||||||||||||
| Build configuration | Description |
| Blinky |
This is a very simple starter example. It creates two tasks,
one software timer, and also uses a button interrupt.
The two tasks communicate via a queue - the queue send task, and the queue receive task. The queue receive task toggles an LED each time it receives a value. Pressing any user button (SW4, SW5, SW7 or SW8) will generate an interrupt, the service routine for the interrupt resets a software timer before turning an LED on. The software timer has a five second period, and when the five seconds has expired, the software timer callback function turns the LED off again. Therefore, pressing a button will turn the LED on, and the LED will remain on until a full five seconds pass without a button being pressed again. The Blinky build configuration uses the main-blinky.c source file.
|
| Full |
This is a comprehensive demo that creates lots of tasks,
queues, semaphores (of various types) and software timers. It also
includes the embedded web server.
The Full build configuration creates a lot of tasks from the set of standard demo tasks. The standard demo tasks don't perform any particular function. Their purpose is firstly to test the FreeRTOS port, and secondly to provide examples of how to use the FreeRTOS API functions. Additional tasks created by the Full build configuration include:
|
Hardware setup
The demo application includes tasks that send and receive characters through a UART.
The characters sent by one task must be received by another. An error condition is
flagged if any character is missing, or received out of order.
There are two common ways of ensuring that every transmitted character is also received. The first is to use a loopback connector that links the transmit pin to the receive pin. The second is to connect the UART to an echo server. The SP605 hardware uses a UART to USB converter, removing the possibility of fitting a loopback connector. Therefore, in this case, the UART must be connected to an external echo server. During development, the free (Windows) Comm Echo utility was used for this purpose. Comm Echo can be downloaded from http://www.serialporttool.com/CommEcho.htm.
The required network setup is described in the following section.
The demo application uses the LEDs and buttons that are built onto the SP605 hardware, so no further hardware setup is required.
Network setup
The IP address assigned to the SP605 hardware is set by the constants
configIP_ADDR0 to configIP_ADDR3. These are specified at the bottom of the
FreeRTOSConfig.h header file (located in the FreeRTOS/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemo directory)
Constants that define the MAC address and the NET mask are located in the same place of
the same file.
The IP addresses used by the web browser and the SP605 hardware must be compatible. This can be ensured by making the first three octets of both IP addresses the same. For example, if the web browser computer uses IP address 192.168.0.1, then the SP605 development board can be given any address in the range 192.168.0.2 to 192.168.0.254 (other than any addresses that already exist on the same network).
The MAC address assigned to the SP605 must be unique on the network to which it is being attached.
Importing the demo application project into the SDK Eclipse workspace
To import the Xilinx Software Development Kit (SDK) project into an existing or new Eclipse Workspace:
Remember that only the RTOSDemo project needs to be built explicitly, and that the XPS project used to generate the hardware project is also provided in the FreeRTOS/Demo/MicroBlaze_Spartan-6_EthernetLite/PlatformStudioProject directory.
Note: The two build configurations each include and exclude different files in their respective builds. For example, the Full build configuration builds main-full.c, and the Blinky build configuration instead builds main-blinky.c. The Eclipse Project Explorer window should show an icon with a cross through it to indicate which files are excluded from the active build configuration. However - this particular functionality does not appear to be working correctly. Changing build configurations will ensure the correct files are built, and the correct files are excluded, but the Project Explorer windows will not necessarily update its icons correctly.
Running the demo application using the SDK tools
The Blinky and Full build configurations require separate debug configurations, and care must be taken to select the correct debug configuration each time a new debug session is started.
The Full build configuration will behave as follows:
The Blinky build configuration will behave as follows:

The served run time stats page - showing
how much CPU time each task has consumed
The third served page shows a large JPG image.
Callback functions that need to be supplied by the application
This is an application defined callback function used to install the tick interrupt handler. It is provided as an application callback, rather than being an integral part of the kernel port layer, because the kernel will run on lots of different MicroBlaze and FPGA configurations - not all of which will have the same timer peripherals defined or available.
vApplicationSetupTimerInterrupt() must install the kernel defined function vPortTickISR() as the tick interrupt handler.
The official demo application includes an example implementation of vApplicationSetupTimerInterrupt() in main-full.c and main-blinky.c. The example implementation uses the AXI Timer 0 as the tick interrupt source. If an AXI Timer 0 peripheral is available on your hardware platform, then the example implementation can be used without modification.
This is an application defined callback function used to clear whichever interrupt was installed by the the vApplicationSetupTimerInterrupt() callback function. It is provided as an application callback because the kernel will run on lots of different MicroBlaze and FPGA configurations - not all of which will have the same timer peripherals defined or available.
The official demo application includes an example implementation of vApplicationClearTimerInterrupt() in main-full.c and main-blinky.c. The example implementation complements the example implementation of vApplicationSetupTimerInterrupt() found in the same files by clearing the interrupt generated by the AXI Timer 0 peripheral. If your application does not modify the provided example implementation of vApplicationSetupTimerInterrupt(), then the provided example implementation of vApplicationClearTimerInterrupt() can also be used without any modification.
Implementing an interrupt service routines (ISR)
Functions that implement ISRs are normal C functions, but must conform to the following
prototype.
void ISRFunctionName( void *ISRParameter );
Context switching from an ISR
It is common for an ISR to cause a task to leave the Blocked
state. For example, consider the case where a task processes data that arrives
on a queue. When the queue is empty, there is no data to process, and the task
might opt to enter the Blocked state to wait for more data to become available.
If an ISR then sends data to the queue, the task would
automatically leave the Blocked state as the queue would no longer be empty.
If an ISR causes a task to leave the Blocked state, and the task that leaves the Blocked state has a priority that is higher than or equal to the currently executing task (the task that was interrupted), then a context switch should be performed in the ISR to ensure the ISR returns directly to the newly unblocked, higher priority task. The ISR will have interrupted one task, but returned to another.
The macro portYIELD_FROM_ISR() is an interrupt safe version of taskYIELD(). It takes a single parameter that, if none zero, will indirectly cause a context switch to occur. Below is an example use of portYIELD_FROM_ISR(), which is taken from the file serial.c in the official demo application:
/* Note that this function is called from the UART interrupt handler, it is not
itself an interrupt handler, so its prototype does not have to match that
required by all interrupt handlers. */
static void prvRxHandler( void *pvUnused, unsigned portBASE_TYPE uxByteCount )
{
signed char cRxedChar;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* While there are characters to process. */
while( XUartLite_IsReceiveEmpty( xUartLiteInstance.RegBaseAddress ) == pdFALSE )
{
/* Obtain the next character. */
cRxedChar = XUartLite_ReadReg( xUartLiteInstance.RegBaseAddress,
XUL_RX_FIFO_OFFSET);
/* Place the received character in the received queue. If writing to the
queue causes a task to leave the Blocked state, and the task has a
priority equal to or above the priority of the interrupted task, then
xHigherPriorityTaskWoken will automatically get set to pdTRUE inside the
xQueueSendFromISR() function itself. */
xQueueSendFromISR( xRxedChars, &cRxedChar, &xHigherPriorityTaskWoken );
}
/* Call portYIELD_FROM_ISR(), passing in xHigherPriorityTaskWoken. If
xHigherPriorityTaskWoken was set to pdTRUE inside xQueueSendFromISR(), then
calling portYIELD_FROM_ISR() here will cause the ISR
to return directly to the newly unblocked task. If xHigherPriorityTaskWoken
has retained its initialised value of pdFALSE, then calling
portYIELD_FROM_ISR() here will have no effect. */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
Installing and enabling an ISR
The following functions are provided for installing, enabling and disabling
interrupts (in the interrupt controller) respectively. The Xilinx BSP library
functions that have similar functionality must not be used.
An example of how to use these functions is contained in the implementation of vApplicationSetupTimerInterrupt(), which is contained in both main-full.c and main-blinky.c. Another example is contained in the implementation of prvSetupHardware() in main-blinky.c.
/*
* Installs pxHandler as the interrupt handler for the peripheral specified by
* the ucInterruptID parameter.
*
* ucInterruptID:
*
* The ID of the peripheral that will have pxHandler assigned as its interrupt
* handler. Peripheral IDs are defined in the xparameters.h header file, which
* is itself part of the BSP project. For example, in the official demo
* application for this port, xparameters.h defines the following IDs for the
* four possible interrupt sources:
*
* XPAR_INTC_0_UARTLITE_1_VEC_ID - for the UARTlite peripheral.
* XPAR_INTC_0_TMRCTR_0_VEC_ID - for the AXI Timer 0 peripheral.
* XPAR_INTC_0_EMACLITE_0_VEC_ID - for the Ethernet lite peripheral.
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
*
*
* pxHandler:
*
* A pointer to the interrupt handler function itself. This must be a void
* function that takes a (void *) parameter.
*
*
* pvCallBackRef:
*
* The parameter passed into the handler function. In many cases this will not
* be used and can be NULL. Some times it is used to pass in a reference to
* the peripheral instance variable, so it can be accessed from inside the
* handler function.
*
*
* pdPASS is returned if the function executes successfully. Any other value
* being returned indicates that the function did not execute correctly.
*/
portBASE_TYPE xPortInstallInterruptHandler( unsigned char ucInterruptID,
XInterruptHandler pxHandler, void *pvCallBackRef );
/*
* Enables the interrupt, within the interrupt controller, for the peripheral
* specified by the ucInterruptID parameter.
*
* ucInterruptID:
*
* The ID of the peripheral that will have its interrupt enabled in the
* interrupt controller. Peripheral IDs are defined in the xparameters.h header
* file, which is itself part of the BSP project. For example, in the official
* demo application for this port, xparameters.h defines the following IDs for
* the four possible interrupt sources:
*
* XPAR_INTC_0_UARTLITE_1_VEC_ID - for the UARTlite peripheral.
* XPAR_INTC_0_TMRCTR_0_VEC_ID - for the AXI Timer 0 peripheral.
* XPAR_INTC_0_EMACLITE_0_VEC_ID - for the Ethernet lite peripheral.
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
*
*/
void vPortEnableInterrupt( unsigned char ucInterruptID );
/*
* Disables the interrupt, within the interrupt controller, for the peripheral
* specified by the ucInterruptID parameter.
*
* ucInterruptID:
*
* The ID of the peripheral that will have its interrupt disabled in the
* interrupt controller. Peripheral IDs are defined in the xparameters.h header
* file, which is itself part of the BSP project. For example, in the official
* demo application for this port, xparameters.h defines the following IDs for
* the four possible interrupt sources:
*
* XPAR_INTC_0_UARTLITE_1_VEC_ID - for the UARTlite peripheral.
* XPAR_INTC_0_TMRCTR_0_VEC_ID - for the AXI Timer 0 peripheral.
* XPAR_INTC_0_EMACLITE_0_VEC_ID - for the Ethernet lite peripheral.
* XPAR_INTC_0_GPIO_1_VEC_ID - for the button inputs.
*
*/
void vPortDisableInterrupt( unsigned char ucInterruptID );
Exception handling (for advanced users only)
To enable FreeRTOS exception handling, first the MicroBlaze itself must be
configured to include exception handling functionality, and second
configINSTALL_EXCEPTION_HANDLERS must be set to 1 in FreeRTOSConfig.h.
Setting configINSTALL_EXCEPTION_HANDLERS to 1 will cause both the code and
data space consumed by the kernel to increase.
The following functions are provided to install the FreeRTOS exception handler, and process an exception when it occurs respectively. The functionality of the FreeRTOS exception handler itself is described in the comments above the function prototypes found in portmacro.h, and replicated below.
An example implementation of vApplicationExceptionRegisterDump() is provided in both main-full.c and main-blinky.c.
/* * vPortExceptionsInstallHandlers() is only available when the MicroBlaze * is configured to include exception functionality, and * configINSTALL_EXCEPTION_HANDLERS is set to 1 in FreeRTOSConfig.h. * * vPortExceptionsInstallHandlers() installs the FreeRTOS exception handler * for every possible exception cause. * * vPortExceptionsInstallHandlers() can be called explicitly from application * code. After that is done, the default FreeRTOS exception handler that will * have been installed can be replaced for any specific exception cause by using * the standard Xilinx library function microblaze_register_exception_handler(). * * If vPortExceptionsInstallHandlers() is not called explicitly by the * application, it will be called automatically by the kernel the first time * xPortInstallInterruptHandler() is called. At that time, any exception * handlers that may have already been installed will be replaced. * * See the description of vApplicationExceptionRegisterDump() for information * on the processing performed by the FreeRTOS exception handler. */ void vPortExceptionsInstallHandlers( void ); /* * The FreeRTOS exception handler fills an xPortRegisterDump structure (defined * in portmacro.h) with the MicroBlaze context, as it was at the time the * exception occurred. The exception handler then calls * vApplicationExceptionRegisterDump(), passing in a reference to the completed * xPortRegisterDump structure as its parameter. * * The FreeRTOS kernel provides its own implementation of * vApplicationExceptionRegisterDump(), but the kernel provided implementation * is declared as being 'weak'. The weak definition allows the application * writer to provide their own implementation, should they wish to use the * register dump information. For example, an implementation could be provided * that writes the register dump data to a display, or a UART port. */ void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump );
RTOS port specific configuration
The kernel and demo behaviour can be customised using the configuration constants
contained in the file FreeRTOS/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemo/FreeRTOSConfig.h.
The majority these configuration constants are used for all FreeRTOS ports, and are
described on the Customisation
page of this web site, and in the FreeRTOS Reference Manual.
The following constants are specific to this port:
/* If configINSTALL_EXCEPTION_HANDLERS is set to 1, then the kernel will automatically install its own exception handlers before the kernel is started, if the application writer has not already caused them to be installed using the vPortExceptionsInstallHandlers() API function. vPortExceptionsInstallHandlers() is described on this web page. */ #define configINSTALL_EXCEPTION_HANDLERS 1 /* configINTERRUPT_CONTROLLER_TO_USE must be set to the ID of the interrupt controller that is going to be used directly by FreeRTOS itself. Most hardware designs will only include on interrupt controller, so can use the same setting as shown here. XPAR_INTC_SINGLE_DEVICE_ID is itself defined in the xparameters.h header file, which is part of the Xilinx BSP library project. */ #define configINTERRUPT_CONTROLLER_TO_USE XPAR_INTC_SINGLE_DEVICE_ID
Memory allocation
Source/Portable/MemMang/heap_3.c is included in the MicroBlaze demo application makefile to provide the memory
allocation required by the real time kernel.
Please refer to the Memory Management section of the API documentation for
full information.
heap_3.c uses the standard malloc() and free() functions, called from within a scheduler lock section, to make them thread safe. The total available heap size is set at the top of the linker script located in the \Demo\MicroBlaze_Spartan-6_EthernetLite\SDKProjects\RTOSDemo\src directory.