Jump to content

Cross platform GPIO using MMIO approaching 4M writes per second


Recommended Posts

Posted

I have been bouncing ideas around with@diozerofor using MMIO in a generic way to achieve fast GPIO for times when performance (bit banging, software based PWM, low CPU latency, etc) is required. This is my first attempt using a NanoPi Duo (H2+) which should work on any H2+ or H3 based SBC. What I've done is write a register mapper, so I can extract the register masks without having to do it by hand from the datasheet. Hand mask making is tedious and error prone. The generic part will come in by externalizing the register offsets and masks. This will happen after I build my next project using an Odroid C2. Also, since the Duo didn't have PUDs, so I could not map those. That will come with the C2. Anyways, the benefits are:

  • Cross platform based on chipset. Most other high performance libraries only support a few boards since they bypass the kernel. Some may be faster, but if you only support a few deprecated boards what good is it? Look at https://periph.io/platformhttps://github.com/SilverThings/bulldog, etc.
  • Everything is pre-calculated instead of hideous code like this you have elegant code like this.
  • More room for improvement using various MMIO techniques. Using my c-periphery wrapper for now. 

 

Performance comparison (look at the code to see what each method does). Note this is write frequency, not square wave frequency. Also note maximum CPU utilization is 25% because only one core is used leaving the rest for your program:

09:08:32.940 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Running GPIOD write test with 10000000 samples
09:09:13.933 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - 488138.24 writes per second
09:09:13.954 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Running good MMIO write test with 10000000 samples
09:09:49.957 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - 555555.56 writes per second
09:09:49.958 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Running better MMIO write test with 10000000 samples
09:10:22.007 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - 624102.85 writes per second
09:10:22.009 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Running best MMIO write test with 10000000 samples
09:10:27.246 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - 3820439.35 writes per second

And the register mapper:

09:08:32.044 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Configuration registers
09:08:32.146 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin   4  GPIOA4 Port A Reg CFG0 Mask 00010000
09:08:32.180 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin   5  GPIOA5 Port A Reg CFG0 Mask 00100000
09:08:32.211 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  11 GPIOA11 Port A Reg CFG1 Mask 00001000
09:08:32.255 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  12 GPIOA12 Port A Reg CFG1 Mask 00010000
09:08:32.279 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  13 GPIOA13 Port A Reg CFG1 Mask 00100000
09:08:32.311 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  14 GPIOA14 Port A Reg CFG1 Mask 01000000
09:08:32.347 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  15 GPIOA15 Port A Reg CFG1 Mask 10000000
09:08:32.380 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  16 GPIOA16 Port A Reg CFG2 Mask 00000001
09:08:32.417 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin 198  GPIOG6 Port G Reg CFG0 Mask 01000000
09:08:32.441 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin 199  GPIOG7 Port G Reg CFG0 Mask 10000000
09:08:32.468 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin 203 GPIOG11 Port G Reg CFG1 Mask 00001000
09:08:32.494 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 1 Pin   3  BUTTON Port L Reg CFG0 Mask 00001000
09:08:32.525 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 1 Pin  11 GPIOL11 Port L Reg CFG1 Mask 00001000
09:08:32.545 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Data registers
09:08:32.559 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin   4  GPIOA4 Port A Reg DAT  Mask 00000010
09:08:32.592 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin   5  GPIOA5 Port A Reg DAT  Mask 00000020
09:08:32.620 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  11 GPIOA11 Port A Reg DAT  Mask 00000800
09:08:32.648 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  12 GPIOA12 Port A Reg DAT  Mask 00001000
09:08:32.676 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  13 GPIOA13 Port A Reg DAT  Mask 00002000
09:08:32.712 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  14 GPIOA14 Port A Reg DAT  Mask 00004000
09:08:32.752 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  15 GPIOA15 Port A Reg DAT  Mask 00008000
09:08:32.780 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin  16 GPIOA16 Port A Reg DAT  Mask 00010000
09:08:32.804 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin 198  GPIOG6 Port G Reg DAT  Mask 00000040
09:08:32.832 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin 199  GPIOG7 Port G Reg DAT  Mask 00000080
09:08:32.856 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 0 Pin 203 GPIOG11 Port G Reg DAT  Mask 00000800
09:08:32.888 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 1 Pin   3  BUTTON Port L Reg DAT  Mask 00000008
09:08:32.917 [main] INFO  com.codeferm.periphery.demo.DuoMmioMap - Chip 1 Pin  11 GPIOL11 Port L Reg DAT  Mask 00000800

 

IMG_20201108_184812.jpg

  • sgjava changed the title to Cross platform GPIO using MMIO approaching 4M writes per second
Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines