FreeRTOS on Concerto F28M35H52C1 problems

meetech wrote on Friday, May 11, 2012:

Is anyone using FreeRTOS on the TI Concerto chip? I’m having problems with tasks and queues. Anyone having any success?

rtel wrote on Friday, May 11, 2012:

There is no official code for the Concerto, but I know that FreeRTOS is used by a number of people on the CM3 side, and all the standard FreeRTOS Cortex-M3 ports (for the various compilers) should not give any problems.  There is no official code for the C2000 side though.

Can you explain the problem you are having?

meetech wrote on Friday, May 11, 2012:

Thanks for your response, Richard.
I started my development by using a limited example program from TI that sends messages from one node to another. In doing this, TI used their own RTOS for the C28 DSP side and FreeRTOS to implement the message handling on the CM3 side. They provided 2 sets of tasks to serrvice the IPC ram and to handle the data received and to prepare data for transmission. The IPC handler uses a software interrupt to communicate intent / alert to the other side.
As this demo did not include any actual interaction with the outside world, I added tasks to handle the UART Tx and Rx along with ring buffers to accumulate serial data. The procedure is pretty basic - collect serial data, convert it to the proper format and pass it to a PLC (power line communication) network. My original intent was to use an interrupt to receive all UART input, but when I added that interrupt to the program, the operation hangs (the uart demo program works fine when run by itself).  So, to work around for the time being, I just use the UART tasks to collect and send serial data. This should work, I believe, as I am only running at 38400 baud.
There are several general uncertainties in this system, those being the new chip, the stability of CCSv4 (I have been advised not to use CCSv5 for this chip), and my inexperience with FreeRTOS. I am simply trying to eliminate uncertainties in order to narrow down the problem.
Using FreeRTOS, I set up queues to transfer messages from one task to another. I have tested this transfer and have found that the data placed onto the queue is not the same as the data taken off the queue - usually just zeros. I assume this is just a bug on my part, but I  modeled my implementation of the queues according to those in the example that appeared to be working.
Here is the initialization code for all tasks and queues. You might take a look and see if anything appears irregular? Thanks:

