Jump to content
Sign in to follow this  
jim

UART problems

Recommended Posts

I can't get the UART (pins 0 and 1) working.  I've tried all the tests -uart_test, serial_test.py and .c.  I've tested three different usb->ttl devices in every type of configuration I could.  I've tested the pis with gpio_set, they turn on and off.  Nothing seems to work

Any ideas?

Share this post


Link to post
Share on other sites

Looking at dmesg log, the A10 UART 2 is enabled as /dev/ttyS1, but it appears that opening /dev/ttyS1 does not work as expected. Running a dump of the GPIO configuration registers, it shows the GPIO pins are configured as digital inputs by default.

I wrote a quick C program to set the state to UART2 for the IO pins and can confirm the serial port works as /dev/ttyS1. I tested using minicom with the TX/RX pins connected together for a loopback test.

If this would help you, I can make the code available for configuring the IO pins for serial IO.

Enjoy!
Bill

Share this post


Link to post
Share on other sites
Quote
Can you please explain more? Are you saying GPIO and UART both don't work? Can you please take a picture of your setup?
 

What I mean is that the debug serial port works just fine with my serial/UART converter, so it's not that.  And I checked the pins with "gpio_set" to see if they worked.  Since they turn on and off, I assume it's not the pins. 

Share this post


Link to post
Share on other sites

Ok. I am working on a general utility for setting the pin modes for the pcDuino. In the mean time, here is a link to my code for setting and resetting the pin assignments for uart2.

Download setuart2 onto your pcDuino, make it executable, and run.
 

Code: [select]

wget http://the-greathouses.net/files/setuart2
chmod +x setuart2

To enable uart2 (on /dev/ttyS1):

Code: [select]

sudo ./setuart2 on

To disable uart2 (GPIO I/O enabled):

Code: [select]

sudo ./setuart2 off

If you do not want to use sudo each time you run the command, you can give it root privileges:

Code: [select]

sudo chown root setuart2
sudo chmod u+s setuart2

Place the program on your path so you do not need to specify the directory it is in.

Enjoy!
Bill

Share this post


Link to post
Share on other sites

Right now, it is a quick hack of some code I have been working on for a while. I'll post the sources when I have something not quite so embarrassing -- hopefully before the weekend.  embarrassed.gif


Enjoy!
Bill

Share this post


Link to post
Share on other sites

I couldn't get /dev/ttyS1 to work where work means being able to put a scope on pin 1 (TX) on the pcDuino board and run a test program that sends data to /dev/ttyS1 and see pin 1 toggling.  I ran mhord's serial_test.cpp program https://github.com/sparkfun/pcDuino/blob/master/examples/serial_test/serial_test.cpp
which as I understand it is supposed to send the text "Hello World!" to /dev/ttyS1  The TX pin and not even the RX pin toggles.  I tried putty, minicom and still nothing.   

When I ran "sudo ./setuart2  on" I did see a change in the behavior of pin 1.   Instead of being floating like an input it changed to active high (3.3V).  I just couldn't get it to toggle.   I ran everything as root.   I can't figure out what the problem is.   Any help would be appreciated.   

Share this post


Link to post
Share on other sites

The simplest test to confirm the serial port is operational is to do a simple "loopback" test from the pcDuino by connecting the RX to TX pin on the header with a header jumper. The run your favorite Linux terminal program and confirm you receive the characters you type. I used minicom for my testing.

To install minicom:

Code: [select]

sudo apt-get update
sudo apt-get install -y minicom

To configure minicom:

Code: [select]

sudo minicom -sSet the serial port to /dev/ttyS1 and turn off hardware handshake. Save this as your default setting and exit minicom.

Then to test your serial port with minicom:

Code: [select]

sudo ./setuart2 on
minicom -oWhile the RX-TX jumper is connected, anything you type should be displayed. Remove the jumper and your typing will not be displayed. To exit minicom, type "Ctrl-A q". For help while in minicom, type "Ctrl-A z".

I checked out the test program you linked to also. With the jumper from RX-TX this should work also.

Enjoy!
Bill

Share this post


Link to post
Share on other sites

