Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

printf from task

Posted by Nobody/Anonymous on March 16, 2005
Hi,
I try to use FreeRTOS on a ATMega64.
I got a task like:

void ManTask( void *pvParameters )
{
while(1)
{
if(intflag)
{
printf_P( PSTR("%.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X \r\n"),
manval, mantemp[0], mantemp[1], mantemp[2], mantemp[3],
mantemp[4], mantemp[5], mantemp[6], mantemp[7] );
intflag = 0;
vTaskDelay( portTICK_RATE_MS * 100 );
TIMSK |= _BV(TICIE1);
}
else
vTaskDelay( portTICK_RATE_MS * 5 );
}
}

Hope this is readable :-)
In this case, printf sends lot of garbage.
If I split the long printf for giving out only one value
in a for() loop it works better.
Playing around with the tasks stack value changes something.
But it still doesn't work.
How do i calculate the stack size for a task?
How do I calculate the portTOTAL_HEAP_SIZE ?
And how is printf coming in?
Thanks!

RE: printf from task

Posted by Nobody/Anonymous on March 16, 2005
printf is likely to use a LOT of stack, and is generally best avoided. You can increase the stack of the task that calls printf, but how about writting a simple routined to do the same. For example, from the wiznet demo source code:

void ultoa( unsigned portLONG ulVal, unsigned portCHAR *pcBuffer, portLONG lIgnore )
{
unsigned portLONG lNibble;
portLONG lIndex;

----/* Simple routine to convert an unsigned long value into a
----string in hex format. */

----/* For each nibble in the number we are converting. */
----for( lIndex = 0; lIndex < ( sizeof( ulVal ) * 2 ); lIndex++ )
----{
--------/* Take the top four bits of the number. */
--------lNibble = ( ulVal >> 28 );

--------/* We are converting it to a hex string, so is the number
--------in the range 0-10 or A-F? */
--------if( lNibble < 10 )
--------{
------------pcBuffer[ lIndex ] = '0' + lNibble;
--------}
--------else
--------{
------------lNibble -= 10;
------------pcBuffer[ lIndex ] = 'A' + lNibble;
--------}

--------/* Shift off the top nibble so we use the next nibble next
--------time around. */
--------ulVal <<= 4;
----}

----/* Mark the end of the string with a null terminator. */
----pcBuffer[ lIndex ] = 0x00;
}

You have to call it for each value you want to add to the string.

When a stack is created it is filled with a known value (0xa5 ?). Using a debugger you can see the stack, how much is left at 0xa5 is how much spare stack you have. Failing this you can write a CheckFreeStackSpace() function to walk up the stack until it runns out of 0xa5's [I think there is an example in the PC port.c file in the download]. The number of 0xa5's it finds is the size of the unused stack. ISR's, function calls, stack variables must all be taken into consideration when deciding how much stack you need.

As with the stack size, portTOTAL_HEAP_SIZE is best determined through trial - if an allocation fails, you have too little :-)


RE: printf from task

Posted by Nobody/Anonymous on March 16, 2005
Which compiler are you using? printf_P is not standard.

RE: printf from task

Posted by Nobody/Anonymous on March 16, 2005
It seems that printf out of a task has problems when printing out values of global variables.
Sometimes it didn't find the end of the string and
prints out endlessly.
Looks like something is wrong with the adressing of global
variable out of a task?
Never had problems with printf, printf_P before.
I'm using WinAVR with libc 1.2.3.

RE: printf from task

Posted by Nobody/Anonymous on March 16, 2005
A few of quick questions -

1 Are you calling printf from within a critical section?
2 Is the behaviour the same with different optimisation levels?
3 Can you access global variables correctly other than within the printf()? [The scheduler accesses file scope variables without a problem, so is there something different when using a library function?]

RE: printf from task

Posted by Nobody/Anonymous on March 17, 2005
1 Are you calling printf from within a critical section?
-no

2 Is the behaviour the same with different optimisation levels?
-no

3 Can you access global variables correctly other than within the printf()? [The scheduler accesses file scope variables without a problem, so is there something different when using a library function?]
- Don't know. The only way to show variables is printf.

Something like
printf_P( PSTR("%02X %02X %02X %02X %02X %02X %02X %02X \r\n"),
manval, mantemp[0], mantemp[1], mantemp[2], mantemp[3], mantemp[4], mantemp[5], mantemp[6] );

works from main, but nor from a task.
I really don't know where to look at eventually.
I will drop FreeRTOS to see if all works standalone.
Maybe I can say more then.
Thank you

RE: printf from task

Posted by Nobody/Anonymous on March 17, 2005
I would guess definately stack problems.

RE: printf from task

Posted by Nobody/Anonymous on March 17, 2005
It looks like printfing short strings works while longer ones fail. Timer tick is every millisecond so its likely that a context-switch occurs or is tested for. But the context should be saved by portSaveContext right? So that the pointers printf holds for parsing the string and creating a new one should be restored.
So if you say there's a stack problem how can I verify this?

RE: printf from task

Posted by Richard on March 17, 2005
Short strings working would also point towards a stack issue.

printfing should be fine even if a context switch occurs PROVIDED the library function is reenterant - which it <should> be in this case.

If you cannot check the stack area using a debugger, then how about finding the longest string you can printf, then increase the stack a bit, and see if the longest string you can printf also increases. A bit crude, ideally the use of debugger or simulator would assist.

Can you run your code in AVR studio? You might not get the context switches occurring properly, but if you try the printf from the first task that executes, stepping through the code at the C source level and inspecting the RAM within the simulator IDE would provide a lot of clues.

RE: printf from task

Posted by Jörg Krein on April 15, 2005
Hello again,

I now got running GDB over JTAG (more or less).
Observing the task with printf the backtrace command says: 'previous frame inner to this frame (corrupt stack?)'
So I know the stack is corrupt.
But why? Any suggestions where to go from here?
Regards,
Joerg

RE: printf from task

Posted by Jörg Krein on April 18, 2005
Hi,
I found the fault was on my side ;-)
For the port I had to change the timer interrupt to
update the OCR1 register, as I couldn't use the timer overflow.
OCR1A += (unsigned portSHORT) ( (portCPU_CLOCK_HZ / portTICK_RATE_HZ) / portCLOCK_PRESCALER );
Unfortunatly the interrupt routine uses the 'naked' attribute.
So because of the addition registers and flags get corrupted.
Without the 'naked' everything seems to work fine.
Maybe there's is a way to avoid the double context saving ?
Regards,
Joerg

RE: printf from task

Posted by Matt van de Werken on May 17, 2005
Hi all:

I've been fighting with printf's on an atmega128 for a day and a half now, using gcc + freertos. It turns out that the task using printf MUST have the stack size increased to not crash the micro; I used a value of 255, since I only really have one task that uses printf. As the app develops, though, I think I'll try to reduce/eliminate the printf calls, judging from some of the comments in this thread.

Cheers,
mvdw.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS