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.

CCS/EK-TM4C1294XL: Blinking LED with UART Connection Need Help and Suggestions

Part Number: EK-TM4C1294XL
Other Parts Discussed in Thread: MIKROELEKTRONIKA, , SYSBIOS

Tool/software: Code Composer Studio

Hello i am new with the RTOS programming and i try finish up my project for university. 

In the project we  use a output module as a 7 segment. ( 2 digit ) from MIKROE - 1201 - 7seg Click - 2 digit - 5V, Mikroelektronika.

I made the SPI communication and the UART communication with the module.

On the terminal i can create tasks with a certain speed and the created tast is printing on the terminal with a certain period of time which is set by user. 

At the same time when we create a task on the 7 segment digit 1 display the task ID and the digit 2 display the speed of the task. 

I want to add a function which start a blinking a led on the board Tiva C series EK-TM4C1294XL Evaluation Kit Connected launch pad. 

Down below you can find the code that i prepared. 

/************************************************************
 * ============ empty_min.c - Produktion Line ============ *
 * *
 * Autor: 
 * Date: 07.10.2019 *
 *************************************************************

 **************************** Header Files ****************************/

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/ssi.h"
#include <driverlib/uart.h> // Supplies UART


// driver library for SPI peripheral
uint32_t g_ui32SysClock; // system clock in Hz
uint8_t font[10] = {0x7E, 0x0A, 0xB6, 0x9E, 0xCA, 0xDC, 0xFC, 0x0E, 0xFE, 0xDE}; // 7-Segment font, letters 0 to 9

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

/* TI-RTOS Header files */

#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/USBMSCHFatFs.h>

#include <ti/sysbios/knl/Semaphore.h>
//#include <ti/sysbios/knl/Mailbox.h>

/* Board Header file */
#include "Board.h"
#include "EK_TM4C1294XL.h"

/**************************** Compiler Commands ****************************/

#define TASKSTACKSIZE 512 // Max task size, see
#define MAX_TASKS 10 // max possible tasks

/**************************** Global variables & Structs ****************************/

Error_Block eb; // Error Block

/* UART0 Handle, Parameters and uart0 Semaphore */
UART_Handle uart0;
UART_Params uart0Params;

Semaphore_Struct sem_uart0_write_struct; // Semaphore save the uart0
Semaphore_Handle sem_uart0_write_handle;

/* Task Struct and Stacksize*/
Task_Struct task_Manager_Struct;
Char task_Manager_Stack[TASKSTACKSIZE];

Task_Struct taskStruct[MAX_TASKS];
Char taskStack[MAX_TASKS][TASKSTACKSIZE];

Task_Struct taskDisplayManagerStruct;
Char task_DisplayManager_Stack[TASKSTACKSIZE];

/* Global Variable */
bool show = 1;
int speed[MAX_TASKS]; // Task speed field
unsigned char buf[1]; // buffer for reading data from uart0

/**************************** Function definitions ****************************/
void itoc(int);
int ctoi(char);
/**************************** Tasks ****************************/


// Configuration of SPI (SSI3, on BoosterPack 2 connector, master mode, 9 Mbps)
void InitSpi(void) {

    // enable peripherals
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); // enable SSI3 (for SPI)
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); // enable port Q for SSI I/O-pins

    // configure pins as SSI3 pins
    GPIOPinConfigure(GPIO_PQ0_SSI3CLK); // Q0 for Clk
    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1); // Q3 for Master Output Slave Input (MOSI)
    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0); // Q2 for Master Input Slave Output (MISO)

    // configure pins for SSI3
    GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_0);

    // configure SSI3 communication
    // SSI base address (SSI3), SSI clk (120 MHz), data transfer protocol (Motorola Mode 0),
    // mode of operation (Master), SPI clock rate (9 Mbps), bits per frame (8)
    SSIConfigSetExpClk(SSI3_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 9000000, 8);

    SSIEnable(SSI3_BASE); // enable the SSI3 module

    // Configure latch pin for 74HC595 (7seg click)
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); // enable port Q
    GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_5, GPIO_PIN_5); // set pin P5 to 1
    GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_5); // configure pin P5 for output
}
//****************************************************************************


//****************************************************************************
// send byte over SPI on BoosterPack 2 connector, latch byte to outputs of 74HC595 (7seg click) after sending
void SpiSend (uint8_t data) {
    SSIDataPut(SSI3_BASE, data); // send byte over SPI
    SysCtlDelay(100); // wait until byte was sent

    GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_5, 0); // latch byte to outputs of 74HC595 (7seg click) with 0 on P5
    GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_5, GPIO_PIN_5); // set P5 back to 1
    // pulse width with no delay and optimization 2 is about 100 ns (measured), slow enough
}

