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/EVMK2G: RTOS exception

Part Number: EVMK2G
Other Parts Discussed in Thread: SYSBIOS

Tool/software: Code Composer Studio

Hello,

I'm completely new to TI deveices, tools, etc., but I'm quite experienced with C code using 8 and 16 bits microcontrollers, ATXmega devices from ATMEL, and National Instruments Labwindows CVI to program user interfaces.

I'm now trying to jump into the TI world to use 66AK2Gxx to convert our semi digital audio limiter/register into a full digital device, for what I have purchased the EVMK2G board with the audio addon board.

After quite an amount of training through the available material (quite good and complete by the way) I have just compiled my first small piece of code in CCS with RTOS to run in EVMK2G. It includes a task declared in .cfg, a time interrupt every second and UART communication. Everything seems to go fine but when I run this little piece of code using EVMK2G, when the process goes into the timer's interrupt and executes an UART_printf, the program crashes. After trying to figure out why quite a while, I just cannot dicover why this crashes. The code is:

/*
* ======== main.c ========
*/

#include <xdc/std.h>
#include <xdc/cfg/global.h>

#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

#include <ti/sysbios/BIOS.h>

#include <ti/sysbios/knl/Task.h>

#include "stdio.h"
#include "stdint.h"
#include "stdlib.h"
#include "string.h"

/* BOARD */
#include <ti/board/board.h>

/* UART Header files */
#include <ti/drv/uart/UART.h>
#include <ti/drv/uart/UART_stdio.h>
#include <ti/drv/uart/test/src/UART_board.h>

void taskFxn(UArg a0, UArg a1)
{
System_printf("enter taskFxn()\n");
UART_printf("Entra task\n");

Task_sleep(10);

System_printf("exit taskFxn()\n");
UART_printf("Sale task\n");

System_flush(); /* force SysMin output to console */
return;
}

void Tempo1S(UArg a0)
{
System_printf("Entra tempo\n");
System_flush(); /* force SysMin output to console */
UART_printf("Entra Tempo\n");
return;
}

void Board_initUART(void)
{
Board_initCfg boardCfg;

boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;

Board_init(boardCfg);
return;
}

/*
* ======== main ========
*/
Int main()
{
Task_Handle task;
Error_Block eb;

Board_initUART();

System_printf("enter main()\n");

Error_init(&eb);
task = Task_create(taskFxn, NULL, &eb);
if (task == NULL) {
System_printf("Task_create() failed!\n");
UART_printf("Task create() failed\n");
BIOS_exit(0);
}

BIOS_start(); /* does not return */
return(0);
}

And the configuration file is:

var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
var Main = xdc.useModule('xdc.runtime.Main');
var Memory = xdc.useModule('xdc.runtime.Memory')
var SysMin = xdc.useModule('xdc.runtime.SysMin');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');

var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
var Swi = xdc.useModule('ti.sysbios.knl.Swi');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
var Timer = xdc.useModule('ti.sysbios.hal.Timer');
var ti_sysbios_timers_timer64_Timer = xdc.useModule('ti.sysbios.timers.timer64.Timer');
var Settings = xdc.useModule('ti.board.Settings');
var ti_drv_uart_Settings = xdc.useModule('ti.drv.uart.Settings');
var ti_osal_Settings = xdc.useModule('ti.osal.Settings');
var CpIntc = xdc.useModule('ti.sysbios.family.arm.a15.tci66xx.CpIntc');
var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');

/*
* Uncomment this line to globally disable Asserts.
* All modules inherit the default from the 'Defaults' module. You
* can override these defaults on a per-module basis using Module.common$.
* Disabling Asserts will save code space and improve runtime performance.
Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
*/

/*
* Uncomment this line to keep module names from being loaded on the target.
* The module name strings are placed in the .const section. Setting this
* parameter to false will save space in the .const section. Error and
* Assert messages will contain an "unknown module" prefix instead
* of the actual module name.
Defaults.common$.namedModule = false;
*/

/*
* Minimize exit handler array in System. The System module includes
* an array of functions that are registered with System_atexit() to be
* called by System_exit().
*/
System.maxAtexitHandlers = 4;

