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.

MSP430f2274 strange return values during program execution

Other Parts Discussed in Thread: MSP430F2274, MSP430-IQMATHLIB

Hi guys,


I'm facing a very strange behavior with a project of mine based on the MSP430F2274.

The bug shows off once in a while, here are the functions related to it:

// ____________________________________________________________________________

//Reports the actual temperatures and the PWM values.

void ReportStatus()
{
	sprintf((char *) printBuffer,
			"Sens. Temp.: %03.1f\t Estimated Rack Temp.: %03.1f"
					"\tPWM1: %+4d\r", ((float) isSensTemp) / 10, ((float) SensToRack(isSensTemp)) / 10,
			PWM1Value);
	Print((char *) printBuffer);
}

// ____________________________________________________________________________

// Transmit the given character array over the UART.

void Print(char * array)
{
	char * iterator;
	for (iterator = array; *iterator != '\0'; ++iterator)
	{
		while (!(IFG2 & UCA0TXIFG))
			;																// Wait until the tx buffer is empty
		UCA0TXBUF = *iterator;				// Put character in the tx buffer
	}
	while (!(IFG2 & UCA0TXIFG))
		;																// Wait until the tx buffer is empty
}

// ____________________________________________________________________________




// Converts a sensor temp. value into a rack temp. value

int32_t SensToRack(int32_t temperature)
{
	return roomTemp + (temperature - roomTemp) * 1.1963;
}

int main(void)
{
	ConfigureUART();
	ConfigurePeltier();
	InitVariables();
	ADS_ConfigureADS();
	while (1)
	{
		if (cmdFlag == CMD_available)
		{
			cmdFlag = CMD_empty;
			ParseCommand();
		}
		if (control == ctrl_loop)
		{
			isSensTemp = ADS_FetchTemperature();
			CalculatePWM();
			ApplyPWM();
			if (reportFlag == rep_report)
			{
				reportFlag = rep_blank;
				ReportStatus();
			}
			control = ctrl_running;
		}
	}
}

// UART Rx interrupt routine
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
	// Add characters
	if (UCA0RXBUF != '\r')
	{
		*rxPtr = UCA0RXBUF;
		++rxPtr;
		if (rxPtr - rxBuffer > 99) rxPtr = rxBuffer;
	}
	else
	{
		// Command is gathered.
		*rxPtr = '\0';
		rxPtr = rxBuffer;
		strcpy((char *) cmdBuffer, (char *) rxBuffer);
		// Set Flag and clear any low power mode.
		cmdFlag = CMD_available;
	}
}

#pragma vector=PORT2_VECTOR
__interrupt void PORT2_ISR(void)
{
	if (P2IFG & BIT1)
	{
		// DRDY (ADS1246/7/8) interrupt routine
		P2IFG &= ~BIT1;
		if (ADS_status == ADS_cont_measuring && control == ctrl_running) control =
				ctrl_loop;
		if (ADS_status == ADS_measuring || ADS_status == ADS_calibrating) __bic_SR_register_on_exit(
				CPUOFF);
	}
}

During operation, I sometimes get such a line.

Sens. Temp.: 6.6     Estimated Rack Temp.: 23.0    PWM1: -424

So, we know that the isSensTemp = 66.

roomTemp = 230 always (const)

But SensToRack(isSensTemp) seems to yield 230

instead of 230 + (66-230) * 1.1963  = 33.

My guess, is maybe the way the return statement is written causes a problem ?

If somehow an interrupt happens at that precise moment where the return statement has to be made ?

Anybody can guess what I'm doing wrong ?

Thanks a lot for your help.

