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/CC2650: Semaphore_pend() halting program AND leading to Several Error messages

Part Number: CC2650

Tool/software: TI-RTOS

Hello,

I have been attempting an issue for so long now I am ready to throw my keyboard at the wall. In hopes of actually completing this job, I have come to reach out for help. The code below defines two tasks. Task 1 is executed first due to its higher priority and then reaches a Semaphore_pend(), at which point the entire program halts (I checked this with a breakpoint).I would like control to be sent over to Task 2 (w/ lower priority here). If I comment out the defining lines of task 2 (where params is set and Task_construct() is called), then the code executes fine (only I need task 2 to be running!)

My goal: Start executing task 1, pend() the task, enter task 2, an alert()/interrupt is called form Sensor controller whose callback calls a post(), control returns to Task 1 until the next pend()... repeat.

Note: if I do not use a breakpoint and run the code, I get the error below... Thank you to the kind soul who will toil to figure this out!

/*
 * 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.
 */

/*
 *  ======== empty.c ========
 */
/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>

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

#include <ti/sysbios/heaps/HeapBuf.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/IHeap.h>

#include "cyc_counterR1.h"
/* TI-RTOS Header files */
// #include <ti/drivers/I2C.h>
#include <ti/drivers/PIN.h>
// #include <ti/drivers/SPI.h>
#include <ti/drivers/UART.h>
// #include <ti/drivers/Watchdog.h>

#include "scif.h"
#include "ex_include_tirtos.h"
#define BV(n)               (1 << (n))
// Display error message if the SCIF driver has been generated with incorrect operating system setting
#ifndef SCIF_OSAL_TIRTOS_H
    #error "SCIF driver has incorrect operating system configuration for this example. Please change to 'TI-RTOS' in the Sensor Controller Studio project panel and re-generate the driver."
#endif

// Display error message if the SCIF driver has been generated with incorrect target chip package
#ifndef SCIF_TARGET_CHIP_PACKAGE_QFN48_7X7_RGZ
    #error "SCIF driver has incorrect target chip package configuration for this example. Please change to 'QFN48 7x7 RGZ' in the Sensor Controller Studio project panel and re-generate the driver."
#endif

/* Board Header files */
#include "Board.h"
#include "l_list.h"

//#define SERIALSTACK 2048
#define CYCSTACK 2048
#define LIDARSTACK 2048

char msg[64]; // To hold the message
char out[64]; // to hold output message
_Bool read_again = 0;
_Bool start_readings = 1;
_Bool first_char = 1;
int ext = 0; // can remove
long serial_time = 0;
long serial_dist = 0;
long serial_sensor = 0;
//
//// For reading / writing via serial
//Task_Struct serial_task_Struct;
//Char serial_task_0[SERIALSTACK];

Task_Struct algo_task_Struct;
Char algo_task_1[CYCSTACK];

Task_Struct lidar_task_Struct;
Char lidar_task_2[LIDARSTACK];

Semaphore_Struct semStruct;
Semaphore_Handle semHandle;

UART_Handle comm_handle; // comm handle
UART_Params comm_params; // comm parameters

HeapBuf_Params params;
HeapBuf_Handle heap_buff;
extern IHeap_Handle heap;
extern Memory_Stats heapStats;
extern Error_Block eb;


void scCtrlReadyCallback(void) {

} // scCtrlReadyCallback

void scTaskAlertCallback(void) {

    // Wake up the OS task
    Semaphore_post(semHandle);

} // scTaskAlertCallback

Void format_msg()
{
	static char *token = NULL;
	token = strtok(msg, ","); // Gets time
	serial_time = atol(token); // Stores time via pointer
	token = strtok(NULL, ","); // Gets distance
	serial_dist= atol(token); // Stores distance via pointer
	token = strtok(NULL, "!"); // Gets sensor
	serial_sensor = atol(token); // Stores sensor via pointer
	token = NULL;

}


void format_count_data()
{
	int size = sizeof(DATA_OUT)/sizeof(int);

	static char longbuff[15];

	sprintf(longbuff, "%d", time_out);

	strcat(out, longbuff); // Converts time to char array, stores it in msg
	strcat(out, ","); // Adds a comma
	static int k = 0; // Used for iteration, is only declarted/created once

	for(k=0; k<size; k++)
	{
		sprintf(longbuff, "%i", DATA_OUT[k]);
		strcat(out, longbuff); // Stores all data in char array
		if (k != (size - 1))
			strcat(out, ","); // Delimiter
	}
	k = 0;
	strcat(out, "!"); // Final delimiter
}

