Reputation: 13
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
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
Reputation: 495
Depending on your image and kernel...
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