This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Error While building freertos_demo project

Other Parts Discussed in Thread: EK-TM4C1294XL, TM4C1294NCPDT

Hi,

I am using CCS 6.1.0.00104 and TivaWare_C_Series-2.1.1.71 for EK-TM4C1294XL

Imported freertos_demo project in workspace. Created a copy of the project as freeRTOS_2 in the same work space.

Made some changes in FreeRTOSConfig.h file for creating Timer tasks and changed configCPU_CLOCK_HZ. But those changes were not reflected. The reason was in Project => Build Settings => ARM Comiler, one of include path was pointing to freertos_demo project.

I changed this to point to freeRTOS_2 and after that when I tried to build the project it is showing many errors of variable not found. If I keep freertos_demo path than it is working fine.

Attached screenshot for error and the zip code. Can you help me out why this issue is happening?

Thanks,
Bhavesh

freeRTOS_2.zip

  • Hi Bravesh,

    This post is related to an example provided as part of the TivaWare product. I am moving it to the TM4C forum in hopes of a quicker response.

    Regards,
    -- Emmanuel
  • Hello Bhavesh

    The path are relative to the TivaWare. Since there is no directory called freeRTOS_2 in the TivaWare installation it will not work.

    Regards
    Amit
  • Hi Amit,

    So does it means that we have to manage settings in another project? Also the include path in compiler is pointed to project stored in local WorkSpace not to installation directory. And when I deleted the freertos_demo project from WorkSpace it is giving same error.

    Configuration settings should not take from installation directory instead it should be from Current Project. Otherwise it will create issues for future development or enhancements in project/s.

    Is there any solution or work around for this?

    Thanks,
    Bhavesh

  • Hello Bhavesh

    Why is main.h included in the freeRTOSConfig.h?

    Regards
    Amit
  • Hi Amit,

    My plan is not to include library files in all .c and .h files. Instead I created a main.h which will have all library includes as well as all extern variable defined and include this main.h in each file for reference.

    I renamed it but still getting same error.

    Thanks,
    Bhavesh

  • Hello Bhavesh,

    What is very strange is that you are using PART_TM4C1294NCPDT which does not have LCD Controller being referred to by the file pinout.c

    I am getting errors for the same. Please cleanup your project first...

    Regards
    Amit
  • Hi Amit,

    I have modified pinout.c in my local directory. This was a linked resource and it directly refers to one in Drivers directory in Tivaware. So it was not included in attached code.

    Please find attached the same.

    Thanks,
    Bhavesh

    //*****************************************************************************
    //
    // pinout.c - Function to configure the device pins on the DK-TM4C129X.
    //
    // Copyright (c) 2013-2015 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.1.71 of the DK-TM4C129X Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "drivers/pinout.h"
    
    //*****************************************************************************
    //
    //! \addtogroup pinout_api
    //! @{
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //! Configures the device pins for the standard usages on the DK-TM4C129X.
    //!
    //! This function enables the GPIO modules and configures the device pins for
    //! the default, standard usages on the DK-TM4C129X.  Applications that require
    //! alternate configurations of the device pins can either not call this
    //! function and take full responsibility for configuring all the device pins,
    //! or can reconfigure the required device pins after calling this function.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    PinoutSet(bool bEthernet, bool bUSB)
    {
        //
        // Enable all the GPIO peripherals.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    
        //
        // PA0-1 are used for UART0.
        //
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // PB0-1/PD6/PL6-7 are used for USB.
        // PQ4 can be used as a power fault detect on this board but it is not
        // the hardware peripheral power fault input pin.
        //
        if(bUSB)
        {
            HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
            HWREG(GPIO_PORTD_BASE + GPIO_O_CR) = 0xff;
            ROM_GPIOPinConfigure(GPIO_PD6_USB0EPEN);
            ROM_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
            ROM_GPIOPinTypeUSBDigital(GPIO_PORTD_BASE, GPIO_PIN_6);
            ROM_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);
            ROM_GPIOPinTypeGPIOInput(GPIO_PORTQ_BASE, GPIO_PIN_4);
        }
        else
        {
            //
            // Keep the default config for most pins used by USB.
            // Add a pull down to PD6 to turn off the TPS2052 switch
            //
            ROM_GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_6);
            MAP_GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA,
                                 GPIO_PIN_TYPE_STD_WPD);
    
        }
    
        //
        // PF0/PF4 are used for Ethernet LEDs.
        //
        if(bEthernet)
        {
            //
            // this app wants to configure for ethernet LED function.
            //
            ROM_GPIOPinConfigure(GPIO_PF0_EN0LED0);
            ROM_GPIOPinConfigure(GPIO_PF4_EN0LED1);
    
            GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
    
        }
        else
        {
    
            //
            // This app does not want Ethernet LED function so configure as
            // standard outputs for LED driving.
            //
            ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
    
            //
            // Default the LEDs to OFF.
            //
            ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, 0);
            MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4,
                                 GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD);
    
    
        }
    
        //
        // PJ0 and J1 are used for user buttons
        //
        ROM_GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        ROM_GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1, 0);
    
        //
        // PN0 and PN1 are used for USER LEDs.
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        MAP_GPIOPadConfigSet(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1,
                                 GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD);
    
        //
        // Default the LEDs to OFF.
        //
        ROM_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1, 0);
    }
    
    //*****************************************************************************
    //
    //! Configures the USB pins for ULPI connection to an external USB PHY.
    //!
    //! This function configures the USB ULPI pins to connect the DK-TM4C129X board
    //! to an external USB PHY in ULPI mode.  This allows the external PHY to act
    //! as an external high-speed phy for the DK-TM4C129X.  This function must be
    //! called after the call to PinoutSet() to properly configure the pins.
    //!
    //! \return None.
    //
    //*****************************************************************************
    #ifdef USE_ULPI
    void
    USBULPIPinoutSet(void)
    {
        //
        // Enable all the peripherals that are used by the ULPI interface.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
    
        //
        // ULPI Port B pins.
        //
        ROM_GPIOPinConfigure(GPIO_PB2_USB0STP);
        ROM_GPIOPinConfigure(GPIO_PB3_USB0CLK);
        ROM_GPIOPinTypeUSBDigital(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
        GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3,
                         GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD);
    
        //
        // ULPI Port P pins.
        //
        ROM_GPIOPinConfigure(GPIO_PP2_USB0NXT);
        ROM_GPIOPinConfigure(GPIO_PP3_USB0DIR);
        ROM_GPIOPinConfigure(GPIO_PP4_USB0D7);
        ROM_GPIOPinConfigure(GPIO_PP5_USB0D6);
        ROM_GPIOPinTypeUSBDigital(GPIO_PORTP_BASE, GPIO_PIN_2 | GPIO_PIN_3 |
                                                   GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPadConfigSet(GPIO_PORTP_BASE,
                         GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5,
                         GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD);
    
        //
        // ULPI Port L pins.
        //
        ROM_GPIOPinConfigure(GPIO_PL5_USB0D5);
        ROM_GPIOPinConfigure(GPIO_PL4_USB0D4);
        ROM_GPIOPinConfigure(GPIO_PL3_USB0D3);
        ROM_GPIOPinConfigure(GPIO_PL2_USB0D2);
        ROM_GPIOPinConfigure(GPIO_PL1_USB0D1);
        ROM_GPIOPinConfigure(GPIO_PL0_USB0D0);
        ROM_GPIOPinTypeUSBDigital(GPIO_PORTL_BASE, GPIO_PIN_0 | GPIO_PIN_1 |
                                                   GPIO_PIN_2 | GPIO_PIN_3 |
                                                   GPIO_PIN_4 | GPIO_PIN_5);
        GPIOPadConfigSet(GPIO_PORTL_BASE,
                         GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
                         GPIO_PIN_4 | GPIO_PIN_5,
                         GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD);
        //
        // ULPI Port M pins used to control the external USB oscillator and the
        // external USB phy on the DK-TM4C129X-DPHY board.
        //
        // PM1 - Enables the USB oscillator on the DK-TM4C129X-DPHY board.
        // PM3 - Enables the USB phy on the DK-TM4C129X-DPHY board.
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_1 | GPIO_PIN_3);
        ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1 | GPIO_PIN_3, GPIO_PIN_1 |
                                                                   GPIO_PIN_3);
    }
    #endif
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    

  • Hello Bhavesh,

    Files missing are display_task.h and spider_task.h. Also FS_ROOT is undeclared. Can you share the settings and files?

    Regards
    Amit
  • Hi Amit,

    I am testing the code on EK-TM4C1294XL board which does not have support for Display. So I have removed files from project and made code changes to stop referring to them. But if required please find files attached.

    About FS_ROOT, I did not find the same in original DK-129x project. So I am not sure what that path corresponds to. If you can give me hint I can give you answer on that.

    Thanks,
    Bhavesh

    //*****************************************************************************
    //
    // random.c - Random number generator utilizing MD4 hash function of
    //            environmental noise captured as the seed and a linear congruence
    //            generator for the random numbers.
    //
    // Copyright (c) 2005-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "random.h"
    
    //*****************************************************************************
    //
    // The pool of entropy that has been collected.
    //
    //*****************************************************************************
    static uint32_t g_pui32RandomEntropy[16];
    
    //*****************************************************************************
    //
    // The index of the next byte to be added to the entropy pool.
    //
    //*****************************************************************************
    static uint32_t g_ui32RandomIndex = 0;
    
    //*****************************************************************************
    //
    // The random number seed, which corresponds to the most recently returned
    // random number.  This is set based on the entropy-generated random number
    // by RandomSeed().
    //
    //*****************************************************************************
    static uint32_t g_ui32RandomSeed = 0;
    
    //*****************************************************************************
    //
    // Add entropy to the pool.
    //
    //*****************************************************************************
    void
    RandomAddEntropy(uint32_t ui32Entropy)
    {
        //
        // Add this byte to the entropy pool.
        //
        ((uint8_t *)g_pui32RandomEntropy)[g_ui32RandomIndex] = ui32Entropy & 0xff;
    
        //
        // Increment to the next byte of the entropy pool.
        //
        g_ui32RandomIndex = (g_ui32RandomIndex + 1) & 63;
    }
    
    //*****************************************************************************
    //
    // Seed the random number generator by running a MD4 hash on the entropy pool.
    // Note that the entropy pool may change from beneath us, but for the purposes
    // of generating random numbers that is not a concern.  Also, the MD4 hash was
    // broken long ago, but since it is being used to generate random numbers
    // instead of providing security this is not a concern.
    //
    //*****************************************************************************
    void
    RandomSeed(void)
    {
        uint32_t ui32A, ui32B, ui32C, ui32D, ui32Temp, ui32Idx;
    
        //
        // Initialize the digest.
        //
        ui32A = 0x67452301;
        ui32B = 0xefcdab89;
        ui32C = 0x98badcfe;
        ui32D = 0x10325476;
    
        //
        // Perform the first round of operations.
        //
    #define F(a, b, c, d, k, s)                                                  \
        {                                                                        \
            ui32Temp = a + (d ^ (b & (c ^ d))) + g_pui32RandomEntropy[k];        \
            a = (ui32Temp << s) | (ui32Temp >> (32 - s));                        \
        }
        for(ui32Idx = 0; ui32Idx < 16; ui32Idx += 4)
        {
            F(ui32A, ui32B, ui32C, ui32D, ui32Idx + 0, 3);
            F(ui32D, ui32A, ui32B, ui32C, ui32Idx + 1, 7);
            F(ui32C, ui32D, ui32A, ui32B, ui32Idx + 2, 11);
            F(ui32B, ui32C, ui32D, ui32A, ui32Idx + 3, 19);
        }
    
        //
        // Perform the second round of operations.
        //
    #define G(a, b, c, d, k, s)                                                  \
        {                                                                        \
            ui32Temp = a + ((b & c) | (b & d) | (c & d)) +                       \
                       g_pui32RandomEntropy[k] +   0x5a827999;                   \
            a = (ui32Temp << s) | (ui32Temp >> (32 - s));                        \
        }
        for(ui32Idx = 0; ui32Idx < 4; ui32Idx++)
        {
            G(ui32A, ui32B, ui32C, ui32D, ui32Idx + 0, 3);
            G(ui32D, ui32A, ui32B, ui32C, ui32Idx + 4, 5);
            G(ui32C, ui32D, ui32A, ui32B, ui32Idx + 8, 9);
            G(ui32B, ui32C, ui32D, ui32A, ui32Idx + 12, 13);
        }
    
        //
        // Perform the third round of operations.
        //
    #define H(a, b, c, d, k, s)                                                  \
        {                                                                        \
            ui32Temp = a + (b ^ c ^ d) + g_pui32RandomEntropy[k] + 0x6ed9eba1;   \
            a = (ui32Temp << s) | (ui32Temp >> (32 - s));                        \
        }
        for(ui32Idx = 0; ui32Idx < 4; ui32Idx += 2)
        {
            H(ui32A, ui32B, ui32C, ui32D, ui32Idx + 0, 3);
            H(ui32D, ui32A, ui32B, ui32C, ui32Idx + 8, 9);
            H(ui32C, ui32D, ui32A, ui32B, ui32Idx + 4, 11);
            H(ui32B, ui32C, ui32D, ui32A, ui32Idx + 12, 15);
    
            if(ui32Idx == 2)
            {
                ui32Idx -= 3;
            }
        }
    
        //
        // Use the first word of the resulting digest as the random number seed.
        //
        g_ui32RandomSeed = ui32A + 0x67452301;
    }
    
    //*****************************************************************************
    //
    // Generate a new random number.  The number returned would more accruately be
    // described as a pseudo-random number since a linear congruence generator is
    // being used.
    //
    //*****************************************************************************
    uint32_t
    RandomNumber(void)
    {
        //
        // Generate a new pseudo-random number with a linear congruence random
        // number generator.  This new random number becomes the seed for the next
        // random number.
        //
        g_ui32RandomSeed = (g_ui32RandomSeed * 1664525) + 1013904223;
    
        //
        // Return the new random number.
        //
        return(g_ui32RandomSeed);
    }
    
    random.h
    //*****************************************************************************
    //
    // spider_task.c - Tasks to animate a set of spiders on the LCD, one task per
    //                 spider.
    //
    // Copyright (c) 2009-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_types.h"
    #include "driverlib/interrupt.h"
    #include "grlib/grlib.h"
    #include "grlib/widget.h"
    #include "drivers/touch.h"
    #include "display_task.h"
    #include "idle_task.h"
    #include "images.h"
    #include "priorities.h"
    #include "random.h"
    #include "freertos_demo.h"
    #include "spider_task.h"
    #include "FreeRTOS.h"
    #include "task.h"
    #include "queue.h"
    #include "semphr.h"
    //*****************************************************************************
    //
    // The stack size for the spider control task.
    //
    //*****************************************************************************
    # define STACKSIZE_CONTROLTASK  128
    
    //*****************************************************************************
    //
    // The stack sizes for the spider tasks.
    //
    //*****************************************************************************
    # define STACKSIZE_SPIDERTASK   128
    
    //*****************************************************************************
    //
    // The following define the screen area in which the spiders are allowed to
    // roam
    //
    //*****************************************************************************
    #define AREA_X                  8
    #define AREA_Y                  24
    #define AREA_WIDTH              303
    #define AREA_HEIGHT             (231 - 24 - 20)
    
    //*****************************************************************************
    //
    // The size of the spider images.
    //
    //*****************************************************************************
    #define SPIDER_WIDTH            24
    #define SPIDER_HEIGHT           24
    
    //*****************************************************************************
    //
    // The following define the extents of the centroid of the spiders.
    //
    //*****************************************************************************
    #define SPIDER_MIN_X            (AREA_X + (SPIDER_WIDTH / 2))
    #define SPIDER_MAX_X            (AREA_X + AREA_WIDTH - (SPIDER_WIDTH / 2))
    #define SPIDER_MIN_Y            (AREA_Y + (SPIDER_HEIGHT / 2))
    #define SPIDER_MAX_Y            (AREA_Y + AREA_HEIGHT - (SPIDER_HEIGHT / 2))
    
    //*****************************************************************************
    //
    // The item size, queue size, and memory size for the spider control message
    // queue.
    //
    //*****************************************************************************
    #define CONTROL_ITEM_SIZE       sizeof(unsigned long)
    #define CONTROL_QUEUE_SIZE      10
    
    //*****************************************************************************
    //
    // The queue that holds messages sent to the spider control task.
    //
    //*****************************************************************************
    static xQueueHandle g_pControlQueue;
    
    //*****************************************************************************
    //
    // The amount the spider moves horizontally for each direction of movement.
    //
    // For this and all subsequent arrays that are indexed by direction of
    // movement, the indices are as follows:
    //
    //     0 => right
    //     1 => right and down
    //     2 => down
    //     3 => left and down
    //     4 => left
    //     5 => left and up
    //     6 => up
    //     7 => right and up
    //
    //*****************************************************************************
    static const int32_t g_pi32SpiderStepX[8] =
    {
        1, 1, 0, -1, -1, -1, 0, 1
    };
    
    //*****************************************************************************
    //
    // The amount the spider moves vertically for each direction of movement.
    //
    //*****************************************************************************
    static const int32_t g_pi32SpiderStepY[8] =
    {
        0, 1, 1, 1, 0, -1, -1, -1
    };
    
    //*****************************************************************************
    //
    // The animation images for the spider, two per direction of movement.  In
    // other words, entries 0 and 1 correspond to direction 0 (right), entries 2
    // and 3 correspond to direction 1 (right and down), etc.
    //
    //*****************************************************************************
    static const uint8_t *g_ppui8SpiderImage[16] =
    {
        g_pui8SpiderR1Image,
        g_pui8SpiderR2Image,
        g_pui8SpiderDR1Image,
        g_pui8SpiderDR2Image,
        g_pui8SpiderD1Image,
        g_pui8SpiderD2Image,
        g_pui8SpiderDL1Image,
        g_pui8SpiderDL2Image,
        g_pui8SpiderL1Image,
        g_pui8SpiderL2Image,
        g_pui8SpiderUL1Image,
        g_pui8SpiderUL2Image,
        g_pui8SpiderU1Image,
        g_pui8SpiderU2Image,
        g_pui8SpiderUR1Image,
        g_pui8SpiderUR2Image
    };
    
    //*****************************************************************************
    //
    // The number of ticks to delay a spider task based on the direction of
    // movement.  This array has only two entries; the first corresponding to
    // horizontal and vertical movement, and the second corresponding to diagonal
    // movement.  By having the second entry be 1.4 times the first, the spiders
    // are updated slower when moving along the diagonal to compensate for the
    // fact that each step is further (since it is moving one step in both the
    // horizontal and vertical).
    //
    //*****************************************************************************
    uint32_t g_pui32SpiderDelay[2];
    
    //*****************************************************************************
    //
    // The horizontal position of the spiders.
    //
    //*****************************************************************************
    static int32_t g_pi32SpiderX[MAX_SPIDERS];
    
    //*****************************************************************************
    //
    // The vertical position of the spiders.
    //
    //*****************************************************************************
    static int32_t g_pi32SpiderY[MAX_SPIDERS];
    
    //*****************************************************************************
    //
    // A bitmap that indicates which spiders are alive (which corresponds to a
    // running task for that spider).
    //
    //*****************************************************************************
    static uint32_t g_ui32SpiderAlive;
    
    //*****************************************************************************
    //
    // A bitmap that indicates which spiders have been killed (by touching them).
    //
    //*****************************************************************************
    static uint32_t g_ui32SpiderDead;
    xTaskHandle g_sSpiderTask; // FIXME
    //*****************************************************************************
    //
    // Determines if a given point collides with one of the spiders.  The spider
    // specified is ignored when doing collision detection in order to prevent a
    // false collision with itself (when checking to see if it is safe to move the
    // spider).
    //
    //*****************************************************************************
    static int32_t
    SpiderCollide(int32_t i32Spider, int32_t i32X, int32_t i32Y)
    {
        int32_t i32Idx, i32DX, i32DY;
    
        //
        // Loop through all the spiders.
        //
        for(i32Idx = 0; i32Idx < MAX_SPIDERS; i32Idx++)
        {
            //
            // Skip this spider if it is not alive or is the spider that should be
            // ignored.
            //
            if((HWREGBITW(&g_ui32SpiderAlive, i32Idx) == 0) ||
               (i32Idx == i32Spider))
            {
                continue;
            }
    
            //
            // Compute the horizontal and vertical difference between this spider's
            // position and the point in question.
            //
            i32DX = ((g_pi32SpiderX[i32Idx] > i32X) ?
                     (g_pi32SpiderX[i32Idx] - i32X) :
                     (i32X - g_pi32SpiderX[i32Idx]));
            i32DY = ((g_pi32SpiderY[i32Idx] > i32Y) ?
                     (g_pi32SpiderY[i32Idx] - i32Y) :
                     (i32Y - g_pi32SpiderY[i32Idx]));
    
            //
            // Return this spider index if the point in question collides with it.
            //
            if((i32DX < SPIDER_WIDTH) && (i32DY < SPIDER_HEIGHT))
            {
                return(i32Idx);
            }
        }
    
        //
        // No collision was detected.
        //
        return(-1);
    }
    
    //*****************************************************************************
    //
    // This task manages the scurrying about of a spider.
    //
    //*****************************************************************************
    static void
    SpiderTask(void *pvParameters)
    {
        uint32_t ui32Dir, ui32Image, ui32Temp;
        int32_t i32X, i32Y, i32Spider;
    
        //
        // Get the spider number from the parameter.
        //
        i32Spider = (long)pvParameters;
    
        //
        // Add the current tick count to the random entropy pool.
        //
        RandomAddEntropy(xTaskGetTickCount());
    
        //
        // Reseed the random number generator.
        //
        RandomSeed();
    
        //
        // Indicate that this spider is alive.
        //
        HWREGBITW(&g_ui32SpiderAlive, i32Spider) = 1;
    
        //
        // Indicate that this spider is not dead yet.
        //
        HWREGBITW(&g_ui32SpiderDead, i32Spider) = 0;
    
        //
        // Get a local copy of the spider's starting position.
        //
        i32X = g_pi32SpiderX[i32Spider];
        i32Y = g_pi32SpiderY[i32Spider];
    
        //
        // Choose a random starting direction for the spider.
        //
        ui32Dir = RandomNumber() >> 29;
    
        //
        // Start by displaying the first of the two spider animation images.
        //
        ui32Image = 0;
    
        //
        // Loop forever.
        //
        while(1)
        {
            //
            // See if this spider has been killed.
            //
            if(HWREGBITW(&g_ui32SpiderDead, i32Spider) == 1)
            {
                //
                // Wait for 2 seconds.
                //
                vTaskDelay((1000 / portTICK_RATE_MS) * 2);
    
                //
                // Clear the spider from the display.
                //
                DisplayImage(i32X - (SPIDER_WIDTH / 2), i32Y - (SPIDER_HEIGHT / 2),
                             g_pui8SpiderBlankImage);
    
                //
                // Indicate that this spider is not alive.
                //
                HWREGBITW(&g_ui32SpiderAlive, i32Spider) = 0;
    
                //
                // Delete the current task.  This should never return.
                //
                vTaskDelete(NULL);
    
                //
                // In case it does return, loop forever.
                //
                while(1)
                {
                }
            }
    
            //
            // Enter a critical section while the next move for the spider is
            // determined.  Having more than one spider trying to move at a time
            // (via preemption) would make the collision detection check fail.
            //
            taskENTER_CRITICAL();
    
            //
            // Move the spider.
            //
            i32X += g_pi32SpiderStepX[ui32Dir];
            i32Y += g_pi32SpiderStepY[ui32Dir];
    
            //
            // See if the spider has cross the boundary of its area, if it has
            // collided with another spider, or if random chance says that the
            // spider should turn despite not having collided with anything.
            //
            if((i32X < SPIDER_MIN_X) || (i32X > SPIDER_MAX_X) ||
               (i32Y < SPIDER_MIN_Y) || (i32Y > SPIDER_MAX_Y) ||
               (SpiderCollide(i32Spider, i32X, i32Y) != -1) ||
               (RandomNumber() < 0x08000000))
            {
                //
                // Undo the previous movement of the spider.
                //
                i32X -= g_pi32SpiderStepX[ui32Dir];
                i32Y -= g_pi32SpiderStepY[ui32Dir];
    
                //
                // Get a random number to determine the turn to be made.
                //
                ui32Temp = RandomNumber();
    
                //
                // Determine how to turn the spider based on the random number.
                // Half the time the spider turns to the left and half the time it
                // turns to the right.  Of each half, it turns a quarter of a turn
                // 12.5% of the time and an eighth of a turn 87.5% of the time.
                //
                if(ui32Temp < 0x10000000)
                {
                    ui32Dir = (ui32Dir + 2) & 7;
                }
                else if(ui32Temp < 0x80000000)
                {
                    ui32Dir = (ui32Dir + 1) & 7;
                }
                else if(ui32Temp < 0xf0000000)
                {
                    ui32Dir = (ui32Dir - 1) & 7;
                }
                else
                {
                    ui32Dir = (ui32Dir - 2) & 7;
                }
            }
    
            //
            // Update the position of the spider.
            //
            g_pi32SpiderX[i32Spider] = i32X;
            g_pi32SpiderY[i32Spider] = i32Y;
    
            //
            // Exit the critical section now that the spider has been moved.
            //
            taskEXIT_CRITICAL();
    
            //
            // Have the display task draw the spider at the new position.  Since
            // there is a one pixel empty border around all the images, and the
            // position of the spider is incremented by only one pixel, this also
            // erases any traces of the spider in its previous position.
            //
            DisplayImage(i32X - (SPIDER_WIDTH / 2), i32Y - (SPIDER_HEIGHT / 2),
                         g_ppui8SpiderImage[(ui32Dir * 2) + ui32Image]);
    
            //
            // Toggle the spider animation index.
            //
            ui32Image ^= 1;
    
            //
            // Delay this task for an amount of time based on the direction the
            // spider is moving.
            //
            vTaskDelay(g_pui32SpiderDelay[ui32Dir & 1]);
    
            //
            // Add the new tick count to the random entropy pool.
            //
            RandomAddEntropy(xTaskGetTickCount());
    
            //
            // Reseed the random number generator.
            //
            RandomSeed();
        }
    }
    
    //*****************************************************************************
    //
    // Creates a spider task.
    //
    //*****************************************************************************
    static uint32_t
    CreateSpider(int32_t i32X, int32_t i32Y)
    {
        uint32_t ui32Spider;
    
        //
        // Search to see if there is a spider task available.
        //
        for(ui32Spider = 0; ui32Spider < MAX_SPIDERS; ui32Spider++)
        {
            if(HWREGBITW(&g_ui32SpiderAlive, ui32Spider) == 0)
            {
                break;
            }
        }
    
        //
        // Return a failure if no spider tasks are available (in other words, the
        // maximum number of spiders are already alive).
        //
        if(ui32Spider == MAX_SPIDERS)
        {
            return(1);
        }
    
        //
        // Adjust the starting horizontal position to make sure it is inside the
        // allowable area for the spiders.
        //
        if(i32X < SPIDER_MIN_X)
        {
            i32X = SPIDER_MIN_X;
        }
        else if(i32X > SPIDER_MAX_X)
        {
            i32X = SPIDER_MAX_X;
        }
    
        //
        // Adjust the starting vertical position to make sure it is inside the
        // allowable area for the spiders.
        //
        if(i32Y < SPIDER_MIN_Y)
        {
            i32Y = SPIDER_MIN_Y;
        }
        else if(i32Y > SPIDER_MAX_Y)
        {
            i32Y = SPIDER_MAX_Y;
        }
    
        //
        // Save the starting position for this spider.
        //
        g_pi32SpiderX[ui32Spider] = i32X;
        g_pi32SpiderY[ui32Spider] = i32Y;
    
        //
        // Create a task to animate this spider.
        //
        if(xTaskCreate(SpiderTask, (signed portCHAR *)"Spider",
                       STACKSIZE_SPIDERTASK, (void *)ui32Spider,
                       tskIDLE_PRIORITY + PRIORITY_SPIDER_TASK, NULL) != pdTRUE)
        {
            return(1);
        }
    
        //
        // Success.
        //
        return(0);
    }
    
    //*****************************************************************************
    //
    // The callback function for messages from the touch screen driver.
    //
    //*****************************************************************************
    static int32_t
    ControlTouchCallback(uint32_t ui32Message, int32_t i32X, int32_t i32Y)
    {
        portBASE_TYPE bTaskWaken;
    
        //
        // Ignore all messages other than pointer down messages.
        //
        if(ui32Message != WIDGET_MSG_PTR_DOWN)
        {
            return(0);
        }
    
        //
        // Pack the position into a message to send to the spider control task.
        //
        ui32Message = ((i32X & 65535) << 16) | (i32Y & 65535);
    
        //
        // Send the position message to the spider control task.
        //
        xQueueSendFromISR(g_pControlQueue, &ui32Message, &bTaskWaken);
    
        //
        // Perform a task yield if necessary.
        //
    #if defined(__Check_Later)
        taskYIELD_FROM_ISR(bTaskWaken);
    #endif
    
        //
        // This message has been handled.
        //
        return(0);
    }
    
    //*****************************************************************************
    //
    // Determines if a given touch screen point collides with one of the spiders.
    //
    //*****************************************************************************
    static int32_t
    SpiderTouchCollide(int32_t i32X, int32_t i32Y)
    {
        int32_t i32Idx, i32DX, i32DY, i32Best, i32Dist;
    
        //
        // Until a collision is found, there is no best spider choice.
        //
        i32Best = -1;
        i32Dist = 1000000;
    
        //
        // Loop through all the spiders.
        //
        for(i32Idx = 0; i32Idx < MAX_SPIDERS; i32Idx++)
        {
            //
            // Skip this spider if it is not alive.
            //
            if((HWREGBITW(&g_ui32SpiderAlive, i32Idx) == 0) ||
               (HWREGBITW(&g_ui32SpiderDead, i32Idx) == 1))
            {
                continue;
            }
    
            //
            // Compute the horizontal and vertical difference between this spider's
            // position and the point in question.
            //
            i32DX = ((g_pi32SpiderX[i32Idx] > i32X) ?
                     (g_pi32SpiderX[i32Idx] - i32X) :
                     (i32X - g_pi32SpiderX[i32Idx]));
            i32DY = ((g_pi32SpiderY[i32Idx] > i32Y) ?
                     (g_pi32SpiderY[i32Idx] - i32Y) :
                     (i32Y - g_pi32SpiderY[i32Idx]));
    
            //
            // See if the point in question collides with this spider.
            //
            if((i32DX < (SPIDER_WIDTH + 4)) && (i32DY < (SPIDER_HEIGHT + 4)))
            {
                //
                // Compute distance (squared) between this point and the spider.
                //
                i32DX = (i32DX * i32DX) + (i32DY * i32DY);
    
                //
                // See if this spider is closer to the point in question than any
                // other spider encountered.
                //
                if(i32DX < i32Dist)
                {
                    //
                    // Save this spider as the new best choice.
                    //
                    i32Best = i32Idx;
                    i32Dist = i32DX;
                }
            }
        }
    
        //
        // Return the best choice, if one was found.
        //
        if(i32Best != -1)
        {
            return(i32Best);
        }
    
        //
        // Loop through all the spiders.  This time, the spiders that are dead but
        // not cleared from the screen are not ignored.
        //
        for(i32Idx = 0; i32Idx < MAX_SPIDERS; i32Idx++)
        {
            //
            // Skip this spider if it is not alive.
            //
            if(HWREGBITW(&g_ui32SpiderAlive, i32Idx) == 0)
            {
                continue;
            }
    
            //
            // Compute the horizontal and vertical difference between this spider's
            // position and the point in question.
            //
            i32DX = ((g_pi32SpiderX[i32Idx] > i32X) ?
                     (g_pi32SpiderX[i32Idx] - i32X) :
                     (i32X - g_pi32SpiderX[i32Idx]));
            i32DY = ((g_pi32SpiderY[i32Idx] > i32Y) ?
                     (g_pi32SpiderY[i32Idx] - i32Y) :
                     (i32Y - g_pi32SpiderY[i32Idx]));
    
            //
            // See if the point in question collides with this spider.
            //
            if((i32DX < (SPIDER_WIDTH + 4)) && (i32DY < (SPIDER_HEIGHT + 4)))
            {
                //
                // Compute distance (squared) between this point and the spider.
                //
                i32DX = (i32DX * i32DX) + (i32DY * i32DY);
    
                //
                // See if this spider is closer to the point in question than any
                // other spider encountered.
                //
                if(i32DX < i32Dist)
                {
                    //
                    // Save this spider as the new best choice.
                    //
                    i32Best = i32Idx;
                    i32Dist = i32DX;
                }
            }
        }
    
        //
        // Return the best choice, if one was found.
        //
        return(i32Best);
    }
    
    //*****************************************************************************
    //
    // This task provides overall control of the spiders, spawning and killing them
    // in response to presses on the touch screen.
    //
    //*****************************************************************************
    static void
    ControlTask(void *pvParameters)
    {
        uint32_t ui32Message;
        int32_t i32X, i32Y, i32Spider;
    
        //
        // Initialize the touch screen driver and register a callback function.
        //
        TouchScreenInit(g_ui32SysClock);
        TouchScreenCallbackSet(ControlTouchCallback);
    
        //
        // Lower the priority of the touch screen interrupt handler.  This is
        // required so that the interrupt handler can safely call the interrupt-
        // safe FreeRTOS functions (specifically to send messages to the queue).
        //
        IntPrioritySet(INT_ADC0SS3, 0xc0);
    
        //
        // Loop forever.
        //
        while(1)
        {
            //
            // Read the next message from the queue.
            //
            if(xQueueReceive(g_pControlQueue, &ui32Message, portMAX_DELAY) ==
               pdPASS)
            {
                //
                // Extract the position of the screen touch from the message.
                //
                i32X = ui32Message >> 16;
                i32Y = ui32Message & 65535;
    
                //
                // Ignore this screen touch if it is not inside the spider area.
                //
                if((i32X >= AREA_X) && (i32X < (AREA_X + AREA_WIDTH)) &&
                   (i32Y >= AREA_Y) && (i32Y < (AREA_Y + AREA_HEIGHT)))
                {
                    //
                    // See if this position collides with any of the spiders.
                    //
                    i32Spider = SpiderTouchCollide(i32X, i32Y);
                    if(i32Spider == -1)
                    {
                        //
                        // There is no collision, so create a new spider (if
                        // possible) at this position.
                        //
                        CreateSpider(i32X, i32Y);
                    }
                    else
                    {
                        //
                        // There is a collision, so kill this spider.
                        //
                        HWREGBITW(&g_ui32SpiderDead, i32Spider) = 1;
                    }
                }
            }
        }
    }
    
    //*****************************************************************************
    //
    // Sets the speed of the spiders by specifying the number of milliseconds
    // between updates to the spider's position.
    //
    //*****************************************************************************
    void
    SpiderSpeedSet(uint32_t ui32Speed)
    {
        //
        // Convert the update rate from milliseconds to ticks.  The second entry
        // of the array is 1.4 times the first so that updates when moving along
        // the diagonal, which are longer steps, are done less frequently by a
        // proportional amount.
        //
        g_pui32SpiderDelay[0] = (ui32Speed * (1000 / portTICK_RATE_MS)) / 1000;
        g_pui32SpiderDelay[1] = (ui32Speed * 14 * (1000 / portTICK_RATE_MS)) /
                                10000;
    }
    
    //*****************************************************************************
    //
    // Initializes the spider tasks.
    //
    //*****************************************************************************
    uint32_t
    SpiderTaskInit(void)
    {
        uint32_t ui32Idx;
    
        //
        // Set the initial speed of the spiders.
        //
        SpiderSpeedSet(10);
    
        //
        // Create a queue for sending messages to the spider control task.
        //
        g_pControlQueue = xQueueCreate(CONTROL_QUEUE_SIZE, CONTROL_QUEUE_SIZE);
        if(g_pControlQueue == NULL)
        {
            return(1);
        }
    
        //
        // Create the spider control task.
        //
        if(xTaskCreate(ControlTask, (signed portCHAR *)"ControlTask",
                       STACKSIZE_CONTROLTASK, NULL,
                       tskIDLE_PRIORITY + PRIORITY_CONTROL_TASK, &g_sSpiderTask) != pdTRUE)
        {// FIXME
            return(1);
        }
    
        //
        // Create eight spiders initially.
        //
        for(ui32Idx = 0; ui32Idx < 8; ui32Idx++)
        {
            //
            // Create a spider that is centered vertically and equally spaced
            // horizontally across the display.
            //
            if(CreateSpider((ui32Idx * (AREA_WIDTH / 8)) + (AREA_WIDTH / 16),
                            (AREA_HEIGHT / 2) + AREA_Y) == 1)
            {
                return(1);
            }
    
            //
            // Provide an early indication that this spider is alive.  The task is
            // not running yet (since this function is called before the scheduler
            // has been started) so this variable is not set by the task (yet).
            // Manually setting it allows the remaining initial spiders to be
            // created properly.
            //
            HWREGBITW(&g_ui32SpiderAlive, ui32Idx) = 1;
        }
    
        //
        // Success.
        //
        return(0);
    }
    
    spider_task.h
    //*****************************************************************************
    //
    // display_task.c - Task to display text and images on the LCD.
    //
    // Copyright (c) 2009-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "grlib/grlib.h"
    #include "drivers/kentec320x240x16_ssd2119.h"
    #include "display_task.h"
    #include "idle_task.h"
    #include "priorities.h"
    #include "FreeRTOS.h"
    #include "task.h"
    #include "queue.h"
    #include "semphr.h"
    //*****************************************************************************
    //
    // This structure defines the messages that are sent to the display task.
    //
    //*****************************************************************************
    typedef struct
    {
        uint32_t ui32Type;
        uint16_t ui16X;
        uint16_t ui16Y;
        const char *pcMessage;
    }
    
    tDisplayMessage;
    xTaskHandle g_sDisplayTask; // FIXME
    //*****************************************************************************
    //
    // The stack size for the display task.
    //
    //*****************************************************************************
    #define STACKSIZE_DISPLAYTASK   128
    
    //*****************************************************************************
    //
    // Defines to indicate the contents of the display message.
    //
    //*****************************************************************************
    #define DISPLAY_IMAGE           1
    #define DISPLAY_STRING          2
    #define DISPLAY_MOVE            3
    #define DISPLAY_DRAW            4
    
    //*****************************************************************************
    //
    // The item size, queue size, and memory size for the display message queue.
    //
    //*****************************************************************************
    #define DISPLAY_ITEM_SIZE       sizeof(tDisplayMessage)
    #define DISPLAY_QUEUE_SIZE      10
    
    //*****************************************************************************
    //
    // The queue that holds messages sent to the display task.
    //
    //*****************************************************************************
    static xQueueHandle g_pDisplayQueue;
    
    //*****************************************************************************
    //
    // The most recent position of the display pen.
    //
    //*****************************************************************************
    static uint32_t g_ui32DisplayX, g_ui32DisplayY;
    
    //*****************************************************************************
    //
    // This task receives messages from the other tasks and updates the display as
    // directed.
    //
    //*****************************************************************************
    static void
    DisplayTask(void *pvParameters)
    {
        tDisplayMessage sMessage;
        tContext sContext;
    
        //
        // Initialize the graphics library context.
        //
        GrContextInit(&sContext, &g_sKentec320x240x16_SSD2119);
        GrContextForegroundSet(&sContext, ClrWhite);
        GrContextBackgroundSet(&sContext, ClrBlack);
        GrContextFontSet(&sContext, g_psFontFixed6x8);
    
        //
        // Loop forever.
        //
        while(1)
        {
            //
            // Read the next message from the queue.
            //
            if(xQueueReceive(g_pDisplayQueue, &sMessage, portMAX_DELAY) == pdPASS)
            {
                //
                // Determine the message type.
                //
                switch(sMessage.ui32Type)
                {
                    //
                    // The drawing of an image has been requested.
                    //
                    case DISPLAY_IMAGE:
                    {
                        //
                        // Draw this image on the display.
                        //
                        GrImageDraw(&sContext, (uint8_t *)sMessage.pcMessage,
                                    sMessage.ui16X, sMessage.ui16Y);
    
                        //
                        // This message has been handled.
                        //
                        break;
                    }
    
                    //
                    // The drawing of a string has been requested.
                    //
                    case DISPLAY_STRING:
                    {
                        //
                        // Draw this string on the display.
                        //
                        GrStringDraw(&sContext, sMessage.pcMessage, -1,
                                     sMessage.ui16X, sMessage.ui16Y, 1);
    
                        //
                        // This message has been handled.
                        //
                        break;
                    }
    
                    //
                    // A move of the pen has been requested.
                    //
                    case DISPLAY_MOVE:
                    {
                        //
                        // Save the new pen position.
                        //
                        g_ui32DisplayX = sMessage.ui16X;
                        g_ui32DisplayY = sMessage.ui16Y;
    
                        //
                        // This message has been handled.
                        //
                        break;
                    }
    
                    //
                    // A draw with the pen has been requested.
                    //
                    case DISPLAY_DRAW:
                    {
                        //
                        // Draw a line from the previous pen position to the new
                        // pen position.
                        //
                        GrLineDraw(&sContext, g_ui32DisplayX, g_ui32DisplayY,
                                   sMessage.ui16X, sMessage.ui16Y);
    
                        //
                        // Save the new pen position.
                        //
                        g_ui32DisplayX = sMessage.ui16X;
                        g_ui32DisplayY = sMessage.ui16Y;
    
                        //
                        // This message has been handled.
                        //
                        break;
                    }
                }
            }
        }
    }
    
    //*****************************************************************************
    //
    // Sends a request to the display task to draw an image on the display.
    //
    //*****************************************************************************
    void
    DisplayImage(uint32_t ui16X, uint32_t ui16Y, const uint8_t *pui8Image)
    {
        tDisplayMessage sMessage;
    
        //
        // Construct the message to be sent.
        //
        sMessage.ui32Type = DISPLAY_IMAGE;
        sMessage.ui16X = ui16X;
        sMessage.ui16Y = ui16Y;
        sMessage.pcMessage = (char *)pui8Image;
    
        //
        // Send the image draw request to the display task.
        //
        xQueueSend(g_pDisplayQueue, &sMessage, portMAX_DELAY);
    }
    
    //*****************************************************************************
    //
    // Sends a request to the display task to draw a string on the display.
    //
    //*****************************************************************************
    void
    DisplayString(uint32_t ui16X, uint32_t ui16Y, const char *pcString)
    {
        tDisplayMessage sMessage;
    
        //
        // Construct the message to be sent.
        //
        sMessage.ui32Type = DISPLAY_STRING;
        sMessage.ui16X = ui16X;
        sMessage.ui16Y = ui16Y;
        sMessage.pcMessage = pcString;
    
        //
        // Send the string draw request to the display task.
        //
        xQueueSend(g_pDisplayQueue, &sMessage, portMAX_DELAY);
    }
    
    //*****************************************************************************
    //
    // Sends a request to the display task to move the pen.
    //
    //*****************************************************************************
    void
    DisplayMove(uint32_t ui16X, uint32_t ui16Y)
    {
        tDisplayMessage sMessage;
    
        //
        // Construct the message to be sent.
        //
        sMessage.ui32Type = DISPLAY_MOVE;
        sMessage.ui16X = ui16X;
        sMessage.ui16Y = ui16Y;
    
        //
        // Send the pen move request to the display task.
        //
        xQueueSend(g_pDisplayQueue, &sMessage, portMAX_DELAY);
    }
    
    //*****************************************************************************
    //
    // Sends a request to the display task to draw with the pen.
    //
    //*****************************************************************************
    void
    DisplayDraw(uint32_t ui16X, uint32_t ui16Y)
    {
        tDisplayMessage sMessage;
    
        //
        // Construct the message to be sent.
        //
        sMessage.ui32Type = DISPLAY_DRAW;
        sMessage.ui16X = ui16X;
        sMessage.ui16Y = ui16Y;
    
        //
        // Send the pen draw request to the display task.
        //
        xQueueSend(g_pDisplayQueue, &sMessage, portMAX_DELAY);
    }
    
    //*****************************************************************************
    //
    // Initializes the display task.
    //
    //*****************************************************************************
    uint32_t
    DisplayTaskInit(void)
    {
        //
        // Create a queue for sending messages to the display task.
        //
        g_pDisplayQueue = xQueueCreate(DISPLAY_QUEUE_SIZE, DISPLAY_ITEM_SIZE);
        if(g_pDisplayQueue == NULL)
        {
            return(1);
        }
    
        //
        // Create the display task.
        //
        if(xTaskCreate(DisplayTask, (signed portCHAR *)"Display",
                       STACKSIZE_DISPLAYTASK, NULL,
                       tskIDLE_PRIORITY + PRIORITY_DISPLAY_TASK, &g_sDisplayTask) !=  pdTRUE)
        { // FIXME
            return(1);
        }
    
        //
        // Success.
        //
        return(0);
    }
    

    display_task.himages.cimages.h

  • Hello Bhavesh,

    The file htmldata.h is commented and missing. I added the same from the main freertos_demo project and compile is now clean

    Regards
    Amit
  • Hi Amit,

    I am still getting the error even after adding the file. Also can you verify in Project => Build Settings => ARM compiler, include path is not pointing to --include_path="D:/tiNew/WorkSpace/freertos_demo".
    It is working fine if I keep the path as above. Can you please share your code with me?

    Thanks,
    Bhavesh

  • Hello Bhavesh,

    I do not have the paths as you have on your machine. So I had to change all of them to point to the default locations. I am not sure how useful will that be to you. By the way I added the file in the workspace.

    Regards
    Amit