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.

TMC4C123GXL launchpad uart stdio and the gnu toolchain

Other Parts Discussed in Thread: EK-TM4C123GXL, SYSBIOS, CONTROLSUITE

Hi all, first post and just getting started with tiva c and TI rtos.

used tools:

  • TI-RTOS TivaC 2.16.01.14
  • gnu v4.8.4 linaro
  • CCS 6.1.2.00015 

I can't help but notice that the uartconsole example is missing from the gnu demos (which is probably due to the way `add_device` works), so I tried making my own using the gnu extension `fopencookie` (of which at least the symbol seems to be present).

So far, however, my code seems to hang after calling `fprintf`.

Steps to reproduce:

  • Open a new project and use TI-RTOS Examples->EK-TM4C123GXL evaluation kit->driver examples->gnu driver examples->empty examples-> empty (minimal project)

Notes:

  • I'm testing with a serial monitor on my PC. `UART_write` on its own works fine.
  • breakpoints at the callbacks don't ever get called.
  • Even when the `cookie_io_functions_t` simply return the requested number (`return n`), the program terminates
  • The led blink code from the minimal example is still present and runs in the same loop (fine using `UART_write`)

Any help would greatly be appreciated. (either pointing out the flaw in my current setup, or directing me to a better way to implement a uart console with the gnu toolchain.)

The debugger console displays the following:

FSR = 0x0000
HFSR = 0x40000000
DFSR = 0x0000000b
MMAR = 0xffffffd4
BFAR = 0xffffffd4
AFSR = 0x00000000
Terminating execution...

I'm using the following code:

/*
 *  ======== empty_min.c ========
 */
/* XDCtools Header files */
#include <xdc/std.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>

//c header files
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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

#define TASKSTACKSIZE   512

Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];


int noop(void) { return -1; }
size_t uartReadFx(void *cookie, char *buf, size_t n)
{
  return n;
  //return UART_read((UART_Handle)cookie, buf, n);
}
size_t uartWriteFx(void *cookie, const char *buf, size_t n)
{
  return n;
  //return UART_write((UART_Handle)cookie, buf, n);
}
cookie_io_functions_t uartcookievect =
    {
        (cookie_read_function_t*)&uartReadFx,
        (cookie_write_function_t*)&uartWriteFx,
        (cookie_seek_function_t*)&noop,
        (cookie_close_function_t*)&noop
    };
UART_Handle uart_handle;
UART_Params uartParams;
FILE* uartcookief;

/*
 *  ======== heartBeatFxn ========
 *  Toggle the Board_LED0. The Task_sleep is determined by arg0 which
 *  is configured for the heartBeat Task instance.
 */
Void heartBeatFxn(UArg arg0, UArg arg1)
{
    while (1) {
        Task_sleep((UInt)arg0);
        GPIO_toggle(Board_LED0);
        char s[] = "hii\n";
        //UART_write(uart_handle, s, strlen(s));
        fprintf(uartcookief, s);
        fflush(uartcookief);
    }
}

/*
 *  ======== main ========
 */
int main(void)
{
    Task_Params taskParams;

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

    Task_Params_init(&taskParams);
    taskParams.arg0 = 1000;
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);

    //setup uart io
    UART_Params_init(&uartParams);
    uartParams.baudRate = 115200;
    uartParams.readEcho = UART_ECHO_OFF;
    uart_handle = UART_open(Board_UART0, &uartParams);

    uartcookief = fopencookie((void*) uart_handle, "w+", uartcookievect);
    setlinebuf(uartcookief);
    //setvbuf(uartcookief, NULL, _IOLBF, 128);

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

    /* Start BIOS */
    BIOS_start();

    return (0);
}

TI-RTOS TivaC 2.16.01.14

  • Have you confirmed that the return value from fopencookie() is non-zero?

    Alan
  • Alan DeMars said:
    Have you confirmed that the return value from fopencookie() is non-zero?

    Alan

    Hi Alan,

    Thank you for your response.
    Yes I have verified through the debugger.
    I can provide you with the values of any other fields as well.

    Best Regards,

  • I get this error when I try to compile the empty_min.c you provide:

    ../empty_min.c:43:1: error: unknown type name 'cookie_io_functions_t'
    cookie_io_functions_t uartcookievect =
    ^
    ../empty_min.c:45:10: error: 'cookie_read_function_t' undeclared here (not in a function)
    (cookie_read_function_t*)&uartReadFx,

    Is there a #include <> statement missing?

    Alan
  • I added

    #undef __STRICT_ANSI__

    at the top of empty_min.c and now the build completes. I'm attempting to recreate and debug the problem now.

    Alan
  • The application was dying within fprintf() due to a memory allocation failure when attempting to dynamically create a re-entrancy structure. The BIOS.heapSize setting for the empty min example is only 1024 bytes. By bumping this up to 4096, the application runs continuously. The LED toggles on and off once per second. However, I don't see any "hii" output on the serial port.
  • I was able to get the application to run successfully by increasing the TASKSTACKSIZE to 1024 bytes, increasing Program.stack to 1024 bytes, and uncommenting the code in your uartReadFxn() and uartWriteFxn() functions.

    Incidentally, the Error raised when Memory_alloc() was failing printed meaningful information into the SysMin output buffer (visible with ROV). This clearly indicated that the Heap was too small:

    ,61: out of memory: handle=0x200006ac, size=1032
    ,ti.sysbios.heaps.HeapMem: line 361: out of memory: handle=0x200006ac, size=1032

    Alan
  • Thanks Alan,

    I've got it up and running.
    This should simplyfy IO alot compared to the direct register access with interrupts I needed to use with the c2000 controlsuite.

    I'm just checking the ROV and now I feel a bit of a dummy for not using it before.
    It seems really usefull.
    I haven't used the heap on a MCU before.
    Fopencookie seems to require a lot of memory.

    Some final questions:

    • Would you recommend this aproach as a proper analog to add_device as used in the uartconsole demo?
    • Would you recommend this aproach for IO?

    Best regards,
    Jeroen

  • I'm glad to hear the you're up and running!

    Sadly, I'm not qualified to make any recommendations on the general use of this approach.

    Alan