Nessim

  • Hi Nessim,

    It looks like the C implicit type casting and type promotion works as expected for your SensToRack() function (I verified this). 

    Have you attempted to monitor your RAM usage (stack and heap)?  The sprintf() library function requires a significant amount of heap space (on the order of 100's of bytes), and that's before floating point values are considered.  This combined with your global variables and stack usage might be posing a problem on this device, since the F2274 only has 1kB of total RAM.  Since the problem is occurring intermittently, it may be possible that you are running into a stack/heap overflow at run-time.

    Keep in mind that the MSP430 has no hardware support for floating point, so all of your floating point math operations are being handled in a run-time library, which is extremely inefficient.  I would strongly recommend that you consider using fixed-point arithmetic (via some type of IQ-Math) to avoid using floating point types.  We have libraries available for this here: http://www.ti.com/tool/msp430-iqmathlib.

    You mention that you think an interrupt might be causing the error.  Unless the ISR modifes the roomTemp variable it should not effect the result, as ISR's do a full register context save and restore.  However, if you are at the limits of the stack/heap, and you get an interrupt, the ISR could be corrupting memory and effecting your result.Thus, I think it makes sense for you to verify that you do not have any memory corruption errors as a result of memory allocation by the runtime library for sprintf() or a soft floating point calculation. 

    Walter

  • Hi,

    thanks for reply on such a strange topic :-)

    No i did not checked the ram stack / heap. But I'd like too:

    I couldnt find a guide how to do so, could you suggest a thread / guide please ?

    Meanwhile, I'll work on improving the code....

    Thanks

    Nessim

  • Are you working with and IDE such as CCS or IAR?  If so, which?

    Walter

  • Hi,

    yeah sorry

    CCS v 5.5 

  • Nessim,

    Let's try this out.  I've attached a file called memsafety.c.

    8117.memsafety.c
    //*****************************************************************************
    //
    //! memsafety.c
    //
    //! This utility runs before main() and does the following:
    //!  (1) Fill the entire heap with SAFETY_PATTERN
    //!  (2) Fill the entire stack, with the exception of the first 4 bytes,
    //!  with SAFETY_PATTERN.  The first 4 bytes contain the return pointer
    //!  and current stack frame, and must not be altered.
    //!
    //! This allows for the memory to be viewed at runtime to see what sections
    //! of stack and heap were used by various functions.
    //
    //*****************************************************************************
    #include <msp430.h>
    #include <stdint.h>
    
    //*****************************************************************************
    //
    //! \def SAFETY_PATTERN defines the pattern to insert into the stack and heap.
    //
    //*****************************************************************************
    #define SAFETY_PATTERN (0xCD)
    
    //*****************************************************************************
    //
    //! The following are linker symbols to access the stack and heap
    //
    //! \var _stack is first word of the stack.
    //! \var __STACK_END is the address of the last word of the stack.
    //! \var _sys_memory is the first word of the heap.
    //! \var __SYSMEM_SIZE is the size of the heap
    //
    //*****************************************************************************
    extern int16_t _stack;
    extern void * __STACK_END;
    extern int16_t _sys_memory;
    extern void *__SYSMEM_SIZE;
    
    //*****************************************************************************
    //
    //! The following function replaces the RTL _system_pre_init() function at link
    //! time, and is called by the boot function before autoinit().
    //! It initilizes the heap and stack to a known pattern (SAFETY_PATTERN) at the
    //! beginning of execution.
    //
    //*****************************************************************************
    int16_t _system_pre_init(void)
    {
    	uint8_t *pMem;
    	uint16_t ui16Size;
    
    	// Stop the watchdog timer
    	WDTCTL = WDTPW | WDTHOLD;
    
    	// Fill the heap
    	pMem = (uint8_t*)(&_sys_memory);
    	ui16Size = (uint16_t)(&__SYSMEM_SIZE);
    	__no_operation();
    	while (ui16Size--)
    	{
    		*(pMem++) = SAFETY_PATTERN;
    	}
    	__no_operation();
    
    	// Fill the stack
    	pMem = (uint8_t*)(&_stack);
    	ui16Size = (uint16_t)((uint8_t*)(&__STACK_END) - pMem);
    	ui16Size -= 4;
    	__no_operation();
    	while (ui16Size--)
    	{
    		*(pMem++) = SAFETY_PATTERN;
    	}
    	__no_operation();
    
    	// Return 1 to init segments
    	return 1;
    }
    
    
    

    If you place this file in your project root, it will automatically fill your stack and heap memory space with 0xCD at runtime before you enter main().  This will allow you to use the memory browser feature in CCS to look at the stack/heap memory and determine if you ever overrun it.  Hint: if the last word of the stack is not 0xCDCD, you've overrun your stack.  When you just get into main(), all of the stack should be 0xCDCD with the exception of the first few bytes which are used before you arrive at main().

    In the example below, I called sprintf() and passed it a float argument.  Upon returning from the call to sprintf(), I observed that at least 580 bytes of stack space were needed.  In this test, I set my stack size absurdly large at 1kB just to be safe. 

    I want to correct my earlier statement that sprintf() uses lots of heap- it actually uses lots of stack; it is printf() that uses heap as it needs to set up IO stream buffer space.  I apologize for any confusion!

    You can adjust the stack allocation size in the linker properies in CCS as shown below.  Note that you can't use a stack this big in your project because you only have 1kB of RAM!

    This analysis should give you an idea of stack usage.  If your stack is still at the default 160B, the test I performed here demonstrates that you will need considerably more than that.

    Regards,
    Walter

  • Hi,

    Thanks for the tutorial and explanation:

    I'll try it first thing monday.

    But seem to be a memory problem like you said.

    I found out it happens when I flood the µC with commands. So if the stack overflows, it will be understandable why, and that some code does not get executed.

    Nice Weekend.

    Nessim

  • Hi again,

    just to specify that the guess was right, i actually had a overflow every time I called sprintf().

    I increased the stack to 512, seems to work now, I still got some free stack space....

    Thanks again

    NBA

  • No problem, glad to hear you were able to work it out.  It's always good practice to keep an eye on stack usage to watch out for overflows, as the CPU does not check for them.

    Walter

  • Hello,


    well, it turned out to not being the  (only) issue:
    after nearly one hour the issue came out again.

    So after several iterations in the code,

    I set up the stack and heap to 256, changed the code to enhance debugging, made sure to turn optimizations off, then tried to limit when the error propagation occurs then I found out:

    int32_t SensToRack(int32_t temperature)
    {
    	int32_t newTemp = temperature;
    	newTemp -= roomTemp;
    	newTemp = newTemp * 1.1963;
    	newTemp += roomTemp;
    	if (newTemp == 230)
    	{
    		_no_operation();
    	}
    	return newTemp;
    }

    when the error occurs ( break point at _no_operation() )  the debugger says that the variable temperature 63,
     so we know that the variable passing occurred without problems, but somewhere in the calculation, something goes wrong.

    I tried to change new temp to volatile to force ram writing, but without success:

    The memory browsing showed:

    _sys_memory:  was all CDCD (untouched)
    _Errno: was all CDCD except the first 2 bytes 0000
    _Stack

    _stack
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD    CDCD
    CDCD    03BD    8B06    8AD8    5380    0000    0000    0000
    4090    0B78    00D1    2DC0    06F6    150F    8CE7    0128
    2B80    0044    2000    0EEC    2B80    0044    0000    4090
    0000    5380    0000    0B78    0000    0000    00D1    240B
    0010    0000    8000    0000    12B0    0531    974C    0000
    0000    E000    0014    46DC    7803    240B    0010    4673
    F694    0F06    9325    46DC    7803    240B    00F6    0000
    A868    4673    F694    0F06    9325    ABAA    003F    0000
    00E6    0000    0000    4DE6    0000    9B12    B058    B480
    3FFF    3FFF    3FFF    3FFF    3FFF    3FFF    3FFF    3FFF


    So a memory overflow (stack or heap) did not happen.
    I remind that the interrupts do nothing but setting flags and clearing the CPUOFF.

    It's really odd, but help would be much appreciated.
    Maybe is this caused by the errata ? There are CPU issues with the micro controller when I look at the errata Sheet?

    Cheers

    Nessim

  • Hi there,

    finally solved it: the error was caused by the float point multiplication that sometimes yielded 0. After which adding 230 resulted in the wrong estimation.  I found out, even when with CCS v6 that somehow the multiplication was not "solid enough" so I changed the operation like follows:

    int32_t SensToRack(int32_t temperature)
    {
    	temperature -= roomTemp;
    	temperature = temperature * 11963;
    	temperature = temperature / 10000;
    	temperature += roomTemp;
    	return temperature;
    }

    This way, only integer operations are made. Which solved the problem.

    Cheers

    Nessim

**Attention** This is a public forum