Void lidar_task(UArg arg0, UArg arg1)
{
	static uint16_t dist1 = 0;

	// Initialize the Sensor Controller
	scifOsalInit();
	scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);
	scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
	scifInit(&scifDriverSetup);

	// Set the Sensor Controller task tick interval to 1 millisecond
	//scifStartRtcTicksNow(0x00010000);
	scifStartRtcTicksNow(65);

	// Configure to trigger interrupt at first result, and start the Sensor Controller's I2C Light
	// Sensor task (not to be confused with OS tasks)
	scifStartTasksNbl(BV(SCIF_I2C_LIGHT_SENSOR_TASK_ID));

	uint16_t status = scifTaskData.i2cLightSensor.state.i2cStatus;
	if (status!=0x00) {
	System_printf("I2C Error!!!!\n");
	System_flush();
	}

	uint8_t fast_counter=0;

	// Main loop
	while (1) {

		// Wait for an ALERT callback
		Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);

		// Clear the ALERT interrupt source
		scifClearAlertIntSource();


		UInt32 t = Clock_getTicks();

		add_1(t, scifTaskData.i2cLightSensor.output.value[0]);
		add_2(t, scifTaskData.i2cLightSensor.output.value[1]);

		scifAckAlertEvents();
	}

}

Void cyc_algo(UArg arg0, UArg arg1)
{

	/* ***Setup for algorithm*** */
	// Applies initial data for sensor 1
	toggle = 0;
	wl[toggle] = 1;

	// Waits for data to be available
	while(!rm_1(&py_time, &py_dist))
	{
	}

	// Stores data in appropriate variables
	dist_data[toggle][0] = dist_data[toggle][1]; // buff_dist = current_dist
	dist_data[toggle][1] = py_dist; // curr_dist = next dist
	time_data[toggle][7] = time_data[toggle][4]; // buffer_time = temp time
	time_data[toggle][4] = py_time; // temp_time = new time

	// Applies initial data for sensor 2
	toggle = 1;
	wl[toggle] = 1;

	// Waits for data to be available
	while(!rm_2(&py_time, &py_dist))
	{
	}

	// Stores data in appropriate variables
	dist_data[toggle][0] = dist_data[toggle][1]; // buff_dist = current_dist
	dist_data[toggle][1] = py_dist; // curr_dist = next dist
	time_data[toggle][7] = time_data[toggle][4]; // buffer_time = temp time
	time_data[toggle][4] = py_time; // temp_time = new time

	while (1) {
		if (bool_cond[toggle][4]) // Can shift
		{
			toggle = (toggle == 0) ? 1:0;

			// Waits for appropriate data
			if (toggle == 0)
			{
				while(!rm_1(&py_time, &py_dist)){};
			}
			else
			{
				while(!rm_2(&py_time, &py_dist)){};
			}

			// Stores data in appropriate variables
			dist_data[toggle][0] = dist_data[toggle][1]; // buff_dist = current_dist
			dist_data[toggle][1] = py_dist; // curr_dist = next dist
			time_data[toggle][7] = time_data[toggle][4]; // buffer_time = temp time
			time_data[toggle][4] = py_time; // temp_time = new time

		}

		bool_cond[toggle][4] = 1; // Sets can shift to 1

		// Multiplexer like functionality
		if (wl[toggle] == 1)
		{
			if (while_loop1())
			{
				if (output_ready)
				{
					// Sends data to python
					format_count_data();
////					UART_write(comm_handle, out, strlen(out));
					System_printf("OUTPUT: %s\n", out);
					out[0]='\0';
					System_flush();
					clear_output();
					output_ready = 0; // Data has been written to python
				}
				continue;
			}
		}
		if (wl[toggle] == 2)
		{
			if (while_loop2())
			{
				continue;
			}
		}
		if (wl[toggle] == 3)
		{
			if (while_loop3())
			{
				continue;
			}
		}
	}

}

//Void read_write(UArg arg0, UArg arg1)
//{
//	msg[0] = '\0'; // Initializes array to have no contents (VERY IMPORTANT!)
//
//	char *read_val; // Holds read value
//	char rdy[] = "r!"; // Holds ready string
//	char next[] = "^d!"; // Holds "done reading" string
//
//	System_printf("Variables set up\n");
//	System_flush();
//
//	// Create a UART with data processing off. //
//	UART_Params_init(&comm_params);
//	comm_params.writeDataMode = UART_DATA_BINARY;
//	comm_params.readDataMode = UART_DATA_BINARY;
//	comm_params.readReturnMode = UART_RETURN_FULL;
//	comm_params.readEcho = UART_ECHO_OFF;
//	comm_params.baudRate = 115200;
//	comm_handle = UART_open(Board_UART0, &comm_params);
//
//	System_printf("COMM set-up\n");
//	System_flush();
//
//
//}

