AbhraneelBera / wiringBone

Wiring/Arduino style library for BeagleBone Black Platform
25 stars 14 forks source link

Strange Bus error #8

Open KaiboFu opened 8 years ago

KaiboFu commented 8 years ago

Hi, the wiringBone library is a very good library. But i meet a strange problem when using it. The Arduino-like codes are as follows:

#include <iostream>
using namespace std;

void setup(){
        Serial2.begin(9600);
}
unsigned char ch;
void loop(){
        while(Serial2.available())
        {
                //cout << "test" << endl;
                ch = Serial2.read();
                cout <<endl<< "Receive: " << ch <<endl;
        }
}

(P9_11 and P9_13 are all set to UART mode in UserPinConfig.h, Before I find the wiringBone library, I implement my own C++ codes and the codes work well for reading and writing through UART4)

The strange things are as follows:

  1. If I run the above Arduino-like codes using wiringBone library first, the codes works well and can read buffer normally. Then if i run my own C++ program for UART, it does not works and seems to block at the reading function, e,g, read(fd, &buff, 1). Then I use the MINICOM tool to test /dev/ttyO4, but even the MINICOM cannot read anything(My own C++ program and the MINICOM can both read through /dev/ttyO4 normally before).
  2. If I restart the BBB board and run my own C++ codes first, my own program works and can read buffer normally. Then I run the above Arduino-like codes, I meet the "bus error". The debugging info using gdb is as follows:

image

The linux kernal version in my BBB board is : Linux version 3.8.13-bone70 (root@a5-imx6q-wandboard-2gb) (gcc version 4.6.3 (Debian 4.6.3-14) ) #1 SMP Fri Jan 23 02:15:42 UTC 2015

I am still unable to find the reason of the problem and the way to solve it. Any help is greatly appreciated .

KaiboFu commented 8 years ago

One simple example of C++ codes is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;

int openPort();
int setCom(int fd);
int openPort()
{
    int fd = open("/dev/ttyO4",O_RDWR|O_NOCTTY|O_NDELAY);
    if(fd < 0)
    {
        return -1;
    }
    return fd; 
}
int setCom(int fd)
{
    struct termios new_cfg,old_cfg;
    int speed;

    if(tcgetattr(fd,&old_cfg) != 0)
    {
        cout << "tcgetattr fails" <<endl;
        return -1;
    }
    new_cfg = old_cfg;
    cfmakeraw(&new_cfg);
    new_cfg.c_cflag |= CLOCAL|CREAD;
    new_cfg.c_cflag &= ~CSIZE;
    speed = B9600;
    cfsetispeed(&new_cfg,speed);
    cfsetospeed(&new_cfg,speed);
    new_cfg.c_cflag|=CS8;           /// data bit: 8
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;
    new_cfg.c_cflag &= ~CSTOPB;    ///stop bit: 1
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 1;
    tcflush(fd,TCIOFLUSH);//flush cache data
    if((tcsetattr(fd,TCSANOW,&new_cfg))!= 0)
    {
        cout << "tcsetattr fails" <<endl;
        return -1;
    }
    return 0;
}

int main()
{
    int fd = 0; 
    if((fd = openPort())>0)
    {   
        if(setCom(fd) < 0)
        {
            cout<< "setCom fails"<<endl;
        }
        else
        {
            cout<<"openPort is OK"<<endl;
        }
    }
    else
    {
        cout<<"openPort fails"<<endl;
        return -1;
    }
    unsigned char buff;
    while(1)
    {
        if(read(fd, &buff, 1) > 0)
            cout << "I receive " << buff << endl;
    }

    return 0;
}

Wish your help and reply!

Rahul5214 commented 8 years ago

A bus error is trying to access memory that can't possibly be there. You've used an address that's meaningless to the system, or the wrong kind of address for that operation. Wiringbone has auto clean feature at program exit so maybe you are accessing invalid memory location after you terminate wiringbone code. Try to run your C++ code and wiringbone code simultaneously(in two different tabs) and see if it works.

KaiboFu commented 8 years ago

Thanks for your kind reply @Rahul5214. I run the two programs as you say.

  1. I run the wiringbone code in the first terminal and it works. When the wiringBone codes are running, I open a second terminal and run the C++ codes. The C++ codes still can not read anything. I also test the MINICOM tool in the second terminal and it cannot read either.
  2. I run the C++ code in the first terminal and it works. When the C++ codes are running, I open a second terminal and run the wiringbone codes. The bus error occurs.
  3. I test the MINICOM tool in the first terminal and it works. When the MINICOM is reading buffer, I open a second terminal and run the wiringbone codes. The bus error occurs. (C++ codes, MINICOM --> UART2, wiringBone codes --> UART4)

(if you have time, running the two codes on your board is greatly appreciated!!)

KaiboFu commented 8 years ago

I have some strange findings. @Rahul5214 @AbhraneelBera . The scenario is that: I restart the my BBB board and open two terminals (nothing else has been done). In the first terminal, I just type the commands as follows: image

In the second terminal, I just try to run the wiringBone codes, but it also meet the bus error: image

The output is the debugging info and the codes seem to terminate at the line 107 ( *(ctrl0 + CONTROL) = (1 << SOFT_RST_N); ) PWM.cpp , as follows: image

Do you have any ideas and have you meet the same problem ?

AbhraneelBera commented 8 years ago

Hi @KaiboFu, The wiringBone library is fully dependent on beaglebone-universal-io device trees. The beaglebone-universal-io has the capability of configuring all the pins on the P8 and P9 header. It also loads the necessary drivers when you try to use a pin for some specific perpose, for example if any pru pin is used then it will load the drivers for pru (which it will always do). A wiringBone code will automatically load the beaglebone-universal-io dtb during startup. As I can see from the above post that you are trying to load the BB-UART4 dtb. Please note that if you load this cape then wiringBone will fail to load the beaglebone-universal-io dtb. As a result the pru drivers are not loaded, and you are getting a bus error when the code is trying to write in the ctrl0 register of pru. Therefore please dont load the BB-UART4 dtb and try to run the wiringBone code again.

For the second issue that you posted (after running a wiringBone code no other program is able to read/write through uart) , the answer solely depends on whether you are using the beaglebone-universal-io dtb or not. Here is a trick you can try, considering that you are not loading the BB-UART4 dtb and wiringBone is able to load the beaglebone-universal-io dtb successfully : The auto clean-up feature of the library will set all the pins (being used) to default mode when the program exits. Therefore when the wiringBone code exits it sets the modes of P9_11 and P9_13 to default (which is gpio). Therefore before running other programs which needs to access UART4 you will have to manually set the pin modes to uart from command line. Now, the trick is, if you want to prevent wiringBone from doing the auto clean-up you can stop the program using ctrl+z. This will kill the program abruptly and the pins will remain in uart mode. Give it a try and let me know.

KaiboFu commented 8 years ago

@AbhraneelBera Thanks for your reply. Your answer is right. I follow your instruction and the problem solves. Finally, the WiringBone is a very good library, more documentations are greatly appreciated!!!