// tasks to pass data through the IPC
void IPC_Task_init(void)
{     
  portBASE_TYPE rtn_code;
 
  // init IPC driver - init interrupt in cm3_ipc_driver.c
  CM3_IPC_init();

  // create the semaphore for RX HCT sync 
  vSemaphoreCreateBinary(xBinaryIPCRxSema4);

  // create the IPC HCT TX queue
  xQueueIPCHctTx = xQueueCreate(CM3_IPC_HCT_TX_QUEUE_SIZE,sizeof(CM3_IPC_HCT_MSG_s));

  if (xQueueIPCHctTx == NULL)
  { // can not create the queue, increase the heap size
    CM3_IPC_hnd.err_create_queue++;
    return;
  }
 
  // create the CM3 IPC TX task
  rtn_code = xTaskCreate( vCM3_IPC_tx_task, ( signed portCHAR * ) “CM3_IPC_TX”,
              CM3_IPC_TX_TASK_STACK_SIZE, NULL, CM3_IPC_TX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }

  // create the CM3 IPC RX task
  rtn_code = xTaskCreate( vCM3_IPC_rx_task, ( signed portCHAR * ) “CM3_IPC_RX”,
              CM3_IPC_RX_TASK_STACK_SIZE, NULL, CM3_IPC_RX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
}

// tasks to handle data for HTC
void HCT_Task_init(void)
{     
  portBASE_TYPE rtn_code;
  memset(&Uart0_data,0,sizeof(Uart0_data));
  Uart0_ptr=0; 
  // create the HCT TX queue to post msgs from COM / other to IPC
  xQueueHCT_Example_TX = xQueueCreate(HCT_EXAMPLE_TX_QUEUE_SIZE,sizeof(CM3_IPC_HCT_MSG_s));
  if (xQueueHCT_Example_TX == NULL)
  {
  UARTSend(“xQueueHCT_Example_TX fail”,25);
    return ;
  }
 
  rtn_code=xTaskCreate( vHCT_Example_TX_task, ( signed portCHAR * ) “HCT_tx”,
                CM3_HCT_Example_TASK_STACK_SIZE, NULL,
                CM3_HCT_Example_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
  // create the msg queue for example RX task
  // create the IPC HCT TX queue
  xQueueHCT_Example_RX = xQueueCreate(HCT_EXAMPLE_RX_QUEUE_SIZE,sizeof(CM3_IPC_HCT_MSG_s));
  if (xQueueHCT_Example_RX == NULL)
  {
  UARTSend(“xQueueHCT_Example_RX fail”,25);
    return ;
  }

  rtn_code=xTaskCreate( vHCT_Example_RX_task, ( signed portCHAR * ) “HCT_rx”,
                CM3_HCT_Example_TASK_STACK_SIZE, NULL,
                CM3_HCT_Example_TASK_PRIORITY + 3, NULL );

  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
}

// initialize COM tasks to service uart0 input from interrupt and output data from queue
void COM_Task_init(void)
{
  portBASE_TYPE rtn_code;
 
  RingBufInit((tRingBufObject *)&uart0_rb_rx, UART_RX_buffer,UART_BUF_SIZE);
  RingBufInit((tRingBufObject *)&uart0_rb_tx, UART_TX_buffer,UART_BUF_SIZE);
  // RX task to create message from uart input and send to HCT
  rtn_code=xTaskCreate( vCOM_RX_task, ( signed portCHAR * ) “COM_rx”,
                COM_RX_TASK_STACK_SIZE, NULL,
                COM_RX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }

  // TX task to output from circ buf to uart port until finished
  rtn_code=xTaskCreate( vCOM_TX_task, ( signed portCHAR * ) “COM_tx”,
                COM_TX_TASK_STACK_SIZE, NULL,
                COM_TX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }

}

meetech wrote on Friday, May 11, 2012:

Added note: As you can see, all of the priorities are the same. I have added vTaskDelay times of 20ms to all tasks except the UART tasks as I believe the delay will prevent the task from re-running until that time has passed and I want UART data to serviced as fast as possible. Is that logic correct?
Thanks,
Pat

rtel wrote on Friday, May 11, 2012:

Looking at the init code there is nothing obviously wrong - although I cannot see what the task stack sizes are.  Maybe you could post the interrupt code?  Or the code writing to and reading form the queues (please use the “codify” tags when you post code so the formatting is maintained) as it would not be easy to get different data out of a queue to that put in, unless you had complete RAM corruption somewhere.

Generically, I can tell you the most likely cause of any interrupt related problem is going to be, because the majority of problems on Cortex-M class microcontrollers turns out to be this, and that is interrupt priorities.

You must ensure that your UART interrupt priority is equal to or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY, which is defined in FreeRTOSConfig.h.  When you do that, remember that Cortex-M devices are arse backwards, in that the lower the number you assign to an interrupt priority the higher priority of the interruptis.  So 1 is a very high priority, despite being a very low number.  Absolutely never leave interrupt priorities unassigned if the interrupt handler uses FreeRTOS calls because by default it will definitely be above configMAX_SYSCALL_INTERRUPT_PRIORITY.

Then also check out http://www.FreeRTOS.org/FAQHelp.html for information on other common problems, like calling API functions that don’t end in FromISR from the interrupt handler, and checking for stack overflow, etc.

Regards.

meetech wrote on Friday, May 11, 2012:

Richard,
I tried setting uart and ipc priorities lower, higher, and finally equal to FreeRTOS, but it still hangs

// from echo demo 
    // Enable processor interrupts.
    IntMasterEnable();
    // Set GPIO E4 and E5 as UART pins.
    GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    GPIOPinConfigure(GPIO_PE4_U0RX);
    GPIOPinConfigure(GPIO_PE5_U0TX);
    // Configure the UART for 115,200, 8-N-1 operation.
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(SYSTEM_CLOCK_SPEED), 38400,
                        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                         UART_CONFIG_PAR_NONE));
    // Enable the UART interrupt.
    IntRegister(INT_UART0, UARTIntHandler);
  // set the priority lower than FreeRTOS
