beautifulsmall
Posts: 20
Joined: Mon Jun 04, 2012 9:57 pm

uart comms in C

Mon Jun 04, 2012 10:30 pm

Hi, want to use the header uart for comms to a pic, I have stopped the uart console comms by removing ttyAMA0 references from /boot/cmdline.txt and /etc/inittab and can get comms to my laptop terraterm with minicom on Rpi.
But how do I send data from a C program ?
Running Debian with Frank-buss w1-test update (fantastic) for spi (and I2c) which appear in /dev (after adding "I2C-dev " the /etc/modules file.
the example gpio and spi both cc ok and run in sudo mode (in gpio example changed gpio to 17 to 25 and delay(1) to udelay(10000) but im really a HW engineer and Gerts and bootc's air is in my lifebelt.

can I send data byte wise to the uart direct ? with a poke (showing my age)
also does devmem work in some window?
Many thanks .
working on accel /gyro/si1143/pic33e integration.

User avatar
jbeale
Posts: 4003
Joined: Tue Nov 22, 2011 11:51 pm

Re: uart comms in C

Tue Jun 05, 2012 1:37 am

Are you looking for something like the below? This is from a bootloader using the serial port, written by dwelch67. See also http://www.raspberrypi.org/phpBB3/viewt ... &start=100

https://github.com/dwelch67/raspberrypi ... loader02.c

unsigned int uart_recv ( void )
{
while(1)
{
if(GET32(AUX_MU_LSR_REG)&0x01) break;
}
return(GET32(AUX_MU_IO_REG)&0xFF);
}
//------------------------------------------------------------------------
void uart_send ( unsigned int c )
{
while(1)
{
if(GET32(AUX_MU_LSR_REG)&0x20) break;
}
PUT32(AUX_MU_IO_REG,c);
}

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: uart comms in C

Tue Jun 05, 2012 5:08 am

^not this

http://tldp.org/HOWTO/Serial-Programming-HOWTO/ (basic overview)
http://tldp.org/HOWTO/Serial-HOWTO.html (some largely useless bits and pieces related specifically to uarts)

Simon

beautifulsmall
Posts: 20
Joined: Mon Jun 04, 2012 9:57 pm

Re: uart comms in C

Tue Jun 05, 2012 8:14 pm

Thanks for these suggestions. The PUT32 gives an error and I cant find the source code for the function anywhere, I used the address from the bootloader code and tried outw(65,0x20215040); which is the AUX_MU_IO_REG .This gives a segmentation fault but at least it compiles.
The GPIO code looses me when it does a malloc and maps it ?
Is it possible to do a direct memory read/write from C or does linux get in the way and im just being stupid.
Thanks.

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: uart comms in C

Wed Jun 06, 2012 8:06 am

You don't need to do direct memory reads and writes. You need to use the POSIX interface to the serial port.

Something like this (completely untested, typed directly into the browser) code should do it for you.

Code: Select all

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

int main(int argc, char ** argv) {
  int fd;
  // Open the Port. We want read/write, no "controlling tty" status, and open it no matter what state DCD is in
  fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1) {
    perror("open_port: Unable to open /dev/ttyAMA0 - ");
    return(-1);
  }

  // Turn off blocking for reads, use (fd, F_SETFL, FNDELAY) if you want that
  fcntl(fd, F_SETFL, 0);

  // Write to the port
  int n = write("Hello Peripheral\n");
  if (n < 0) {
    perror("Write failed - ");
    return -1;
  }

  // Read up to 255 characters from the port if they are there
  char buf[256];
  n = read(fd, (void*)buf, 255);
  if (n < 0) {
    perror("Read failed - ");
    return -1;
  } else if (n == 0) printf("No data on port\n");
  else {
    buf[n] = '\0';
    printf("%i bytes read : %s", n, buf);
  }

  // Don't forget to clean up
  close(fd);
  return 0;
}

beautifulsmall
Posts: 20
Joined: Mon Jun 04, 2012 9:57 pm

Re: uart comms in C

Wed Jun 06, 2012 12:00 pm

Thanks tufty, thats worked ok , i just had to modify the
int n = write("Hello Peripheral\n");
to the format int write(int fd, char *Buff, int NumBytes);

int n = write(fd,"Hello",6);
my comms default is 9600baud
cheers.

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: uart comms in C

Wed Jun 06, 2012 2:55 pm

beautifulsmall wrote:Thanks tufty, thats worked ok , i just had to modify the
int n = write("Hello Peripheral\n");
to the format int write(int fd, char *Buff, int NumBytes);

int n = write(fd,"Hello",6);
my comms default is 9600baud
cheers.
Oh, duh. Yeah. My bad.

If you want to set the baud rate, you need to get into meddling with termios. For example...

Code: Select all

struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
tcsetattr(fd, TCSANOW, &options);

sumanharapanahalli
Posts: 20
Joined: Mon Oct 08, 2012 5:14 am
Location: Bangalore, India

UART communication in C

Wed Dec 12, 2012 9:47 am

beautifulsmall wrote:Thanks tufty, thats worked ok , i just had to modify the
int n = write("Hello Peripheral\n");
to the format int write(int fd, char *Buff, int NumBytes);

int n = write(fd,"Hello",6);
my comms default is 9600baud
cheers.

Hi,

I am using the code given above [ with corrections]

I am able to send data from Pi to the terminal in the computer but I am not able to receive the data into PI.
The program stops after the read function is executed; initially I thought that its waiting for data but later i see that even after the data is sent from computer the program remain there, I am not able to understand what's the problem.

Can you please help me solve the same
Thanks & Regards
Sumanth

sumanharapanahalli
Posts: 20
Joined: Mon Oct 08, 2012 5:14 am
Location: Bangalore, India

Re: uart comms in C

Wed Dec 12, 2012 10:36 am

Just changed the function fcntl(fd, F_SETFL, FNDELAY) instead of fcntl(fd, F_SETFL, 0).

With this change the program did not wait for the data but error is "Read failed- : Resource temporarily unavailable".
Can someone help me solve this.
Thanks & Regards
Sumanth

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: uart comms in C

Wed Dec 12, 2012 10:49 am

When you say it stops, do you mean it hangs in place, or that the program exits? Are you getting any terminal output on the Pi? What terminal software are you using on the PC, and are you sure you're set up to not use flow control, 8N1 @ <baudrate>, and all that cack?

About the only thing that occurs to me software-wise is that it may be blocking on the read, in which case :

a - my memory as to how to make an fd nonblocking is flaky (looking back, the implementation above is certainly "iffy"). Try fcntl(fd, F_SETFL, O_NONBLOCK);
b - If it's blocking, you might get it to work by sending 256 characters or more down the serial port (enough to get it past the block).
c - you'd be able to see what's going on by running the program through gdb.

"c" above holds in all cases.

Simon

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: uart comms in C

Wed Dec 12, 2012 11:03 am

Actually, thinking about it a bit more, I'm being a tool, and my reading code is neither one thing nor the other.

Read the documents I linked to earlier, and you'll be able to work it out. Understanding what's going on with POSIX read() and write() isn't immediately obvious, but it's worth working through it yourself. Any reply I make to explain would, of necessity, be as long or longer than the howtos I linked above.

Simon

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4257
Joined: Mon Jan 09, 2012 3:16 pm

Re: uart comms in C

Wed Dec 12, 2012 11:17 am

You'll need to change the read a bit and make it into a loop. If the read is non-blocking, then it will immediately exit and say there are no characters available. So you could loop until you got characters, but that is not the most efficient way to do it.

Probably the best way is to keep it blocking, but only read one character at a time. When that character is CR (value 13... or maybe 10 in some circumstances) then you know you have a complete line of text.

(I haven't tested this either.)

Code: Select all

i = 0;
do
{
  char c;
  n = read(fd, (void*)&c, 1);
  if (n > 0)
  {
    buf[i++] = c;
  }
}
while (c != '\r' && i < 255 && n > 0);
buf[i] = '\0';

if (n < 0) {
    perror("Read failed - ");
    return -1;
} else if (i == 0)
  printf("No data on port\n");
else {
    printf("%d bytes read : %s", n, buf);
}
Of course the if(i == 0) will never trigger, because the read will wait until there is something to read. However that is not always what you want to do. There's a good discussion about the alternatives here.

sumanharapanahalli
Posts: 20
Joined: Mon Oct 08, 2012 5:14 am
Location: Bangalore, India

Re: uart comms in C

Thu Dec 13, 2012 1:41 pm

I get the error as "Read failed- : Resource temporarily unavailable"

The application does not wait for data now, I did follow the instruction given in the link -
http://www.irrational.net/2012/04/19/us ... rial-port/

even now the i get the same error.
Thanks & Regards
Sumanth

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: uart comms in C

Thu Dec 13, 2012 4:54 pm

Yep, you're still getting EAGAIN, meaning that there's nothing available on the serial port at the time you're trying to read.

I'l say it again. Go read the documentation I linked to earlier, understand what's going on, and work it out for yourself. Don't rely on code snippets typed untested into the browser by people like me. When you've written your own code and it doesn't work, *then* come back for help.

User avatar
[email protected]
Posts: 2024
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK

Re: UART communication in C

Thu Dec 13, 2012 5:15 pm

sumanharapanahalli wrote:
beautifulsmall wrote:Thanks tufty, thats worked ok , i just had to modify the
int n = write("Hello Peripheral\n");
to the format int write(int fd, char *Buff, int NumBytes);

int n = write(fd,"Hello",6);
my comms default is 9600baud
cheers.

Hi,

I am using the code given above [ with corrections]

I am able to send data from Pi to the terminal in the computer but I am not able to receive the data into PI.
The program stops after the read function is executed; initially I thought that its waiting for data but later i see that even after the data is sent from computer the program remain there, I am not able to understand what's the problem.

Can you please help me solve the same
You might want to have a look at the serial library that's in wiringPi. It'll solve all these issues (well, it should!)

https://projects.drogon.net/raspberry-p ... l-library/

-Gordon
--
Gordons projects: https://projects.drogon.net/

User avatar
peepo
Posts: 308
Joined: Sun Oct 21, 2012 9:36 am

Re: uart comms in C

Sat Jun 22, 2013 3:45 pm

this all wfm but...

it seems one needs to run minicom first, then quit else program hangs.
ie after reboot

why might this be?

gdb -e run produces no output in the case of hang.

User avatar
liudr
Posts: 702
Joined: Sat Jun 01, 2013 12:11 am
Location: Central MN, USA

Re: uart comms in C

Sun Jun 23, 2013 8:34 pm

I think I've provided the complete code to set up the serial port to rid all the useless console features of linux:

http://www.raspberrypi.org/phpBB3/viewt ... 82#p372182

This above code should go after you open the port and before you set its property with tcsetattr.

The first link provided by tufty gives you some sample code but without the complete set of parameters on my post it will be useless to you.
Arduino data loggers, user interface, printed circuit board designer since 2009, RPI 3B 2B 2B Zero Jessie, assembly/C/C++/java/python programmer since the 80's

budi
Posts: 19
Joined: Sat Nov 09, 2013 3:36 am

Re: uart comms in C

Sat Nov 16, 2013 5:21 am

int n = write("Hello Peripheral\n");
to the format int write(int fd, char *Buff, int NumBytes);

int n = write(fd,"Hello",6);
my comms default is 9600baud

It's work,thx.
but how if i want sent a int type?
sory I am newbe

User avatar
joan
Posts: 16247
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: uart comms in C

Sat Nov 16, 2013 8:38 am

budi wrote:int n = write("Hello Peripheral\n");
to the format int write(int fd, char *Buff, int NumBytes);

int n = write(fd,"Hello",6);
my comms default is 9600baud

It's work,thx.
but how if i want sent a int type?
sory I am newbe
To send an int, e.g.

int myInt;
int newInt;

myInt = 78123;

write(fd, &myInt, sizeof(myInt)); /* pass address and size in bytes of myInt to send an int */

...

read(fd, &newInt, sizeof(newInt)); /* to receive an int */

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4257
Joined: Mon Jan 09, 2012 3:16 pm

Re: uart comms in C

Sun Nov 17, 2013 10:06 am

budi wrote:but how if i want sent a int type?
sory I am newbe
Don't.

If you just send strings, then you can use non-printable characters, like New-Line, to frame it. If the receiver gets out of step it just has to wait for the next framing character to get back in step. But if you send "binary" values, such as integers, there are no framing characters available because the individual bytes of the integer can have any values, including zero and new-line. The receiver has to work by dead-reckoning and if it gets out of step there is no way for it to synchronise ever again. There are techniques you can use that help, but they are complex and none of them are perfect. Because the bytes can be zero, you can't use the standard string functions, which all depend on the only zero being at the end of the string.

Also, using sizeof(int) only works if an integer is the same size on both machines. If one machine uses 4-byte integers and the other uses 2-byte integers, that simple code will fail.

To send an integer, convert it to a string.

Code: Select all

int myInt = 42;
char myname[]="Fred";
double pi = 3.141592265

char s[100];
sprintf (s, "%s, %d, %f\n", myname,myInt,pi);
write(fd, s, strlen(s));
Receiving it gets a bit more complex, since you need to receive until you get the framing character.

Code: Select all

int myint;
char myname[100];
double pi;

int i;
char s[100], c;
for (i=0; i<sizeof(s); i++)
{
    read(fd, &c, 1);
    s[i] = c;
    if (c == '\n')
        break;
}

sscanf(s, "%s, %d, %f\n", myname, &myint, &pi);

budi
Posts: 19
Joined: Sat Nov 09, 2013 3:36 am

Re: uart comms in C

Mon Nov 18, 2013 4:42 am

thx a lot that's work :)
but why sometimes its running a previous program, although I have been delete/command that?
example:
first I wrote

char s[100];
sprintf (s, "K%03i%03i\n", x,y);
write(fd, s, strlen(s));

then I change it

char s[100];
sprintf (s, "K%03i%03i\n", 10,-20);
write(fd, s, strlen(s));

it's still run the firs program

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4257
Joined: Mon Jan 09, 2012 3:16 pm

Re: uart comms in C

Mon Nov 18, 2013 8:54 am

That's usually the result of one of two mistakes:
  1. You forgot to save the file before compiling it.
  2. You forgot to compile it.
It can also be caused because you moved around where you were saving the compiled program. If in doubt, delete all the executable files and all the object files (.o) and then recompile.

slqa
Posts: 6
Joined: Tue Aug 13, 2013 8:06 am

Re: uart comms in C

Thu Nov 21, 2013 8:11 pm

Hi,
I wrote a code to use uart with microcontroler. I'm sending few string from RPI to microcontroler which parses this instructions and makes some things, but unfortunately I have a big lag like 3-4s. I use 115200baudrate, nonblock mode. I'm reading a data in infinite loop, which breaks when it reads good message.
Could anyone have a problem something like that?

Edit. I added tcflush function after each of loop and this solved the problem.

Regards slqa
Last edited by slqa on Sat Nov 23, 2013 7:31 am, edited 1 time in total.

budi
Posts: 19
Joined: Sat Nov 09, 2013 3:36 am

Re: uart comms in C

Sat Nov 23, 2013 5:57 am

thank a lot rurwin

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4257
Joined: Mon Jan 09, 2012 3:16 pm

Re: uart comms in C

Sun Nov 24, 2013 10:40 am

There's another two causes of the same problem.

1. You're not executing the code-path you think you are.
2. You're not editing the code-path that is executing.

In both these cases single-stepping in a debugger or inserting lots of debug printf's can show you where you are going wrong.

I get all four bugs on a regular basis. Number 2 above happens a lot when you've got two sections of code that are almost identical.

Return to “C/C++”