1
\$\begingroup\$

Let's say I want to drive a SPI peripheral using bit-banging with a ESP8266 module. So I have the datasheet for that peripheral telling me it has this setup time and that hold time etc. The question is, how do I know how much time (approximately even) passes between one line of code that pulls the MOSI HIGH for example until the next line pulling the SCK HIGH so I know if I need a delay between those lines and if so, for how long?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Let's discuss bit-bang, and only the SPI Master side (though the slave side is similar) and in C language.


The first simple approach,

Create functions that has critical timing area written in assembly language. Number of clock cycles taken for each instruction is usually in the datasheet with instruction set list. Perhaps Tensilica takes a single clock for most of the instructions.

How to do that without reading the 1,000 pages of a datasheet?:

  1. Write a simple bit-bang and for(;;) loop timing code in C, then compile and generate assembly list.
  2. Take the timing critical section from the generated assembly code list.
  3. Adjust the assembly code by adding NOP, JUMP, and etc, while looking at the instructions list.
  4. Embed the assembly code in a C function, and make it callable.

The second approach,

What helps us: SPI operation is synchronous to clock. Thus, all the timing is referenced to clock. Slave side waits for the Master operations and times operations to the clock (and strobe) signal from the master. SPI can specify setup and hold time, though no need to specify timeout.
So, we can do loose signalling, but cannot hurry and violate setup and hold time.

  1. Write a bit-bang code along with delay() (for() loop or call to a delay()) between one bang to another.
  2. Tune the delay() while monitoring the timing on the signal pins, just enough to avoid timing violation.

The third method:

You would still wish your SPI does not block other tasks, holding 100Mhz RISC processor for some mS, 1mS * 1000uS * 100Mhz = 100,000 instruction cycles.

  1. Create a timer ISR. The way how to use timer can go some distance, depending on your imagination, such as; variable timing, enable & disable.
  2. The ISR does bit-bang according to the "scheduled sequence" to generate SPI timing.
  3. Create a virtual registers set that simulates something similar to hardware SPI registers.
  4. Create a spool/FIFO in memory, and have the ISR pass data from/to the drivers via the spool/FIFO.

These methods can be combined, too. Not a trivial work for someone just starting. :-)

\$\endgroup\$
2
\$\begingroup\$

I can think of three options:

  1. Tear into the assembly code used to execute the function of pulling the MOSI pin high and count the clock cycles used to execute each line.

  2. Run the code on some of the header pins and probe them on an oscilloscope.

  3. Use a dedicated SPI interface so you don’t have to worry about it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.