int main(void)
{
    Task_Params serial_params;
    Task_Params algo_params;
    Task_Params lidar_params;

	Semaphore_Params semParams;

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

//    /* Construct read/write Task thread */
//    Task_Params_init(&serial_params);
//    serial_params.stackSize = SERIALSTACK;
//    serial_params.stack = &serial_task_0;
//    serial_params.priority = 1;
//    Task_construct(&serial_task_Struct, (Task_FuncPtr)read_write, &serial_params, NULL);

    /* Construct test Task thread */
    Task_Params_init(&algo_params);
    algo_params.stackSize = CYCSTACK;
    algo_params.stack = &algo_task_1;
    algo_params.priority = 1;
    Task_construct(&algo_task_Struct, (Task_FuncPtr)cyc_algo, &algo_params, NULL);

    /* Construct lidar Task thread */
    Task_Params_init(&lidar_params);
    lidar_params.stackSize = LIDARSTACK;
    lidar_params.stack = &lidar_task_2;
    lidar_params.priority = 2;
    Task_construct(&lidar_task_Struct, (Task_FuncPtr)lidar_task, &lidar_params, NULL);

	/* Construct a Semaphore object to be use as a resource lock, inital count 1 */
	Semaphore_Params_init(&semParams);
	semParams.mode = Semaphore_Mode_BINARY;
	Semaphore_construct(&semStruct, 0, &semParams);

	/* Obtain instance handle */
	semHandle = Semaphore_handle(&semStruct);

	/* Declare and define the heap */
	char buf[2560]; // IN MAU, in CC2650 this is in BYTES

	Error_init(&eb);
	HeapBuf_Params_init(&params);
	params.blockSize = 16; // 16 MAUs = 16 bytes per block
	params.numBlocks = 160; // 160 blocks (16 bytes/block * 160 blocks= 2560 bytes)
	params.buf = (Ptr)buf; // Stores buffer as a character array of bytes
	params.bufSize = 2560; // Number of bytes contained within buffer
	heap_buff = HeapBuf_create(&params, &eb); // Sets all properties for the heap handle
	heap = HeapBuf_Handle_upCast(heap_buff);

    System_printf("Starting BIOS\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();

    init_sens_structs();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

  • UPDATE: If I monitor every interrupt and task via System_printf() and System_flush() (slowing the process down), the algorithm runs perfectly as expected. Although I actually don't want these flushes there, as you would assume...

  • Turns out that line 220 was calling functions within the task, overloading the stack. I made this assumption and changed the function call to a Boolean variable and it fixed the problem
  • Heads-up on your heap also. The stack main() uses is used for the ISR stack after BIOS_start is called. The stack is reset to the beginning once BIOS_start is called. So bad things are going to happen to any allocated memory. I'd make char buf[2560]; a global instead of a local.

  • Could you go into a little more detail and be a little more clear as i think you are describing an issue i am having now. Thank you
  • You have this

    int main(void)

    {

       ...

       char buf[2560]; // IN MAU, in CC2650 this is in BYTES

       ...

       HeapBuf_Params_init(&params);

       params.blockSize = 16; // 16 MAUs = 16 bytes per block

       params.numBlocks = 160; // 160 blocks (16 bytes/block * 160 blocks= 2560 bytes)

       params.buf = (Ptr)buf; // Stores buffer as a character array of bytes

       params.bufSize = 2560; // Number of bytes contained within buffer

       heap_buff = HeapBuf_create(&params, &eb); // Sets all properties for the heap handle

       heap = HeapBuf_Handle_upCast(heap_buff);

        ...

        BIOS_start()

    }

    The buf array is on the stack that main() is using. Once you call BIOS_start(), that stack is reset and used as the stack for interrupts. So when you alloc a buffer from that heap, you are potentially corrupting the system stack (bad thing!). Or your system stack is changing (as it should) and potentially corrupting your allocated blocks and/or the linked list of free blocks in the heap (bad thing!). 

    You need to move the definition of buf up (and call it a more unique and meaningful name) so it's a global variable.

    char myHeapBuffer[2560]; // IN MAU, in CC2650 this is in BYTES

    int main(void)

    {

       ...

       params.buf = (Ptr)myHeapBuffer; // Stores buffer as a character array of bytes

    This might be the problem you are seeing on your other posts.

    Todd

  • Many thanks. I will change this at work tomorrow and let you know the outcome!
  • Hello!

    So I have done what you have suggested and in fact the overflow issues have disappears (you have no idea how much I appreciate that). There is one final issue that you may be able to help me with. All the ROV errors in the BIOS tab have disappeared (thanks to your tip) except for these two (image below). What could possibly be causing this?

  • ROV tries to interpret structures (e.g. Task_Struct) before they are constructed and gives the error. Once the construct calls is made (e.g. Task_construct), it is shown properly. One exception is that if you have the RF module, these errors continue to show. They are not real errors. We have fixed this in the next version coming out in a month or two.

    Todd
  • I have heard of this phenomenon, however, the error persists during execution (After BIOS_start()) and finally when my program halts, this is the only error the ROV continually shows. Do you think there is some memory overflow issue here?
  • Behold! You were correct about this too, everything is in working order, my program was not halting - I was merely not putting the System_flush() in the right place to view output. I cannot thank you enough!