//! The hardware priority mechanism will only look at the upper N bits of the
//! priority level (where N is 3 for the Concerto family), so any
//! prioritization must be performed in those bits.  The remaining bits can be
	IntPrioritySet(INT_UART0,160);  
    
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
Here is the init stuff for the tasks:
// COM tasks config data
#define COM_RX_TASK_STACK_SIZE        ( configMINIMAL_STACK_SIZE + 80 )
#define COM_TX_TASK_STACK_SIZE        ( configMINIMAL_STACK_SIZE + 80)
/* Task priorities. */
#define COM_RX_TASK_PRIORITY          ( tskIDLE_PRIORITY + 1 )
#define COM_TX_TASK_PRIORITY          ( tskIDLE_PRIORITY + 1 )
//#define COM_RX_QUEUE_SIZE	(4)
#define COM_TX_QUEUE_SIZE	(4)
hct:
/* The OLED task uses the sprintf function so requires a little more stack too. */
#define CM3_HCT_Example_TASK_STACK_SIZE        ( configMINIMAL_STACK_SIZE + 80 )
/* Task priorities. */
#define CM3_HCT_Example_TASK_PRIORITY          ( tskIDLE_PRIORITY + 1 )
#define HCT_EXAMPLE_RX_QUEUE_SIZE       (4)
#define HCT_EXAMPLE_TX_QUEUE_SIZE       (4)
uart:
// COM tasks config data
#define COM_RX_TASK_STACK_SIZE        ( configMINIMAL_STACK_SIZE + 80 )
#define COM_TX_TASK_STACK_SIZE        ( configMINIMAL_STACK_SIZE + 80)
/* Task priorities. */
#define COM_RX_TASK_PRIORITY          ( tskIDLE_PRIORITY + 1 )
#define COM_TX_TASK_PRIORITY          ( tskIDLE_PRIORITY + 1 )
//#define COM_RX_QUEUE_SIZE	(4)
#define COM_TX_QUEUE_SIZE	(4)
config file:
/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/
#define configUSE_PREEMPTION			1
#define configUSE_IDLE_HOOK				0
#define configUSE_TICK_HOOK				1
#define configCPU_CLOCK_HZ				( ( unsigned long ) 75000000 )
#define configTICK_RATE_HZ				( ( portTickType ) 1000 )
#define configMINIMAL_STACK_SIZE		( ( unsigned short ) 80 )
#define configTOTAL_HEAP_SIZE			( ( size_t ) ( 6000 ) )
#define configMAX_TASK_NAME_LEN			( 12 )
#define configUSE_TRACE_FACILITY		0
#define configUSE_16_BIT_TICKS			0
#define configIDLE_SHOULD_YIELD			0
#define configUSE_CO_ROUTINES 			0
#define configUSE_MUTEXES				1
#define configCHECK_FOR_STACK_OVERFLOW	2
#define configUSE_RECURSIVE_MUTEXES		1
#define configQUEUE_REGISTRY_SIZE		10
#define configGENERATE_RUN_TIME_STATS	0
#define configMAX_PRIORITIES		( ( unsigned portBASE_TYPE ) 5 )
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet			1
#define INCLUDE_uxTaskPriorityGet			1
#define INCLUDE_vTaskDelete					1
#define INCLUDE_vTaskCleanUpResources		0
#define INCLUDE_vTaskSuspend				0
#define INCLUDE_vTaskDelayUntil				1
#define INCLUDE_vTaskDelay					1
#define INCLUDE_uxTaskGetStackHighWaterMark	1
#define configKERNEL_INTERRUPT_PRIORITY 		( ( unsigned char ) 7 << ( unsigned char ) 5 )	/* Priority 7, or 255 as only the top three bits are implemented.  This is the lowest priority. */
//#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( ( unsigned char ) 5 << ( unsigned char ) 5 )  /* Priority 5, or 160 as only the top three bits are implemented. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	160
#if (0)
extern volatile unsigned long ulHighFrequencyTimerTicks;
/* There is already a high frequency timer running - just reset its count back
to zero. */
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ( ulHighFrequencyTimerTicks = 0UL )
#define portGET_RUN_TIME_COUNTER_VALUE()	ulHighFrequencyTimerTicks
#endif

meetech wrote on Saturday, May 12, 2012:

And here’s task code with posts and semaphore

