I am currently working on a project where I want to monitor the data between a SPI master and a slave and block some data.
More precisely, only certain commands on the path between slave and master, i.e. MISO, need to be blocked.
My idea is to monitor only the MISO line with an Arduino Uno or Nano, i.e. to buffer answers from the slave in the Arduino, to block certain data and to forward all further data to the master. An overview can be found in the appendix.
Now my questions:
Is my idea possible?
If my idea is possible, can you help me find an approach? I don't have a plan how to proceed.
If my idea is not possible, do you have any idea how I can do it differently/better?
wvmarle:
Why not simply ignore the commands you don't want to act upon in the server?
Unfortunately I have no access to the two SPI devices (Master and Slave). Therefore the Man in The middle approach with the Arduino.
The goal of the project is to build an access system for a fully automatic coffee machine. However, I don't want to touch the main board of the coffee machine, but I want to clamp myself with the Arduino between the control panel and the main board. So I can prevent the operation as long as there is no activation, still allow commands to clean the machine and determine which button was pressed to get the coffee.
You're definitely going to need two SPI buses on your Arduino, a regular Uno offers only one. You may be able to bitbang a second one but only if your bus clock speed is low enough.
You should also realise that you're going to severely slow down communication as you have to read the slave's response, wait until it's complete, then decide whether you're going to pass it on to master. How master is going to react to this delay is unpredictable.
This also means you have to connect the CLK to your MiM device, and do some trickery with the SS line.
Do read up a lot on the workings on the SPI bus so you have a better understanding on what you're trying to do.
Great to hear that somebody thinks it will be possible
You're definitely going to need two SPI buses on your Arduino, a regular Uno offers only one. You may be able to bitbang a second one but only if your bus clock speed is low enough.
What do you mean with „bitbang a Second one“?
This also means you have to connect the CLK to your MiM device, and do some trickery with the SS line.
The devices are not using the SS line...
Why do I need to connect the CLK? I just want to monitor the MISO and save, analyze and possibly block the transferred bytes. Do I need SPI ports on the Arduino at all?
JsonParser:
The devices are not using the SS line...
Are you sure it's SPI then? Or maybe it's just one device on the bus, then indeed it's not needed.
Why do I need to connect the CLK? I just want to monitor the MISO and save, analyze and possibly block the transferred bytes. Do I need SPI ports on the Arduino at all?
How do you plan on reading MISO without clock signal?
As said before: go and read up on how SPI works. Thoroughly. You obviously don't even know the basics.
There are only serial data on the MISO bus, which can probably be read with a digital.read(). I had hoped that someone had already gathered experience here and shared it with me.
I could also imagine to use SoftwareSPI and have to do some research.
What I need is a reasonable approach to solve my problem. Unfortunately I lack the experience here...
JsonParser:
There are only serial data on the MISO bus, which can probably be read with a digital.read(). I had hoped that someone had already gathered experience here and shared it with me.
You can read the MISO line with digital.read() but you cannot make sense of what your are reading without the CLK line. Somehow you seem to believe (or want to believe) you can do without it.
Until you understand that you need CLK, your chances of writing the program you want are not good.
srnet:
You can read the MISO line with digital.read() but you cannot make sense of what your are reading without the CLK line. Somehow you seem to believe (or want to believe) you can do without it.
Ok, if I need the CLK to understand the commands, what do I have to do?
Is there any way I can solve this on the software side? So a digital pin for MISO and one for the CLK, then the synchronization via software?
You need to get really creative with the SPI bus on the Arduino. MISO of your slave to your MOSI (as your Arduino acts as SPI slave!), MISO of your Arduino to the actual master's MISO, and CLK connected to all three devices.
You also have to connect the SS line to both your Arduino and the original slave (assuming it uses one), so you know the master is talking to you and/or expecting data from you.
Then have your Arduino read the commands that come in over your MOSI, and the moment you know what the command is (by reading one or more bytes - whatever amount you need to determine whether it's a command you want to pass on or not) you can start relaying the data to master by writing it back to MISO. Or not, of course.
That will of course also cause a delay in the transmission, which may or may not be a problem.
What I don't know is how the slave tells the master it starts its transmission... do look up the SPI specification on this... if master expects the data from slave to come in at the first clock tick, things will go wrong as you are delaying the transmission with your MiM.
I don't see this working. When the master sends a clock pulse to read data, it is expecting the slave to put the data bit on the line in only a few nanoseconds. It does this bit-by-bit and you can't read the whole byte and then make a decision on what to send. By that time, the master has already sent the 8 clock pulses and is not accepting any more bits.
You may be able to re-implement the slave in the Arduino. If the communication is predictable, you can get the answer from the slave before the master asks you for that data item.
The man in the middle approach will work only if the MITM accepts complete transmissions, interprets them and passes on only the desired transmissions, with separate buses for the two outer devices.
I also agree that a dual SPI should be your startpoint.
If you do attempt to build a SPI MITM then there are a number of things to consider that may affect the complexity / feasibility. Having access to a logic analyzer / oscilloscope / BusPirate can make debug much easier.
Please note that what you are describing could be a moderately involved project. You will definitely need to get familiar with the general SPI protocol and the specifics of the SPI data protocol implemented by your machine.
For the following I am assuming that the coffee machine main board is the SPI master attached to a single slave control panel, and will refer to the SPI transactions as logically separate write and read operations.
What does the physical signaling look like? Master’s clock rate, clock polarity, SPI transaction word sizes, how reads/writes/addresses/commands are indicated, etc.
What is the high level signaling mechanism between the main board and control panel? For example: Is the main board effectively issuing MOSI polling read transactions to a status register on the control panel which returns a key-pressed status flag? Upon a successful poll, does the master read a different address to fetch the last keypress(es)?
Does the control panel have any feedback / outputs, like a display? Do you expect the master may periodically issue other SPI write transactions to the panel (unrelated to the key entry)?
How are the SPI read transactions performed? Does the master expect the first bit of the addressed register on the SCLK edge following the last address/command bit? Or is there a command read-back phase first?
Is there a gap/mask in SCLK pulses during the turnaround from master read transaction and slave response? This strongly impacts the timing budget for your intermediate bridge device.
Depending on answers to the above, you should be able to get a much better idea of what effort may be involved.
If the communication patterns are simple enough, you might discover that you can emulate the control panel status collection/polling by your MITM SPI device, which latches the keypresses into its own register space. The main board SPI master can then query your MITM device. Essentially most of the MITM-controller communications are asynchronous to the main board-MITM communications.
By doing this, you may be able to alleviate some of the timing challenges associated with relaying “reads” across the SPI MITM device.
Finally, your MITM device would then easily be able to “block” or alter the return data/status from the slave (eg. To ignore a front-panel keypress on the controller board when you have wished to “block” it according to your access control).
TomGeorge:
Hi,
What are the two devices?
Master?
Slave?
Can you post links to spec/data of them please.
Why do you need to block commands from the master to the slave?
We need better information to give you decent solutions.
Thanks.. Tom..
Since the question has come up again here, I describe the project again briefly. The basic goal is already in the posts #1 and #2.
The goal of the project is to build an access system for a fully automatic coffee machine. However, I don't want to touch the main board of the coffee machine, but I want to clamp myself with the Arduino between the control panel and the main board. So I can prevent the operation as long as there is no activation, still allow commands to clean the machine and determine which button was pressed to get the coffee.
I have a logic analyzer from Saleae and next week (probably Wednesday) I will read the communication between the two devices and post screenshots here. Many thanks for the discussion and support.
With the help of the Saleae logic analyzer I was able to find out the following:
the transfer rate is 500.000 baud
The communication starts with the rising edge of the clock.
The display is the slave and the motherboard is the master.
MSB first
The master permanently asks the slave with two different commands if it is still there and the slave responds accordingly. There are two possible standard answers which can be assigned exactly to the commands of the master.
The questions and answer pairs are as follows:
Case 1:
MOSI: '22' MOSI: '22' MOSI: '16' MOSI: '2' MOSI: O
MOSI: any data
MOSI: any data
MOSI: any data
MOSI: any data
MOSI: any data
MOSI: any data MOSI: '16' MOSI: '3'
I now have the following approach to reach my goal and a few more questions:)
As Impulsive suggested, the Arduino simulates the display and answers the master as long as there is no activation (via RFID). The MISO line between motherboard and display is separated by a transistor which is used as a switch. So the keys on the display don't work anymore but the motherboard is still happy.
As soon as the activation is done, the Arduino no longer simulates the display and the transistor is switched through, so that the motherboard and the display are again connected via MISO. So the keys on the display work again.
JsonParser:
As Impulsive suggested, the Arduino simulates the display and answers the master as long as there is no activation (via RFID). The MISO line between motherboard and display is separated by a transistor which is used as a switch. So the keys on the display don't work anymore but the motherboard is still happy.
Sounds feasible
Note that you'll have to use a MOSFET for this, not a BJT. This as a MOSFET will conduct in both directions, which is needed for being able to drive the line high/low (SPI is push/pull). With a BJT you can go only one way.
How can the ARDUINO become a SPI slave with a transmission rate of 500000 baud?
How can the ARDUINO react to the commands of the MASTER with the "alive" response? How to program this/approach to program this?
This is asking for a lmgtfy link. I'm too lazy for even that. 500 kHz is no problem for an Arduino, just make sure you use the hardware SPI. It supports frequencies up to clk/2 (i.e. 8 MHz for a 16 MHz processor clock).
Which transistor is the right one?
How to connect the transistor correctly?
Not sure if a basic transistor can work for this. I think you need a tri-state non-inverting buffer for this, such as the 74HC125 or 74HC126. Then for good measure you can also switch CLK and MOSI.
Be sure to set your Arduino's MISO to INPUT (or put it through the fourth buffer if the SPI library doesn't let you do this easily - the parts I mentioned are quad buffers) or it will interfere with the MISO of the display. MOSI and CLK should be INPUT already, so you should be able to eavesdrop on them without disrupting communication, so you can see what's going on.
Is an ARDUINO Uno sufficient for these purposes?
Yes.
But for final installation you'll want a Nano or Pro Mini. Much easier to properly solder onto a PCB or piece of perfboard/stripboard.
wvmarle:
Be sure to set your Arduino's MISO to INPUT (or put it through the fourth buffer if the SPI library doesn't let you do this easily - the parts I mentioned are quad buffers) or it will interfere with the MISO of the display. MOSI and CLK should be INPUT already, so you should be able to eavesdrop on them without disrupting communication, so you can see what's going on.
I don't understand what you're saying. Which of my questions are you answering?
First of all, it is most important for me to know how to make an Arduino the SPI slave and whenever the byte sequence comes from the master (as described in post #17) I send the "Alive" response.
Does anyone have a code example for me that I can use as a guide?