Thanks much,  I was able to get the loop back test to work with minicom.   It echoed characters with the RX-TX loop back jumper in place and did not when the jumper was removed. However, the voltage on the TX pin is not changing each time I hit a key in spite of a character being echoed each time I hit a key.   

I am seeing the voltage on TX pulsing low periodically but with no clear correlation to the keys being pressed.  Except that it doesn't occurr at all if I don't push any keys.   It looks like maybe the uart is buffering input and sending it in bunches every so often but, then how does it echo the right character immediately every time I hit a key?  Something is fishy.   minicom would have to figure out that I have the jumper in place and bypass the uart altogether.   

The real test will be to connect some other serial device to the pins and see if I can communicate with it.  Has anyone actually communicated with another device?  I am trying to communicate with an XBee radio module on an arduino wireless shield. 

Share this post


Link to post
Share on other sites

Unless you are using a digital storage oscilloscope, it can be difficult to trigger on and capture a serial data stream. This can be particularly difficult when using a high baud rate. Since a non-storage oscilloscope is looking for repetitive patterns, one way around this is to write a program that repeatedly sends the same data stream on a fixed time interval. Another option, is to set the baud rate to some low value (for example, 300 baud).

The loopback test confirms that a valid asynchronous serial data stream is being transmitted and received. It does not confirm that the baud rates are accurate. Connecting to another device will help to confirm the baud rates are accurate.

Enjoy!
Bill

Share this post


Link to post
Share on other sites

You're right.  Sorry my bad,  Problem was indeed scope operator error. I needed to set the scope trigger to trigger on a low going signal with a threshold of 2V or so to see the pulses.  When running the scope at a slow sweep the sampling rate was so low it missed most of the character transmission waveforms.  I'm using a DSO Nano storage scope.   /dev/ttyS1 on the pcDuino is working fine.  I'm getting good 3.3V digital waveforms out of the TX pin every time I hit a key in minicom.   I tested at 9600 baud too. 

Share this post


Link to post
Share on other sites

I have integrated your setuart code into my application but, it would be comforting to have the source in case some Ubuntu or PCduino change down the road breaks it.    If the code is so embarrassing (I doubt it - It works!) just e-mail the source to me at mholler@pacbell.net.  I would appreciate it.  
Mark

Share this post


Link to post
Share on other sites

Better late than never...  embarrassed.gif

Here is the simplified code for setting and resetting the second UART pin modes. It would be a simple matter to wrap the code as a library function for those wanting to call directly instead of using the command line version. One note though, the application attempting to set the pin modes must have root privileges -- which is not necessarily a good idea for most applications. My recommendation is to use the stand-alone utility at board boot via the /etc/rc.local or other start-up script that is run with root privileges. The other alternative is to chown/chmod the application to run with root privileges.  Your choice.

/*
 * setuart2.c
 *
 * Simple utility for enabling second UART on pcDuino
 *
 * Copyright (C) 2013 William Greathouse, Brecksville, OH, USA
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>

#define PAGE_SIZE       4096
#define GPIO_PAGE       0x01c20000
#define GPIO_OFFSET     0X0800

volatile unsigned int *gpio;

int main(int argc, char *argv[])
{
    int mem_fd;
    void *gpio_map;
    unsigned int setting;
    unsigned int pullup;


    /* Check for somewhat reasonable input from the command line */
    if ( argc != 2 ||
            (strcasecmp(argv[1], "on")  != 0 &&
             strcasecmp(argv[1], "off") != 0) )
    {
        fprintf(stderr, "%s: either 'on' or 'off' argument is required\n",
            argv[0]);
        return 1;
    }

    /***** This is the meat of the code *****/

    /* Get access to the device memory map -- This requires root authority! */
    mem_fd = open("/dev/mem", O_RDWR|O_SYNC);
    if (mem_fd < 0)
    {
        perror("/dev/mem");
        return 1;
    }

    gpio_map = mmap(
        NULL,
        PAGE_SIZE,
        PROT_READ|PROT_WRITE,
        MAP_SHARED,
        mem_fd,
        GPIO_PAGE);

    close(mem_fd); // no longer needed

    if (gpio_map == MAP_FAILED)
    {
        perror("gpio_map");
        fprintf(stderr, "mmap error=%d\n", (int)gpio_map);
        return 2;
    }

    /* Now get a pointer to the gpio region */
    gpio = (volatile unsigned int *)gpio_map + GPIO_OFFSET/4;

    /* How we want to set up the pin modes */
    setting = gpio[0x120/4+2] & 0xffff00ff;
    pullup  = gpio[0x140/4] & 0xffffff0f;
    if (strcasecmp(argv[1], "on") == 0)
    {
        setting |= 0x00003300;
    }
    else
    {
        pullup |= 0x00000050;
    }

    /* set the pin modes */
    gpio[0x120/4+2] = setting;
    gpio[0x140/4]   = pullup;

    /* Warm and fuzzy... display the new settings for the pin modes */
    fprintf(stdout, " PI_CFG2:0x%08x\n", gpio[0x120/4+2]);
    fprintf(stdout, "PI_PULL1:0x%08x\n", gpio[0x120/4+8]);

    /* No longer need the memory map, so give it up */
    munmap(gpio_map, PAGE_SIZE);

    return 0;
}

