FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [March 2005 Threads] printf from taskPosted 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 taskPosted 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 taskPosted by Nobody/Anonymous on March 16, 2005 Which compiler are you using? printf_P is not standard.
RE: printf from taskPosted 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 taskPosted 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 taskPosted 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 taskPosted by Nobody/Anonymous on March 17, 2005 I would guess definately stack problems.
RE: printf from taskPosted 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 taskPosted 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 taskPosted 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 taskPosted 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 taskPosted 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.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|