Cannot set Pin in Navio+ with Raspberry Pi 4 + Ubuntu 18.04 arm64

Hi guys,
After completing with success the test with the combo Navio+ raspberry pi 3 with Ubuntu 18.04 arm64, I got the new raspberry pi 4 and I tried to run the demo code in your Navio2 C++/Python GitHub repository.

Results:
ADC works;
IMU works;
GPS works;

LED and Servo are now working and I tried to understand the problem… So fai i suspect that your Pin class is not ready for raspberry pi 4 (or at least you didn’t released the patch as the new Navio2 uses rcio instead).

Could you give me some hint although probably could be better to add a few lines of code into the example repo to fix for all the people out there.

Waiting for your help,

V

Hi Vincenzo,

May I ask you to clarify what examples you had issues with? Have any of the examples worked incorrectly?

Hi Polina,
thanks for the reply. Please refer to the following case:

Board: Navio+
Raspberry Pi version: 4 / 4Gb

After running the example code fetched from Navio2 Repo, I noticed that every example using the class Pin was not working. After a little bit of digging into the Raspberry Pi details I noticed the following error:

In the file gpio.cpp

the function Pin::getRaspberryPiVersion() does not support raspberry pi v.4, why?

if you cat the file /proc/cpuinfo in my case, the result yields to:

Hardware	: BCM2835
Revision	: c03112
Serial		: 10000000e0b3d26d
Model		: Raspberry Pi 4 Model B Rev 1.2

which selects in your code the wrong platform… in particular, v3. There is also another issue, which is the base peripheral address for raspberry pi 4, which is:

#define BCM2711_PERI_BASE   0xFE000000

here the changes I implemented to fix the issue:

bool Pin::init()
{
    int mem_fd;
    if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
        warn("/dev/mem cannot be opened");
        return false;
    }

uint32_t address = 3;
int version = getRaspberryPiVersion();
if (version == 1) {
    address = GPIO_BASE(BCM2708_PERI_BASE);
} else if (version == 2) {
    address = GPIO_BASE(BCM2709_PERI_BASE);
} else if (version == 3) {
    address = GPIO_BASE(BCM2835_PERI_BASE);
} else if (version == 4) {
    address = GPIO_BASE(BCM2711_PERI_BASE);
}

void *gpio_map = mmap(
    NULL,                 /* any adddress in our space will do */
    BLOCK_SIZE,           /* map length */
    PROT_READ|PROT_WRITE, /* enable reading & writting to mapped memory */
    MAP_SHARED,           /* shared with other processes */
    mem_fd,               /* file to map */
    address               /* offset to GPIO peripheral */
);

if (gpio_map == MAP_FAILED) {
    warn("cannot mmap memory");
    return false;
}

/* No need to keep mem_fd open after mmap */
if (close(mem_fd) < 0) {
    warn("cannot close mem_fd");   
    return false;
} 

_gpio = reinterpret_cast<volatile uint32_t *>(gpio_map); // Always use volatile pointer!

return true;
}

and then I also modified the

int Pin::getRaspberryPiVersion() const
{
#ifndef DEFAULT_BOARD_VER
    char buffer[MAX_SIZE_LINE];
    const char* hardware_description_entry = "Hardware";
    const char* v1 = "BCM2708";
    const char* v2 = "BCM2709";
    const char* v3 = "BCM2835";
    const char* v4 = "BCM2711";
    char* flag;
    FILE* fd;

    fd = fopen("/proc/cpuinfo", "r");

    while (fgets(buffer, MAX_SIZE_LINE, fd) != NULL) {
        flag = strstr(buffer, hardware_description_entry);

        if (flag != NULL) {
            if (strstr(buffer, v4) != NULL) {
                fclose(fd);
                return 4;
            } else if (strstr(buffer, v3) != NULL) {
                fclose(fd);
                return 3;
            } else if (strstr(buffer, v2) != NULL) {
                fclose(fd);
                return 2;
            } else if (strstr(buffer, v1) != NULL) {
                fclose(fd);
                return 1;
            }
        }
    }
    fclose(fd);
    return 3;
#else

    /* defaults to DEFAULT_BOARD_VER */
    fprintf(stderr, "Forcing RPi version to <%d>\n", DEFAULT_BOARD_VER);
    return DEFAULT_BOARD_VER;
#endif
}

then you can build the library and the examples with the compiler option

-DDEFAULT_BOARD_VER=4

to get everything working for the Raspberry Pi 4 case.

I hope this post can help some other developer who need your product to work without your raspbian image…

I would like also to mention that, the example code you released in full of warnings and small bugs, which can be highlighted by removing all the warning filters you establish in your make files… which I friendly recommend as best practice.