UINT16 HCT_Example_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{
//  portTickType xDelay = 20/ portTICK_RATE_MS;
  CM3_IPC_HCT_MSG_s ipcMsg; // condense HCT_MSG_HD_s to shorter structure
  portBASE_TYPE rtn_code;  
  ipcMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  ipcMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  ipcMsg.msg_len = msg_len;  
  // post message without wait   
  rtn_code = xQueueSendToBack(xQueueHCT_Example_TX,&ipcMsg, 0); //xDelay);
  if (rtn_code == errQUEUE_FULL)
  { // error to post message, free
    UARTSend("HCT_TX_Queue_full",17);
    return 1;
  }
  return 0;
 
}
// TX HCT data to IPC then WL
void vHCT_Example_TX_task( void *pvParameters )
{
//#ifdef IPC_PHY_TX_TEST
  portTickType xDelay = 20/ portTICK_RATE_MS;
//#endif
  portBASE_TYPE rtn_code;  
  CM3_IPC_HCT_MSG_s ipcMsg; //ipcMsg; // 
  
  // Loop forever 
  while(1)
  {
      // wireline message queue, sends type_tag, len, and pbuf
      rtn_code = xQueueReceive(xQueueHCT_Example_TX,(void *)&ipcMsg,portMAX_DELAY);
    if ((rtn_code == errQUEUE_EMPTY))//&&(!PSG_set))
    {      
		continue;
    }
	if (ipcMsg.msg_len > 0) //(PSG_set)
	{
	    hct_cnt.tx_msg++;
		// send message to wireline - replace with input message
		HCT_Data_Transfer((UINT8*) ipcMsg.pbuffer, (UINT16) ipcMsg.msg_len);		
	}
// IPC PHY TX test is a compiler pre-define for TX build only
#ifdef IPC_PHY_TX_TEST
    Toggle_LED(LED_3);
    Toggle_LED(LED_AFE_1);
#endif
    
    // wait the message queue
    vTaskDelay( xDelay );
    hct_cnt.tx_msg++;
	
  }
}
// Example usage:msgs rcvd from IPC are placed on the HCT queue
UINT16 HCT_Example_RX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{
  CM3_IPC_HCT_MSG_s hctMsg; // condense HCT_MSG_HD_s to shorter structure
  portBASE_TYPE rtn_code;  
  hctMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  hctMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  hctMsg.msg_len = msg_len;  
//  memcpy(hctMsg.pbuffer,pbuf,hctMsg.msg_len);
  // post message without wait   
  rtn_code = xQueueSendToBack(xQueueHCT_Example_RX,&hctMsg, 0);
  if (rtn_code == errQUEUE_FULL)
  { // error to post message, free
    
    return 1;
  }
  return 0;
 
}
void vHCT_Example_RX_task( void *pvParameters )
{
  	portBASE_TYPE rtn_code;
  	CM3_IPC_HCT_MSG_s hctMsg; // tag,len,pbuf
  	// init the task
	portTickType xDelay = 20/ portTICK_RATE_MS; 
    // data from C28 -> IPC queue -> IPC-RX -> HCT queue -> HCT RX -> here    
    // or from uart
  	// Loop forever 
  	while(1)
  	{
  		
  		// clear temp buffer
  		memset(&hctMsg,0,sizeof(hctMsg));
		rtn_code = errQUEUE_EMPTY;
#ifndef IPC_PHY_TX_TEST //RX task
  		
  	  	// wireline message queue, returns tag, len, and pbuf
  	  	rtn_code = xQueueReceive(xQueueHCT_Example_RX,(void *)&hctMsg,portMAX_DELAY);
      	if ((rtn_code != errQUEUE_EMPTY) && (hctMsg.msg_len > 2)) // process queue with WL input data
      	{
      		// process WL input msg here
			// send complete message to wireline as echo test
			// post onto HCT TX to IPC TX to WL TX
			HCT_Example_TX_Task_Post(HCT_MSG_TYPE_DATA_TRANSFER, 0, (UINT16)hctMsg.msg_len, (UINT8*)hctMsg.pbuffer);
			if ((hct_cnt.rx_msg & 0xf) == 8)
			{
		    // test output
		    	Toggle_LED(LED_2);
		    	Toggle_LED(LED_AFE_2);
			    Toggle_LED(LED_PLCD_4);
      		}
      	}
#endif  
		// else there may be uart input	  	
  	  	if (rtn_code == errQUEUE_EMPTY)
  	  	{ 
  	  		     
	    // if no WL data, then OK to TX UART data to WL
	    	if (!RingBufEmpty((tRingBufObject *) &uart0_rb_rx))
	    	{
		 		while (!RingBufEmpty((tRingBufObject *) &uart0_rb_rx))
				{
					Uart0_data[Uart0_ptr++] = RingBufReadOne(&uart0_rb_rx);
				}
			}
			
			// verify PLUS or GPS msg from uart input
			int rslt;
			if (Uart0_ptr > 0)
			{
				rslt = Verify_msg(Uart0_data,&Uart0_ptr);
				if ( (rslt == PLUS) || (rslt == GPS))
				{
					// send complete message to wireline
					// post onto TX for WL
					HCT_Example_TX_Task_Post(HCT_MSG_TYPE_DATA_TRANSFER, 0, (UINT16)Uart0_ptr, (UINT8*)Uart0_data);
					// msg complete, reset buffer
					Uart0_ptr=0;
		    		memset(Uart0_data,0,sizeof(Uart0_data));
#ifndef IPC_PHY_TX_TEST //RX task getting uart input - rare
			    // test output
			    Toggle_LED(LED_2);
			    Toggle_LED(LED_AFE_3);
			    Toggle_LED(LED_PLCD_5);
    
#endif
				}
				else if (rslt == 0)
				{
					Uart0_ptr = 0; // bad msg, restart
		    		memset(Uart0_data,0,sizeof(Uart0_data));
				}
				// else only partial msg, keep collecting data
	
			}
		}	// end of test for errQue
      	
Toggle_LED(LED_AFE_3);
    	hct_cnt.rx_msg++;
   		vTaskDelay( xDelay );
  	} // end while
}
//
// Define the COM_Rx task to input data from the com port and send to the HCT_RX task. 
void vCOM_RX_task( void *pvParameters )
{
  // init the task
    UINT8 dat;
//    portTickType xDelay = 20/ portTICK_RATE_MS;
  // Loop forever 
  while(1)
  {
        // Read the next character from the UART 
        dat = (UINT8)UARTCharGetNonBlocking(UART0_BASE);
        // put on ring buffer
        RingBufWriteOne(&uart0_rb_rx,dat);
        // or just echo directly
    Toggle_LED(LED_AFE_2);
//    UARTSendByte(RingBufUsed(&uart0_rb_rx));
    com_cnt.rx_msg++;
//    vTaskDelay( xDelay );
  }
}
//
// define COM TX task to output msg from TX ring buffer to com0 port 
void vCOM_TX_task( void *pvParameters)
{
  // init the task
//	portTickType xDelay = 20/ portTICK_RATE_MS; 
   // Loop forever 
  while(1)
  {
 	while (!RingBufEmpty((tRingBufObject *) &uart0_rb_tx))
	{
		UARTSendByte(RingBufReadOne(&uart0_rb_tx)); 
	}
//    vTaskDelay( xDelay );
    com_cnt.tx_msg++;
  }
}
void CM3_Post_HCT_RX_Semaphore(void)
{
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  portBASE_TYPE rtn_code;
  
  rtn_code = xSemaphoreGiveFromISR(xBinaryIPCRxSema4,&xHigherPriorityTaskWoken);
  if (rtn_code == pdFAIL)
  {
    CM3_IPC_hnd.err_post_sema4++;
  }
}
void vCM3_IPC_rx_task( void *pvParameters )
{
  portBASE_TYPE rtn_code;
  portTickType xDelay = 20/ portTICK_RATE_MS;
  // init the task
  // fake take the semaphore because it is available when created
  xSemaphoreTake(xBinaryIPCRxSema4,0);
  
  // Loop forever 
  while(1)
  {
    // wait the semaphore from interrupt
    rtn_code = xSemaphoreTake(xBinaryIPCRxSema4,portMAX_DELAY);
    if (rtn_code == pdFALSE)
    {
      CM3_IPC_hnd.err_get_sema4++;
      continue;
    }
    vTaskDelay( xDelay );
    
    // get the message from IPC RAM
    CM3_IPC_HCT_Receive_Packet();
    // CM3 is ready to receive
    CM3_IPC_setStat(1);
  }
}
//msg from HCT is posted onto the IPC queue for TX to C28
UINT16 CM3_IPC_HCT_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{
  CM3_IPC_HCT_MSG_s hctMsg;
  portBASE_TYPE rtn_code;
  CM3_IPC_hnd.tx_post_msg++;
  
  hctMsg.pbuffer = pbuf;
  hctMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK);
  hctMsg.msg_len = msg_len;  
  // post message without wait   
  rtn_code = xQueueSendToBack(xQueueIPCHctTx,&hctMsg, 0);
  
  if (rtn_code == errQUEUE_FULL)
  { // error to post message, free
    CM3_IPC_hnd.err_send_queue_full++;
    UARTSend("IPC_ERR",7);
    return 1;
  }
  return 0;
}
// task to send HCT to IPC and C28
void vCM3_IPC_tx_task( void *pvParameters )
{
  portBASE_TYPE rtn_code;
  CM3_IPC_HCT_MSG_s hctMsg;
  // init the task
  portTickType xDelay = 20/ portTICK_RATE_MS;
  
  // Loop forever 
  while(1)
  {
    // wait the message queue - 
    rtn_code = xQueueReceive(xQueueIPCHctTx,(void *)&hctMsg,portMAX_DELAY);
    if (rtn_code == errQUEUE_EMPTY)
    {
      CM3_IPC_hnd.err_receive_queue_empty++;
      // how long to wait??
      continue;
    }
    
    // send the HCT message to C28 and set the interrupt for service
    CM3_IPC_Send_HCT_Msg(&hctMsg);
    vTaskDelay( xDelay );
    
  }
}
void CM3_IPC_HCT_RX_ISR(void)
{
  // stat
  CM3_IPC_hnd.rx_isr++;
  
  // mark CM3 is busy
  CM3_IPC_setStat(0);
  // post semaphore to task
  CM3_Post_HCT_RX_Semaphore();
  
  // Acknowledge IPC INT3 from C28 to ACK
  HWREG(MTOCIPC_BASE + IPC_O_CTOMIPCACK) |= IPC_CTOMIPCACK_IPC3;
}

