I know TinyClr is not mature, but I’ve problem with SPI.
I want to code a driver for nRF8001 BLE module.
I need to share CS pin between SPI and Gpio. Is there a way to do that ?
In NETMF 4.3, when declaring SPI, in configuration GPIO_NONE can be passed:
_rst = new OutputPort(rstPin, true);
_req = new OutputPort(reqPin, true);
_rdy = new InterruptPort(rdyPin, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
_spi = new SPI(new SPI.Configuration(Cpu.Pin.GPIO_NONE, false, 0, 0, false, true, 100, spiModule));
@ Bauland - Interesting, can you provide a schematic that shows the shared SPI chip select and GPIO. I know your question is about TinyClr not been able to share the these signals. But I want to understand the hardware case for the designing a module where there is a possibility of side-effects.
Here some extract:
However, nRF8001 does not behave as a pure SPI slave device; nRF8001 can receive new data over-theair
at any time or be busy processing a connection event or new data. Consequently, the traditional CSN
signal used to initiate an SPI transaction is replaced by two active low hand-shake signals; RDYN and
REQN.
These hand shake signals allow nRF8001 to notify the application controller when it has received new data
over-the-air and also to hold new data exchanges initiated by the application controller until it is ready to
accept and process them. The ACI connections are shown in Figure 7.
@ Bauland - After looking at the datasheet for the nRF8001, their use of the “chip select” does have a dual purpose which is a request a transaction and wait for the “RDYN” from the nRF8001 to indicate it is ready for a SPI transfer to begin. This is not a typical SPI bus transaction, hence your request to share a GPIO line with the SPI chip select seemed odd to me.
In looking at the Trr timing (page 26) there is no max. time giving to wait to the “RDYN” signal to indicate that the nRF8001 is ready. Note 1, does say this will take up to the time of a “radio event” plus the typical response time. I could not find any timing for “radio event” so this maximum time to wait is unknown to me. It may exist in the Bluetooth protocol how ever.
I was going to suggest that .NETMF typically sets the SPI chip select active well in advance of the data transfer, but with out knowing what the maximum time to expect before the nRF8001 will respond with “RDYN” this would not be reliable.
The one solution I can see is to build you own SPI bus protocol in software accounting for the “RDYN” pin. Yes would be quite slow.
Another solution would be to select an unused GPIO pin for the nRF8001 chip select line in the SPI.Confifguration (or possibly your code of GPIO_NONE may work), the before starting a SPI bus transaction, have a software bring “REQN” active (low) and then have the software poll for the “RDYN” signal to go active (low) then call the _spi.WriteRead method. There would be some extra delay, as the .NETMF time to assert the fake chip select is kind of wasted, but likely faster then the software SPI solution.
Good luck
Phil
P.S. This was kind of inline with my original post concerns that the SPI chip select can cause the SPI device to change state, at least the vendor described the behavior in your case.
The unused chip select pin declared in the SPI.Configuration statement, in the second solution does not connect to any other device. The software controlled “REQN” signal connects to the nRF8001 chip select. The “REQN” signal request the start of a SPI transaction, the software must then wait for the “RDYN” pin to go active, the “REQN” is also held active (low) till after the WriteRead method returns when it is then returned to the inactive state (hi).
The “REQN” is an output from the .NETMF hardware and the “RDYN” is an input to the .NETMF hardware. It is the “RDYN” signal that causes the issue, as this signal is used to do flow control of the SPI bus transactions.
So if I understand, I must have a :
[ul]REQN signal as digital output signal,
RDY signal as input signal,
CS for SPI as an unused pin (just to let SPI think it is a true pin)
MOSI/MISO/CLK as usual SPI pin[/ul]
@ Bauland - Yes, that is correct hardware connections.
You may or may not be able to get away with the GPIO_NONE parameter in the SPI.Configuration statement.
I received my first event ! After some byte order problems, I can now implement these complete module.
Many thanks to PHITEK, John, and Brett for tips, advices …
If I can propose a functionnality for TinyClr is adding a paramter to specify in which order data are read (Msb or Lsb), it would be very nice. As a workaround, I added this extensions:
readBuffer)
{
spi.Read(readBuffer);
InvertBytes(readBuffer);
}
private static void InvertBytes(byte[] bytes)
{
// Iterate over all bytes
for (var i = 0; i < bytes.Length; i++)
{
if (bytes[i] == 0 || bytes[i] == 0xFF)
continue;
byte output = 0;
for (var j = 0; j < 8; j++)
{
output <<= 1;
output |= (byte)(bytes[i] & 0x01);
bytes[i] >>= 1;
}
bytes[i] = output;
}
}
@ Bauland - If you can find somewhere in the existing desktop/IoT UWP API where data order can be specified for SPI, we’d have an easier time implementing it.
A lookup table will probably be the fastest but has the biggest size.
Array stepping is the most understandable (maintainability), but is probably the slowest.
Lookup table seems to me a bad idea indeed for microcontroller.
Your idea seems fine. Only test can say what is best solution. I don’t know if I’ll have time to that.