/*
* Uncomment this line to disable the Error print function.
* We lose error information when this is disabled since the errors are
* not printed. Disabling the raiseHook will save some code space if
* your app is not using System_printf() since the Error_print() function
* calls System_printf().
Error.raiseHook = null;
*/

/*
* Uncomment this line to keep Error, Assert, and Log strings from being
* loaded on the target. These strings are placed in the .const section.
* Setting this parameter to false will save space in the .const section.
* Error, Assert and Log message will print raw ids and args instead of
* a formatted message.
Text.isLoaded = false;
*/

/*
* Uncomment this line to disable the output of characters by SysMin
* when the program exits. SysMin writes characters to a circular buffer.
* This buffer can be viewed using the SysMin Output view in ROV.
SysMin.flushAtExit = false;
*/

/*
* The BIOS module will create the default heap for the system.
* Specify the size of this default heap.
*/
BIOS.heapSize = 0x1000;

/*
* Build a custom SYS/BIOS library from sources.
*/
BIOS.libType = BIOS.LibType_Debug;

/* System stack size (used by ISRs and Swis) */
Program.stack = 0x2000;

/* Circular buffer size for System_printf() */
SysMin.bufSize = 0x200;

/*
* Create and install logger for the whole system
*/
var loggerBufParams = new LoggerBuf.Params();
loggerBufParams.numEntries = 16;
var logger0 = LoggerBuf.create(loggerBufParams);
Defaults.common$.logger = logger0;
Main.common$.diags_INFO = Diags.ALWAYS_ON;

System.SupportProxy = SysMin;
var ti_sysbios_timers_timer64_Timer0Params = new ti_sysbios_timers_timer64_Timer.Params();
ti_sysbios_timers_timer64_Timer0Params.instance.name = "Timer1S";
ti_sysbios_timers_timer64_Timer0Params.period = 1000000;
Program.global.Timer1S = ti_sysbios_timers_timer64_Timer.create(-1, "&Tempo1S", ti_sysbios_timers_timer64_Timer0Params);
Settings.boardName = "evmK2G";
ti_drv_uart_Settings.socType = "k2g";
Settings.common$.logger = logger0;
ti_drv_uart_Settings.enableProfiling = false;
ti_drv_uart_Settings.libProfile = "release";
BIOS.customCCOpts = "-Wunused -Wunknown-pragmas -ffunction-sections -fdata-sections -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -mabi=aapcs -g -Dfar= -D__DYNAMIC_REENT__ -mapcs";
ti_osal_Settings.socType = "k2g";
LoggingSetup.sysbiosSwiLogging = true;
LoggingSetup.sysbiosHwiLogging = true;
LoggingSetup.sysbiosSemaphoreLogging = true;
LoggingSetup.loggerType = LoggingSetup.LoggerType_STOPMODE;

Using a console in CCS connected to the serial port, when I run the program, in the console I get:

Entra task

Sale task

E

This is that the task is executed correctly but when it reaches the timer interrut code, it seems that UART_printf function strats sending the string but after the first character is sent the program crashes, as if the first UART interrupt inside the timer interrupt is not accepted. ¿Why is this so?

