sgjava Posted November 8, 2020 Posted November 8, 2020 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/platform, https://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
Recommended Posts