void DisplayManager(UArg zehner, UArg einser)
{
    SpiSend(font[einser]); // output next digit
    SpiSend(font[zehner]);
    //Task_sleep(10);
}
/**************************** Tasks ****************************/

/* Slave Task */
int Slave_Task(UArg ID)
{
    Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER); // Save uart0, if uart0 is used, wait forever
    UART_write(uart0, "Task ", sizeof("Task ")); // write to uart0
    itoc(ID); // itoc - int to char
    UART_write(uart0, buf, 1);
    UART_write(uart0, " Started!\r\n", sizeof(" Started!\r\n"));
    Semaphore_post(sem_uart0_write_handle); // Free uart0
    Task_sleep(speed[ID]); // Task sleep for speed time

    while(1) // infinity loop
    {
        if(show) // show products in terminal if true
        {
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "Task ", sizeof("Task "));
            itoc(ID);
            UART_write(uart0, buf, 1);
            UART_write(uart0, " speed ", sizeof(" speed "));
            itoc(speed[ID]/1000);
            UART_write(uart0, buf, 1);
            UART_write(uart0, " \r\n", sizeof(" \r\n"));
            Semaphore_post(sem_uart0_write_handle);
        }
        Task_sleep(speed[ID]);
    }
}

/* Task Manager */
void Task_Manager(void) // Task Manager, control all Tasks and the Interface
{
    Task_Params taskParams; // Task Parameter
    Task_Params DisplayParams;
    int i, ID = 0; // ID to identify the Task
    char choice; // choice - for the command comming from uart0
    int durchschnitt = 0; // Variables

    Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER); // Save uart0
    UART_write(uart0, "\r\nCreate Task ...\r\n", sizeof("\r\nCreate Task ...\r\n")); // write uart0
    Semaphore_post(sem_uart0_write_handle); // Free uart0

    while(1)
    {
        UART_read(uart0, &choice, 1); // read from uart0 and save it to "choice"

        switch(choice) // switch case
        {
        /* t - changing last task speed */
        case 's':
            if(ID==0) // if no Task, break
                break;
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "\r\nEdit last task speed: ", sizeof("\r\nEdit last task speed: "));
            UART_read(uart0, &choice, 1);

            if((int)(choice-48)<=0 || (int)(choice-48)>=9) // ASCII input -> integer output
            {
                UART_write(uart0, " invalid Speed, only 1 to 9 allowed.\r\n", sizeof(" iinvalid Speed, only 1 to 9 allowed.\r\n"));
                break;
            }
            speed[ID-1] = (int)(choice-48)*1000; //ASCII -> int (48 == 0)

            UART_write(uart0, "\r\n", sizeof("\r\n"));
            Semaphore_post(sem_uart0_write_handle);
            break;

            /* n - create new Task */
        case 'n':
            if(ID>=10) // Max 10 Tasks (0-9)
                break;
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "Task speed: ", sizeof("Task speed: "));
            UART_write(uart0, "\r\n", sizeof("\r\n"));
            Semaphore_post(sem_uart0_write_handle);

            UART_read(uart0, &choice, 1);
            if((int)(choice-48)<=0 || (int)(choice-48)>=9)
            {
                UART_write(uart0, " invalid Speed, only 1 to 9 allowed.\r\n", sizeof(" invalid Speed, only 1 to 9 allowed.\r\n"));
                break;
            }

            speed[ID] = (int)(choice-48)*1000; //ASCII -> int (48 == 0)
            Task_Params_init(&taskParams);
            taskParams.arg0 = ID;
            Task_construct(&taskStruct[ID], (Task_FuncPtr)Slave_Task, &taskParams, NULL);
            Task_Params_init(&DisplayParams);
            DisplayParams.arg0 = ID;
            DisplayParams.arg1 = ctoi(choice);
            Task_construct(&taskDisplayManagerStruct, (Task_FuncPtr)DisplayManager, &DisplayParams, NULL);
            ID++;
            break;

            /* d - delete Task */
        case 'd':
            if(ID<=0) // Max 10 Tasks (0-9)
                break;
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "\r\nDelete Task\r\n", sizeof("\r\nDelete Task\r\n"));
            Semaphore_post(sem_uart0_write_handle);
            ID--; // reset the Task ID
            speed[ID] = BIOS_WAIT_FOREVER; // Task should wait forever
            break;

            /* a - avg. speed */
        case 'a':
            durchschnitt = 0;

            for(i=0; i<10; i++)
            {
                durchschnitt += 10/(speed[i]/1000);
            }

            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "Average \r\n", sizeof("Average \r\n"));
            itoc((int)durchschnitt/10);
            UART_write(uart0, buf, 1);
            UART_write(uart0, " Product per Second\r\n", sizeof(" Product per Second\r\n"));
            Semaphore_post(sem_uart0_write_handle);

            durchschnitt = 0;
            break;

            /* l - show list with all Tasks */
        case 'l':
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "Task list: \r\n", sizeof("Task list: \r\n"));
            UART_write(uart0, "Task: 0 1 2 3 4 5 6 7 8 9\r\n", sizeof("Task: 0 1 2 3 4 5 6 7 8 9\r\n"));
            UART_write(uart0, "---------------------------\r\nSpeed: ", sizeof("---------------------------\r\nSpeed: "));
            for(i=0; i<10; i++)
            {
                itoc(speed[i]/1000);
                UART_write(uart0, buf, 4);
                UART_write(uart0, " ", sizeof(" "));
            }
            UART_write(uart0, "\r\n", sizeof("\r\n"));
            Semaphore_post(sem_uart0_write_handle);
            break;

            /* r - return how much tasks are running (producing) */
        case 'r':
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "Total Running Tasks: ", sizeof("Total Running Tasks: "));
            itoc(ID);
            UART_write(uart0, buf, 1);
            UART_write(uart0, "\r\n", sizeof("\r\n"));
            Semaphore_post(sem_uart0_write_handle);

            DisplayParams.arg0 = 0;
            DisplayParams.arg1 = ID;
            Task_construct(&taskDisplayManagerStruct, (Task_FuncPtr)DisplayManager, &DisplayParams, NULL);
            break;


            /* h - Help list */
        case 'h':
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "----------------------- Task Factory -----------------------\r\n"
                       " n -> Create Task\r\n"
                       " d -> Delete Task\r\n"
                       " r -> Show Total Running Tasks\r\n"
                       " l -> Speed List\r\n"
                       " a -> Average Production Speed\r\n"
                       " s -> Edit Last Task Speed\r\n"
                       " h -> HELP\r\n"
                       "---------------------------------------------------------\r\n",
                       sizeof("----------------------- Task Factory -----------------------\r\n"
                               " n -> Create Task\r\n"
                               " d -> Delete Task\r\n"
                               " r -> Show Total Running Tasks\r\n"
                               " l -> Speed List\r\n"
                               " a -> Average Production Speed\r\n"
                               " s -> Edit Last Task Speed\r\n"
                               " h -> HELP\r\n"
                               "---------------------------------------------------------\r\n"));
            Semaphore_post(sem_uart0_write_handle);
            break;

            /* default - no character math */
        default:
            Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
            UART_write(uart0, "Invalid Command, Enter 'h' for HELP!\r\n", sizeof("Invalid Command, Enter 'h' for HELP!\r\n"));
            Semaphore_post(sem_uart0_write_handle);
            break;
        }
    }
}

/**************************** Functions ****************************/

/* itoc - Change a integer to a global char field (string)*/
void itoc(int z)
{
    if(z==0)
        buf[0]='0';
    if(z==1)
        buf[0]='1';
    if(z==2)
        buf[0]='2';
    if(z==3)
        buf[0]='3';
    if(z==4)
        buf[0]='4';
    if(z==5)
        buf[0]='5';
    if(z==6)
        buf[0]='6';
    if(z==7)
        buf[0]='7';
    if(z==8)
        buf[0]='8';
    if(z==9)
        buf[0]='9';
}

int ctoi(char c)
{
    switch(c)
    {
    case '1':
        return 1;
        break;
    case '2':
        return 2;
        break;
    case '3':
        return 3;
        break;
    case '4':
        return 4;
        break;
    case '5':
        return 5;
        break;
    case '6':
        return 6;
        break;
    case '7':
        return 7;
        break;
    case '8':
        return 8;
        break;
    case '9':
        return 9;
        break;
    }
}

/**************************** main ****************************/

int main(void)
{
    Task_Params taskParams; // Task Parameter
    Semaphore_Params semParams; // Semaphore Parameter

    Error_init(&eb); // Error Function

    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initUART();


    // configure CPU clock to 120 MHz
    g_ui32SysClock = SysCtlClockFreqSet(( SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN
            | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

    InitSpi(); // SPI configuration
    /* Create a UART for text reading/writing to the terminal */
    UART_Params_init(&uart0Params);
    uart0Params.writeDataMode = UART_DATA_TEXT;
    uart0Params.readDataMode = UART_DATA_TEXT;
    uart0Params.readReturnMode = UART_RETURN_FULL;
    uart0Params.readEcho = UART_ECHO_ON;
    uart0Params.baudRate = 115200;
    uart0 = UART_open(Board_UART0, &uart0Params);

    /* Construct a Semaphore object to be used as a resource lock for the uart0 port */
    Semaphore_Params_init(&semParams);
    Semaphore_construct(&sem_uart0_write_struct, 0, &semParams);
    /* Obtain instance handle */
    sem_uart0_write_handle = Semaphore_handle(&sem_uart0_write_struct);
    Semaphore_post(sem_uart0_write_handle);

    Semaphore_pend(sem_uart0_write_handle, BIOS_WAIT_FOREVER);
    UART_writePolling(uart0, "\r\n\r\n ************************ Task Factory ************************\r\n", sizeof("\r\n\r\n ************************ Task Factory ************************\r\n"));
    Semaphore_post(sem_uart0_write_handle);

    /* Initialize & Construct Task_Manager */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task_Manager_Stack;
    Task_construct(&task_Manager_Struct, (Task_FuncPtr)Task_Manager, &taskParams, NULL);

    /* Turn on user LED */
    //GPIO_write(Board_LED0, Board_LED_ON);

    /* Start BIOS */
    BIOS_start();

    return (0);
}

Now i know that the heartbeat function can be defined as a 

Void heartBeatFxn1(UArg arg0, UArg arg1)
{
    while (1) {

        Task_sleep((unsigned int)arg0);
        GPIO_toggle(Board_LED0);

    }
}

Task_Struct task0Struct;
Task_Struct task1Struct;

Char task0Stack[TASKSTACKSIZE];
Char task1Stack[TASKSTACKSIZE];

/* Construct heartBeat Task thread */
Task_Params_init(&taskParams);
taskParams.arg0 = 500;
taskParams.stackSize = TASKSTACKSIZE;
taskParams.stack = &task0Stack;
Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);

How i can implement these function to my own code and work with the same time. 

Can you please help me out with the suggesitons. 

  • Hello Ali,

    It should be simple, you just need to construct both tasks. You may want to give the tasks a priority when doing so though, which can be done with:

    taskParams.priority = x;

    Where x = the priority you want to assign. The lower the number, the higher the priority.

    You also will probably want to name your tasks which can be done with:

    taskParams.instance->name = "DefineYourTaskNameHere";

    For the first task you construct, you would set the stackSize. But for subsequent tasks you wouldn't. So it would basically look like this to add the heartbeat to your other application:

    Task_Params_init(&taskParams);
    taskParams.stack = &task0Stack;
    taskParams.instance->name = "heartBeatTask";
    taskParams.priority = 3;
    taskParams.arg0 = 500;
    Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);

    And then you'd add the following to your application:

    taskParams.instance->name = "TaskManager";
    taskParams.priority = 1;

  • Dear Ralph, 

    Thank you very much for your kind reply.  Please check the pictures down below. 

    But I think i didnt express myself so clearly. And a little bit confused with the code that you send to me. 

    How i can read the and apply the given speed from the keyboard to the blinking of the led. 

    From the Uart connection i have a menu which i can select 

    n   ->  new Task\r\n" when i press to n from the keyboard it starts the creat the task with a certain speed which is defined by the user and it start to print this speed to the termianl screen on the code composer studio. 

    I use this code for this. 

    /* Slave Task */
    int Slave_Task(UArg ID) Please check this part. 
    then i enter the speed under the 
    /* Task Manager */
    void Task_Manager(void) // Task Manager, control all Tasks and the Interface
    which it starts a task for me. 
    In this point how i can get the same speed to my led blinking and implement it ? 

  • Hello Ali,

    Do you want to blink the LED continuously until a new input is given then? And have the rate of the blinking vary based on the speed?

  • Yes i want to blink to led with the given input speed. 

    till the momen next input given 

    then the led will blink with the new given input speed. 

    It will be always blinking according to the last task speed which is given by the user. 

    Thanks a lot for your time and effort. 

  • You can create a ti.sysbios.knl.Clock function and have it run at the period you want. If the rate change is made, just stop the Clock, change the period, start the Clock. The Clock function can simply toggle the LED for you.

    Todd