SPI bus generic driver and ST L6480

More
07 Feb 2015 09:19 #55763 by yeltrow
I am building up a Shizuoka AN-S mill and I am going to try running the large stepper motors on it using L6480 eval boards from ST Micro. The boards provide a 25A capabile stepper controller good to 85V. They can autonomously generate pulses, run at a velocity, run to a position, and other cool stuff. BUT to talk to it I need a SPI driver. I intend to send commands over a few parallel port pins using the SPI protocol. I am planning to write a SPI driver and then a component that talks to the SPI driver to make the motors run. Do I need to write a SPI driver, or is one hiding out there that I have not found? If I write one, it could be used for all kinds of SPI parts like port expanders, displays, temperature sensors, and analog inputs.

The SPI BUS driver will have these pins:
TOSPYBUFF
TOSPYBUFFSP
FROMSPYBUFF
FROMSPYBUFFSP
BUFFLOCK
MOSI
MISO
CLOCK
CHIPSELECT

BUFFLOCK – PIN will be used to let the SPIBUS component know that it is being written to and that it cannot change the state of the buffers NOR the position of the stack pointers. The SPIBUS component will work off of a private copy of the buffers keeping track of how much data it has sent or received since the buffer was locked. After the lock is removed, it will update the buffers based on what transcribed since the lock was put in place. This is to prevent a race condition when SPIBUS is in the base thread and preempts the software talking to it. Before writing to the buffers or reading from them, BUFFLOCK should be and the other component should not change ANYTHING until the component is called again. Then it can modify the buffers, snapshot the FROMSPIBUFF/reste FROMSPIBUFFSP etc. After the modifications, BUFFLOCK can be set back to zero again releasing control of the buffers back to the SPIBUS component.

TOSPIBUFF – An array of unsigned [32]. Only 8 bits of the unsigned are used. Holds the bytes that will be sent to the SPI bus. The data in the buffer will be shifted down automatically as the SPIBUS component sends the data out. [0] is the oldest data, [31] will contain the newest.

TOSPIBUFFSP – unsigned bi-directional – Contains how many bytes of data are in the buffer. When 0, the buffer is empty. When at 31, it is full.

FROMSPIBUFF – An array of unsigned [32]. Only 8 bits of each unsigned are used. Holds the bytes that came from the SPI bus. The consumer of the data in the buffer is responsible for shifting the data in the buffer. The SPIBUS component puts the newest data at the highest slot in the buffer. [0] is the oldest data, [31] will contain the newest.

FROMSPIBUFFSP – unsigned bi-directional – Contains how many bytes of data are in the buffer. When 0, the buffer is empty. When at 31, it is full. It is the responsibility of the consumer of the data to update this stack pointer.

Important: before trying to read the data in the FROM buffers, use BUFFLOCK to freeze it. Wait a cycle. Read BUFFLOCK to make sure it is locked. Then modify the buffers to show you have read them and clear BUFFLOCK.

Master out, slave in (MOSI) is used for the SPI driver to send data to some physical pins. It should be connected to an output pin. It will be connected to the data input on the slave devices.

Master In Slave out (MISO) is used to read responses from the slaves. It must be an input pin. It will be connected to the slave data output.

CLOCK – This is connected to an output pin on your LinuxCNC box and will be connected to a clock input on your SPI bus parts.

CHIPSELECT – This line (usually active LOW) goes to a low or zero state to signal the chip connected to it that it is being talked to. This allows multiple chips to talk on the same SPI bus with only a single additional line for each. Four wires for one chip, Five for two, etc.

This is my beginning spec -- I am really wondering if the locking part is necessary, but it seems that SPIBUS could get data and try to modify the buffers before the component talking to it knows what happened. Design input is very welcome.
Attachments:

Please Log in or Create an account to join the conversation.

More
07 Feb 2015 12:27 #55766 by yeltrow
As I progress on the driver I am trying to figure out a way to make it as generic as possible. Some devices want CS to stay low between bytes, and others want it to toggle. For the first go I plan to have it go to an idle state each time the output buffer is allowed to empty. If one needs more clocks to get some response data, one can just pad with 0's and tell it those are valid data. As long as the other driver is also in the base thread, I think that could work. Another option I am considering is a parameter that tells it how many bits between cycling chipselect. That would allow the spi bus driver to click merrilly along with only periodic contact with the higher level threads when toggling cs is required every 8 or 16 bits... open to advice.

