I’m trying to interface to a device which uses 2 wire SPI (well 3 is you include Chip Select).
(I’m using SPI slave, but I think the overall implementation is basically the same regardless of master or slave mode0
In this configuration, the MISO and MOSI lines are combined, into a single data line.
Currently the SPI library doesn’t support this, but the STM32F1 (and F4) do support this mode.
However, looking in the library and the underlying code in the core, I can’t see a way to use (2 wire) bi-direction SPI, at the sketch level, without setting up the while of the SPI at register level.
As far as I can tell, to enable Bi-Directional mode an additional bit needs to be set in SPI CR1
https://github.com/rogerclarkmelbourne/ … /spi.h#L87
However this is no way to pass this “bit” into any of the upper level calls
I initially thought that I could merge this bit / flag into the MODE
e.g.
SPI_MODE3 | SPI_CR1_BIDIMOD
[RogerClark – Sun Dec 09, 2018 6:04 am] –
…
If anyone has a view on this, I’d be interested to get some feedback .Thanks
Roger
Would you consider this “mode” a generally useful implementation for SPI? Consider that this is the first I have heard for this need in all of the years of LeafLabs’ and all the added years of STM32duino.
I am generally opposed to mucking new functionality into existing behavior; more so since you have previously indicated a desire to achieve the existing core. My recommendation is to create new functions (for your use), document in the WiKi why and how it is implemented, and to leave the core implementation untouched. I have not looked at the SPI class implementation in years, but can you not inherit and adjust the behavior inside your own code?
There is always the one-off need but core enhancements of basic SPI at this stage in the life cycle just seems dangerous.
Ray
I am not sure how many devices use the 2 Wire SPI protocol.
I do some across it from time to time, but it’s not used by any of the mainstream modules targeted at Arduino and hobbies users.
I don’t think this mode is implemented for the Official STM core, since it isn’t part of the Arduino API.
But , I’ve not looked at the structure of the Official STM core in terms of the SPI library, and the underlying SPI code in the core, to see if it would be easier to write a sketch to operate in this mode, using that core.
So no matter which core I use, I either need to modify the core, or replicate portions of the core and SPI library into the sketch.
The easiest option is probably to have my own personal branch of the repo, so I can modify that, and leave the master version alone.
[RogerClark – Sun Dec 09, 2018 8:10 pm] –
…
I do come across it from time to time, but it’s not used by any of the mainstream modules targeted at Arduino and hobbies users.
…
The easiest option is probably to have my own personal branch of the repo, so I can modify that, and leave the master version alone.
Well, that is my thinking. Steve has his own source tree as do others for that same specific reason: personal need. SPI/I2C is already a priority topic for new users, anything but a break-fix is just going to generate forum noise on when/why/how.
I still favor class inheritance and extension; there should be no performance penalty even IF you use SPI “as-is” and SPI-enhanced… there will be a small amount of SRAM allocated as pointers to the virtual functions, but it is almost a non-issue. The compiler does the work and resolves calls between virtual and non-virtual calls at compile time.
Ray
SPI.beginTransactionSlave(SPISettings(20000, MSBFIRST , SPI_MODE3 | SPI_CR1_BIDIMODE, DATA_SIZE_8BIT));I like your solution.
Some more changes would be needed, because datamode is uint8_t
https://github.com/rogerclarkmelbourne/ … SPI.h#L147
and all the constructors
https://github.com/rogerclarkmelbourne/ … SPI.h#L118
I did try changing datamode to unit32_t but found that the mode was an enum when its passed deeper into the core.
But moving the flag bit from the datamode to the flags in BeginSlave would resolve this, as flags is 32 bit.
I’d probably need to make the same change to Begin() as to BeginSlave
Ray.
Steve’s solution does add 2 lines of code, but since BeginTransaction or Begin is not called that frequently it would not cause a performance hit
Changing datamode from uint8_t to unit32_t would probably make no difference to either RAM use or performance in general, because the compiler seems to favor promoting most data types to 32 bits for most operation, probably since its faster
One way to extend and not impact Begin and BeinTransction, either add new functions e.g. BeginBirdirectional etc or to overload the constructor.
However in this case, if Steve’s solution works, the changes are fairly minimal and perhaps would not be too much of a risk to include into the existing functions
I’ll need to do some testing.
I also have a few more things to work out…
In Bidirectional mode, SPI.transfer can’t be used / would not work. Only SPI.read and SPI.write can be used.
I would not modify these functions to set / clear the Direction flag, as that would cause a bit hit on performance.
I’ll need a separate function to set Tx Mode and Rx Mode, since the spec seems to say that SPI must be disabled and re-enabled when the direction is changed.
I’ll take a look at it this evening, as it must be better than bit banging
BTW.
I did try connecting MISO and MOSI together and then setting PA6 (the output in this case), to pinMode INPUT when I want to receive data.
However, something very odd happens when I re-enable PA6 even if I re-init SPI.
Which is a shame, as setting PA6 to input does stop it outputting when I don’t want it to.
For dataMode 16 bit would actually suffice because SPI_CR1_BIDIMODE_BIT is 15 only. 32 bit resolution is of course future-safe.
I think the changes can be classified as low risk.
However, me I never used this mode, and I have no application/hardware on which to test it.
[stevestrong – Sun Dec 09, 2018 11:28 pm] –
…
However, me I never used this mode, and I have no application/hardware on which to test it.
Yes, same here.
I once preached to my team that there is no such thing as a low-risk change; all changes must walk the same validation road to production.
I’m still in favor of creating a sub-master branch on github.com to encapsulate Roger’s specific need(s.)
[RogerClark – Sun Dec 09, 2018 11:21 pm] –
…
BTW.I did try connecting MISO and MOSI together and then setting PA6 (the output in this case), to pinMode INPUT when I want to receive data.
However, something very odd happens when I re-enable PA6 even if I re-init SPI.
Which is a shame, as setting PA6 to input does stop it outputting when I don’t want it to.
So, maybe this is an area that Mr. Pillon should comment upon?
… after all, it is addressed in the reference manual and his team may elect to incorporate the mode in the official core.
Ray
[mrburnette – Mon Dec 10, 2018 1:04 am] –[RogerClark – Sun Dec 09, 2018 11:21 pm] –
…
BTW.I did try connecting MISO and MOSI together and then setting PA6 (the output in this case), to pinMode INPUT when I want to receive data.
However, something very odd happens when I re-enable PA6 even if I re-init SPI.
Which is a shame, as setting PA6 to input does stop it outputting when I don’t want it to.So, maybe this is an area that Mr. Pillon should comment upon?
… after all, it is addressed in the reference manual and his team may elect to incorporate the mode in the official core.Ray
I think I’ll need to build a standalone test for this, as the behavior of the SPI system seems to be very odd when I connect MISO and MISO together, when SPI is in Slave mode and is being sent an external clock.
Of course it could be the interaction with the rest of the system which is causing this, because the SPI master is still sending data onto its MOSI, its just that the STM is simultaneously putting different data onto PA6 (its MISO).
Luckily the target hardware has resistors in series with the SPI data lines, which allow the signals from SPI master to be overridden.
I think I”m going to give up on this, and just use bit-banging, since the data rate is so slow (19kHz)
I did implement the BiDirectional functionality using Steve’s method, but I got the same sort of strange results as when I tried connecting MISO and MOSI together externally (via a 10 k resistor)
I’ll need to read the errata for the STM32, because I’m using SPI mode3 in Slave mode, and I’m getting glitches in some cases, (very small pulses on the data line), rather than the data I requested.
If I change the mode, I can get the first byte that I want to send, reading the correct value on my logic analyser, but the next byte is wrong.
So I’ll abandon using the SPI hardware for sending the data, as its not worth spending any more time on it, since the end result may be useless as well, as currently the UHF radio I’m trying to modify, is not outputting audio which my PC decoder software can read – so there may be something else which make it impossible to use this FM analog radio with digital radio modes (4 FSK)
I think there may be some bugs with the SPI slave implementation.
Using SPI MODE 3, I’m seeing strange spikes / glitches on MISO, when I should see pulses as long as the clock signal.
Strangely, sometimes it seems to work and sometimes it doesn’t ![]()
I’m probably going to have to build a test rig to isolate whether the problem is being caused by the “Master” that I’m connecting to, or some problem with the Slave setup.
The SPI clock speed which the Master is sending is very slow 19kHz, but I presumed that it wouldn’t make any difference, since the STM32 must be using the incoming clock to read in each “bit” on one edge of the clock, and would need to put the data onto the bus onto the opposite edge of the clock pulse.


