- El objetivo de este documento es dar los pasos para implementar el Sistema Operativo FreeRTOS a la plataforma ZedBoard con el Zynq-7000 (xc7z020) y demostrar su funcionamiento por medio de un ejemplo de 3 tareas.
- Lo que se implementara:
1.- Pasos para correr FreeRTOS en
SDK
2.- Implementación de 3 tareas a
realizar en SDK.
a)
Tarea 1: Impresión de “HOLA MUNDO” vía UART del ZYNQ.
b)
Tarea 2: Encender LED’s de PL (Programmable Logic) de ZYNQ
c)
Tarea 3: Leer switch de PL de ZYNQ
3.- Construir interfaz AXI con
vivado para PS (Process System)
- INTERFAZ AXI CON VIVADO PARA PS
Iniciaremos creando por medio de
vivado el esquema de interconexión AXI para los led’s y switches.
A continuación se muestra el diagrama de bloques:
- Activando UART 1 de PS.
- Seleccionando 8 leds de la ZedBoard con AXI GPIO 0.
- Seleccionando 8 switch de la ZedBoard con AXI GPIO 1.
- Por ultimo crear HDL Wrapper y Output Products.
Y Generate Bitstream.
- Realizar exportación de hardware y Lanzar SDK.
- IMPLEMENTAR FreeRTOS EN SDK
- Hacer clic en Xilinx Tools/Repositories
- Clic en New y buscar la carpeta freertos_zynq_v1_02_a. Clic en Reescan Repositories, después Apply y por ultimo OK.
- Crear un Board Support Package
- Configuracion del Xilinx Board Support
- Crear un proyecto nuevo. File/Application Project
- Escoger como OS Plataform: Freertos_zynq después clic en next. Escogemos Hello World. Y por último Finish.
- Si llegara a existir algún error en el BSP al estar programando, se puede Re-generar nuevamente el código como se muestra en la siguiente figura. Haciendo clic derecho sobre la carpeta freertos_zynq_bsp_0.
- Implementar el siguiente código:
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "xil_printf.h"
#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xgpio.h"
// The
following constant is used to determine which channel of the GPIO is
// used for
the LED if there are 2 channels supported.
#define CHANNEL_1 1 // out 32 bits
#define CHANNEL_2 2 // out 32 bits
#define GPIO_ID_LEDS XPAR_AXI_GPIO_0_DEVICE_ID
#define GPIO_ID_SWITCH XPAR_AXI_GPIO_1_DEVICE_ID
/* Priorities
at which the tasks are created. */
#define HELLO_WORLD_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define LEDS_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define SWITCH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/*-----------------------------------------------------------*/
static void
taskHelloWorld( void *pvParameters
);
static void
taskLeds( void *pvParameters
);
static void
taskSwitch( void *pvParameters
);
/*
* This example creates two tasks were each
task prints a statement.
* Each task yields after it prints a message
which apppears on
* console alternatively. Sometimes, due to
scheduler algorithm the
* task might be pre-empted
before print could complete.
*/
/*-----------------------------------------------------------*/
XGpio
Gpio_0, Gpio_1; // The Instance of the GPIO Driver
int cnt=0;
int main( void )
{
int
Status;
init_platform();
// Initialize the
GPIO driver
Status =
XGpio_Initialize(&Gpio_0, GPIO_ID_LEDS);
if
(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status =
XGpio_Initialize(&Gpio_1, GPIO_ID_SWITCH);
if
(Status != XST_SUCCESS) {
return
XST_FAILURE;
}
// Clear the LEDs
XGpio_DiscreteWrite(&Gpio_0,
CHANNEL_1, 0);
prvInitializeExceptions();
/* Start the two
tasks */
xTaskCreate( taskHelloWorld, ( signed char
* ) "HELLO",
configMINIMAL_STACK_SIZE,
NULL,
HELLO_WORLD_TASK_PRIORITY,
NULL );
xTaskCreate( taskLeds, ( signed char
* ) "LEDS",
configMINIMAL_STACK_SIZE,
NULL,
LEDS_TASK_PRIORITY,
NULL );
xTaskCreate( taskSwitch, ( signed char
* ) "SWITCH",
configMINIMAL_STACK_SIZE,
NULL,
SWITCH_TASK_PRIORITY,
NULL );
/* Start the tasks
and timer running. */
vTaskStartScheduler();
/* If all is well,
the scheduler will now be running, and the following line
will never be reached. If the following line does execute, then
there was
insufficient FreeRTOS heap memory
available for the idle and/or timer tasks
to be created. See the memory management section on the
FreeRTOS web site
for more details. */
for(
;; );
}
long int
delay, ust_limit = 83333323;
/*-----------------------------------------------------------*/
static void
taskHelloWorld( void *pvParameters
)
{
portTickType
xNextWakeTime;
xNextWakeTime = xTaskGetTickCount();
for(
;; )
{
xil_printf("HELLO WORLD :)\r\n");
//for(delay=0;delay<ust_limit;delay++){};
vTaskDelayUntil(&xNextWakeTime,
500 / portTICK_RATE_MS );
taskYIELD();
}
}
/*-----------------------------------------------------------*/
static void
taskLeds( void *pvParameters
)
{
portTickType
xNextWakeTime;
xNextWakeTime = xTaskGetTickCount();
for(
;; )
{
XGpio_DiscreteWrite(&Gpio_0,
CHANNEL_1, cnt++);
//for(delay=0;delay<ust_limit;delay++){};
vTaskDelayUntil(&xNextWakeTime,
500 / portTICK_RATE_MS );
taskYIELD();
}
}
/*-----------------------------------------------------------*/
static void
taskSwitch( void *pvParameters
)
{
int
a=0;
portTickType
xNextWakeTime;
xNextWakeTime = xTaskGetTickCount();
for(
;; )
{
// Read state of push buttons and determine which ones changed
a = XGpio_DiscreteRead(&Gpio_1, CHANNEL_1);
xil_printf("
Switch = %d\n",
a);
//for(delay=0;delay<ust_limit;delay++){};
vTaskDelayUntil(&xNextWakeTime,
500 / portTICK_RATE_MS );
taskYIELD();
}
}
/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook( void )
{
/*
vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set
to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a
call to pvPortMalloc() fails.
pvPortMalloc() is called internally
by the kernel whenever a task, queue or
semaphore is created. It is also called by various parts of the demo
application. If heap_1.c or heap_2.c are used, then the
size of the heap
available to pvPortMalloc() is
defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the
xPortGetFreeHeapSize() API function can be used
to query the size of free heap space
that remains (although it does not
provide information on how the
remaining heap might be fragmented). */
taskDISABLE_INTERRUPTS();
for(
;; );
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char
*pcTaskName )
{
( void
) pcTaskName;
( void
) pxTask;
/*
vApplicationStackOverflowHook() will only be called if
configCHECK_FOR_STACK_OVERFLOW is
set to either 1 or 2. The handle and
name
of the offending task will be passed
into the hook function via its
parameters. However, when a stack has overflowed, it is
possible that the
parameters will have been corrupted,
in which case the pxCurrentTCB variable
can be inspected directly. */
taskDISABLE_INTERRUPTS();
for(
;; );
}
void vApplicationSetupHardware( void )
{
/* Do nothing */
}
- IMPLEMENTACION EXITOSA!
No hay comentarios.:
Publicar un comentario