Jump to content


Photo

UART problems


  • Please log in to reply
25 replies to this topic

#1 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:13 PM

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?



#2 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:13 PM

Can you please explain more? Are you saying GPIO and UART both don't work? Can you please take a picture of your setup?



#3 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:13 PM

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



#4 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:13 PM

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. 



#5 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:13 PM

Bill, 

I would be interested in that code.



#6 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

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-greathous.../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



#7 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

Bill,

That worked.  Thanks!



#8 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

Could you post the source for that code?  I's like to see if I could do the same thing in python. 



#9 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

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



#10 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

cool.



#11 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

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/s...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.   



#12 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

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



#13 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

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. 



#14 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:14 PM

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



#15 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:15 PM

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. 



#16 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:15 PM

Great!

Enjoy!
Bill



#17 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:16 PM

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



#18 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:16 PM

bgreat, 
It would still be nice if you posted your setuart2 source code no matter how ugly it is.   Or you could just e-mail it to me mholler@pacbell.net.   I'll trade you my XBee gateway code for it if necessary. 



#19 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:16 PM

I have been real busy with work and this just slipped by me.  embarrassed.gif

No trades necessary. I will post the code before the weekend is out.

Enjoy!
Bill



#20 jim

jim

    Advanced Member

  • Administrators
  • 3,385 posts

Posted 13 February 2015 - 07:16 PM

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






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users