In some applications you need greater amounts of RAM. Microcontrollers like the STM32 only have around 20 to some hundred kilobytes of internal RAM. So what do you do if your application needs require some megabytes of RAM, for example in high speed data acquisition systems?
One simple solution to this problem is the use of external static RAM (SRAM). These components have a good availability and are very easy to handle. They can be connected to STM32 controllers using the FSMC (flexible static memory controller) interface. Basically you just connect the address and data busses and control lines together and you are nearly ready to go. The rest consists of some harmless lines of code. 😉
But routing all the lines between SRAM and controller on the PCB can be quite tedious and may drive you mad. For example if you want to embed a 512Kx16 bit device, you need 16 data lines (D0:D15) and 19 address lines (A0:A18) – not including some important control signals like chip select or write enable. The naive approach would be to connect A0 on the controller side to A0 on the RAM side, A1 one the one side to A1 on the other side, and so on…
The problem with this approach is that the pins on both IC packages are kind of randomly placed, so routing these signals is a nightmare and often results in having more layers on your PCB than actually needed.
A much better approach is pin swapping and therefore just ignoring the order of the bus signals. Static RAMs are accessed by providing an address on the address bus while performing a read or write operation on the data bus. This can only happen byte or word-wise, one at a time. There are no burst operations involved or allowed. So it does not matter if you want to access memory address 0x22 in software and in reality (through pin swapping of A1->A2 and A5->A7 as an example) you actually access address 0x84.
Just be sure that you don’t introduce any gaps in the address bus by skipping whole signal lines. This would eventually lead to strange problems in software.
You can even swap pins within the data bus because the same rule as above applies. But be very very careful here!
16 bit SRAM components are organized in upper and lower bytes. That’s why you get two additional signals, usually called UB and LB. The STM32 controller always reads 16 bits, even if a piece of software wants to read only 8 bits of an address. The other byte is just discarded internally. But if the controller wants to write only 8 bits, it will use the dedicated upper and lower byte signals. This becomes a problem if you swap upper byte pins with lower byte pins or vice versa (e.g. D3->D9), so don’t do that! If you just swap data pins within the same byte group (e.g. D3->D7 and D9->D12), you won’t get any trouble.
To sum it all up:
Changing the order of the bus signals can greatly reduce the pain while routing your PCB.
Pin swapping within the address bus is no problem at all as long as you only swap (and not skip) the signals.
Changing the order of the data lines is also allowed as long as you only swap signals within the same byte group.
This is a very intriguing idea! It makes sense to me (as purely a software person) but I wonder about accessing locations using different sizes. For example, if we write using a 32-bit instruction (so 2 sequential 16-bit access) but then try to read using 8-bit accesses, will the correct data be returned?
in this case I described (16 bit data bus), using 32 bit accesses should also work as the RAM is aligned to 16 bit addresses. Actually there is no real difference between one or more sequential accesses because the address on the address bus changes after every 16 bit access. So, a 2 sequential 16 bit access results in two separate bus cycles.
The only restriction is that pin swappings must only be done within the same byte group (as described in my post) because there are separate signals for the lower/upper bytes which are used by the controller.
If you violate this restriction, you will get garbage when working with different sizes of the bus access.