Part Number: CC2650
Tool/software: TI-RTOS
Hello
I have a single HWI and it simply uses System_printf() and a Semaphore_post(); Somehow, I am getting an exception. There are photos below including my code that should help identify the issue. What doesn't make sense is that I increased the HWI buffer from 768 to 4096 and the stack still raises an exception. I'm not sure how a HWI stack is allocated within the context of a Task (does the HWI stack get used up when a HWI is called)? Please note that there is an external .c file "cyc_counterR1.h" containing an algorithm with about 2 kbytes of data and several functions. These functions are exposed to the entirety of the code running on the CC2650, but the functions are only called from within the scope of Task2 (cyc_algo). Could it be that when a HWI occurs while executing one of these functions, much of the data is being put onto the HWI stack for holding purposes? I have run out of options and cannot find a solution. Thank you for your help ahead of time
/*
* 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 <xdc/runtime/Types.h>
#include <xdc/runtime/Timestamp.h>
#include <ti/sysbios/heaps/HeapBuf.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/IHeap.h>
#include <xdc/runtime/Log.h>
#include <ti/uia/events/UIAEvt.h>
#include <ti/uia/events/UIAErr.h>
#include <ti/uia/events/UIAStatistic.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 4096
#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 HWI_ERROR()
{
System_printf("HWI ERROR\n");
System_flush();
}
void scCtrlReadyCallback(void) {
// System_printf("rdycallback\n");
} // scCtrlReadyCallback
void scTaskAlertCallback(void) {
System_printf("alertcallback\n");
// System_flush();
// 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)
{
Types_FreqHz fhz;
Timestamp_getFreq(&fhz);
Log_info0("Testing");
// System_printf("TIMESTAMP FREQ: %d - %d", fhz.hi, fhz.lo);
// System_flush();
// 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();
}
// Main loop
while (1) {
// Wait for an ALERT callback
// System_printf("pending...\n");
// System_flush();
Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
// Clear the ALERT interrupt source
scifClearAlertIntSource();
UInt32 t = Clock_getTicks()/100;
System_printf("Writing data\n");
add_1(t, scifTaskData.i2cLightSensor.output.value[0]*10);
add_2(t, scifTaskData.i2cLightSensor.output.value[1]*10);
scifAckAlertEvents();
}
}
Void cyc_algo(UArg arg0, UArg arg1)
{
System_printf("cycalgo\n");
/* ***Setup for algorithm*** */
// Applies initial data for sensor 1
toggle = 0;
wl[toggle] = 1;
System_printf("toggle\n");
// Waits for data to be available
while(!s1_rdy)
{
System_printf("while1\n");
}
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
// System_printf("s1 t, d: %d %d\n", py_time, py_dist);
// System_flush();
// Applies initial data for sensor 2
toggle = 1;
wl[toggle] = 1;
// Waits for data to be available
while(!s2_rdy)
{
}
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
// System_printf("s2 t, d: %d %d\n", py_time, py_dist);
// System_flush();
while (1) {
if (bool_cond[toggle][4]) // Can shift
{
toggle = (toggle == 0) ? 1:0;
// Waits for appropriate data
if (toggle == 0)
{
while(!s1_rdy){
;
}
// System_flush();
rm_1(&py_time, &py_dist);
// Log_write5( UIAEvt_intWithKey, py_dist, 0, 0,(IArg)"py_dist");
if (py_dist<1500)
{
System_printf("s1 t, d: %d %d\n", py_time, py_dist);
System_flush();
}
}
else
{
while(!s2_rdy){System_printf("Waiting in s2\n");}
// System_flush();
rm_2(&py_time, &py_dist);
if (py_dist<1500)
{
System_printf("s1 t, d: %d %d\n", py_time, py_dist);
System_flush();
}
}
// 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())
{
System_printf("Wl1\n");
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';
clear_output();
output_ready = 0; // Data has been written to python
// System_flush();
// BIOS_exit(1);
}
continue;
}
}
if (wl[toggle] == 2)
{
System_printf("Wl1\n");
if (while_loop2())
{
continue;
}
}
if (wl[toggle] == 3)
{
System_printf("Wl1\n");
if (while_loop3())
{
continue;
}
}
System_flush();
}
}
//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 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 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 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(¶ms);
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(¶ms, &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);
}