Raspberry Pi GPIO Notes: ^^^^^^^^^^^^^^^^^^^^^^^^ Hardware Characteristics: http://www.mosaic-industries.com/embedded-systems/microcontroller-projects/raspberry-pi/gpio-pin-electrical-specifications https://www.raspberrypi.org/documentation/hardware/raspberrypi/gpio/README.md https://elinux.org/Rpi_Low-level_peripherals *Based on documentation for the bcm2835 library, there are no "ports" for which bytes are written to independently in the GPIO. Either the pins are addressed independently, or one large byte is written to all the pins, with a mask selecting only specified pins to actually be changed ( bcm2835_gpio_write_mask() ). - http://www.airspayce.com/mikem/bcm2835/ - http://www.airspayce.com/mikem/bcm2835/group__gpio.html - https://www.iot-programmer.com/index.php/books/22-raspberry-pi-and-the-iot-in-c/chapters-raspberry-pi-and-the-iot-in-c/35-raspberry-pi-iot-in-c-introduction-to-the-gpio?showall=&start=2 -Also: bcm2835_peri_set_bits() *Given above, data pins (and possibly address pins as well) should be sequential, so that a byte can be << shifted into position for a masked write. *Doesn't appear to be any function to read in the levels at multiple pins... -Is here: http://www.airspayce.com/mikem/bcm2835/group__lowlevel.html - Makes it even clearer that the GPIO is treated as one 32bit byte of data. - bcm2835_gpio_pad() ? - I don't think so because the "pad control" can also be set. -Actually sets slew rate, hysteresis, and output current, for a range of GPIO pins. *Chip I/O 16-24 might be good for data. *Order of GPIO pins and order of associated bits in pin mask is all jumbled up. See bcm2835.h for the actual associations. *Any pin can be set for interrupts on rising or falling edge, or in sync with the system clock. *Setting pin input/output mode seems to be another task without a function to do the whole bus at once. bcm2835_gpio_fsel() only does one pin at a time bcm2835_peri_write() to register? *Look into how to set the power-on default state of the GPIOs, I remember reading that this was possible After looking into this deeply I'm finally fairly certain that the GPIO is (or at least, can be) read/written as one unsigned 32bit variable. As a result, it will be very helpful to have all the data and address lines placed sequentially in relation to the GPIO order. This way, the data byte to be read/written can be shifted ( >> or << ) back/forth from the starting pin of the data and address busses. Here is the pinout that I've decided on, based on the pin assignments described in the header file of the bcm2835 library (bcm2835.h): http://www.airspayce.com/mikem/bcm2835/ Descrip.|Bit |Pin | D0 |16 |36 | D1 |17 |11 | D2 |18 |12 | D3 |19 |35 | - GPFSEL 1/2 D4 |20 |38 | D5 |21 |40 | D6 |22 |15 | D7 |23 |16 | A0 |7 |26 | A1 |8 |24 | A2 |9 |21 | A3 |10 |19 | - GPFSEL 0/1 A12 |11 |23 | A14 |12 |32 | #HALT |27 |13 | -Jumper to GND R/#W |13 |33 | PB6 |5 |29 | - GPFSEL0 IRQ_LATCH |6 |31 | #OE |24 |18 | LATCH_EN|25 |22 | - GPFSEL1 IRQ |26 |37 | #D/A |N/A |9 | -GND on pi 3V3 |N/A |1 | 5V |N/A |2 | GND |N/A |6 | Note: Pins counted from 1, bits counted from 0. *Other GPIO Libs: http://wiringpi.com/ -digitalWriteByte (int value) sets first 8 bits at once (two writes req.), but that desn't help much because I need more than 8 active lines. -Otherwise no advantage over bcm2835 and doesn't offer low level functions http://abyz.me.uk/rpi/pigpio/ -Has functions to read/write whole GPIO. Not to set modes though? *Low-Level I/O Tutorial: http://www.muddyengineer.com/2016/11/low-level-c-programming-raspberry-pi/ http://www.muddyengineer.com/2016/11/c-programming-raspberry-pi-2-gpio-driver/ -Doesn't describe writing bytes to the GPIO, but look at bcm2835 lowlevel function code - it may have done everything for me. https://elinux.org/RPi_GPIO_Code_Samples http://codeandlife.com/2015/03/25/raspberry-pi-2-vs-1-gpio-benchmark/ http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/ -- Good for examples too. *Use bcm2835 with the low level "peri" functions. This looks to be as simple and fast as you would get practically in any case. *"BCM2835 ARM Peripherals" document page 90 onwards describes the register mapping of the BCM2835. -See also: https://elinux.org/BCM2835_datasheet_errata *Interrupts can be used to avoid polling the edge detection register. Need to use the Linux GPIO subsystem and poll() in C. -A sort-of example: https://stackoverflow.com/questions/34808276/poll-on-raspberry-gpio-sysfs-raspberry -Best (fastest) interrupt handling would require a proper Linux device driver. Or running in a RTOS. -Example of the latter: https://github.com/enricorov/Pinterrupt -See: https://www.raspberrypi.org/forums/viewtopic.php?p=1149836 -Some valuable low-level info: http://xinu.mscs.mu.edu/Interrupt_handling_(Raspberry_Pi) -Hints at usage with Linux: https://www.iot-programmer.com/index.php/books/22-raspberry-pi-and-the-iot-in-c/chapters-raspberry-pi-and-the-iot-in-c/55-raspberry-pi-and-the-iot-in-c-input-and-interrupts?start=1 -Getting into it properly here: https://www.iot-programmer.com/index.php/books/22-raspberry-pi-and-the-iot-in-c/chapters-raspberry-pi-and-the-iot-in-c/55-raspberry-pi-and-the-iot-in-c-input-and-interrupts?start=2 -Useful search: http://duckduckgo.com/lite/?kd=-1&kh=-1&kl=au-en&kp=-1&kaf=1&k1=-1&q=bcm2835+EDR+Interrupt+handling Emulation on RPi: https://www.raspberrypi.org/forums/viewtopic.php?t=54357 DMA: Don't really understand how, but this project seems to improve GPIO performance and timing using DMA: https://github.com/Wallacoloo/Raspberry-Pi-DMA-Example 3D Printer Control: https://github.com/Wallacoloo/printipi This forum thread starts off with some interesting description of DMA usage, then ends up using other hardware features of the BCM2835: https://forums.adafruit.com/viewtopic.php?t=52389 Real-Time Linux: Not relevent, but discussion in comments goes into details on Real Time Linux kernels and the Raspberry Pi: https://hackaday.com/2017/12/26/fast-3d-printing-with-raspberry-pi-but-not-how-you-think/ RTLinux description: http://www.faqs.org/docs/Linux-HOWTO/RTLinux-HOWTO.html#toc3 Modern RTLinux (Preempt-RT): https://wiki.linuxfoundation.org/realtime/documentation/start Preempt-RT kernel compilation for Raspberry Pi: https://hackaday.io/project/123415-real-time-kernel-preempt-rt-for-raspberry-pi https://lemariva.com/blog/2018/07/raspberry-pi-preempt-rt-patching-tutorial-for-kernel-4-14-y https://www.frank-durr.de/?p=203 https://github.com/emlid/linux-rt-rpi https://www.talkunafraid.co.uk/2014/04/real-time-kernels-and-audio-on-the-raspberry-pi/ Tiny Core(!): http://wiki.tinycorelinux.net/wiki:custom_kernel -May need the special Rpi "tools" (1GB download) to be downloaded like in the tutorials for Raspbian. Pre-built PREEMPT_RT kernels: *the frank-durr.de tutorial offers one for v. 4.4.9 = 2016 era Raspbian *SD card image from 2015 here (also interesting benchmark): https://emlid.com/au/raspberry-pi-real-time-kernel/ *RealtimePi: https://guysoft.wordpress.com/2017/10/09/realtimepi/ -https://github.com/guysoft/RealtimePi -Download here (new versions under "nightly"): http://unofficialpi.org/Distros/RealtimePi/ -Part of this project, which could be useful for making a final PiTrex distro: https://github.com/guysoft/CustomPiOS Preempt-RT Q&A: http://linuxgizmos.com/adding-real-time-to-linux-with-preempt-rt/ Alternative Patch: http://www.rtai.org/ -Allows code to control priorities directly, but have to figure out how that works. https://lemariva.com/blog/2018/02/raspberry-pi-rt-preempt-vs-standard-kernel-4-14-y Linux Kernel Module: ^^^^^^^^^^^^^^^^^^^^ *If pitrexio-gpio was a kernel module, would this prevent write operations being interrupted by other Linux processes? Module tutorials: http://derekmolloy.ie/writing-a-linux-kernel-module-part-1-introduction Linux Kernel Module Programming Guide (old): http://www.tldp.org/LDP/lkmpg/ http://www.tldp.org/LDP/lkmpg/2.6/html/index.html https://morethanuser.blogspot.com/2013/04/raspberry-pi-gpio-interrupts-in-kernel.html http://web.archive.org/web/20121127061023/http://www.kernel.org/doc/Documentation/gpio.txt Comparing with the PREEMPT_RT Patch: http://www.l3oc.com/2015/05/user-space-vs-kernel-space-gpio-speed_11.html https://unix.stackexchange.com/questions/87625/what-is-difference-between-user-space-and-kernel-space *Try out the optimisations intended to minimise the effects of Linux processes extending vector drawing operations and causing incorrectly drawn vectors. Based on these tests, decide what the most significant issue is and look into whether a Linux kernel driver, or Real-TIme Linux configuration, would prevent it. -I currently suspect Linux processes running during the loop waiting for a write to set the timer 1 counter register. If this is the main issue, then the question is how to ensure that the vectrexwrite() function runs directly, without any risk of other code being run while it polls the state of RDY.