rtel wrote on Saturday, May 12, 2012:

Not sure, again from my skimming of the code there does not appear to be anything obviously wrong.

Regards.

meetech wrote on Saturday, May 12, 2012:

Passing a structure to a queue should not cause a problem, then?

rtel wrote on Sunday, May 13, 2012:

Passing a structure to a queue should not cause a problem, then?

That should not be a problem.  The queue sends in your code are sending the same size of structure used to dimension each queue when the queue is created, as far as I can see.

You have to be careful though.  For example, you have the following line:

ipcMsg.pbuffer = pbuf;

and then post ipcMsg to a queue, with the message pbuffer member containing a pointer to pbuf, and pbuf is a parameter being passed in to the function.  Where is pbuf defined, and does it still exist when you get the message out the other end of the queue?  You have only copied a pointer to a buffer into your structure, not the contents of the buffer, so if the buffer being pointed to no longer exists (maybe it was on a task stack?) or if the contents of the buffer have been modified since the structure was sent to the queue, then what you read out of the buffer will differ to what the buffer contained when the message was created.

Regards.

meetech wrote on Monday, May 14, 2012:

Richard,
Thanks for the advice, but the buffer in question is defined as a global buffer, so I don’t think that is the problem. Here is a detailed example of the issue:
Notice in the post that I output the message length anf then the final character of the message (in this case 0x0f and 0xd0) as a test. Then, in the task, I output again. The first and second outputs give me 0f 0d and 0f 0d. The third gives me 0f 00.