I would very much appreciate some help at this point. Thanks in advance. 

  • Hello,

    Sorry for the delay in getting to this thread. Can you please elaborate of the following and also please attach your code instead of adding it to your post.  

     

    user6185197 said:
    This is that the task is executed correctly but when it reaches the timer interrut code, it seems that UART_printf function strats sending the string but after the first character is sent the program crashes, as if the first UART interrupt inside the timer interrupt is not accepted.

    I am guessing from the output that the task was launched correctly so you observed the prints then the timer interrupt event occurs that calls TImer1S but when it hits UART_printf ,the code hangs after the first character is printed. Is that correct ? 

    If Tempo1S is an ISR then you should not put any debug logs in an ISR for two reasons. One when ISR, it should disable interrupts acknowledge the interrupt, clear the flag and then re-enable the interrupts. As ISR runs in interrupt disabled state a debug print only increases the duration of ISR. also UART_printf is configured in blocking mode and in interrupt mode which means that the UART_printf API will stall until all characters are printed so I am not sure if you want to put a blocking call in you timer interrupt handler. I am also wondering if this creates a nested interrupt condition.

    Also, curious in your code you are using SYStem printf and UART_printf. Can you explain why you need two different debug IO mechanism in the code.

    Regards,

    Rahul

  • Hello Rahul, thanks for your help.

    I am guessing from the output that the task was launched correctly so you observed the prints then the timer interrupt event occurs that calls TImer1S but when it hits UART_printf ,the code hangs after the first character is printed. Is that correct ? 

    Yes, that's correct.

     

    Also, curious in your code you are using SYStem printf and UART_printf. Can you explain why you need two different debug IO mechanism in the code.

    No particular reason, I was just elaborating above one of the TI examples that had the SYStem print and I just added the UART print beacuse my aim at this moment is to test de UART; I just didn't delete the SYStem print.

     

    Please allow me two days before I elaborate on your suggestion, I will be out of the office the rest of today and tomorrow, and I will come back to this thread then.

     

    Thanks again and best regards.

     

  • Sorry, forgot to attach the code, here it goes

    /*
     *  ======== main.c ========
     */
    
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/BIOS.h>
    
    #include <ti/sysbios/knl/Task.h>
    
    #include "stdio.h"
    #include "stdint.h"
    #include "stdlib.h"
    #include "string.h"
    
    /* BOARD */
    #include <ti/board/board.h>
    
    /* UART Header files */
    #include <ti/drv/uart/UART.h>
    #include <ti/drv/uart/UART_stdio.h>
    #include <ti/drv/uart/test/src/UART_board.h>
    
    void taskFxn(UArg a0, UArg a1)
    {
        System_printf("enter taskFxn()\n");
        UART_printf("Entra task\n");
    
        Task_sleep(10);
    
        System_printf("exit taskFxn()\n");
        UART_printf("Sale task\n");
    
        System_flush(); /* force SysMin output to console */
        return;
    }
    
    void Tempo1S(UArg a0)
    {
        System_printf("Entra tempo\n");
        System_flush(); /* force SysMin output to console */
        UART_printf("Entra Tempo\n");
        return;
    }
    
    void Board_initUART(void)
    {
        Board_initCfg boardCfg;
    
        boardCfg = BOARD_INIT_PINMUX_CONFIG |
                   BOARD_INIT_MODULE_CLOCK  |
                   BOARD_INIT_UART_STDIO;
    
        Board_init(boardCfg);
        return;
    }
    
    /*
     *  ======== main ========
     */
    Int main()
    { 
        Task_Handle task;
        Error_Block eb;
    
        Board_initUART();
    
        System_printf("enter main()\n");
    
        Error_init(&eb);
        task = Task_create(taskFxn, NULL, &eb);
        if (task == NULL) {
            System_printf("Task_create() failed!\n");
            UART_printf("Task create() failed\n");
            BIOS_exit(0);
        }
    
        BIOS_start();    /* does not return */
        return(0);
    }
    
    0020.app.cfg

  • Hello Rahul:

    I've been working around this problem and yes it looks like something to do with nested interrupts. I have taken the UART_printf outside the timer interrupt by just setting a variable and doing UART_printf inside the idle function whenever that variable is set. Nevertheless I have not been able to change UART to callback mode instead of blocking mode to test that part you suggest.

    So know the questions are:

    1.- I imagine that when the board is initialized, because it is beeing initializaed with BOARD_INIT_UART_STDIO, the system assigns a handle to the uart instance. How can I know that handle in order to close that uart, change writeMode and readMode to UART_MODE_CALLBACK, and reopen again? 

    2.- I have seen in the .cfg file that interrupt nesting is allowed. ¿Why then nesting interrupts is a problem?

    Thanks in advance and best regards. 

  • Please refer to the UART LLD examples where it will show how the application can take over the bpard UART handle which is defined as a global and should be available for you to use from the application.

    The .cfg allows for interrupt nesting in the TI RTOS level but this doesn`t gurantee that they are handled correctly. you need to select the right priorities, masking and nested interrupt handling as per ur usecase and try and keep HWIs short to prevent these situations from arising frequently. Also, any nesting using driver call back functions are not always under the control of TI RTOS as a callback unlike HWI is driver defined way to reduce the size of HWI used and allow driver to invoke callback after HWI has been acknowledged and cleared in the system

    Regards,

    Rahul

  • Thanks Rahul.

    I will take a closer look to those examples.

    Regards.