2nd SPI Interface on Teensy?

Status
Not open for further replies.

syso2342

Well-known member
Is the 2nd SPI Interface also accessible with the Teensy SPI Library when using the 1st
SPI Interface?

Also: Is it possible to use the UART in SPI Mode (asynchronous mode) as in the atmega168/328
to have more SPI ports available?
 
also... is there a chip we can purchase which adds SPI ports? Lots of SPI port expander chips - to add UARTs and GPIO but I didn't find a chip to merely add more SPI ports.

The need I have is that when the SPI port is in use for a many-millisecond transfer, as in Ethernet interfaces and SPI / SD cards, a different SPI device with perishable data cannot wait 10's or 100's of mSec to get use of the SPI port. Examples: REal time data acquisition; fast displays; Communications receiver gets a message, requests an interrupt and needs the ISR to run very soon since another message may arrive soon after the one just received, and there's no hardware FIFO for more than one pending received packet. This SPI transactions library cannot eliminate this problem if some program "owns" the SPI port for a long time, e.g., an SD card read.

Ideally, the MCU would have 3 or so SPI ports. A software SPI could be done for some devices but that is a bit CPU hoggy too. Lacking hardware ports, maybe the way to let the communications radios with small packet sizes (say, 75 bytes worst case) is with a software SPI lacking more hardware SPIs.
 
Last edited:
Steve,

I've got the same problem. Need to log data through I2C with about 1KHz and write it out to radio and SD simultaneously. Furthermore, I need to record timestamps when the data becomes available with microsecond precision (actually, microsecond accuracy!). So, I ended up with interrupt-generated timestamps and a queue scheduler for I2C and SPI. I2C queue handling is done in interrupts and SPI transfers are handled through DMA. Everything else goes through loop()-functions, no RTOS involved (so far), as this project is directed towards students.

In order to avoid lengthy write calls to Bill's FANTASTIC SdFat libraries, I create a new file with file.createContiguous(), so that on further calls, I only need to write a data block, without any risk to have to wait for FAT operations.

Effectively, my loop() function runs without any blocking. I measure loop execution time and output some statistics on that: Average 20 us, max 45 us.

Usage on the SPI bus (Radio + SD card) definitely is low and certainly would support more devices. One of the key elements was Christoph's DMASpi library (see https://github.com/crteensy/DmaSpi), that removes all blocking from SPI operations and frees the CPU for more important things. On the backside, I had to adapt the RF24 library as well as SdFat, quite a bit of work.
 
can the SD card code do something to start a command to the card, but take slave select false and let some other SPI device use the chip if the SD card is going to do nothing for 100's of mSec?

With the RFM69 and other radios that interrupt, you know the issue. The CPU can't mask and delay taking the interrupt more than about 5mSec because another frame may come in. The SPI Transactions approach would let the SD card driver hog the SPI port for a long time, and real time communications and SPI based data acquisition will fail. So either another SPI port can be had, or software SPI could be used to synthesize another port for devices with low volume data.

I'm doing SPI to both the radio and the SPI Flash chip (not an SD card). The RFM modules rely on use of an interrupt to notify received message or transmit complete. The received message interrupt is the issue as if the to take that interrupt is 10's of mSec, as would be if a busy SPO-flash/SD card driver masked interrupts from all or one SPI device.

I simply ensure the radio is in the idle state before using the SPI port for other devices. This means waiting for any on-going transmission to finish, the idle the radio so it will not receive and will not interrupt. When the port is no longer in use, I reenable the receiver. On occasion, I'll miss an incoming message. But I use reliable datagrams that retransmit if no ACK is received. Not desired but with just one SPI port that's the best that can be done.

The worst case is receiving a packet, getting an interrupt for that, then not sending the ACK for that received packet promptly enough. The ACK timeout can be lengthened but that hurts throughput when the packet error rate is higher than normal due to RF conditions (retransmissions are delayed).

All this is a mess due to SPI port sharing where some devices have perishable data.

DMA SPI would have the same problem with port sharing as having the CPU drive the SPI port. Worse complexity, I'd say, for things like communications and sensors where the data can come at any time, and sharing the DMA controlled SPI port with an ISR is the same problem again, but worse.
 
Last edited:
Is the 2nd SPI Interface also accessible with the Teensy SPI Library when using the 1st
SPI Interface?

It's never really accessible, unless you have some very special application which doesn't need the SCLK signal, because Freescale didn't provide any pin on the 64 pin package for that signal. Only the main SPI port has all its signals available on real pin.
 
Yes, right now the SD library is hogging the SPI bus while the SD card is busy. It really needs to deassert the chip select and call SPI.endTransaction(), and try again, while waiting.

Fixing this is high on my priority list. Of course, patches or pull requests are welcome, if anyone wants to work on this before I do.
 
Why does the SD card do that? I've not written code for one. But the Spansion SPI flash chips (really cheap) have no long delays and they can be clocked at 108MHz on 1 to 4 concurrent SPI channels. Perhaps 4 SPIs at once goes to another MCU and that manages the streams and creates one USB3 rate stream (in a thumb drive).
 