// msgs from COM or other are posted to the IPC TX task
UINT16 HCT_Example_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{
//  portTickType xDelay = 20/ portTICK_RATE_MS;
  CM3_IPC_HCT_MSG_s ipcMsg, ipcMsg2; // condense HCT_MSG_HD_s to shorter structure
  portBASE_TYPE rtn_code; 
  ipcMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  ipcMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  ipcMsg.msg_len = msg_len;  
  // post message without wait   
  rtn_code = xQueueSendToBack(xQueueHCT_Example_TX,&ipcMsg, 0); //xDelay);
  xQueuePeek( xQueueHCT_Example_TX, (void*)&ipcMsg2, 0 ) ;
COM_TX_byte(ipcMsg.msg_len);		
COM_TX_byte(ipcMsg.pbuffer[msg_len-1]);		
COM_TX_byte(ipcMsg2.msg_len);		
COM_TX_byte(ipcMsg2.pbuffer[msg_len-1]);		
//COM_TX(ipcMsg.pbuffer, (UINT8) ipcMsg.msg_len);					
  if (rtn_code == errQUEUE_FULL)
  { // error to post message, free
//    UARTSend("HCT_TX_Queue_full",17);
    return 1;
  }
  return 0;
 
}
// TX HCT data to IPC then WL
void vHCT_Example_TX_task( void *pvParameters )
{
//#ifdef IPC_PHY_TX_TEST
  portTickType xDelay = 10/ portTICK_RATE_MS;
//#endif
// memset(&hct_cnt,0,sizeof(hct_cnt));
  portBASE_TYPE rtn_code;  
  CM3_IPC_HCT_MSG_s ipcMsg; //ipcMsg; // 
  // Loop forever 
  while(1)
  {
      // wireline message queue, sends type_tag, len, and pbuf
      rtn_code = xQueueReceive(xQueueHCT_Example_TX,(void *)&ipcMsg,portMAX_DELAY);
    if ((rtn_code != errQUEUE_EMPTY))//&&(!PSG_set))
    {      
COM_TX_byte((UINT8)ipcMsg.msg_len);		
COM_TX_byte((UINT8)ipcMsg.pbuffer[ipcMsg.msg_len - 1]);					
//		continue;
//    }
// IPC PHY TX test is a compiler pre-define for TX build only
//#ifdef IPC_PHY_TX_TEST
	// process plus cmd : test broadcast or verify ID, service IO, response
	// if update, then respond with data
//	WL_msg_format((UINT8*)ipcMsg.pbuffer, (UINT8) ipcMsg.msg_len);
	// if this node is PSG, then send msg to CCUs. If node is CCU, then send responses to PSG
	// use WL_cmd_format  
	if (ipcMsg.msg_len > 2) //(PSG_set)
	{
	    hct_cnt.tx_msg++;
		// send message to wireline - replace with input message
		HCT_Data_Transfer((UINT8*) ipcMsg.pbuffer, (UINT16) ipcMsg.msg_len);		
	}
// IPC PHY TX test is a compiler pre-define for TX build only
#ifdef IPC_PHY_TX_TEST
    Toggle_LED(LED_3);
    Toggle_LED(LED_AFE_1);
//    Toggle_LED(LED_AFE_3);
//    Toggle_LED(LED_PLCD_4);
#endif
    }    
    // wait the message queue
    vTaskDelay( xDelay );
    hct_cnt.tx_msg++;
	
  }
}

meetech wrote on Monday, May 14, 2012:

Caveat:
I may have two problems:
When I output the full message as a test, I only receive 17 chars total. My buffers are set to 200. a count of 17 is reached, I receive no more characters until the next test input. I’ve tried adjusting blocking delays, task priorities … but can’t seem to get any more chars at a time. Plus, when I extract the chars from the queue, all the values except the length are set to zero (to do this, I turn off the pre-queue msg output and turn on the post-queue msg output). All the data has been zeroed. There are no other accesses to this queue.
Any insight here would be most helpful.
Thanks,
Pat

rtel wrote on Tuesday, May 15, 2012:

I’m not sure I’m following your explanation exactly, but I can look at the code, which is not complex and does not contain apparent errors.  Although obviously there is an error somewhere, it could be external to these code snippets (memory allocation problem, heap crashing into stack, something overwriting your global buffer, etc.).

In the code you just posted, you set up a message that contains a length value, and a pointer to something you previously stated was a global buffer.  This message is then sent to a queue, and received by another task.  The receiving task then looks at the message length field - ignoring the characters in the buffer (which were never sent down the queue, only a pointer to them was) when the receiving task reads the length field, is that correct?  When it reads the pointer to the global buffer, does the pointer actually point to the global buffer as expected?

Regards.

meetech wrote on Tuesday, May 15, 2012:

Three screen shots with the code used and variations in the code. Without loading the queue, the test output of data is correct.  The queue call was commented out. See comments between each example. What am I doing wrong?
Thanks

