Part Number: MSP432P4011
Other Parts Discussed in Thread: SYSCONFIG
Hello forum, I'm developing an application with MSP432 using TI-RTOS -
Part - MSP432P4011
TI-RTOS version - We are using the Simplelink MSP432P4 SDK, version 3.30.0.13
CCS v9.2.0.00013
The design has 2 threads - Thread 1: SensorThread with priority 1 (lower) and Thread 2: DataCaptureThread with priority 2 (higher). The idle thread has priority 0.
We have used the POSIX and pThread architecture to schedule RTOS events within a thread and to pre-empt or trigger the other thread. SensorThread is the main thread in the application, which gathers data through ADCs, talks to 2 SPI slaves and reads data etc. DataCapture thread is a high priority thread that needs to be triggered when certain conditions are detected.
For configuring the GPIOs, ADCs, SPI etc, we are using the sysconfig tool. Individually, we have developed and tested the low-level SPI/ADC drivers through this application in the thread initialization phase and it works fine. The problem is arising when we try to integrate it with the RTOS scheduler using semaphores.
Here's my code -
The file main_tirtos.c has
/*
* ======== main ========
*/
int main(void)
{
/* Call driver init functions */
Board_init();
SensorThread_createTask();
DataCaptureThread_createTask();
BIOS_start();
return (0);
}
The SensorThread.c looks like this -
void SensorThread_createTask(void)
{
pthread_attr_t pAttrs;
struct sched_param priParam;
struct mq_attr attr;
int retc;
int detachState;
/*
* Message Queue to send messages to sensor thread.
* It is non-blocking to allow it to be called by ISRs (e.g. GPIO and
* Timer callbacks).
*/
attr.mq_maxmsg = ST_MSG_NUM; //Defined as 6
attr.mq_msgsize = ST_MSG_SIZE; //Defined as sizeof(stEvt_t)
attr.mq_flags = 0;
appMsgQueue = mq_open("sensor", O_RDWR | O_CREAT | O_NONBLOCK, 0664, &attr);
if (appMsgQueue == (mqd_t)-1) {
/* mq_open() failed */
while (1);
}
/* Semaphore to notify sensor thread that msg is present. */
retc = sem_init(&appMsgSem, 0, 0);
if (retc == -1) {
while (1);
}
/* Set priority and stack size attributes */
pthread_attr_init(&pAttrs);
priParam.sched_priority = ST_TASK_PRIORITY;
detachState = PTHREAD_CREATE_DETACHED;
retc = pthread_attr_setdetachstate(&pAttrs, detachState);
if (retc != 0) {
/* pthread_attr_setdetachstate() failed */
while (1);
}
pthread_attr_setschedparam(&pAttrs, &priParam);
retc |= pthread_attr_setstacksize(&pAttrs, ST_TASK_STACK_SIZE);
if (retc != 0) {
/* pthread_attr_setstacksize() failed */
while (1);
}
/* Create Sensor Thread with priority = 1 */
retc = pthread_create(&sensorthread_handler, &pAttrs, SensorThread_taskFxn, NULL);
if (retc != 0) {
/* pthread_create() failed */
while (1);
}
}
/*
* ======== sensorThread ========
*/
static void SensorThread_init(void)
{
/* Initialize Display */
Display_Params_init(¶ms_disp);
handle_disp = Display_open(Display_Type_UART, ¶ms_disp);
if (handle_disp == NULL) {
// Display_open() failed
while(1);
}
// Output to Display
Display_printf(handle_disp, 0, 0, "Display Initialized");
/* Enable GPIO CallBack Functions */
/* Call driver init functions */
GPIO_init();
// Output to Display
Display_printf(handle_disp, 0, 0, "GPIO Initialized");
/* Open and initialize the SPI ports */
SPI_init();
SPI_Params_init(&spiParams_ADE);
spiParams_ADE.bitRate = 5000000;
spiParams_ADE.frameFormat = SPI_POL1_PHA1;
spiParams_ADE.mode = SPI_MASTER;
spiParams_ADE.transferMode = SPI_MODE_BLOCKING;
spiParams_ADE.dataSize = 8;
spi_ADE = SPI_open(ADE_SPI, &spiParams_ADE);
if (spi_ADE == NULL) {
// Error opening SPI
Display_printf(handle_disp, 0, 0, "Error opening SPI port for ADE!");
while (1);
}
// Output to Display
Display_printf(handle_disp, 0, 0, "SPI Port for ADE Open");
//Do AFE Initializations here
ADE_Init(&spi_ADE, &handle_disp);
// Output to Display
Display_printf(handle_disp, 0, 0, "ADE Initialized");
SPI_Params_init(&spiParams_Kernel);
spiParams_Kernel.bitRate = 2000000;
spiParams_Kernel.frameFormat = SPI_POL0_PHA1;
spiParams_Kernel.mode = SPI_MASTER;
spiParams_Kernel.transferMode = SPI_MODE_BLOCKING;
spiParams_Kernel.dataSize = 8;
spiParams_Kernel.transferTimeout = 500;
spi_Kernel = SPI_open(KERNEL_SPI, &spiParams_Kernel);
if (spi_Kernel == NULL) {
// Error opening SPI
Display_printf(handle_disp, 0, 0, "Error opening SPI port for Kernel!");
while (1);
}
// Output to Display
Display_printf(handle_disp, 0, 0, "SPI Port for Kernel Open");
/* Toggle GPIO to indicate status*/
GPIO_write(LED4, 1);
Display_printf(handle_disp, 0, 0, "Setting Gains to x100");
//Set gain of 100
SensorThread_SetGain(1);
Display_printf(handle_disp, 0, 0, "Initializing ADCs");
// One-time init of ADC driver
ADC_init();
// initialize optional ADC parameters
ADC_Params_init(&AX_params);
ADC_Params_init(&AY_params);
ADC_Params_init(&AZ_params);
ADC_Params_init(&TEMP_INT_params);
ADC_Params_init(&TEMP_EXT_params);
/* Set GPIO Interrupts */
GPIO_setCallback(MSP_WAKE, SensorThread_WDTCallbackFxn);
GPIO_enableInt(MSP_WAKE);
GPIO_setCallback(IRQ, SensorThread_ADE_IRQCallbackFxn);
GPIO_enableInt(IRQ);
GPIO_setCallback(REV_PWR, SensorThread_ADE_REVPCallbackFxn);
GPIO_enableInt(REV_PWR);
GPIO_setCallback(VOLTAGE_ZX, SensorThread_ADE_VoltageZXCallbackFxn);
GPIO_enableInt(VOLTAGE_ZX);
//Activate the WDT by giving it a pulse
GPIO_write(MSP_DONE, 1);
Task_sleep(100); //Wait for some time (Duration??)
GPIO_write(MSP_DONE, 0);
Display_printf(handle_disp, 0, 0, "WDT Activated");
}
static void *SensorThread_taskFxn(void *arg0)
{
// Initialize application
SensorThread_init();
Display_printf(handle_disp, 0, 0, "Sensor Thread has been Initialized");
stEvt_t msg;
int retc;
while (1) {
/* Wait for a change to occur */
retc = sem_wait(&appMsgSem);
if (retc == 0) {
retc = mq_receive(appMsgQueue, (char *)&msg, sizeof(msg), NULL);
if (retc != -1) {
switch (msg.hdr.event) {
case ST_DUMMY_EVT:
break;
case ST_WDT_EVT:
SensorThread_processWDTEvent();
break;
case ST_IRQ_EVT:
SensorThread_processADE_IRQEvent();
break;
case ST_REVP_EVT:
SensorThread_processADE_REVPEvent();
break;
case ST_VOLTAGE_ZX_EVT:
SensorThread_processADE_VoltageZXEvent();
break;
case ST_CAPTURED_DATA_EVT:
SensorThread_processCapturedDataEvent((float *)msg.pData);
break;
default:
break;
}
}
}
}
}
The stEvt_t and other data structures are as follows -
/*********************************************************************
* TYPEDEFS
*/
typedef struct
{
uint16_t event; // Event type.
uint8_t state; // Event state;
}appEvtHdr_t;
// App event.
typedef struct
{
appEvtHdr_t hdr; // event header.
uint8_t *pData; // Event payload
} stEvt_t
When I run this code, it executes as expected, till it enters the infinite while(1) look in the SensorThread task function -
I can see all the initalizations happening as expected, but when the code enters the while(1) and if any new "event" is posted, I get an exception in the ROV.
For example, I have registered a callback function on one of the GPIO pins labelled as "MSP_WAKE" in the above code, referenced here -
/* Set GPIO Interrupts */
GPIO_setCallback(MSP_WAKE, SensorThread_WDTCallbackFxn);
GPIO_enableInt(MSP_WAKE);
The pin configuration has been set in Sysconfig as Interrupt priority - 7 (lowest priority), Mode - input, Pull - Pull Up, Interrupt Trigger - Falling Edge, Callback function - NULL - (This is set to NULL because for some reason, if I try registering the callback here, Sysconfig gives me an error, so I chose to do it in runtime).
The SensorThread_WDTCallbackFxn and EnqueueEvent functions are as -
static void SensorThread_WDTCallbackFxn(uint_least8_t index)
{
SensorThread_enqueueMsg(ST_WDT_EVT, NULL, NULL);
}
/*
* Creates an event message and puts the message in RTOS queue
*/
static void SensorThread_enqueueMsg(uint16_t event, uint8_t state,
uint8_t *pData)
{
stEvt_t *pMsg;
int retc;
// Create dynamic pointer to message.
if ((pMsg = malloc(sizeof(stEvt_t))))
{
pMsg->hdr.event= event;
pMsg->hdr.state = state;
pMsg->pData = pData;
}
retc = mq_send(appMsgQueue, (char *)pMsg, sizeof(stEvt_t), 0);
if (retc == -1) {
// Failed to send to message queue
}
retc = sem_post(&appMsgSem);
if (retc == -1) {
while (1);
}
The code enters the while(1) and waits for an event to post. It waits in the idle task, while both other tasks are blocked. If an event is posted (ex, GPIO is triggered), I get an exception. The ROV image is shown below-
The exact error is
Idle Task - "Invalid task internal state: pend element address (0x0) is not within the task's stack"
Semaphore - "Problem scanning pend queue. Target memory read failed at address 0xBEBEBEBE, length: 8. This read is at an INVALID address according to the application's section map.". This happens on other event triggers as well, like a timer callback function trying to enqueue an RTOS event using the SensorThread_enqueueMsg function.
This error is very similar to 2 prev. E2E posts but I havent been able to resolve it based on the comments posted on those posts -
1) https://e2e.ti.com/support/legacy_forums/embedded/tirtos/f/355/t/452095
There was no solution posted
2) https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/689774
The solution talks about zero-latency interrupts causing an issue. The resolution posted was to change the HWI disable priority to 16 in the .CFG file. However, there is no .CFG file in my project!!
There is possibly some error in our implementation, but we are unable to pinpoint exactly what is causing this. Is there any way to solve this issue? Help will be greatly appreciated!