Please Log in or Create an account to join the conversation.

More
24 Feb 2015 11:52 - 28 Feb 2015 23:27 #56262 by yeltrow
I have some working code. They are both built as components. Attached are an example spi client that would talk to the spibus driver. I have included a hal script spitest.hal. To test I use:

sudo comp --install spibus.comp
sudo comp --install spiclient.comp
halrun -I spitest.hal
start

in another window I start halscope and attach traces to mosi clock chipselect etc and watch the pair of them make fancy lines.
** Why is my code not ready yet??? **
Because I haven't figured out how to use rtapi_mutex_try without crashing my machine. I commented it out in the section labeled crash. The odds are that a read and write may never happen between the time I check the flag and the time I write it, but whe you are talking to the motor drivers for a machine tool, you can't be too careful.

I welcome comments, corrections, suggestions.

-- EDIT 2015-02-28 -- I have removed the attachements below - Please see newer post for most recent progress of this driver.
Last edit: 28 Feb 2015 23:27 by yeltrow.

Please Log in or Create an account to join the conversation.

More
24 Feb 2015 17:37 #56266 by mhaberler
I think locking and preemption is a no-no in RT operations, you need to get by with atomic operations

this is why in the machinekit fork we introduced lockfree ringbuffers - to enable queued communications between any combination of RT and userland comps.

For a comp example, see the delayline component here: github.com/luminize/machinekit/compare/vel-extrusion-delayline

- Michael
The following user(s) said Thank You: yeltrow

Please Log in or Create an account to join the conversation.

More
26 Feb 2015 11:21 #56306 by yeltrow
Michael,
Thank you for the pointers. Thanks to yourself and others I am learning more every day. I am working through your examples. I can understand the lines of code, but it is taking me a while to put all the pieces together and understand how they work. It will take me a while to learn my way to an elegant and robust solution.

Best Regards,
Matt

Please Log in or Create an account to join the conversation.

More
28 Feb 2015 23:32 - 05 Mar 2015 12:20 #56359 by yeltrow
Current status for the spi driver, example component, and max7219ds driver.
5.5bytes/ms with 10us base period! I have a MAX7219DS driver chip with eight 7-seg LED's
working as a free running counter. It completes 100,000 display updates in about 5 minutes. That comes to 333Hz with 14 byte messages.

The max driver just counts up and pushes those numbers to the display. It doesn't support decimal points yet. I will probably add some stuff to it to make it possible to display a floating point number or an integer. There is a font library someone developed for it that could be implmented to display strings, which might be kind of fun. Because of some buffer pointer fencepost case, it currently is limited to 7 of the 8 digits because it loads the buffer with ALL of the digits data at the same time.

The spibus driver has a fixed number of bits between chip select raises, so that needs fixed. It won't be able to work with sharing the spibus amongst multiple chips without changing the message sizes, so that needs updated. I could implement some functions to add_two_bytes_to_buff and add_one_byte_to_buff with a slaveID number that gets set as a param at the beginning of the file. Multiple chip select lines are not implemented.

The buffers are still a mess. They are a pin per byte, which makes for a TON of pins. Ideally I would like to implement a shared memory space that publishes a pointer to it via a set of hal pins. That would make it possible to use HAL to wire the buffers together so that everyone can talk without having N pin tospibus + N pin fromspibus + N pin chipselect + N pin dropCs arrays (think 16 pins per each of these!).

The spiclient.comp driver needs guarded against sending out of range txBuffSp values. These can cause infinite loop lockups which need a reboot to fix. These guards need to be implmented
in the function call so someone writing a new spi driver doesn't have to write perfect code.

I have been kindly directed to the work machinekit has done with ring.h being used to communicated between components. I have written ring buffered serial drivers in the past and it seems like a good way to implement what I need to do. I have not yet tried to pull ring.h into my drivers to see if it causes the compiler to explode. I have not yet gone deep enough into ATP's implementations of his spi and smartserial drivers to figure out how to make calls to my driver with configuration strings like his. Both of those activities are planned.

--- 2015-03-04 -- Removed attachements -- see later posts for updated versions.
Last edit: 05 Mar 2015 12:20 by yeltrow.

