> By using mmap and toggling the register directly from a C++ program, the GPIO can be toggled at about 2.8 MHz, much faster than the device driver approach.
I mean, it doesn't need to be C++. I was getting pretty close to that speed with the same strategy (mmap the registers directly) with a python library I wrote. It's not exactly pretty, and was the first semi-major python project I was working on, but it was fairly functional.[1] If I remember right (it was quite a while ago), I was routinely seeing speeds around 1MHz. BUT you'll occasionally see hiccups of as much as tenths of a second, because Linux is decidedly not real-time.
I ran into a pretty tall brick wall when I started trying to do pin muxing[2] using the same strategy. Going pretty far down this path lead me to the conclusion that the best strategy for boards like BB/RazPi is to run them on an exokernel and then have per-language libraries that access the registers, with the exokernel[3] enforcing memory access rules. You could even use that library on multiple platforms by declaring the memory mapping for the registers as, for example, a json schema. All of the systems on a chip that I looked at datasheets for while I was working on that project (which was admittedly an extremely limited sample size) go through the same strategy of fixed physical memory addresses for peripheral pins.
[1] https://github.com/Badg/hwiopy
[2] Pinmuxing is the process of switching functions for a given pin. Basically, SoC's are so small that the chip designers will put more than one thing, say USB + GPIO + HDMI, on the same pin. Muxing -- which is ultimately also controlled by a fixed physical register -- switches between modes. Muxing is only available from code running in protected mode, and besides, Linux wets the bed if you try to do this at runtime. That may sound silly -- why would I want to switch between USB and HDMI at runtime -- until you either think of other examples (for example, GPIO vs analog in), or realize how much of a pain in the ass it makes it to do a bunch of operating system modifications just to reconfigure your pinout. Basically, it makes development an enormous pain in the ass.
[3] Exokernels are really cool, basically the lowest level of abstraction you could put in a kernel: it promises not to let you fuck up the hardware, and provides some very basic abstractions, but otherwise just gives you free reign. Very much the "consenting adults" strategy. https://en.wikipedia.org/wiki/Exokernel