This framework proved to be largely unworkable. An alternative approach has been implemented which will appear in 2.6
because of the sequence in which various parts of LinuxCNC (and especially Hostmot2) load, and the complexity of the SPI protocol, it was decided to allow a sub-driver written in comp?
to fetch a pointer to a BSPI module, and interact with it directly rather than through an unmanageable number of HAL pins.
Hostmot2 SPI Sub-Driver Framework
This page is a place to organize the development of a SPI sub-driver for the Hostmot2 driver.
SPI (Serial Peripheral Interface) is a serial bus that the hostmot2 firmware supports. The SPI bus can be used to extend the features of the MESA anything io cards. Specifically, SPI can be used to add analog to digital converters, digital to analog converters, and addition GPIO to the rich feature set already available with hostmot2. Currently (LinuxCNC 2.2.8) SPI communications is not supported by the LinuxCNC hostmot2 driver. This page is to be used to organize the development of an SPI sub-driver for hostmot2.
SPI Loadrt Config Parameter
A large part of the task of developing a SPI sub-driver is specifying how the driver will interact with LinuxCNC through the HAL, and the slave devices through the FPGA. The first thing to decide is how to tell hostmot2 what SPI channels are to be used, and how many frames to setup on each channel. Anyhow the loadrt config parameter should look like this:
The firmware is capable of setting up four SPI channels, each of the integers following SPIFrames specifies how many frames to setup on each channel. If -1 is specified then that SPI channel will not be setup. SPICD specify the number of channel descriptors to allocate for each channel.
SPI HAL Pins
Each channel that is setup will have N number of frames. Each frame will have 4 pin exported to the HAL. The hiearchy of the device will look somthing like this:
Or another way to look at it:
hm2_####.<Instance>.SPI.<SPI Channel Index>.Frame.<Frame Index>.<Frame Parameter>
hm2_####.<Instance>.SPI.<SPI Channel Index>.CD.<Channel Descriptor Index>.<u32 Channel Descriptor>
CD_VAL is the Channel Descriptor- This is a U32 HAL pin that specifies the the SPI settings for the hostmot2 firmware. Details of the channel descriptor are found in the regmap for the firmware. Those interested in writing device specific drivers will need to be familiar with the details of the channel descriptor.
CD_INDEX specifies what channel descriptor to use to transmit(and receive) data for the given frame.
SEND is a U32 HAL pin that is sent to the transmit FIFO on the board. The channel descriptor tells the firmware how many bits to send from the SEND u32. All data is right justified.
RECEIVE is a U32 HAL pin that exposes the return bits from the receive FIFO. Again, the data is right justified. No data is received if bit 31 of the selected channel descriptor is set.
READ is a BIT HAL pin. Is the READ bit is set, then the frame will be process in the hostmot2 read function at the beginning of the thread. If the bit is cleared then the frame will be processed in the hostmot2 write function at the end of the thread. This bit should be set if the frame receives data from the SPI device (Like a ADC), and should be cleared is changing the state of the SPI device (like a PWM).
The SPI Sub-Driver needs to transmit and receive data in the following order:
- Sometime during the firmware setup send the "CD" data to each of the SPI Channels
- Hostmot2 read function:
- Write "SEND" data, only SPI frames with the "READ" bit set, to the SPI transmit FIFO's (Phase A)
- Process the read_tram
- Read "RECEIVE" data, only SPI frames with the "READ" bit set, from the SPI receive FIFO's (Phase B)
- Hostmot2 write function:
- Write "SEND" data, only SPI frames with the "READ" bit cleared, to the SPI transmit FIFO's (Phase C)
- Write the Tram
- (At this point I don't think this is needed)Read "RECEIVE" data, only SPI frames with the "READ" bit cleared, from the SPI receive FIFO's (Phase D)
Device Specific Drivers
A driver could then be made for each device. There isn't really anything to difficult to do here. I believe that a simple realtime component could be written for any new device. Then the HAL pins connected and the interface should be very flexible. The device drivers should even be able to send initialization data to devices without any special features from the HM2 driver.
Code TODO list
I looked through all the code for Hostmot2 and I think that these are all the things that need to be modified:
- define HM2_GTAG_SPI (make- cake walk)
- SPI Section (make- easy once defined)
- Hm2_spi_instance_t structure
- hostmot2_t (modify- easy once defined)
- Declare SPI functions (add- easy once defined, don't really know what they will be yet)
- hm2_SPI_phase_D (may not need this one)
- Hm2_read (modify- fairly easy)
- Hm2_write (modify- fairly easy)
- Hm2_get_general_function_name (modify- easy)
- hm2_parse_config_string (modify- not trivial)
- hm2_parse_module_descriptors (modify- easy)
- hm2_cleanup (modify- easy)
- hm2_print_modules (modify- easy)
- hm2_register (modify- looks hard…)
- hm2_force_write (modify- easy)
- hm2_get_pin_secondary_name (modify- pretty easy)
- hm2_configure_pins (modify- easy)
The next list is what needs to be written. The bulk of the work needs to happen here. The exact functions that will be created are still to be determined. This will depend on how the READ WRITE problem above will be solved.
- SPI.c (I don't really know what all will be in here quite yet)
- hm2_SPI_phase_D (may not need this one)
- Phase A and Phase B together complete a SPI read communication.
- Phase A is placed in the hm2_read function before the tram read. This function send the SPI frames to the FPGA send buffer.
- Phase B is placed in the hm2_read function after the tram read. This function reads the SPI frames from receive buffer from the FPGA.
- Phase C and Phase D together complete a SPI write communication.
- Phase C is placed in the hm2_write function before the tram write. This function send the write SPI frames to the FPGA send buffer
- Phase D is placed in the hm2_write function after the tram write. This function reads the write SPI frames receive buffer from the FPGA. Not likely to ever use this phase, it might be good to include this phase to be complete.