8
\$\begingroup\$

I'm looking for a small, 32KB or so SRAM device that two MCUs can read or write (at two different times; I don't need simultaneous reading/writing.) It would be good if it used a serial interface as well.

The problem I'm trying to solve is sending data between two devices without the other device having to pause to receive this. I would transfer an audio sample into the buffer, then the other chip, as required, would read the audio out, and do something with it.

I've found serial SRAM's like Microchip's 23A256/23K256, however, they seem to have a single serial interface. Is there any way to have two chips accessing this?

Additionally, the receiving device only has 2KB data memory free (maximum) so it looks like using DMA or some similar transfer mechanism through I2C or other interface will not work.

\$\endgroup\$
9
\$\begingroup\$

You don't need dual-port RAM or even a serial RAM with two interfaces; For SPI it's a little trickier, but I2C allows multiple masters "out of the box." Either way, your software will have to monitor the bus conditions to see if it lost the bus and if so, wait for another opportunity.

For SPI, the MOSI, CS and CLK lines must be tri-stated (or open-collector) with pull-up resistors to keep the lines from floating. You will also need some kind of bus arbitration. This can be as simple as a single GPIO between the two masters so that the one with higher priority signals the lower-priority master that the bus is unavailable, but a more elegant solution would be a single open-collector line between the masters. When the bus is idle, neither master is yanking the line down so it floats high with a pull-up. The logic is that if the line is high, the bus is available. The master that wants to use the memory would look at the "bus available" line and if it's high, drive the line low and wait a few ms to make sure the other master didn't grab the bus at the same time. If the RAM SPI CS line is still inactive, it can be safe to assume that the bus is yours. Do the transfer, tri-state your MOSI/CLK lines and let go of the "bus active" signal.

The "wait a few ms after yanking the bus request line low" is necessary since it is possible for both masters to grab the line at the same time.

If you are only ever using one shared device and that device does not require multiple transfers, you could use its CS line as the "bus available" signal, but this isn't quite as robust.

\$\endgroup\$
  • \$\begingroup\$ But if they both grab the line at the same time, and wait for the same amount of time before transmitting, isn't it the same as not waiting at all? \$\endgroup\$ – endolith Oct 6 '10 at 18:19
  • \$\begingroup\$ The idea would be to wait for a few ms + a random few ms. Presumably they would be running different software and various latencies/interrupts/etc would contribute to the randomness of the delay. \$\endgroup\$ – akohlsmith Oct 6 '10 at 20:27
  • 2
    \$\begingroup\$ In my experience, I2C works well in a multi-master environment. It isn't as fast as SPI, however, so if your performance goals require better than 400 kb/s burst transfers you should pursue SPI. \$\endgroup\$ – RBerteig Oct 7 '10 at 8:42
  • 1
    \$\begingroup\$ @endolith: If both devices transmit the same thing, they will be unaware of each other's existence. If they transmit different things, the first device that transmits a "1" while the other was transmitting a "0" should detect that it has lost arbitration, immediately cease transmitting, and most likely expect to retransmit its entire command from the beginning. \$\endgroup\$ – supercat Mar 13 '11 at 17:52
3
\$\begingroup\$

The easiest way would be to implement a multi-master SPI bus. You could use two additional I/O lines between the masters for arbitration using a handshaking mechanism.

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

I see two possible solutions for your problem:

1) Find FIFO chip that is suitable for your needs (one example). It may be not be simple/possible to use as I do not know if FIFO chip with simple interface (such as SPI) exist. The FIFOs I know have parallel interface.

2) Share the mentioned SRAM from Microchip with two SPI masters (in two uControllers). When first is in use, the SPI ports in other uController have to be in high impedance and opposite when second uController will use the SRAM. You will need some simple handshake interface between uControllers (something like read request/read done/busy lines). This can be implemented using 2 or 3 unidirectional connections between uControllers. Your imagination is the limit.

\$\endgroup\$
1
\$\begingroup\$

Incidentally, one approach not yet mentioned for use with parallel memories is to have two or more devices given fixed time slots to access data. This approach was used in many 6502-based computers made by both Apple, Commodore, and some other vendors (not, interestingly, Atari). The popular 6502 microprocessor used a two-phase clock, and always performed its memory accesses on the second half of each cycle (the address was available during the first half, but the data would be written during the second half or latched at the end of the second half). The Apple and Commodore machines would thus during the first half of each memory cycle use an address generated by the video circuitry, latching the data at the end of the half; during the second half of each cycle they would use the address generated by the CPU, and let the CPU either write the data or latch it at the end of its half.

This approach required memory that was twice as fast as would have been required without memory interleaving, and required the addition of 3-state drivers on the processor's address outputs (the 6502's address outputs were always driven high or low) but it otherwise worked very smoothly to make the same memory available to both the processor and to external circuitry.

\$\endgroup\$
0
\$\begingroup\$

There are several ways to do what you want.

  • Program another "buffer MCU" to sit between your two CPUs and buffer the communication -- something like the "Baudrate converter" shown at http://www.romanblack.com/PICthread.htm . Program it to present "dual-port" an indepent interface on each side. The (internal or external) SRAM is directly connected only to this buffer MCU.
  • Reprogram your "transmitter" MCU to store a buffer in SRAM, instead of directly sending it to the receiver, and act as a slave to pull data from that buffer and send it only when your "receiver" MCU (acting as a master) requests it. The (external or internal) SRAM buffer is directly connected only to the transmitter. (i.e., combine the functionality of both what your receiver is doing now, and the above "buffer MCU").
  • Use some GPIO lines, as Andrew Kohlsmith and mjh2007 suggested, to arbitrate between the transmitter and receiver who gets access to a shared external 32 KByte SRAM chip such as the RAMTRON FM24C256.
\$\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.