Enjoy!
Bill

Share this post


Link to post
Share on other sites

Bill, 
Thanks for the source.   Better late than never on my end too.   I'm still using your code although I have found some examples of how to set up the pinmode for  the pcDuino on the sparkfun tutorial page at https://learn.sparkfun.com/tutorials/programming-the-pcduino/serial-communications and was able to carve out the pinmode setup from the example on this page and get it to work.   However, when I tried my code on pcDuino v2 it didn't work nor did setuart2.  It's probably some problem in my hardware connection but, I am worried they changed something in the device drivers which broke my and your code.  Having your source I can dig deeper.  If you know anything about this issue I'm sure you will let me know.   Thanks again for the source. 
Mark

Share this post


Link to post
Share on other sites

Since the kernel code is the same for the pcDuino and pcDuino v2, I can not see an immediate reason why the pin mode setting would not work. I will look at getting a v2 to test.

Thanks for the head up.

Enjoy!
Bill

Share this post


Link to post
Share on other sites

Back to square one with pcDuino V2.   setuart2 no longer works.   The linux image is quite a bit different from what's on V1.  It has a board config at the begining like a bios, It detects my full 1080P monitor and displays at full resolution ( a good thing) and they have added a /home/ubuntu/samples/core/ directory with a couple executables  for setting gpIOs but unfortunately nothing for initializing the ttyS1 serial port.  The serial_test example code from github didn't work for me either. 

Share this post


Link to post
Share on other sites

Also had the same problem on pcDuino3. Also, I'm using perl and not python / c - from command line.

Since outputting 1 on the GPIO0/GPIO1 mode flags didn't do the trick ... I tried to test the loopback method mentioned here http://learn.linksprite.com/pcduino/quick-start/uart-loopback-test-on-pcduino/ . It worked - but I had to change the import from core.h to Arduino.h (using c_environment):

#include <Arduino.h>
#include "Serial.h"

void setup() {
        Serial.begin(115200);
        while (!Serial);
}

void loop()
{
        Serial.println("Hello, world");
        while (Serial.available() > 0) {
                int ret = Serial.read();
                printf("I received:0x%.2x(%c)\n", ret, ret);
        }

        delay(10);
}

and the output looks like:

I received:0x48(H)
I received:0x65(e)
I received:0x6c(l)
I received:0x6c(l)
I received:0x6f(o)
I received:0x2c(,)
I received:0x20( )
I received:0x77(w)
I received:0x6f(o)
I received:0x72(r)
I received:0x6c(l)
I received:0x64(d)
I received:0x0a(
)
I received:0x0a(
)
I received:0x0a(
)

After running the test, magically somehow, the communication with the serial device also started to work! I realized it is something related to the pin modes, so I went to check the code in Serial.begin(). It seems that the Serial.cpp sets the mode to value 3 (IO_UART_FUNC) for the two RX/TX pins.

So now, in command line:

ubuntu@ubuntu:~/c_environment/work/uart_test$ echo 3 > /sys/devices/virtual/misc/gpio/mode/gpio0
ubuntu@ubuntu:~/c_environment/work/uart_test$ echo 3 > /sys/devices/virtual/misc/gpio/mode/gpio1

and then the serial communication with the device started to work smiley.gif

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×