Hoping to be helpful to improve robustness and compatibility,

with my best regards,

V.

1 Like

Hi Vincenzo,

Sorry for the much-delayed response!

Thank you for the putting your time into improving the code. We’ll double-check the examples and correct them accordingly :slightly_smiling_face:

@vincenzocalabro I am interested on getting the Navio2 to work with Ubuntu 20.04. Could you share the steps you followed to do it?

I was thinking to do this:

  1. Install Ubuntu 20.04
  2. Modify /boot/firmware/config.txt as suggested in Experience with Ubuntu 18.04 arm64 and Navio+
  3. Install rcio-dkms from https://github.com/emlid/rcio-dkms

Thanks in advance for any help!

Hi Guido, thanks for supporting this cause :smiley:

I believe that Emlid should help us to properly run their electronics on Ubuntu 18.04 and 20.04 (the latest LTS Ubuntu releases). I believe it is not that hard, especially for them… but despite this assumption, Emlid is dodging this issue with their technical support stuck on the ROS/MAVROS/ARDUPILOT configuration, which is fine for most of their non-technical customers.

I am a R&D manager, trying to make new high-tech underwater robot concepts, using low cost hardware to mitigate final costs. I am planning in volume production, but without the proper technical support especially with Ubuntu, it will be hard to use Emlid product in future (which is a pity). We run Ubuntu on our products, and we are glad of technical support and available community. In addition, most of the ROS2 releases (standard ROS will be soon deprecated) are arm64 and x64, hence not supported by the standard Raspbian, using still 32bit flavor. In Ubuntu ROS and ROS2 are fully supported and binary packages are easily available from standard repository reducing integration and deployment time.

Going back to your question, the steps I mentioned before are referring to a Navio+ in my possession. I discovered that a problem was in a .c function used to detect the board type. All my findings are available in the same link you mentioned.

In am planning to buy a Navio2 for testing soon also because I would like to compare the IMU sensor mounted on the Navio+ (which are the same of Navio2) with the extra IMU with respect to the Allan Variance plot:

allan_acc
allan_gyro

So far I managed to run Navio+ PWM, GPS and IMU on ROS2 without major issues (and also without Emlid support…)

I’m not sure how I could help until I’ll get a Navio2 myself. Let me know how is going and if I can help somehow. I could join you in some video conference to trying to figure out issues,

V.

Hi Vincenzo, thanks for the response!

I am currently doing research on autonomous ground vehicles using Navio2 with ROS Melodic and I would like to migrate to ROS Noetic and ROS2. I really don’t use Ardupilot and I agree that having Ubuntu (or Debian for arm64, check https://wiki.debian.org/Arm64Port) support would make ROS integration a lot easier, since ROS binaries are arm64 and x64. Right now I have to compile ROS from source on the Raspberry Pi (which takes really long) and I couldn’t find how to cross compile ROS for the Emlid Raspbian OS.

I love the Navio2, it is a great fit with the Raspberry Pi at a great price. I started writing some direct integration of the Navio2 to ROS, check https://github.com/gmsanchez/navio2_ros

If some instructions were provided by Emlid, I would be happy to try them on my Raspberry Pi 3 with a Navio2 and report any issue. Do you think the steps I mentioned make sense? At lest to get the Navio2 up and running on Ubuntu and then try the C++ examples.

If you don’t mind to send me the code, I could run some of the Allan Variance tests you want on my Navio2.

Let’s keep our finger crossed and hope that Emlid helps us a little on this!

Cheers!

Dear Guido,

thanks again for the reply :slight_smile:

Nice work with the ROS/Navio2 nodes.

As I can see from your reply you are very much on my same line of thinking about Ubuntu issue with Emlid products.

I’m going to contact you privately trying to share my experience with the Navio+ Pi4 configuration.
Meanwhile I hope @polina.buriak from Emlid could try to push this issue far into the organization, to get for example an experienced hardware engineer to close this issue and extend their hardware support.

I believe that the first steps you mentioned earlier should put you in a good position to trying to remove additional errors from Emlid code and Ubuntu configuration.

Please start with compiling rcio-dkms after setting the config.txt

I believe you should also patch the .c file responsible of finding the board version but we can try to see how to solve this issue together.

After these steps, try to compile all the examples and report what is working and what is not working so we can shrink the scope.

V.

Thanks again!

It really would be great if Emlid helps us a little bit on this. At least using an ARM64 Debian port would allow us to install ROS binaries and it would be more or less the same work than the current Raspbian image. However, I think that ROS is better supported on Ubuntu.

Let’s keep our fingers crossed! :crossed_fingers:

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.