All SD cards have access latency.

The SD library only recently got SPI transaction support. My initial attempt merely starts and stops a transaction when the library begins and ends its use of the card. This code needs to be improved, so the transaction is briefly ended while waiting and restarted to poll.

It's purely a software issue, which I intend to fix soon. Well, unless someone else beats me to it....
 
It's never really accessible, unless you have some very special application which doesn't need the SCLK signal, because Freescale didn't provide any pin on the 64 pin package for that signal. Only the main SPI port has all its signals available on real pin.

I hope that the MCU and package for Teensy++ 3.1 does not suffer that limitation.
 
I'd love to see a $0.50 SMD on a new Teensy, at say, 16 or 32MB or even $1 for a 128MB. Seems to me that the endurance is good enough for the vast majority of use cases, assuming program is reasonable about the write frequency. It could eliminate the need for the larger and more costly and slower SD cards for many or most applications that don't really need GB of storage. Such as
http://www.spansion.com/Products/memory/Serial-Flash/Pages/Spansion FL.aspx#
One of the MCU boards I've used has a S25FL127S chip on it. Very handy. 64KB sectors x 255 plus 4KB sectors x 16.
 
Last edited:
It's never really accessible, unless you have some very special application which doesn't need the SCLK signal, because Freescale didn't provide any pin on the 64 pin package for that signal. Only the main SPI port has all its signals available on real pin.


I've been reading this in my forum search, and it's really what I need for my application. I have just one SCLK signal, and two incoming signals. So how can I used the two spi ports this way?
 
I've been reading this in my forum search, and it's really what I need for my application. I have just one SCLK signal, and two incoming signals. So how can I used the two spi ports this way?
I think you can't use the SPI in this way because the two individual clocks are, well, individual. The second SPI will only latch incoming data on the edge configured by the SPI mode, but not synchronized with another hardware SPI. I think the only application where the second SPI is useful is when you want to generate a clockless output.
 
I think you can't use the SPI in this way because the two individual clocks are, well, individual. The second SPI will only latch incoming data on the edge configured by the SPI mode, but not synchronized with another hardware SPI. I think the only application where the second SPI is useful is when you want to generate a clockless output.

Mmmh, I see. So, I understand from your answer that, although the two bit signal I need to read (one bit each wire, so two wires) are synchronized with its clock signal (the one I'm connecting to SCLK), I won't be able to read the two bits at the same time, right?
 
It's unlikely that unless your chip is built to allow two SPI signals to fill a buffer, etc - the way the UART/Serial channels are - that such independent reads would be possible on a teensy chip.

FWIW, Bill Greimann has developed a bit-bang SoftSPI library that works. So two separate SPI channels on one teensy are possible, though one channel will be slower and simultaneous operation impossible.

I'd wager that a parallax architecture chip might be a better fit for independent, simultaneous operation since that system features multiple independent cores that can be dedicated to particular tasks. Thus a core could take over managing one SPI channel and another core could deal with the other channel. However, I've never worked with parallax, so I can't speak to specifics.

What you could do in the teensy space is use two CPUs that communicate with each other via I2C, for example. They could receive and process the SPI data, then exchange the end results and decide what to do. Or, you compromise and figure out how to let two devices coexist on the SPI bus.
 
Last edited:
Mmmh, I see. So, I understand from your answer that, although the two bit signal I need to read (one bit each wire, so two wires) are synchronized with its clock signal (the one I'm connecting to SCLK), I won't be able to read the two bits at the same time, right?

Yes, you can't read them both without any other effort hardware- and siftware-wise. It might be possible with some external logic, but I have no working example for something like that.
 
It's unlikely that unless your chip is built to allow two SPI signals to fill a buffer, etc - the way the UART/Serial channels are - that such independent reads would be possible on a teensy chip.

FWIW, Bill Greimann has developed a bit-bang SoftSPI library that works. So two separate SPI channels on one teensy are possible, though one channel will be slower and simultaneous operation impossible.

I'd wager that a parallax architecture chip might be a better fit for independent, simultaneous operation since that system features multiple independent cores that can be dedicated to particular tasks. Thus a core could take over managing one SPI channel and another core could deal with the other channel. However, I've never worked with parallax, so I can't speak to specifics.

What you could do in the teensy space is use two CPUs that communicate with each other via I2C, for example. They could receive and process the SPI data, then exchange the end results and decide what to do. Or, you compromise and figure out how to let two devices coexist on the SPI bus.

Thank you for the information! I know the same application I intend has been done with an xmega, but it has two spi ports, so it's easier to do. I've also read about that softspi, the problem then is speed, because my SCLK is 4 MHz and I think that using two softspi (one of the ways I thought) would be too slow. I will think another aproach.


Yes, you can't read them both without any other effort hardware- and siftware-wise. It might be possible with some external logic, but I have no working example for something like that.

Thanks for the clarification. I also thought of using some logic, some kind of SPI multiplexer or another IC that I could interface with the chip signals. I will see.

Thank you all :D!
 
Last edited:
Thank you for the information! I know the same application I intend has been done with an xmega, but it has two spi ports, so it's easier to do. I've also read about that softspi, the problem then is speed, because my SCLK is 4 MHz and I think that using two softspi (one of the ways I thought) would be too slow. I will think another aproach.
From your question I had the impression that you want to read data from two devices at the same time. However, I doubt that the xmega has a feature that synchronizes two SPI masters on a bit timing level. So, what do you really need? If it's OK for you (and the devices and their purpose) to
  1. Select Device A
  2. Read data from A at any speed supported by the device and the Teensy's hardware SPI
  3. Deselect Device A
  4. Select device B
  5. Read data from B
  6. Deselect B
then you can of course do that by correctly asserting and deasserting the devices' chip select signals.

If you need close-to-synchronous transfers on both devices, you can probably get away with some external logic.
 
Hi, sorry if I'm not explaining it well, I'm kind of new to the teensy world, and newer to the spi world :D. I will elaborate a bit more. I'm trying to get the data signals that go to a small LCD. It has a clock signal, and two data lines and two more sync signals. I'm not interfacing another spi ic, so i'm not using the chip select signals.

I was trying to use the two spi ports of the teensy, with one unique clock signal for both, and then one data signal to each din. That way I would be reading both signals. But since this it's not possible, I will have to think something more.

Reading the answer I'm writing I think I've explained it more precisely :p.
 
I'm trying to get the data signals that go to a small LCD. It has a clock signal, and two data lines and two more sync signals. I'm not interfacing another spi ic, so i'm not using the chip select signals.
So you want to "sniff" the SPI data? Which device would be generating the clock, then? The device that sends data to the display, or the Teensy?
 
So you want to "sniff" the SPI data? Which device would be generating the clock, then? The device that sends data to the display, or the Teensy?

Yeah that's it, I'm trying to get the data sent to the lcd. I was going to use the clock from the device since the two data lines are synchronized with it. The device doesn't have a spi port as is, I was just trying to get the data sent to the lcd and I thought about using the SPI port on the teensy. That makes sense? In fact I just have all wired to the teensy in order to make some test. Yesterday I tried only with one of the data lines, using the spi port and I was getting some data. The thing is getting both of the data signals.
 
Do you have any idea about the actual clock speed of the device? Maybe you can go a different route. Two ideas:

  1. What you are describing doesn't look like SPI. Set up a DMA channel to read the two data lines on every clock edge, and let it fill a buffer. You can then try to analyze it in software, or send it elsewhere for storage and later inspection.
  2. use two HC595 shift registers and store each stream of bits in one HC595, and read them after every 8th clock. That way you can cut down the speed you need to handle.
 
Yeah it's as you say, it's not SPI. I just thought that I could use the SPI on the Teensy to sniff the stream to the LCD. The clock signal is 4 MHz, its quite fast. In fact I've used the freqcount function and I can't measure it right. With that frequency, some of your two ideas could work?
 
Do you have any idea about what the sync signals do?

Even if you can sniff the data at that speed I doubt that you can synchronize with the data stream to catch the "start" of some kind of transfer without knowing anything about the sync signals. At 8 Mbps (4 MHz clock, 2 signals), I would take two HC595's and use them to pack the streams into bytes. If you can't do that, using DMA directly might also be an option. I think what you want to do is not out of reach.

Please, supply more technical details. We cannot help you without them and I think you have realized that already.
 
I've seen that haha. I really know what all the signals do. I'm trying to intercept a Game Boy LCD :p. There are 5 signals:

Clock - 4 MHz
Data 0
Data 1
Hsync - 9,2 kHz (approx)
Vsync - 60 Hz

So every Vsync starts drawing the upper-left pixel so it marks the start. Every Hsync marks the start of a new horizontal line of pixels. Whenever you get an hsync, you read Data0 and Data1 to get all the pixels from that line until another hsync occurs. Data0 and Data1 are timed by the 4 MHz clock signal.

I've seen some people doing what I want, going through the fpga route (also the xmega as I said). I wanted to try it with teensy. So what I "tought" was: Set a flag with an interrupt every time a Vsync occurs. Then wait for an Hsync and start reading data. So far i've accomplished vsync interrupts, it's pretty straightforward. Getting Data0 and Data1 is the thing here.
 
Last edited:
Yay! we're getting closer.
  1. How much time do you have between vsync and the first hsync?
  2. How much time do you have between hsync and line data?
  3. How much time do you have between the last data for one line and the following hsync?
  4. What do you want to do with the sniffed data? Store? Forward? Analyze? All of those?
  5. Do you not want any external hardware at all? Then DMA is probably your best bet because it can fill memory in the background.
  6. What size is the display, about what amount of data are we talking here? I could google that, I know.
 
Status
Not open for further replies.
Back
Top