Please Log in or Create an account to join the conversation.

More
03 Mar 2015 06:19 - 05 Mar 2015 12:19 #56416 by yeltrow
PLEASE: ANYONE who has the patience to educate me on a safer way to do what I am doing, please throw me a bone!

I got tired of the huge list of nets between my spibus driver and my spiclient, so I did something really gross and crazy and passed a pointer to the memory within spibus to spiclient over some unsigned int pins. COMP:
- Allocates the buffers and initializes them.
- publishes a pointer to them
- manages the information it gets from the buffers

SPIBUSCLIENT.COMP:
- Checks to see when the spibus has come up
- Receives the pointers to the buffers and checks to see that they are not null
- Generates the byte commands needed to run a chip
- Writes these directly into the hal memory allocated by the spibus.comp driver and pointed to by the pointers it has been given.

SPIVIEW.COMP:
- Can be passed the same pointer to the memory on the spibus via address-byte-low and address-byte-high.
- Exposes all the buffer slots and record keeping on pins so you can see what is going on.



THINGS THAT WILL CAUSE A KERNEL PANIC: can help educate
Passing some other goofy numbers in on the address_byte_low and address_byte_high pins.

Next to do:
- Find a "not crazy" way to pass the allocated memory handles to the spiclients (EXPORT KERNEL SYMBOLS?)
- Modify the proof of principle code to handle more than one client chip
- Modify the MAX7219DS LED driver I wrote to work with the new buffer architecture.
- Maybe test running parport.update method directly from within my driver to increase the bitrates?
Last edit: 05 Mar 2015 12:19 by yeltrow. Reason: REMOVED ATTACHMENTS, See later thread for updated versions

Please Log in or Create an account to join the conversation.

More
05 Mar 2015 12:19 - 14 Mar 2015 20:21 #56492 by yeltrow
spibus.comp Has been updated to serve up a spi connection to multiple chips
on the same bus. Each chip will connect to an address-high-x and address-low-x
where x is the chip to bus connection number. It matches the chipselect-x line. As
each chip's data buffer is emptied, the driver moves onto the next chip in
order (i.e. chip 0, up to 1, and so on up to chip 5). Timing depends on the
amount of data being sent by EVERYONE on the bus. If a chip has nothing in it's
buffer, it does take another cycle through to go on to the next chip, so one could
give up as many as 5 base thread cycles before data gets loaded again.

Address a reset bit to the MAX7219DS driver so the count can be reset to 0.
This was good for testing which display was really hooked to which chip
select line.

I learned that it is VERY important if the data structure is changed to
recompile and reinstall everything that uses the data structure or the
mapping in the compiled code will be wrong -- Duh!

I have updated maxtest.spi to show how two chips can be connected to the
one spibus driver.

Tonight I alternated hooking up the MAX7219DS 8 digit display I have between the chipselect
on pin 3 and 5 of the parallel port and used maxtest.hal to connect everything.
This showed I could drive the dispaly as the first or the 2nd display.

Next steps are to make the MAX7219DS driver a smidge more useful by
setting it up to dispaly fixed point numbers so it could act like a DRO. It might be
cool to find some code to teach it to write X, y, or Z on the the first digit (although
a sticker would be pretty good).
Last edit: 14 Mar 2015 20:21 by yeltrow. Reason: REMOVED ATTACHMENTS, See later thread for updated versions

Please Log in or Create an account to join the conversation.

More
08 Mar 2015 15:20 - 08 Mar 2015 15:21 #56544 by mariusl
Hi Yeltrow
I have been watching your thread from time to time as I have done some work on SPI as well. I want to give your stuff some testing but you refer to a component spiview that I did not see in the list of comps that you provided.

Regards
Marius


www.bluearccnc.com

Last edit: 08 Mar 2015 15:21 by mariusl.
The following user(s) said Thank You: yeltrow

Please Log in or Create an account to join the conversation.

More
09 Mar 2015 06:31 #56558 by yeltrow
i just posted spiview.comp. It will probably work just fine, but you can always skip it. Testing from halrun instead of a full session is highly recommended. Because I am passing pointers, there is a chance of kernel panics if it isn't setup properly.

Please Log in or Create an account to join the conversation.

Time to create page: 0.099 seconds
Powered by Kunena Forum