📄 spi-driver_v2-ifc.txt
字号:
This file describes the interface to the SPI-Driver.PrefaceThe SPI-Driver enables the communication with devices that are designed tointerface to the SPI-Bus. This is a 3-wire bus with a synchronous protocol.It consists of two data lines (one for data from the master to the slaveand one for data from the slave to the master) and a clock line. Alltransfers are done synchronously to this clock. The master must supply thissignal.In addition to these lines there are one or more CE-lines, one for eachslave or chain of slaves. Theoretically there can be as many slaves on thebus as the driver can drive the fan-ins of the receivers.A companion of the SPI-Bus is the MicroWire-Bus from National Semiconductor.It differs only in some minor details and most chips can be connected toeither of the busses. The major difference lies in the relation of the datatransfer and the clock. Thus this driver, although called "SPI-Driver", hasbuiltin capabilities to communicate with both types of chips.The spec of both busses define that for each byte sent out by the masterthere is one byte returned by the slave. So the amount of bytes sent out andthose received is identical per definition. This is relied upon in thisdriver.ImplementationThe SPI-Driver is a character device driver. It expects a block of data andreturns a block of (usually) the same size. As the bustransfers are usually very fast it does not use interrupts, but does thetransfers in a manner, that would be called "polled" if this driver wouldinterface to a printer or similar device. So, the application is blocked fora couple of microsecunds until the data bytes are all sent out and the neware read in.There are two general approaches to the solution: First, the driver is giventhe net data to transfer in a data block and does all addressing by its own.This needs an elaborate IOCTL-function to set up the active states of allCE-lines and the type of chip to address. In a system with many differenttypes of chips and probably on different CEs this would incur a significantoverhead, as for each real data transfer an IOCTL-function call must beperformed.To avoid this the following design was choosen: The resposibility to selectthe correct states of the CEs of the attached chips is moved to theapplication. (Even with the other approach the application must tell thedriver at least once about the active states of all CEs, so this is no realdifference.) Furthermore the user must take care with each transfer toselect the right combination of type and CE. The forementioned approachwould need only a setup once when the application is starting and doing theright things afterwards automatically. But this was not considered a realadvantage as the user still must know about the chips connected to the port.Moreover, the simplier the driver itself is, the easier it can be debuggedand the smaller its code size will be. And a real simple, but versatiledriver will need no updates to accomodate a new high level protocol. This could be a real pain in the neck when chips with data transfer sizes of multiple bytesare intermixed with byte-size types on the same bus.InterfaceBackground information:The IOCTL-function is not used. Like all devices there are two functions toopen and close the channel. As the driver supports only one port there canbe only one channel open at a time. If the user tries to open a secondchannel he gets an error returned. The call to the driver is defined as:static int spi_write (struct inode *inode, struct file *file, const char *buf, int count) where *buf is a pointer to a buffer in user space with a command packet in it *inode and *file are parameters returned from the open of the device (/dev/spi, if the default is used) and count holding the number of bytes in this buffer, including the 3 overhead bytes. return value is count when a correct block was in the buffer and -EINVAL when less than 4 bytes were in.But remember, that a user normally does not call this routine directly. Thenormal way to work with the driver is something like this sequence:(The user uses the device /dev/spi for the communication, not the routinefrom above directly!) #include "spi.h" /* change to location of the file!!! */ int spi_handle; static byte spi_buf[4]; /* or whatever size you might need */ /* setup the data in the buffer */ spi_buf[0] = SEL_SPI_CPOL_0; /* or what your chip needs */ spi_buf[1] = my_CEs_at_start; spi_buf[2] = my_data_byte; spi_buf[3] = my_CEs_at_end; /* now open the device and transfer the data */ spi_handle = open(/dev/spi, O_RDWR); write (spi_handle, spi_buf, 4); read (spi_handle, spi_buf, 4); close (spi_handle);The first byte in the buffer (called spi_buf in the code above) is theprotocol to use for the chip that you want to communicate with at themoment. You can (and usually must) set that for each transfer. You do not have to open and close the device eachtime - one open at the beginning of your program and one close at the end doit as well. But there is no harm by opening and closing the device everytime. The format of the command block in the buffer is defined as follows:(All entries are of size = byte) (Protocol ids defined in spi.h) 1 protocol identifier in the two LSBs (other bits ignored) protocol identifier selects SEL_SPI_CPOL_0 SPI device with CPOL=0 SEL_SPI_CPOL_1 CPOL=1 SEL_UWIRE_CPOL_0 MicroWire device with CPOL=0 SEL_UWIRE_CPOL_1 CPOL=1 2 CE settings to be applied before the transfer of the first data byte 3 first data byte 4 .. n additional data bytes n+1 CE settings to be left after the transfer of the last byteFrom the above table it can be seen that for a block to be valid there mustbe at least 4 bytes in the buffer: 3 overhead bytes and one data byte. Eachdata byte in the buffer is transferred to the SPI-Bus and is thenoverwritten by the byte returned by this transfer. The following paragraph explains inmore detail what the driver does with each of the bytes in the buffer.Note, that only the bytes from position 4 to n are overwritten, not thefirst 3, nor the last one. When there is no need to change them you can"reuse" them.For a write operation the driver first copies the user buffer into a private one for the driver. All operations described below are performedusind the private buffer. The read returns the modified private buffer. WRITE:When called by the user the driver first checks, whether there are at least4 bytes in the buffer (it checks the parameter count, but this shouldreflect the correct number of bytes anyway. Should there be a mismatch thatleads to a memory management fault, the system might crash, but this type offault is to be avoided by the programmer). If this condition is met, thedriver then takes the first byte out of the buffer and selects theappropriate protocol. Only the two LSBs are evaluated and all other bitsdiscarded in the current implementation. The protocol used is defined asin the include file spi.h. Use this definitions and leave the other bitsalone. (A future release of the driver will support the JTAG protocol, sothe other bits are reserved.)Next the driver takes the second byte out of the buffer and simply outputs iton the data lines of the parallel port (without any modification). It isthus the responsibilty of the programmer to keep the state of the idle CEsin a variable of his own, as the driver does not interpret this byte withthe CEs in. The chip is now selected. Now the driver fetches the next, i.e. third byte and transfers it serially on the SPI-Bus. This causes one byte to be sent from the slave to the master,too. This returned byte is stored in the same location in the buffer where the user byte came from, thus overwriting this byte. This step is repeated until all data bytes in the buffer are sent (and overwritten by the slave data).The last step the driver does is to get the last byte in the buffer and,again, simply outputting it to the data lines of the parallel port. Normallythis deadresses the chip and puts the SPI-Bus into its idle state. But whenthe user wants to make a multi-byte transfer with a pause in between then hewould not deaddress the chip, but leave it addressed by using the same valuein this byte as in byte 2. An example of this would be the communicationwith an A/D-converter that is started by the transfer of the first databyte(s) and then needs a significant time for the conversion. In this casethe user would sent the start command to the chip, leave it addressed, waitafter the return from the driver call for a time sufficient long to ensurethat the conversion is done and then complete the cycle by reading in theresult and deaddressing the chip.As there can be only one channel open to the driver at a time, even in amultitasking environment there cannot be another transfer by another programin the time the program in the above example waits for the completion. Sothat program that has successfully opened a channel to the SPI-Driver canrely on an undisturbed multi-block transfer without any locking mechanism.From the description above it can be seen, that the driver does notinterpret any of the bytes in the buffer and it does no checking whether thebytes in the buffer are in any sense meaningful. HINT: As there is no difference on the SPI-Bus between read and writes mostchips treat a byte with a zero value as some sort of NOP. It is common onthe SPI-Bus to send zeroes when a user wants to read a value from a chip. Ina more advanced system the next command would be sent instead, but for astart sending zeroes is a good way to handle the read case.READ:If there was a write prior to an read then the modified private buffercontains usable data that is returned with the read. If there was no writeor there was already a read then the second read will return nothing(because a successful read deallokates the private buffer of the driver).A read MUST be preceded by a write, if you want it to work. Although usuallythere is no need to use a different count in the write and the read, you canspecify a smaller (but not bigger) one in the read. But this is not verymeaningful in most cases. Pin Usage of The Parallel Port.Pin Name Signal Direction (PC is the master) 1 Strobe MOSI Master -> Slave (Data) 2 D0 CE0 Master -> Slave (Chip Enable) ... 9 D7 CE7 11 Busy MISO Slave -> Master (Data) 14 Autolf SCK Master -> Slave (Clock) Here at Paul Elektronik we defined a private standard for the SPI bus on a10 pin header. You can use it freely. The pinout is given below. It ischosen for two reasons: It minimizes crosstalk and allows for arbitrary manyCEs to be used simply by extending the pin header. This extended pin headeris still usable by a 10 pin cable, although only the first CE is usable. 2 4 6 8 10 _________ |o o o o o| Viewed from component side |x o o o o| --------- 1 3 5 7 9 Pin 1 is cut off an a coding plug is inserted into the female connector onthe flat cable. The pins carry these signals:Pin Name Remarks 1 - Cut off to code the pin header 2 MISO 3 GND 4 MOSI 5 GND 6 +5V If supplied via the cable, NC otherwise 7 GND 8 SCK 9 GND 10 CE0 Numbering is relative to the board, not the system Each board with SPI chips starts the numbering from CE0. The mapping (connection) between the CEs of the master and the local ones is done via the cabling harness. If more CEs are used on a board, the pin header is extended as needed withthe additional pins being CEs only. Pin 11 is CE1 then, Pin 12 CE2 and soon.We have a couple of boards that get their power via the cable, so weincluded the +5V. If a board has it's own power supply then the pin is leftopen.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -