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.