Norm_Analog
Norm_Analog

Reputation: 13

Problem using Beaglebone Black UART with C-Program

Stack Overflow,

I desperately need help getting a BeagleBone Black UART to work from a C program. The code that I am attempting to use is listed below. The code came from Chapter 8 of Derek Molloy’s “Beaglebone” book.

The code compiles without any warnings or errors and seems to run. The program passes the sanity checks that are built into the C code below. The program finishes by printing “Finished sending the message, exiting.” to the console.

The fundamental reason that I think the UART4 is not sending data is that I see no activity on P9/13 when monitoring with a nice digital O’scope. I have also tried monitoring the port by way of a PC running a terminal program.

I am convinced the C-program is reading my command-line message (e.g. “testing123”) correctly. I modified to code to print the message to the console and it printed the message as expected. I also modified the code run in a loop to make it easier to monitor P9/13 with the O’scope. The O’scope shows a constant 3.3VDC on the P9/13.

I also blindly tried a pull-down resistor. The port does not provide much current. A 2k Ohm resistor loaded the port to about 0.2 Volts.

I verified that ttyO4 and ttyS4 are in /DEV, whatever that means.

I am not certain what version of Debian that I am using. I monitored the “header” output from J1 and found this: Debian GNU/Linux 9 ebb ttyS0 BeagleBoard.org Debian Image 2019-08-03

Also, I found this: Machine ID: 229f313330aab6c19873bdc15d4645c7 Boot ID: b74381516ae64aefa37415709164f0e4 Operating System: Debian GNU/Linux 9 (stretch) Kernel: Linux 4.14.108-ti-r113 Architecture: arm

Do I need to enable the UART port or pins? If so, how do I do this and how do I confirm it was successfully done? Do I need to hardwire the control lines (e.g. CTS, RTS)? Do I need to edit the uEnv.txt file?

I am almost certain my board is a rev-c.

As a final note, I tried a similar C-code from the “Bad to the Bone” book with similar unfavorable results.

Any help will be greatly appreciated.

Thanks,

Norm

/* Simple send message example for communicating with the
*  UART that is connected to a desktop PC.  */

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<termios.h>
#incl`ude<string.h>

int main(int argc, char *argv[]){
   int file, count;
   if(argc!=2){
       printf("Please pass a message string to send, exiting!\n");
       return -2;
   }
   if ((file = open("/dev/ttyO4", O_RDWR | O_NOCTTY | O_NDELAY))<0){
      perror("UART: Failed to open the device.\n");
      return -1;
   }
   struct termios options;
   tcgetattr(file, &options);
   options.c_cflag = B115200 | CS8 | CREAD | CLOCAL;
   options.c_iflag = IGNPAR | ICRNL;
   tcflush(file, TCIFLUSH);
   tcsetattr(file, TCSANOW, &options);

   // send the string plus the null character
   if ((count = write(file, argv[1], strlen(argv[1])+1))<0){
      perror("UART: Failed to write to the output.\n");
      return -1;
   }
   close(file);
   printf("Finished sending the message, exiting.\n");
   return 0;

Upvotes: 1

Views: 354

Answers (2)

De Funct
De Funct

Reputation: 495

 ////////////////////////////////////////
 // blinkLED.c
 // Blinks the P9_14 pin based on the P9_18 pin
 // Wiring:
 // Setup:
 // See:
 ////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define MAXSTR 100

int main() {
  FILE *fpbutton, *fpLED;
  char LED[] = "50";   // Look up P9.14 using gpioinfo | grep -e chip -e P9.14
  char button[] = "7"; // Look up P9.42 using gpioinfo | grep -e chip -e P9.18
  char GPIOPATH[] = "/sys/class/gpio";
  char path[MAXSTR] = "";

  // Make sure LED is exported
  snprintf(path, MAXSTR, "%s%s%s", GPIOPATH, "/gpio", LED);
  if (!access(path, F_OK) == 0) {
    snprintf(path, MAXSTR, "%s%s", GPIOPATH, "/export");
    fpLED = fopen(path, "w");
    fprintf(fpLED, "%s", LED);
    fclose(fpLED);
  }
 
  // Make it an output LED
  snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", LED, "/direction");
  fpLED = fopen(path, "w");
  fprintf(fpLED, "out");
  fclose(fpLED);

  // Make sure bbuttonutton is exported
  snprintf(path, MAXSTR, "%s%s%s", GPIOPATH, "/gpio", button);
  if (!access(path, F_OK) == 0) {
    snprintf(path, MAXSTR, "%s%s", GPIOPATH, "/export");
    fpbutton = fopen(path, "w");
    fprintf(fpbutton, "%s", button);
    fclose(fpbutton);
  }
 
  // Make it an input button
  snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", button, "/direction");
  fpbutton = fopen(path, "w");
  fprintf(fpbutton, "in");
  fclose(fpbutton);

  // I don't know why I can open the LED outside the loop and use fseek before
  //  each read, but I can't do the same for the button.  It appears it needs
  //  to be opened every time.
  snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", LED,    "/value");
  fpLED    = fopen(path, "w");
  
  char state = '0';

  while (1) {
    snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", button, "/value");
    fpbutton = fopen(path, "r");
    fseek(fpLED, 0L, SEEK_SET);
    fscanf(fpbutton, "%c", &state);
    printf("state: %c\n", state);
    fprintf(fpLED, "%c", state);
    fclose(fpbutton);
    usleep(250000);   // sleep time in microseconds
  }
}

This is older source that may or may not work depending on your kernel/image and date in time of said kernel.

Also...

line 15 and line 16 show gpioinfo as a command. On the BBB, one can find many pins that are available and in what format which is usually default.

Calling config-pin during the source may help or you can have it preset w/ a .dtbo file in /boot/uEnv.txt. Overlays are, was, and still are a thing w/ the am335x on the BBB.

Upvotes: -1

De Funct
De Funct

Reputation: 495

Depending on your image and kernel...

  1. Try /dev/ttyS4
  2. Or try /dev/bone/uart/4

Also...I am pretty sure config-pin was available in kernel 4.14.x even though that kernel is EOL from their org.

If you come across /dev/ttyS4 not working, try config-pin for your specific pins used...

Upvotes: 0

Related Questions