This board brings out only FPGA DIO. Since the FPGA is connected to the processor using SPI which is not atomic, we have created the SBUS which allows safe access from multiple processes. The SBUS mechanism of locking as well as it being a serial bus to the FPGA does put a limit on how fast the DIO can be read or set. Depending on the needs of the application the code can be structured to provide a bit of flexibility in speeds.
The "ts7500.subr" file provides the simplest method for accessing these DIO, but not the fastest:
# If you're in the initrd: source /ts7500.subr # If you're in Debian: source /initrd/ts7500.subr #Usage: setdiopin <pin> <1,0,Z> <b> setdiopin 20 0 #Usage: getdiopin <pin> getdiopin 21
You can also interface with this DIO in C using the example here.
... sbuslock(); setdiopin(21, (getdiopin(21) ^ 0x01)); sbusunlock(); ...
Using this method of an atomic read-modify-write will achieve about a 20KHz wave with a 50% duty cycle.
... sbuslock(); setdiopin(21, 1); setdiopin(21, 0); sbusunlock(); ...
Using this method of atomic writes will achieve about a 30KHz wave with about a 20% duty cycle.
The SBUS link between the FPGA and CPU is SPI with a 16-bit data frame per bus cycle. When setting and reading one pin at a time, a whole 16-bit cycle is used to accomplish the needed goal. If multiple pins need to be set or read at once, a performance gain can be had from reading/writing entire 16bit registers at a time as opposed to iterating through each pin sequentially.
Other factors can contribute to speeds of the SBUS. Since the SBUS is shared across multiple peripherals there could be bus contention. It may also be that there are very few other applications wanting access to the bus, it all depends on usage. There is more overhead in doing a sbuslock() and sbusunlock() after every transaction than there would be to queue up transactions, lock the bus, and then do them all at once. There is also another function provided in sbus.c that is a smarter version of sbusunlock(), it is called sbuspreempt(). sbuspreempt() will check to see if any other applications are blocked in acquiring the lock, if there are, the SBUS is unlocked, giving other applications access to it. If there are no other applications waiting for the lock, the current application retains the lock. The benefit of this, is next time sbuslock() is called, the function returns almost instantly because the lock is already held. This greatly reduces overhead.
It may be necessary to "tune" an application with locking, unlocking, and preempting the SBUS to find what works best if speed is a factor.
The DIO registers are described in the #Syscon section. This board has 40 logical DIO registers on the FPGA to remain consistant with the series, but not all of the pins are brought out. DIO 9 by default is an external reset which is pulled high, and when it is set to 0 the board will reboot. You can disable this functionality by clearing bit 4 of 0x76 in the #Syscon.