Buscar este blog

jueves, 20 de noviembre de 2014

PRACTICA # 9 FREERTOS


  • 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