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.

RTOS/LAUNCHXL-CC1310: HARD FAULT: FORCED: BUSFAULT: PRECISER

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310, SYSBIOS

Tool/software: TI-RTOS

Hi Team,

I have written a firmware where I am using Mailbox concept to get the information on the terminal screen obtained on radio and similarly trying to display the key pressed on the keyboard on the terminal.

What ever data is received by radio over the air is displayed without any problem.

But the issue is if I try to display the data that is obtained in the rx_buffer when hitting any key on keyboard I get "HARD FAULT: FORCED: BUSFAULT: PRECISER" Exception.

There is no difference in the way the data is passed to the UART_write function to get it displayed on screen.

/*
 * CommandRadioUart.c
 *
 *  Created on: Aug 25, 2016
 *      Author: greg
 */
#include "CommandRadio.h"

uint8_t *command;
static uint8_t uart_rxBuffer[2];//Read one byte at a time // Data obtained when hitting key on keyboard
bool echo_char = false;// flag to indicate which data has to be displayed
/***** Variable declarations *****/
static UartRead_Callback Callback;
static void uartReceiveFinished(UART_Handle handle, void *uart_rxBuffer, size_t count);

/* This task is declared in CommandRadio.cfg
 * It transmits text over the UART backchannel USB  */
void uartSendTask(UArg arg0,UArg arg1){
	MsgObj dataRx;

	//char uart_rxBuffer[10];
	//char uart_rxBuffer;//Read one byte at a time
    UART_Params uartParams;

    /*initializing the UART parameters*/
    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_TEXT;
    uartParams.readMode = UART_MODE_CALLBACK;
    uartParams.readDataMode = UART_DATA_TEXT;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.readCallback = uartReceiveFinished;
    uartParams.baudRate = 115200;
    uart = UART_open(Board_UART0, &uartParams);
    if (uart == NULL) {System_abort("Error opening the UART");}

    //int rxBytes = UART_read(uart, &uart_rxBuffer, 1);
    int rxBytes = UART_read(uart, &uart_rxBuffer, 1);

/* The task suspends waiting on reciept of mailbox message.*/
	while(TRUE){
	    UART_read(uart, &uart_rxBuffer, 1);
		Mailbox_pend(rxDataMailbox, &dataRx, BIOS_WAIT_FOREVER);
		processMsg(&dataRx);
	    //UART_read(uart, &uart_rxBuffer, 1);
	}
}

void UartRead_registerCallback(UartRead_Callback callback) {
	Callback = callback;
}

/* This function writes the Text messge to the UART, The UART write can be formated here */
void processMsg(MsgObj *message){
	UART_write(uart, message->buf, strlen(message->buf));
}
/* this function can be called to write to the UART */
void writeToTerminal(String txtString){
	MsgObj writeData;
		writeData.id = Event_Data_Rx;
		writeData.buf = txtString;
		Mailbox_post(rxDataMailbox,&writeData,BIOS_WAIT_FOREVER);
}

static void uartReceiveFinished(UART_Handle handle, void *uart_rxBuffer, size_t count)
{
	command = uart_rxBuffer;

	if(*command == 0x30)
	{
		if(!echo_char)
		{
			echo_char = true;
		}
		else
		{
			echo_char = false;
		}
	}
	Callback(command);
}

The callback function "Callback" is as under
void UartReadCallback(uint8_t *dataValue)
{
	uint8_t Echo_Char[] = "Echo Char";
	if(!echo_char)
	{
		memcpy((void*)&latestDataValue, dataValue, sizeof(dataValue));
		Event_post(Tx_Rx_Event, Key_Pressed_Event);// This triggers to send the data to the other radio and receives acknowledgement which is displayed on the   //terminal window
	}
	else
	{
		//dataValue[1] = '\0';
		//memcpy(Echo_Char,dataValue,sizeof(dataValue));
		writeToTerminal((void*)Echo_Char);
	}
}


So for any key pressed apart from the number 0 (as I am comparing value to 0x30) key on key board the functionality works fine where the radio sends that across to other radio and received acknowledgement which is displayed as "Acknowledgement received" message on the terminal window.
This is the way it is defined
uint8_t ackMsg[] = "Acknowledgment-received";
& it is send to the uart function as "writeToTerminal((void*)ackMsg);"

But whenever I try to hit number 0 as soon as the firmware executes at Maibox_post fucntion the firmware give hard fault exception.

Please provide some input on how to find where the issue lies.

Thank you in advance

Vikram

  • Can you check your stacks?

    The ROV tool in CCS can be used to inspect for stack overflows, and SYS/BIOS module errors in general.

    Please inspect your Task stacks in the Task module in ROV, paying attention to the 'stackPeak' field under the Detailed tab for Task.

    Also inspect your Hwi stack in the Hwi module in ROV, by selecting the Module tab for Hwi.  There is a field named 'hwiStackPeak'

    Finally, in the BIOS module in ROV, click the 'Scan for errors...' tab.

    Let me know what these show.

    Since you're getting an exception, there is a training video that might help here:

    Regards,

    - Rob

  • Hi Robert,

    Thank you for your reply on the query.

    I inspected the Task module, Hwi module and the BIOS module in the ROV and below is what I see.

    In Task module, it shows that Idle Task has stackPeak of 2048 against stackSize of 2048 and is blocked on internal error. This task has 0 priority.

    Secondly in the Hwi module, it shows an exception with hwiStackPeak of 592 against hwiStackSize of 768 and when I view the Exception tab in the Hwi it displays "Hard Fault: FORCED: BUSFAULT: IMPRECISERR"

    but under the exception call stack it shows "symbol not available"

    Lastly in the BIOS module, it gives 4 different information.

    I am attaching the screen shots for all 3 views.

    Hope to get a response soon.

    Thank you

    Vikram

  • Vikram Trivedi said:
    In Task module, it shows that Idle Task has stackPeak of 2048 against stackSize of 2048 and is blocked on internal error. This task has 0 priority.

    Let's focus on this first, since an overflowed stack can lead to all sorts of other errors, and perhaps the other errors are a result of the overflowed Idle Task stack.

    What do you have in your Idle module?  Is it possible that something you've put in there is using so much stack?

    You could try increasing your Idle Task's stack size.  To do so, add this into the .cfg file (or you can do it graphically via the Task module's page):

    Task.idleTaskStackSize = 3096;

    Regards,

    - Rob

  • Hi Rob,

    Thank you for the reply.

    I understand about the fact that the stack size is getting into overrun situation.

    I had tried increasing the stack size for the idle task earlier as well.

    Initially, I had the idle task stack size 512 then I increased to 1024 and then to 2048. Finally as per you say I also increased to 3096. But still it shows the same result.

    One thing I tried is to disable the idle task. and run the code.

    But still in this case also I get an exception.

    Point to note is that I don't have any function in the idle task to run.

    Now there is two scenario in which I get two different exception.

    If I call the UART_write function directly in the "else" scenario" to print whichever key is hit on the keyboard, terminal window shows the key pressed and gives exception "Hard Fault: FORCED: BUSFAULT: IMPRECISERR". In this case I get uart task showing blocked on internal error like it used to show for idle task except that the stackPeak is less than the stackSize so no overrun of stack area.

    And if I call the writeToTerminal function which eventually does mailbox post to call the UART_write function, terminal window does not show the key pressed meaning that UART_write was not called and it throws the exception "Hard Fault: FORCED: BUSFAULT: PRECISERR.Data Access Error. Address = 0x20005000". In this case the uart task does not show any issue just shows that it is blocked at mailbox _pend.

    if the else part of the code is not called then there is not issue in running the firmware.

    In the sense that if I hit any other key except for which the if condition is met, the radio transmits that and receives acknowledgement from another radio and "acknowledgement received" message is displayed on the screen. This means that the mailbox concept works in that case and also the UART_write function does not throw any exception.

    I hope this triggers some idea to you on what is causing the error.

    Vikram

  • I'm still looking into this, and will probably need to consult a team member who is more familiar with the UART driver than I am. My apologies for the delay.

    Regards,

    - Rob
  • Thank you Ron,

    I will waiting for your reply.

    Vikram

  •  *  ======== uartecho.c ========
     */
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/cfg/global.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Mailbox.h>
    #include <ti/sysbios/knl/Event.h>
    #include<string.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/UART.h>
    
    /* Example/Board Header files */
    #include "Board.h"
    
    #include <stdint.h>
    
    #define TASKSTACKSIZE     768
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    /*Event Defines */
    #define Event_Data_Rx   Event_Id_00
    #define Event_Button	Event_Id_01
    
    /* Global memory storage for a PIN_Config table */
    static PIN_State ledPinState;
    
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config ledPinTable[] = {
        Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    typedef struct MsgObj {
        Int	id;             	/* writer task id */
        String	buf;            /* message value */
    } MsgObj, *Msg;
    
    UART_Handle uart;
    uint8_t *command;
    static char uart_rxBuffer;//Read one byte at a time
    
    //typedef void(*UartRead_Callback)(uint8_t *ch);
    
    void writeToTerminal(String txtString);			/* This is the function called to send a mesage to back channel UART */
    void processMsg(MsgObj *message);				/* This is called by reciept of a mailbox message */
    
    //void UartRead_registerCallback(UartRead_Callback callback);
    
    /***** Variable declarations *****/
    //static UartRead_Callback Callback;
    static void uartReceiveFinished(UART_Handle handle, void *uart_rxBuffer, size_t count);
    
    /*
     *  ======== echoFxn ========
     *  Task for this function is created statically. See the project's .cfg file.
     */
    Void echoFxn(UArg arg0, UArg arg1)
    {
    	MsgObj dataRx;
    
    	//char input;
        UART_Params uartParams;
        const char echoPrompt[] = "\fEchoing characters:\r\n";
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        //uartParams.writeDataMode = UART_DATA_BINARY;
        //uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho = UART_ECHO_OFF;
        //UART_Params_init(&uartParams);
        uartParams.writeDataMode = UART_DATA_TEXT;
        //uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.readDataMode = UART_DATA_TEXT;
        //uartParams.readReturnMode = UART_RETURN_FULL;
        //uartParams.readEcho = UART_ECHO_OFF;
        //uartParams.readCallback = uartReceiveFinished;
        uartParams.baudRate = 9600;
        uart = UART_open(Board_UART0, &uartParams);
    
        if (uart == NULL) {
            System_abort("Error opening the UART");
        }
    
        UART_write(uart, echoPrompt, sizeof(echoPrompt));
    
        /* Loop forever echoing */
        while (1) {
            UART_read(uart, &uart_rxBuffer, 1);
            command = (uint8_t*)uart_rxBuffer;
            writeToTerminal((void*)&uart_rxBuffer);
    		Mailbox_pend(rxDataMailbox, &dataRx, BIOS_WAIT_FOREVER);
    		processMsg(&dataRx);
        }
    }
    
    /* This function writes the Text messge to the UART, The UART write can be formated here */
    void processMsg(MsgObj *message){
    	UART_write(uart, message->buf, strlen(message->buf));
    }
    /* this function can be called to write to the UART */
    void writeToTerminal(String txtString){
    	MsgObj writeData;
    		writeData.id = Event_Data_Rx;
    		writeData.buf = txtString;
    		Mailbox_post(rxDataMailbox,&writeData,BIOS_WAIT_FOREVER);
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        PIN_Handle ledPinHandle;
        Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initUART();
    
        /* Construct BIOS objects */
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)echoFxn, &taskParams, NULL);
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        if(!ledPinHandle) {
            System_abort("Error initializing board LED pins\n");
        }
    
        PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
    
        /* This example has logging and many other debug capabilities enabled */
        System_printf("This example does not attempt to minimize code or data "
                      "footprint\n");
        System_flush();
    
        System_printf("Starting the UART Echo example\nSystem provider is set to "
                      "SysMin. Halt the target to view any SysMin contents in "
                      "ROV.\n");
        /* SysMin will only print to the console when you call flush or exit */
        System_flush();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    
    static void uartReceiveFinished(UART_Handle handle, void *uart_RxBuffer, size_t count)
    {
        command = (uint8_t*)uart_rxBuffer;
        writeToTerminal((void*)&uart_rxBuffer);
    }
    
    

    Hi Rob,

    I implemented the Mailbox concept in the uartecho example code and I found below stuff:

    One more finding while I was debugging I found is that if I have the uartParams.readMode = UART_MODE_CALLBACK I get the exception but if I have the uartParams.readMode = UART_MODE_BLOCKING than I don't get the exception.

    I am attaching the firmware for you to replicate the behaviour and see if you get something.

  • Thank you for the code, it makes it much easier to answer if I can try it out. I will give it a try and let you know what I find.

    Regards,

    - Rob

  • Hi Rob,

    Did you get any response back or were you able to replicate the behaviour?

    Looking forward to your response.

    Thank you

    Vikram

  • Hi Vikram,

    I was able to spend some more time on this today with our team expert on the CC13xx.

    One thing we noticed is that your processMsg function seems to have a problem:

    void processMsg(MsgObj *message){
        UART_write(uart, message->buf, strlen(message->buf));
    }

    The strlen(message->buf) is not right here, since no code is null-terminating the string.  message->buf is assigned &uart_rxBuffer, and uart_rxBuffer is:

    static char uart_rxBuffer;//Read one byte at a time

    I don't know that this would cause any exception, but strlen() would end up reading bytes starting at &uart_rxBuffer until it randomly encountered a '\0'.  I think you need a more robust method of determining the UART_write() length.  For now you could just make it 1.  A more permanent solution might be to allow more space in uart_rxBuffer and have the sender null-terminate the string,

    I was able to build and run your cut-down code (not the code from your first post, but the later code) on a CC1310 LAUNCHXL board.  I had add code to create the rxDataMailbox, since your code didn't do so (I assume it was statically created in your .cfg file, which you didn't paste or attach).

    I had some trouble getting the code to run properly at 9600 baud, and had more success at 115200.  There used to be a problem in the UART26XX.c code in calculating an internal timeout which is used in the BLOCKING mode, but that was fixed in the 2.20 version of the TI drivers.  I have a newer version that supposedly has the fix for this, yet I was still having trouble at 9600.  We never determined the cause, however, so we stuck with using 115200 baud.

    What version of TI-RTOS are you using?

    It might be a good idea to use the exception data to track down the culprit, instead of just trying different things (stabbing in the dark).

    The exception dump shows a Data access error occurred at 0x20005000.  Does that address match anything in your symbol table?  You can perhaps find something in your executable's map file.

    Can you see at what address the PC was executing when the exception occurred?

    Regards,

    - Rob

  • Good morning Rob,

    Thank you for your response. Sorry I was out of office on Friday so was not able to check the reply.

    Yes, the rxDataMailbox was statistically created in .cfg file. I missed on mentioning that.

    Below is the piece of code for creating rxDataMailbox :

    var Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox');
    Program.global.rxDataMailbox = Mailbox.create(256, 1);
    Program.global.rxDataMailbox.instance.name = "rxDataMailbox";

    I am using the TI-RTOS v2.20.0.06

    As I mentioned in the last post, I am not getting exception in BLOCKING_MODE but only in the CALLBACK_MODE.

    I had checked the Exception window and it shows hard fault: FORCED: BUSFAULT: PRECISERR.Data Access Error at Address = 0x20005000.

    You are true that exception dump shows Data Access Error at 0x20005000. In the .map file it shows as below :

    20005000  __STACK_END 

    The PC shows address 0x1001ca76 and in the memory map there is no information about address 0x1001ca76. So not sure what it is using for.

    Thank you

    Vikram

  • The BUSFAULT is most likely due to a stack underflow.  The 1310's memory map ends at 0x20004fff.

    When you use the UART_MODE_CALLBACK, your callback function is called from a Swi (Software Interrupt).  Your UartReadCallback() function calls writeToTerminal(), which in turn calls Mailbox_post().  You can't call Mailbox_post() from an Swi or Hwi *unless* the timeout parameter is BIOS_NO_WAIT.  Your crash is likely due to a chain of events that is started by calling Mailbox_post() from the wrong context.

    If you build your example with the "debug.cfg" then your will likely get a cleaner failure that is caught by a SYS/BIOS Assert_raise(), informing that the Mailbox_post() was called from an incorrect threading level.  The "release.cfg" does not enable the Assert module.

    Please also address the code issue that I identified in my last post (regarding the lack of '\0' string terminator), I believe it is a real issue.

    I hope this helps.

    Regards,

    - Rob

  • Hi Rob,

    Thank you for getting back on the post that I had done.

    I had already used the '\0' concept as string terminator to see it worked or not but the result was same.

    I also built the code with the debug.cfg option but I am not able to see the Assert_raise() information as you have mentioned.

    As you mentioned that Mailbox_post can't be used for Swi and Hwi unless the timeout parameter is BIOS_NO_WAIT option but when the same writeToTerminal is called in my firmware for radio whenever a packet is received it works and the packet is displayed on the terminal screen (Ofcourse this is UART_write and not UART_read).

    Vikram

  • Vikram Trivedi said:
    I also built the code with the debug.cfg option but I am not able to see the Assert_raise() information as you have mentioned.

    Do you have this line in your debug.cfg?:

        BIOS.assertsEnabled = true;

    If so, then you should definitely be getting an Assert raised when calling Mailbox_post() from a Swi.  Mailbox_post() calls Semaphore_pend(), and this code from Semaphore_pend() in ti/sysbios/knl/Semaphore.c should be firing:

            /*
             * Assert catches Semaphore_pend calls from Hwi and Swi
             * with non-zero timeout.
             */
            Assert_isTrue((timeout == BIOS_NO_WAIT) ||
                    ((BIOS_getThreadType() == BIOS_ThreadType_Task) ||
                    (BIOS_getThreadType() == BIOS_ThreadType_Main)),
                    Semaphore_A_badContext);

            --sem->count;

    This is from the code path where the semaphore is available for taking.

    Vikram Trivedi said:
    As you mentioned that Mailbox_post can't be used for Swi and Hwi unless the timeout parameter is BIOS_NO_WAIT option but when the same writeToTerminal is called in my firmware for radio whenever a packet is received it works and the packet is displayed on the terminal screen (Ofcourse this is UART_write and not UART_read).

    A Mailbox_post() with BIOS_WAIT_FOREVER called from a Swi or Hwi can work OK if there is a mailbox slot available, and the problems only happen when there is no mailbox slot in which to post the message, in which case the Semaphore_pend() attempts to block the calling Task (which, in your crashing case, is not a Task, it's a Swi).  The Assert should fire even when there is a mailbox slot available.

    Regards,

    - Rob

  • Hi rob,

    Yes, the line
    BIOS.assertsEnabled = true; is there in my .cfg file

    I am trying to understand if the Assert is raised where to view because I am unable to put a breakpoint in the Semaphore.c file

    Vikram
  • Here's a screenshot of my CCS session when this happens, note the callstack in the Debug window.

    Note that System_abort() is called, which means that your program should exit and stop.  Also, there may be some System_printf() output in the CCS console I/O window.

    Regards,

    - Rob

  • That's the thing Rob I don't get any such behaviour about loader_exit().
    It just shows in the Hwi exception that hard fault exception has occured.

    Vikram
  • Vikram Trivedi said:
    That's the thing Rob I don't get any such behaviour about loader_exit().

    SYS/BIOS's "plumbing" when an Assert is raised (i.e., how the system responds to an Assert and where it runs afterwards) is configurable.  It would be configured in your .cfg file.  Could you attach it so that I can have a look?

    Regardless of how your system is responding to the Assert, it is potentially a problem calling Mailbox_post() with BIOS_WAIT_FOREVER (or anything other than BIOS_NO_WAIT) from a Swi thread, and the UART readCallback is called from a Swi thread.  I say "potentially" because it *can* work fine if there is a Mailbox slot available when you call Mailbox_post() from the Swi - the Semaphore_pend() in Mailbox_post() will see that count > 0 and therefore won't attempt to block.  The problem occurs when there is no Mailbox slot available in which to copy your message - the Semaphore_pend() in Mailbox_post() will attempt to block, and there is no blocking allowed from Swi or Hwi thread level.  The Assert is raised when Semaphore_pend() is called from Swi or Hwi level, regardless of the availability of the Semaphore.  So, even in the case where a Mailbox slot is available and there would be no blocking in Semaphore_pend(), the Assert is raised anyways.

    I sounds like your Asserts are not enabled in this case, for whatever reason.  We could try to solve that, but it would serve only to allow you to see the problem directly, which is a good thing, but not really helpful here since we already know that your code is doing something it shouldn't.

    You could verify it in another way, though.  If you change your Mailbox_post() in writeToTerminal() to have BIOS_NO_WAIT, and also check the return value from the Mailbox_post(), it would return FALSE for the case where blocking would be attempted (and a subsequent crash) with a non-BIOS_NO_WAIT timeout:

        if (Mailbox_post(rxDataMailbox,&writeData,BIOS_NO_WAIT) == FALSE) {
            // bad situation that would crash if timeout was BIOS_WAIT_FOREVER
            while (1) ;  // spin here so you can see that this happened when you stop the CPU

        }

    Regards,

    - Rob

  • /*
     * Copyright (c) 2015-2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    
    
    /* ================ Boot configuration ================ */
    var Boot = xdc.useModule('ti.sysbios.family.arm.cc26xx.Boot');
    /*
     * This module contains family specific Boot APIs and configuration settings.
     * See the SYS/BIOS API guide for more information.
     */
    
    
    
    /* ================ Clock configuration ================ */
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    /*
     * When using Power and calibrateRCOSC is set to true, this should be set to 10.
     * The timer used by the Clock module supports TickMode_DYNAMIC. This enables us
     * to set the tick period to 10 us without generating the overhead of additional
     * interrupts.
     *
     * Note: The calibrateRCOSC parameter is set within the Power configuration
     *     structure in the "Board.c" file.
     */
    Clock.tickPeriod = 10;
    
    
    
    /* ================ Defaults (module) configuration ================ */
    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    /*
     * A flag to allow module names to be loaded on the target. Module name
     * strings are placed in the .const section for debugging purposes.
     *
     * Pick one:
     *  - true (default)
     *      Setting this parameter to true will include name strings in the .const
     *      section so that Errors and Asserts are easier to debug.
     *  - false
     *      Setting this parameter to false will reduce footprint in the .const
     *      section. As a result, Error and Assert messages will contain an
     *      "unknown module" prefix instead of the actual module name.
     *
     *  When using BIOS in ROM:
     *      This option must be set to false.
     */
    //Defaults.common$.namedModule = true;
    Defaults.common$.namedModule = false;
    
    
    
    /* ================ Error configuration ================ */
    var Error = xdc.useModule('xdc.runtime.Error');
    /*
     * This function is called to handle all raised errors, but unlike
     * Error.raiseHook, this function is responsible for completely handling the
     * error with an appropriately initialized Error_Block.
     *
     * Pick one:
     *  - Error.policyDefault (default)
     *      Calls Error.raiseHook with an initialized Error_Block structure and logs
     *      the error using the module's logger.
     *  - Error.policySpin
     *      Simple alternative that traps on a while(1) loop for minimized target
     *      footprint.
     *      Using Error.policySpin, the Error.raiseHook will NOT called.
     */
    //Error.policyFxn = Error.policyDefault;
    Error.policyFxn = Error.policySpin;
    
    /*
     * If Error.policyFxn is set to Error.policyDefault, this function is called
     * whenever an error is raised by the Error module.
     *
     * Pick one:
     *  - Error.print (default)
     *      Errors are formatted and output via System_printf() for easier
     *      debugging.
     *  - null
     *      Errors are not formatted or logged. This option reduces code footprint.
     *  - non-null function
     *      Errors invoke custom user function. See the Error module documentation
     *      for more details.
     */
    //Error.raiseHook = Error.print;
    Error.raiseHook = null;
    //Error.raiseHook = "&myErrorFxn";
    
    /*
     * If Error.policyFxn is set to Error.policyDefault, this option applies to the
     * maximum number of times the Error.raiseHook function can be recursively
     * invoked. This option limits the possibility of an infinite recursion that
     * could lead to a stack overflow.
     * The default value is 16.
     */
    Error.maxDepth = 2;
    
    
    
    /* ================ Hwi configuration ================ */
    var halHwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var m3Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
    /*
     * Checks for Hwi (system) stack overruns while in the Idle loop.
     *
     * Pick one:
     *  - true (default)
     *      Checks the top word for system stack overflows during the idle loop and
     *      raises an Error if one is detected.
     *  - false
     *      Disabling the runtime check improves runtime performance and yields a
     *      reduced flash footprint.
     */
    //halHwi.checkStackFlag = true;
    halHwi.checkStackFlag = false;
    
    /*
     * The following options alter the system's behavior when a hardware exception
     * is detected.
     *
     * Pick one:
     *  - Hwi.enableException = true
     *      This option causes the default m3Hwi.excHandlerFunc function to fully
     *      decode an exception and dump the registers to the system console.
     *      This option raises errors in the Error module and displays the
     *      exception in ROV.
     *  - Hwi.enableException = false
     *      This option reduces code footprint by not decoding or printing the
     *      exception to the system console.
     *      It however still raises errors in the Error module and displays the
     *      exception in ROV.
     *  - Hwi.excHandlerFunc = null
     *      This is the most aggressive option for code footprint savings; but it
     *      can difficult to debug exceptions. It reduces flash footprint by
     *      plugging in a default while(1) trap when exception occur. This option
     *      does not raise an error with the Error module.
     */
    //m3Hwi.enableException = true;
    //m3Hwi.enableException = false;
    m3Hwi.excHandlerFunc = null;
    
    /*
     * Enable hardware exception generation when dividing by zero.
     *
     * Pick one:
     *  - 0 (default)
     *      Disables hardware exceptions when dividing by zero
     *  - 1
     *      Enables hardware exceptions when dividing by zero
     */
    m3Hwi.nvicCCR.DIV_0_TRP = 0;
    //m3Hwi.nvicCCR.DIV_0_TRP = 1;
    
    /*
     * Enable hardware exception generation for invalid data alignment.
     *
     * Pick one:
     *  - 0 (default)
     *      Disables hardware exceptions for data alignment
     *  - 1
     *      Enables hardware exceptions for data alignment
     */
    m3Hwi.nvicCCR.UNALIGN_TRP = 0;
    //m3Hwi.nvicCCR.UNALIGN_TRP = 1;
    
    /*
     * Assign an address for the reset vector.
     *
     * Default is 0x0, which is the start of Flash. Ordinarily this setting should
     * not be changed.
     */
    m3Hwi.resetVectorAddress = 0x0;
    
    /*
     * Assign an address for the vector table in RAM.
     *
     * The default is the start of RAM. This table is placed in RAM so interrupts
     * can be added at runtime.
     *
     * Note: To change, verify address in the device specific datasheets'
     *     memory map.
     */
    m3Hwi.vectorTableAddress = 0x20000000;
    
    
    
    /* ================ Idle configuration ================ */
    var Idle = xdc.useModule('ti.sysbios.knl.Idle');
    /*
     * The Idle module is used to specify a list of functions to be called when no
     * other tasks are running in the system.
     *
     * Functions added here will be run continuously within the idle task.
     *
     * Function signature:
     *     Void func(Void);
     */
    //Idle.addFunc("&myIdleFunc");
    
    
    
    /* ================ Kernel (SYS/BIOS) configuration ================ */
    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    /*
     * Enable asserts in the BIOS library.
     *
     * Pick one:
     *  - true (default)
     *      Enables asserts for debugging purposes.
     *  - false
     *      Disables asserts for a reduced code footprint and better performance.
     *
     *  When using BIOS in ROM:
     *      This option must be set to false.
     */
    BIOS.assertsEnabled = true;
    //BIOS.assertsEnabled = false;
    
    /*
     * Specify default heap size for BIOS.
     */
    BIOS.heapSize = 1024;
    
    /*
     * Specify default CPU Frequency.
     */
    BIOS.cpuFreq.lo = 48000000;
    
    /*
     * A flag to determine if xdc.runtime sources are to be included in a custom
     * built BIOS library.
     *
     * Pick one:
     *  - false (default)
     *      The pre-built xdc.runtime library is provided by the respective target
     *      used to build the application.
     *  - true
     *      xdc.runtime library sources are to be included in the custom BIOS
     *      library. This option yields the most efficient library in both code
     *      footprint and runtime performance.
     */
    //BIOS.includeXdcRuntime = false;
    BIOS.includeXdcRuntime = true;
    
    /*
     * The SYS/BIOS runtime is provided in the form of a library that is linked
     * with the application. Several forms of this library are provided with the
     * SYS/BIOS product.
     *
     * Pick one:
     *   - BIOS.LibType_Custom
     *      Custom built library that is highly optimized for code footprint and
     *      runtime performance.
     *   - BIOS.LibType_Debug
     *      Custom built library that is non-optimized that can be used to
     *      single-step through APIs with a debugger.
     *
     */
    BIOS.libType = BIOS.LibType_Custom;
    //BIOS.libType = BIOS.LibType_Debug;
    
    /*
     * Runtime instance creation enable flag.
     *
     * Pick one:
     *   - true (default)
     *      Allows Mod_create() and Mod_delete() to be called at runtime which
     *      requires a default heap for dynamic memory allocation.
     *   - false
     *      Reduces code footprint by disallowing Mod_create() and Mod_delete() to
     *      be called at runtime. Object instances are constructed via
     *      Mod_construct() and destructed via Mod_destruct().
     *
     *  When using BIOS in ROM:
     *      This option must be set to true.
     */
    BIOS.runtimeCreatesEnabled = true;
    //BIOS.runtimeCreatesEnabled = false;
    
    /*
     * Enable logs in the BIOS library.
     *
     * Pick one:
     *  - true (default)
     *      Enables logs for debugging purposes.
     *  - false
     *      Disables logging for reduced code footprint and improved runtime
     *      performance.
     *
     *  When using BIOS in ROM:
     *      This option must be set to false.
     */
    //BIOS.logsEnabled = true;
    BIOS.logsEnabled = false;
    
    
    
    /* ================ Memory configuration ================ */
    var Memory = xdc.useModule('xdc.runtime.Memory');
    /*
     * The Memory module itself simply provides a common interface for any
     * variety of system and application specific memory management policies
     * implemented by the IHeap modules(Ex. HeapMem, HeapBuf).
     */
    
    
    
    /* ================ Program configuration ================ */
    /*
     *  Program.stack is ignored with IAR. Use the project options in
     *  IAR Embedded Workbench to alter the system stack size.
     */
    if (!Program.build.target.$name.match(/iar/)) {
        /*
         *  Reducing the system stack size (used by ISRs and Swis) to reduce
         *  RAM usage.
         */
        Program.stack = 768;
    }
    
    
    
    /*
     * Uncomment to enable Semihosting for GNU targets to print to the CCS console.
     * Please read the following TIRTOS Wiki page for more information on Semihosting:
     * processors.wiki.ti.com/.../TI-RTOS_Examples_SemiHosting
     */
    
    if (Program.build.target.$name.match(/gnu/)) {
        //var SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');
    }
    
    
    
    /* ================ ROM configuration ================ */
    /*
     * To use BIOS in flash, comment out the code block below.
     */
    var ROM = xdc.useModule('ti.sysbios.rom.ROM');
    if (Program.cpu.deviceName.match(/CC26/)) {
        ROM.romName = ROM.CC2650;
    }
    else if (Program.cpu.deviceName.match(/CC13/)) {
        ROM.romName = ROM.CC1350;
    }
    
    
    
    /* ================ Semaphore configuration ================ */
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    /*
     * Enables global support for Task priority pend queuing.
     *
     * Pick one:
     *  - true (default)
     *      This allows pending tasks to be serviced based on their task priority.
     *  - false
     *      Pending tasks are services based on first in, first out basis.
     *
     *  When using BIOS in ROM:
     *      This option must be set to false.
     */
    //Semaphore.supportsPriority = true;
    Semaphore.supportsPriority = false;
    
    /*
     * Allows for the implicit posting of events through the semaphore,
     * disable for additional code saving.
     *
     * Pick one:
     *  - true
     *      This allows the Semaphore module to post semaphores and events
     *      simultaneously.
     *  - false (default)
     *      Events must be explicitly posted to unblock tasks.
     *
     *  When using BIOS in ROM:
     *      This option must be set to false.
     */
    //Semaphore.supportsEvents = true;
    Semaphore.supportsEvents = false;
    
    
    
    /* ================ Swi configuration ================ */
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    /*
     * A software interrupt is an object that encapsulates a function to be
     * executed and a priority. Software interrupts are prioritized, preempt tasks
     * and are preempted by hardware interrupt service routines.
     *
     * This module is included to allow Swi's in a users' application.
     */
    
    /*
     * Reduce the number of swi priorities from the default of 16.
     * Decreasing the number of swi priorities yields memory savings.
     */
    Swi.numPriorities = 6;
    
    
    
    /* ================ System configuration ================ */
    var System = xdc.useModule('xdc.runtime.System');
    /*
     * The Abort handler is called when the system exits abnormally.
     *
     * Pick one:
     *  - System.abortStd (default)
     *      Call the ANSI C Standard 'abort()' to terminate the application.
     *  - System.abortSpin
     *      A lightweight abort function that loops indefinitely in a while(1) trap
     *      function.
     *  - A custom abort handler
     *      A user-defined function. See the System module documentation for
     *      details.
     */
    //System.abortFxn = System.abortStd;
    System.abortFxn = System.abortSpin;
    //System.abortFxn = "&myAbortSystem";
    
    /*
     * The Exit handler is called when the system exits normally.
     *
     * Pick one:
     *  - System.exitStd (default)
     *      Call the ANSI C Standard 'exit()' to terminate the application.
     *  - System.exitSpin
     *      A lightweight exit function that loops indefinitely in a while(1) trap
     *      function.
     *  - A custom exit function
     *      A user-defined function. See the System module documentation for
     *      details.
     */
    //System.exitFxn = System.exitStd;
    System.exitFxn = System.exitSpin;
    //System.exitFxn = "&myExitSystem";
    
    /*
     * Minimize exit handler array in the System module. The System module includes
     * an array of functions that are registered with System_atexit() which is
     * called by System_exit(). The default value is 8.
     */
    System.maxAtexitHandlers = 2;
    
    /*
     * The System.SupportProxy defines a low-level implementation of System
     * functions such as System_printf(), System_flush(), etc.
     *
     * Pick one pair:
     *  - SysMin
     *      This module maintains an internal configurable circular buffer that
     *      stores the output until System_flush() is called.
     *      The size of the circular buffer is set via SysMin.bufSize.
     *  - SysCallback
     *      SysCallback allows for user-defined implementations for System APIs.
     *      The SysCallback support proxy has a smaller code footprint and can be
     *      used to supply custom System_printf services.
     *      The default SysCallback functions point to stub functions. See the
     *      SysCallback module's documentation.
     */
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    SysMin.bufSize = 128;
    System.SupportProxy = SysMin;
    //var SysCallback = xdc.useModule('xdc.runtime.SysCallback');
    //System.SupportProxy = SysCallback;
    //SysCallback.abortFxn = "&myUserAbort";
    //SysCallback.exitFxn  = "&myUserExit";
    //SysCallback.flushFxn = "&myUserFlush";
    //SysCallback.putchFxn = "&myUserPutch";
    //SysCallback.readyFxn = "&myUserReady";
    
    
    
    /* ================ Task configuration ================ */
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    /*
     * Check task stacks for overflow conditions.
     *
     * Pick one:
     *  - true (default)
     *      Enables runtime checks for task stack overflow conditions during
     *      context switching ("from" and "to")
     *  - false
     *      Disables runtime checks for task stack overflow conditions.
     *
     *  When using BIOS in ROM:
     *      This option must be set to false.
     */
    //Task.checkStackFlag = true;
    Task.checkStackFlag = false;
    
    /*
     * Set the default task stack size when creating tasks.
     *
     * The default is dependent on the device being used. Reducing the default stack
     * size yields greater memory savings.
     */
    Task.defaultStackSize = 512;
    
    /*
     * Enables the idle task.
     *
     * Pick one:
     *  - true (default)
     *      Creates a task with priority of 0 which calls idle hook functions. This
     *      option must be set to true to gain power savings provided by the Power
     *      module.
     *  - false
     *      No idle task is created. This option consumes less memory as no
     *      additional default task stack is needed.
     *      To gain power savings by the Power module without having the idle task,
     *      add Idle.run as the Task.allBlockedFunc.
     */
    Task.enableIdleTask = true;
    //Task.enableIdleTask = false;
    //Task.allBlockedFunc = Idle.run;
    
    /*
     * If Task.enableIdleTask is set to true, this option sets the idle task's
     * stack size.
     *
     * Reducing the idle stack size yields greater memory savings.
     */
    Task.idleTaskStackSize = 512;
    
    /*
     * Reduce the number of task priorities.
     * The default is 16.
     * Decreasing the number of task priorities yield memory savings.
     */
    Task.numPriorities = 4;
    
    
    
    /* ================ Text configuration ================ */
    var Text = xdc.useModule('xdc.runtime.Text');
    /*
     * These strings are placed in the .const section. Setting this parameter to
     * false will save space in the .const section. Error, Assert and Log messages
     * will print raw ids and args instead of a formatted message.
     *
     * Pick one:
     *  - true (default)
     *      This option loads test string into the .const for easier debugging.
     *  - false
     *      This option reduces the .const footprint.
     */
    //Text.isLoaded = true;
    Text.isLoaded = false;
    
    
    
    /* ================ Types configuration ================ */
    var Types = xdc.useModule('xdc.runtime.Types');
    /*
     * This module defines basic constants and types used throughout the
     * xdc.runtime package.
     */
    
    
    
    /* ================ TI-RTOS middleware configuration ================ */
    var mwConfig = xdc.useModule('ti.mw.Config');
    /*
     * Include TI-RTOS middleware libraries
     */
    
    
    
    /* ================ TI-RTOS drivers' configuration ================ */
    var driversConfig = xdc.useModule('ti.drivers.Config');
    /*
     * Include TI-RTOS drivers
     *
     * Pick one:
     *  - driversConfig.LibType_NonInstrumented (default)
     *      Use TI-RTOS drivers library optimized for footprint and performance
     *      without asserts or logs.
     *  - driversConfig.LibType_Instrumented
     *      Use TI-RTOS drivers library for debugging with asserts and logs enabled.
     */
    driversConfig.libType = driversConfig.LibType_NonInstrumented;
    //driversConfig.libType = driversConfig.LibType_Instrumented;
    
    
    
    /* ================ Application Specific Instances ================ */
    /* ================ Application Specific Instances ================ */
    var Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox');
    Program.global.rxDataMailbox = Mailbox.create(256, 1);
    Program.global.rxDataMailbox.instance.name = "rxDataMailbox";
    /*var task0Params = new Task.Params();
    task0Params.instance.name = "uartSend";
    task0Params.priority = 1;
    Program.global.uartSend = Task.create("&uartSendTask", task0Params);*/
    

    See above the .cfg file

    also I will try the other way that you have mentioned.

    The problem is that I cannot have BIOS_NO_WAIT in my scenario. So in that case will it be logical to use Event to trigger the mailbox_post so that I can have the BIOS_NO_WAIT option for timeout?

    Vikram

  • Take a look at my full callstack when I get the Assert.  If you were to place a BP on uartReceiveFinished() when using CALLBACK mode, you should see the same callstack as above (without the stuff above uartReceiveFinished()) when you hit that BP.  If not, then we're not running the same code.

    Continuing on from this BP, you will make a call to writeToTerminal() which will call Mailbox_post(), which will call Semaphore_pend(), and with Asserts enabled, an Assert will get raised because you're calling Semaphore_pend() from a Swi.

    Error.policyFxn = Error.policySpin;

    This config setting prevents the Assert from progressing past the Error_raise(), since Error_raise() will just spin in a for (;;) forever loop.  I would expect you to hit that spin, and not get a crash, but loader_exit() will never be reached (nor will abort() or System_abort(), etc.).

    However, I should've seen a *different* problem earlier, and this might be the problem that's causing your crash, before you even get to the point I'm discussing above.  The problem is that your Mailbox message size is larger than the messages that you're passing to the Mailbox APIs.  You're creating a Mailbox with message size of 256, which means that Mailbox will copy 256 bytes from your message location during Mailbox_post(), and it will copy 256 bytes to your provided storage for Mailbox_pend().  Your storage for Mailbox_pend() is:
        typedef struct MsgObj {
            Int id;
            String buf;
        } MsgObj, *Msg;
    which is too small, and Mailbox_post() will stomp all over whatever is after your storage variable, which in this case is a local stack-based MsgObj.

    The storage you provide to Mailbox_pend() needs to be equal to or bigger than the size of your slots in the Mailbox.

    The problem is that I cannot have BIOS_NO_WAIT in my scenario. So in that case will it be logical to use Event to trigger the mailbox_post so that I can have the BIOS_NO_WAIT option for timeout?

    Event_pend() can only be called from a Task, so I don't see how that would help here.

    The Event mechanism allows a Task to know that the following Mailbox_post() will succeed without blocking (in which case it is recommended to pass BIOS_NO_WAIT).  It's possible to "know" in other ways that it won't block, such as when you know that the dynamics of the Mailbox usage will guarantee that there is a slot available when you call Mailbox_post().  But I wouldn't recommend relying on that, and instead recommend following the API guidelines that say "don't call Mailbox_pend() or Mailbox_post() from a Swi or Hwi".

    You're creating only 1 message slot in the Mailbox.  That sort of defeats the purpose of the Mailbox module.  Why not create more slots?

    I would recommend using Queues and Semaphores instead.  To do so, you would create a Queue for sending messages and a Semaphore for synchronizing access to the Queue.  You would embed a Queue_Elem in your MsgObj as the first struct member and create a Semaphore with initial count of 0.  To post a message:
        Queue_put(msgQue, &msg);
        Semaphore_post(msgSem);
    and to retrieve a message:
        Semaphore_pend(msgSem);
        msg = Queue_get(msgQue);

    Regards,

    - Rob

  •  Hi Rob,

    Firstly, I am getting below screen when I insert a  BP at uartReceivedFinished and when that BP is hit.

    I dont see any other stuff that is visivle in your screen shot that you had attached.

    The code is the same stand alone code that I had attached on 10th of February.

    Vikram

  • The lowest entry in your call stack seems invalid.  Is that address 0x1001B010 even valid memory?

    Would you please fix the problem that I identified with your Mailbox message size being too big?  You need to match the size you specify in your Mailbox.create() with the size of the data objects that you give to Mailbox.  Once that is fixed then we can look into your difference in call stack.

    Regards,

    - Rob

  • Yes Rob, 

    I will try the changing of the Mailbox message size today. The only reason I sent that image is to see if that triggered something that you could think of.

    Vikram