Author Topic: how to use printf() in uTASKER??  (Read 14600 times)

Offline tr111

  • Jr. Member
  • **
  • Posts: 72
    • View Profile
how to use printf() in uTASKER??
« on: August 29, 2007, 10:04:49 AM »
hello:
I have #define <stdio.h>
but the printf() can't use???
I only use the fnDebugMsg("\n\rLED ON OFF\n\r") to display int the  LOG_UART0!
but I need that:
printf("err=%d \n",err);
the fnDebugMsg only can printf text!
I don't know why???

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: how to use printf() in uTASKER??
« Reply #1 on: August 29, 2007, 01:06:45 PM »
Hi

The uTasker project avoids the use of libraries so that it is as compiler independent as possible (the libraries vary between compilers used and sometimes can cause the project size to explode when using formatted text, etc.). Debugging with libraries can be more difficult because no source can be found by the debugger - libraries sometimes also have to be rebuilt to suit project/processor settings.

See also http://www.utasker.com/forum/index.php?topic=30.0

This however doesn't exclude the use of libraries.
If you are having a linker problem for the target it is because the demo project doesn't include the necessary standard libraries. Eg. CodeWarrior: You should be able to remove all errors by adding the library C_4i_CF_SZ_MSL.a, which is in the CodeWarrior directory - something like C:\Program Files\Freescale\CodeWarrior for ColdFire V6.3\E68K_Support\msl\MSL_C\MSL_E68k\Lib

____________________________________________
NOTE for M5223X users:
It is also possible to use malloc() rather than uMalloc() if needed to allocate and free memory - although I did find a problem with this since free() crashed when I first started to use it (with CW6.3 but not CW6.4). The mystery could eventually be solved due to the fact that the library used was compiled with different register passing conventions. I have  in the meantime modified the mwerks.h header in Applications\uTaskerV1.3\CodeWarrior_M5223X\uTaskerV1.3\include to ensure a match with the delivered libraries - you may like to do this in your project to be safe - you can get all details in the following thread: http://forums.freescale.com/freescale/board/message?board.id=CWCFCOMM&message.id=1297&query.id=21550#M1297

I added this to the header (which is included in SP5 for the M5223X):
/*
 * Force functions to return values in D0
 */
#pragma pointers_in_A0

___________________________________________________________________

If you can make use of the uTasker driver functions (a small collection of useful routines which are optimised to do quite a lot of tasks usually performed using standard library functions - but with some special features like DMA copy on the M5223X - and as simple as possible) then you will not need to use the libraries. However there could well be cases where these are not adequate - as I said, if libraries are needed there is nothing stopping them being added and used to ensure that development is efficient.


In your specific case, you say that your are outputting to a log file. This indicates that you are using the simulator (note that you can also output to a serial port of your PC by setting SERIAL_PORT_X to the required COM port number).
In this case you will be able to use all libraries without ay difficulties, however printf() output will be directed to somewhere else. If you would like to format output I would suggest using sprint(). This will format the output to a buffer and then you can simply send the buffer to the UART (or log file) with the fnDebugMsg();.

eg.
CHAR buffer[MAX_BUFFER_SIZE];
sprintf(buffer, "err=%d \n",err);
fnDebugMsg(buffer);


Regards

Mark


Offline tr111

  • Jr. Member
  • **
  • Posts: 72
    • View Profile
Re: how to use printf() in uTASKER??
« Reply #2 on: August 30, 2007, 01:30:29 PM »
Thank you very much ! mark !
 

Offline seulater

  • Newbie
  • *
  • Posts: 38
    • View Profile
Re: how to use printf() in uTASKER??
« Reply #3 on: March 29, 2008, 04:17:54 PM »
when i try printf, i got an error of "printf.c:(.text+0x30): undefined reference to `__putchar'"
i forgot to #include <stdio.h>, when i did that i got a new error of "conflicting types for 'size_t'"

i need to have full support for printf, but i don't want to interfere with your code by using it.
 

I am using Crosworks and the new Luminary package

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: how to use printf() in uTASKER??
« Reply #4 on: March 29, 2008, 04:41:37 PM »
Hi

If you have size_t defined in stdio.h you can probably remove the define from types.h. Types.h is a project specific file which assumes no libraries so there is no problems involved by adapting that to suit the project.

putchar() is (I believe) the interface between printf and the output stream (which finally gets to the hardware via something like _out(). This interface could be provided:
Assuming you have a UART open [application.c opens one and sets the debug output to it] (Telnet would also work) you should be able to do this by adding a dummy putchar() somewhere and diverting the output.

Eg.
extern int putchar(char byte_to_send)
{
    CHAR output_string[2];
    output_string[0] = byte_to_send;
    output_string[1] = 0;
    fnDebugMsg(output_string);
}

Although possibly not the most efficient method, this will allows printf() to pass its generated output (assuming each character is via putchar()) to the uTasker debug output. This is then automatically sent to the UART or to TELNET, if there is a connection.

Another method would be to use sprintf() instead of printf(). This will first construct a string, which can be sent using fnDebugMsg() in one go. This can possibly be hidden in a macro so that the user doesn't have know the details.

I have to admit to not ever having used printf() within the uTasker project myself but I believe some users have, so this shouldn't be a big difficulty.

Regards

Mark


Offline seulater

  • Newbie
  • *
  • Posts: 38
    • View Profile
Re: how to use printf() in uTASKER??
« Reply #5 on: March 29, 2008, 11:39:46 PM »
Quote
I have to admit to not ever having used printf() within the uTasker project myself but I believe some users have, so this shouldn't be a big difficulty.

WOW! i thought i never would hear anyone say that! 
it seems you and i are night and day different when it comes to debugging.

i use printf all the time, in every program i ever wrote. i like to know where the uP is at and what its currently doing. printf is my personal debug method. you might think im nuts but i thing debuggers are a waste of time  ;)