CM3_IPC_HCT_MSG_s htxMsg;
// msgs from COM or other are posted to the IPC TX task
UINT16 HCT_Example_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{

  portBASE_TYPE rtn_code;
  htxMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  htxMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  htxMsg.msg_len = msg_len; 
  // post message without wait  
COM_TX(htxMsg.pbuffer, (UINT8) htxMsg.msg_len);
//  rtn_code = xQueueSendToBack(xQueueHCT_Example_TX,&htxMsg, 0); //xDelay);
//  xQueuePeek( xQueueHCT_Example_TX, (void*)&ipcMsg2, portMAX_DELAY ) ;

Adding the queue call following the test output corrupts the data, in many cases shortening to 17 bytes. I thought this was a uart problem originally, but it now appears to be related to the queue.

CM3_IPC_HCT_MSG_s htxMsg;
// msgs from COM or other are posted to the IPC TX task
UINT16 HCT_Example_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{
  portBASE_TYPE rtn_code;
  htxMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  htxMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  htxMsg.msg_len = msg_len; 
  // post message without wait  
COM_TX(htxMsg.pbuffer, (UINT8) htxMsg.msg_len);
  rtn_code = xQueueSendToBack(xQueueHCT_Example_TX,&htxMsg, 0);
//  xQueuePeek( xQueueHCT_Example_TX, (void*)&ipcMsg2, portMAX_DELAY ) ;

I then “peeked” at the queue data to see what was there and found it to be essentially the same as the one above. The send to queue buffer is global and the peek buffer is local. Why is the data corrupted??? I’m obviously missing something here.

CM3_IPC_HCT_MSG_s htxMsg;
// msgs from COM or other are posted to the IPC TX task
UINT16 HCT_Example_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{

  CM3_IPC_HCT_MSG_s ipcMsg2;
  portBASE_TYPE rtn_code;
  htxMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  htxMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  htxMsg.msg_len = msg_len; 
  // post message without wait  
//COM_TX(htxMsg.pbuffer, (UINT8) htxMsg.msg_len);
  rtn_code = xQueueSendToBack(xQueueHCT_Example_TX,&htxMsg, 0); //xDelay);
  xQueuePeek( xQueueHCT_Example_TX, (void*)&ipcMsg2, portMAX_DELAY ) ;
COM_TX(ipcMsg2.pbuffer, (UINT8) ipcMsg2.msg_len);

meetech wrote on Tuesday, May 15, 2012:

Sorry about the images. Is there a code for images from a file / word document?

rtel wrote on Wednesday, May 16, 2012:

There is a lot to look through here, and I am not following it well.  Maybe it will be clearer with the screen shots.

Some people have managed to get images included in the text, I have never tried myself, but am experimenting here using the “Add Image” button above the text intput.  Lets see what happens…

it looks like you have to put a URL between  tags, so the image has to be available online.

Regards.

meetech wrote on Thursday, May 17, 2012:

NOTE: The initialiation code for the tasks is at the bottom of this message.

// to summarize, this task shows the problem I am having. I can post to the TX task by loading the queue. After doing this, I output the data and it is correct.
But, when I instead, output the data after unloading the queue, the data is all zeros (however the message length (ipcMsg.msg_len) is correct. Just the ipcMsg.pbuffer data outputs as all zeros. As you can see, the posting function uses a global structure and the task uses an local version.
This has confounded me for too long. What am I doing wrong??? I am programming the Concerto chip, TI's F28M35H52C1 using CCSv4.2.5 on a WinXP machine.
Thanks for any help.
CM3_IPC_HCT_MSG_s ipcMsg;
// msgs from COM or other are posted to the IPC TX task
UINT16 HCT_Example_TX_Task_Post(UINT16 msg_type, UINT16 msg_tag, UINT16 msg_len, UINT8 *pbuf)
{
//  portTickType xDelay = 20/ portTICK_RATE_MS;
//  CM3_IPC_HCT_MSG_s ipcMsg; // condense HCT_MSG_HD_s to shorter structure
  portBASE_TYPE rtn_code;  
  ipcMsg.pbuffer = pbuf;
  // combine upper 4 bits of type and lower 8 bits of tag. type = 0 is IPC message, IPC tag = 0
  ipcMsg.msg_type_tag = (msg_type & HCT_MSG_TYPE_MASK) | (msg_tag & HCT_MSG_TAG_MASK); //0x00ff,0xf000
  ipcMsg.msg_len = msg_len;  
  // post message without wait   
  rtn_code = xQueueSendToBack(xQueueHCT_Example_TX,&ipcMsg, 0); //xDelay);
//  xQueuePeek( xQueueHCT_Example_TX, &ipcMsg, ( portTickType ) 10 ) ;
//COM_TX_byte((UINT8)msg_len);		
//COM_TX(ipcMsg.pbuffer, (UINT8) ipcMsg.msg_len);					
  if (rtn_code == errQUEUE_FULL)
  { // error to post message, free
    UARTSend("HCT_TX_Queue_full",17);
    return 1;
  }
  return 0;
 
}
// TX HCT data to IPC then WL
void vHCT_Example_TX_task( void *pvParameters )
{
//#ifdef IPC_PHY_TX_TEST
  portTickType xDelay = 10/ portTICK_RATE_MS;
//#endif
// memset(&hct_cnt,0,sizeof(hct_cnt));
  portBASE_TYPE rtn_code;  
  CM3_IPC_HCT_MSG_s htxMsg; //ipcMsg; // 
  // Loop forever 
  while(1)
  {
      // wireline message queue, sends type_tag, len, and pbuf
      rtn_code = xQueueReceive(xQueueHCT_Example_TX,(void *)&htxMsg,portMAX_DELAY);
    if ((rtn_code == errQUEUE_EMPTY))//&&(!PSG_set))
    {      
		continue;
    }
// IPC PHY TX test is a compiler pre-define for TX build only
//#ifdef IPC_PHY_TX_TEST
	// process plus cmd : test broadcast or verify ID, service IO, response
	// if update, then respond with data
//	WL_msg_format((UINT8*)htxMsg.pbuffer, (UINT8) htxMsg.msg_len);
	// if this node is PSG, then send msg to CCUs. If node is CCU, then send responses to PSG
	// use WL_cmd_format
	if (htxMsg.msg_len > 2) //(PSG_set)
	{
	    hct_cnt.tx_msg++;
COM_TX_byte((UINT8)htxMsg.msg_len);		
COM_TX((UINT8*)htxMsg.pbuffer,(UINT8)htxMsg.msg_len);					
		// send message to wireline - replace with input message
		HCT_Data_Transfer((UINT8*) &htxMsg, (UINT16) htxMsg.msg_len);	
	}
// IPC PHY TX test is a compiler pre-define for TX build only
#ifdef IPC_PHY_TX_TEST
    Toggle_LED(LED_3);
//    Toggle_LED(LED_AFE_1);
//    Toggle_LED(LED_AFE_3);
//    Toggle_LED(LED_PLCD_4);
#endif
    
    // wait the message queue
    vTaskDelay( xDelay );
    hct_cnt.tx_msg++;
	
  }
}
// here are the initializations for all three sets of tasks. The one of particular interest is the HCT task, but it utilizes the ring buffer that is initialized in the COM task. Also, the COM task is used to output all test data. 
// tasks to pass data through the IPC
void IPC_Task_init(void)
{      
  portBASE_TYPE rtn_code;
  
  // init IPC driver - init interrupt in cm3_ipc_driver.c
  CM3_IPC_init();
  // create the semaphore for RX HCT sync  
  vSemaphoreCreateBinary(xBinaryIPCRxSema4);
  // create the IPC HCT TX queue
  xQueueIPCHctTx = xQueueCreate(CM3_IPC_HCT_TX_QUEUE_SIZE,sizeof(CM3_IPC_HCT_MSG_s));
  if (xQueueIPCHctTx == NULL)
  { // can not create the queue, increase the heap size
    CM3_IPC_hnd.err_create_queue++;
    return;
  }
  
  // create the CM3 IPC TX task
  rtn_code = xTaskCreate( vCM3_IPC_tx_task, ( signed portCHAR * ) "CM3_IPC_TX", 
              CM3_IPC_TX_TASK_STACK_SIZE, NULL, CM3_IPC_TX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
  // create the CM3 IPC RX task
  rtn_code = xTaskCreate( vCM3_IPC_rx_task, ( signed portCHAR * ) "CM3_IPC_RX", 
              CM3_IPC_RX_TASK_STACK_SIZE, NULL, CM3_IPC_RX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
}
// tasks to handle data for HTC
void HCT_Task_init(void)
{      
  portBASE_TYPE rtn_code;
  memset(&Uart0_data,0,sizeof(Uart0_data));
  Uart0_ptr=0;  	
  // create the HCT TX queue to post msgs from COM / other to IPC
  xQueueHCT_Example_TX = xQueueCreate(HCT_EXAMPLE_TX_QUEUE_SIZE,sizeof(CM3_IPC_HCT_MSG_s));
  if (xQueueHCT_Example_TX == NULL)
  {
  	UARTSend("xQueueHCT_Example_TX fail",25);
    return ;
  } 
  
  rtn_code=xTaskCreate( vHCT_Example_TX_task, ( signed portCHAR * ) "HCT_tx", 
                CM3_HCT_Example_TASK_STACK_SIZE, NULL, 
                CM3_HCT_Example_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
  // create the msg queue for example RX task
  // create the IPC HCT TX queue
  xQueueHCT_Example_RX = xQueueCreate(HCT_EXAMPLE_RX_QUEUE_SIZE,sizeof(CM3_IPC_HCT_MSG_s));
  if (xQueueHCT_Example_RX == NULL)
  {
  	UARTSend("xQueueHCT_Example_RX fail",25);
    return ;
  } 
  rtn_code=xTaskCreate( vHCT_Example_RX_task, ( signed portCHAR * ) "HCT_rx", 
                CM3_HCT_Example_TASK_STACK_SIZE, NULL, 
                CM3_HCT_Example_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
}
// initialize COM tasks to service uart0 input from interrupt and output data from queue
void COM_Task_init(void)
{
  	portBASE_TYPE rtn_code;
  	
  	RingBufInit((tRingBufObject *)&uart0_rb_rx, UART_RX_buffer,UART_BUF_SIZE);
  	RingBufInit((tRingBufObject *)&uart0_rb_tx, UART_TX_buffer,UART_BUF_SIZE);
  // RX task to create message from uart input and send to HCT
  rtn_code=xTaskCreate( vCOM_RX_task, ( signed portCHAR * ) "COM_rx", 
                COM_RX_TASK_STACK_SIZE, NULL, 
                COM_RX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
 
  // TX task to output from circ buf to uart port until finished
  rtn_code=xTaskCreate( vCOM_TX_task, ( signed portCHAR * ) "COM_tx", 
                COM_TX_TASK_STACK_SIZE, NULL, 
                COM_TX_TASK_PRIORITY + 3, NULL );
  if (rtn_code !=pdPASS)
  {
    SysCall_Error();
  }
}