For the impatient, you can skip the background.
I'm programming a set of microcontrollers that communicate with SPI. There's one master and
n slaves that share the bus. There's no chip select. (It's not a bad design, but
n is large and there's not enough space for
n extra lines).
It's therefore the responsibility of the slaves to keep their MISO in high impedance and at most one of them speak. This is done by responding only when their id is polled.
Now we'd like to have an initial discovery phase where the master discovers slaves with what ids are attached to it. To make life easier (on some aspects), we'd like to have the id unique (and therefore e.g. 32 bits). This makes it impossible for the master to simply poll ids one by one and see who responds (there are too many possibilities).
To solve this problem, I devised a variation of binary search where the slaves collectively respond and the master is able to quickly find the minimum id. The slave with that id is told to not participate anymore and the algorithm repeats. (Details unimportant).
There's one problem though. The collective response needs to be the logical OR (or logical AND) of all the responses. I've been told that the line can be configured in such a way that the MISO bus can act as a logical OR. What I've been told is:
- Set MISO on master as Pull-up and
- Set MISO on every slave as Open-drain.
I've tried this, but with even a single slave, this configuration doesn't work (the oscilloscope shows a constant zero on the line). If I configure MISO on the master as high-impedance input, I can see with the oscilloscope that the voltage drops to half where the bits of the outputs from two slaves differ (basically short-circuit I presume).
Note: configuring MISO on master as high-impedance and slaves each as push-pull, I can talk to each of them individually even if there are many of them on the same bus. I mean, I doubt it's a problem of the line itself.
My question is, if this is at all possible, and if so, how can I configure the input and output pins of the master and the slaves so that the shared MISO line would act as logical OR (or logical AND)?
Turned out it becomes an OR with negative-true logic (basically an AND).
The problem with single slave was resolved with writing 1 to the pull-up pin on the master. Previously it had an initial state of 0.
Turned out the ST slave overrides my GPIO configuration of MISO as open-drain and was forcing it high when one was written. I resolved to silencing SPI and outputting MISO in this particular case manually.
Your SPI-without-select is what Microchip uses on their MCP23017 chips (and others). Nothing wrong with that approach.
Yes, what you want is possible, but you must get the slaves to be open-drain. You could cheat by putting a (schottky) diode in series with each output if you can't get them to behave as open-drain.
Your enumeration approach is the same as used by the Dallas one-wire bus for enumereation, and by the CAN bus for arbitration.
But a serious drawback of your approach is that the speed is now limited by the rise time, driven by the pull-up resistor. This will be slower than when driven by a push-pull output, and will likely limit the speed at which you can operate the bus.
If you have two pins to spare on each slave you could daisy-chain them, and have an enumeration scheme based on their place in the daisy chain.