before you send me up the river with that statement, let me explain why. almost ever project i do has some sort of external peripheral i need to talk to. years ago, when i gave debugging a try i got bit by it and never looked back.

Since debugging did not allow me to run full speed so my project worked. when i ran it at full speed i had problems.  it took allot of pulling hair out to find out why. as it turns out a few properly placed printf's running full speed saved the day. the problem was a board trace layout issue, was to close to a power supply rail, and picking up noise. this would only be a problem at full cpu speed.

I would imagine that today debuggers might be different, but i have used printf for so long not and i never run into trouble doing it this way. so i figure why bother with the debugger when i can print the same thing to the terminal.

so if i comment out the your size_t and then use my

void __putchar(int ch)
{
    UARTWriteChar(ch);
}

to write to the uart tx buffer, i should be good to go then.










Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: how to use printf() in uTASKER??
« Reply #6 on: March 29, 2008, 11:57:40 PM »
Hi

Don't misunderstand me with my comment about printf(). I use fnDebugMsg(), fnDebugHex() and fnDebugDec() instead - these are uTasker routines which do simple (but useful) formatted output to the UART or to TELNET (Telet is useful for debugging your debug outputs over the Internet rather than to a local terminal emulator). The only reason why I generally don't use printf() is that it tends to 'bloat' the project. I do use it when windows programming, etc. but like to avoid it for embedded work.

Another thing to note is that I only work occasionally on the target - I use the uTasker simulator for 95% of real development work where printf() type output is also available but not that useful.

As you point out - for real full speed HW operation the debug outputs can save the day, as can simple port outputs for timing measurements (or pattern output for monitoring flow control with a logic analyser). Some chips include a trace port but I haven't had an urge to use this because printf() and GPIO outputs have always been adequate (up to now at least).

Therefore we are probably not so different than you thought (apart for the simulator bit...possibly).

Regards

Mark

Offline seulater

  • Newbie
  • *
  • Posts: 38
    • View Profile
Re: how to use printf() in uTASKER??
« Reply #7 on: March 30, 2008, 12:04:04 AM »
Quote
Therefore we are probably not so different than you thought (apart for the simulator bit...possibly).

Whew... ok i placed the code snippet you send, whith a bit of mod to make compiler happy.

extern int __putchar(char byte_to_send)
{
    CHAR output_string[2];
    output_string[0] = byte_to_send;
    output_string[1] = 0;
    fnDebugMsg(output_string);
}


i added these to lines in LM3Sxxxx.c in the main routine under the multipart section, it compiles without warning, but yet i get nothing out the UART. if i hit return i get the menu to the UART part works. Is it that the code to init the uart has not been initalized yet at this point ?



Code: [Select]
        uTaskerStart((UTASKTABLEINIT *)prtInfo->ptTaskTable, prtInfo->ptNodesTable, PHYSICAL_QUEUES);

fnDebugMsg("Multi Start\r\n");
printf("Multi Start\r\n");

        while ((prtInfo = (MULTISTART_TABLE*)uTaskerSchedule()) == 0) {} // schedule uTasker

    } while (1);
    #else




Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: how to use printf() in uTASKER??
« Reply #8 on: March 30, 2008, 12:23:29 AM »
Hi

I just checked this in the simulator to see what happens.

Your are right that this test is too early. The UART is opened in application.c, which is delay-started after 100ms; therefore when you call it (before scheduling starts) the debug handle is at its default value.

What actually happens depends on whether you have TELNET active in the project. If not, it immediately returns because it doesn't have any output to send the string to.

If Telnet is active in the project it will try to send the string over an open Telnet connection (seeing as there is no valid UART handle and the network route is its default). It will however find no TELNET socket, again because the TELNET socket will be configured only after application.c runs for the first time. Note that it would still return, even if there was a socket, if no connection had been established by a TELNET client.

If you move the test to after the following line in application.c it should work (at least the fnDebuMsg() one and hopefully also the printf() one):

DebugHandle = SerialPortID;  // set the new UART handle for debug output use.

Regards

Mark



Offline seulater

  • Newbie
  • *
  • Posts: 38
    • View Profile
Re: how to use printf() in uTASKER??
« Reply #9 on: March 30, 2008, 12:27:22 AM »
thansk, i jsut found that out shortly before i heard the e-mail "ding" for this thread.
i put the printf in the application thread, and it worked. Although i keeps printing that printf over and over again every so many seconds. Which tells me its a task.

Now, I am just trying to get a grip on all the tasks that are running, where i can stick in my personal code.