EmbeddedRelated.com
Forums

Crossworks, printf/putchar, sprintf?

Started by mjames_doveridge August 27, 2008
In the Crosswoks help, there is a section on customizing putchar, so
allowing o/p from printf() to be redirected byte-by-byte to wherever
it might be needed.

This is all very well, but those of us with multiThreaded C++ code
have a problem - the __putchar is not a method and has no context.
There is no 'stream', void pointer, unsigned or anything that can be
passed though printf() to tell __putchar what object to call when
there are multiple output streams being outputted to by different
threads. Any attempt to 'bypass' the printf() call to set the output
stream in a static/global is going to involve a nasty kludge with
semaphores etc.

Up to now, I have dodged this issue by using temporary strings and
sprintf, but these temporary strings take space, not only in
themselves, but also because they have to be passed to nested methods
or stored as fields in just too many places. It's inefficient on
space and inefficient on code since the output is loaded into the
string byte-by-byte and then I extract the output from the string
byte-by-byte and load it into my output buffers byte-by-byte. It's
all very messy and wasteful. It would be nice if the printf() calls
could just shove output into my buffer objects directly - they have a
'Tmessage::loadChar(char thisChar)' method.

Is there any low-level function like __putchar that is used by
sprintf()? If there is, maybee I can overload that instead and use
the string pointer as some sort of context parameter?

Alternatively, does anyone know of any other bodge around this problem?

At present, I'm defining a structure of temporary strings of varying
length and passing one of these around as sprintf() workspace in every
thread that uses it. You can imagine how good a design I think that
is :((

Rgds,
Martin

An Engineer's Guide to the LPC2100 Series

Hi,

> In the Crosswoks help, there is a section on customizing putchar, so
> allowing o/p from printf() to be redirected byte-by-byte to wherever
> it might be needed.
>
> This is all very well, but those of us with multiThreaded C++ code
> have a problem - the __putchar is not a method and has no context.
> There is no 'stream', void pointer, unsigned or anything that can be
> passed though printf() to tell __putchar what object to call when
> there are multiple output streams being outputted to by different
> threads.

Hang some thread-local data off a ctl V2 task to store the current "stream"
and then have __putchar use the current executing thread's thread-local
stream storage and output to the stream you want. The C library and
Embedded C subset library has no need to support this because tasking is not
in their vocabulary. But you can certainly do it yourself as I have
outlined, all the pieces are there.

> Any attempt to 'bypass' the printf() call to set the output
> stream in a static/global is going to involve a nasty kludge with
> semaphores etc.

Not sure why at this point...

> Up to now, I have dodged this issue by using temporary strings and
> sprintf, but these temporary strings take space, not only in
> themselves, but also because they have to be passed to nested methods
> or stored as fields in just too many places. It's inefficient on
> space and inefficient on code since the output is loaded into the
> string byte-by-byte and then I extract the output from the string
> byte-by-byte and load it into my output buffers byte-by-byte. It's
> all very messy and wasteful. It would be nice if the printf() calls
> could just shove output into my buffer objects directly - they have a
> 'Tmessage::loadChar(char thisChar)' method.

If you want to output to a stream without taking any local storage and
without using sprintf, you just need to look at the reference manual:

http://www.rowley.co.uk/documentation/msp430_1_4/msp430_release_notes.htm

> Is there any low-level function like __putchar that is used by
> sprintf()? If there is, maybee I can overload that instead and use
> the string pointer as some sort of context parameter?

I have described two clean methods to get what you require I think.

> Alternatively, does anyone know of any other bodge around this problem?

No bodge required.

>
> At present, I'm defining a structure of temporary strings of varying
> length and passing one of these around as sprintf() workspace in every
> thread that uses it. You can imagine how good a design I think that
> is :((

I think everything is in place for a clean solution.

Regards,

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Hi,

> If you want to output to a stream without taking any local storage and
> without using sprintf, you just need to look at the reference manual:
>
> http://www.rowley.co.uk/documentation/msp430_1_4/msp430_release_notes.htm

Oops, pasted the wrong link there. This is where I meant:

http://www.rowley.co.uk/documentation/msp430_1_4/hcc_extending_input_output.
htm

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

>
> Oops, pasted the wrong link there. This is where I meant:
http://www.rowley.co.uk/documentation/msp430_1_4/hcc_extending_input_output.
> htm
>

I thought you had again when I saw 'msp430' in the url

This looks very promising! I had seen those 'v'calls and I did wonder...

Thanks again. I'll have a go at this tomorrow. Maybee an end to
'tmpStr[32]' and 'outStr[128]' at last!

Rgds,
Martin