Serial printing in arduino without a library

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I am trying to learn FreeRTOS with an Arduino UNO but I don't want to be very attached to the Arduino infrastructure since I'll probably have to port whatever code I produce to another platform. At the same time I still don't own a hardware debugger. I was thinking that i need some kind of `Serial.print` solution. My idea is to have a task that fetches everything that is put in a queue and send it to serial. I have tried this:

 

void sendStuff(void* arguments)
{
	while (1) {
		if ( xQueueReceive( xQueue, &readmessage, ( TickType_t ) 100) ) {
			while ( !(UCSR0A & (1 << UDRE0)) )
			UDR0 = readmessage;
		}
	}
}

But it doesn't seem to work. I know that "wiring" is right because echoing works:

 

ISR (USART_RX_vect)
{
	ReceivedChar = UDR0;                       // Read data from the RX buffer
	UDR0 = ReceivedChar;                       // Write the data to the TX buffer
}

 

So my question is, is there a way to use Arduino libraries mixed in "regular" C code? And why is not the `sendStuff` task working?

 

X

This topic has a solution.
Last Edited: Wed. Jul 17, 2019 - 08:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

God gave you Serial.print()
Why not use it?
.
From a debugging point of view Serial works well. The input and output is buffered and handled by interrupts.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Arduino gives you the source code. If you don't want to use 'Arduino' but you like its features, then grab the relevant bits of code and massage to suit. The serial part is pretty simple and is basically what you'd write from scratch anyways. For print formatting, there's the classic old printf().

 

After a while you'll come to the realisation that you're just doing the same thing - over again. 

 

 

Anyways, You would want the usart tx interrupt to fetch stuff from the queue rather than have a task. FreeRtos has specific calls that can be called from isrs. Similarly for the receive, the receive isr grabs UDR and pops it into a queue. I'm quite sure many have done what you want with freertos already.

 

Also note that each task has a fair amount of overhead in terms of ram - on a UNO, you don't have lots of ram, so you probably do not want to run too many tasks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agree wit the others but if you do want to implement from scratch then I guess your first question is synchronous (polled) or asynchronous(interrupts). Also apply that to both TX and RX separately (often sync TX, async RX makes a nice combination). Implementing sync for both is clearly easiest. The next thing to do is then just implement a single putchar() and getchar() then connect those to stdout/stdin so now you can use all the library functions like puts/printf/scanf/etc

 

Serial.println() is a clever use of C++ for the overloading but perhaps printf() with format strings is enough. Or, if sticking with C++ you could use iostream output where the overloading of << is very similar to Arduino println() anyway.

 

PS Actually I just realised you said FreeRtos - so you could do sync/polled but in a pre-empted task so it would kind of behave like async anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I have manged to do is to do sync transmit (I block waiting for the queue and once I get something in there I just put it in UDR0, and async receive using the interruption.

 

kartman wrote:

Anyways, You would want the usart tx interrupt to fetch stuff from the queue rather than have a task.

 

Well, that was my first idea yes, but I was wondering how that would work. I mean, the interrupt triggers on transmit, but if I transmit (aka copy the char to UDR0) then I have already done it, haven't I? Or am I misunderstanding when the tx interrupt is triggered?

 

clawson wrote:

The next thing to do is then just implement a single putchar() and getchar() then connect those to stdout/stdin so now you can use all the library functions like puts/printf/scanf/etc

 

That sounds very nice but how would I go about that? If I am using C (as opposed to C++), how would I override the printf and friends so they use serial?

 

 

Thank you very much for your answers!

 

X

 

PS: I am having a really hard time formatting messages in this forum, the editor is not great...

Last Edited: Wed. Jul 17, 2019 - 08:33 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

xntavr wrote:
That sounds very nice but how would I go about that? If I am using C (as opposed to C++), how would I override the printf and friends so they use serial?
FDEV_SETUP_STREAM - there's tons of tutorials about this. Or there is the raw info in the manual:

 

https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

 

There's actually two ways to create the FILE object that attaches the Tx/Rx functions to the stream. FDEV_SETUP_STREAM creates it statically at compile time, fdev_setup_stram() creates it dynamically at run time.

 

I can't help thinking that you may not be the first to attempt such a thing with FreeRTOS so a google for "FDEV_SETUP_STREAM FreeRTOS" may prove fruitful.

EDIT: almost the first thing I hits was:

 

http://symfund.blogspot.com/2014/04/porting-freertos-to-atmega328p-arduino.html

 

but that's very dubious - they are exporting locals.

Last Edited: Wed. Jul 17, 2019 - 08:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That was the clue that I was missing! Thank you!