cancel
Showing results for 
Search instead for 
Did you mean: 

32F417: Any way to make an SPI SRAM to look like normal RAM?

PHolt.1
Senior III

What I am after is trapping an invalid address access e.g. at 0x30000000 and reading or writing 4 bytes from an SPI SRAM.

The invalid address trap does trap the access but do you get the address you attempted to access and (if writing) the data word?

It is basically a virtual memory question.

Obviously it will be rather slow, limited by my 21MHz max SPI clock, but a 2 megabyte/sec "RAM" is better than nothing and would be fine for many applications.

8 REPLIES 8

You could perhaps manage the Bus Fault, I think it provides you with the address, pended/buffer writes probably a head-ache, priority inversion probably going to block interrupts you might want.

https://www.keil.com/appnotes/files/apnt209.pdf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
PHolt.1
Senior III

Thank you. I had a read and while MemManage would do the job (and has a programmable interrupt priority, in case that matters) there appears to be no way to retrieve the data one attempted to write.

Reading-only from this "virtual memory" (reading actually from SPI RAM or whatever) would not be hard.

> Reading-only from this "virtual memory" (reading actually from SPI RAM or whatever) would not be hard.

Well, unless you want to perform it through a predetermined pattern/macro/function (which of course would make the whole exercise moot anyway), you would have a hard time figuring out, into which register to return the read value. This is because at the moment of failure PC already points beyond the instruction which performed the read, and instructions are both one-halfword and two-halfwords long. [EDIT Upon further reading, I may have been wrong: for the MemManage fault, documentation says, "The PC value stacked for the exception return points to the faulting instruction.". So then it's "only" about decoding the offending instruction, filling the proper register, skipping the offending instruction in PC and return. Yummy.]

But if you'd figure this out, you could as easily implement write - once you know, from which register come the data to be written, you simply can just use the content of that register.

There is also an entirely different option, assuming you are using C: do the compiler perform the "different read/write" for you, for variables marked in some special way. This is called "named address spaces" and is something which is surprisingly semi-standardized (or at least acknowledged by the standardization comitee) and even implemented for certain targets (e.g. AVR) in GCC. In the '51 world, due to '51's particular architecture, this is an entirely normal thing and exists in Keil C51 and SDCC under the name of "memory classes" [EDIT just found out that SDCC consciously renamed "storage classes" for "named address spaces" in their documentation, some time ago]

Of course this is something practically out of reach in the same way as your idea is.

JW

S.Ma
Principal

What is the real need behind, the main code source files not available?

PHolt.1
Senior III

Thank you Jan for a great insight : - )

I thought: a debugger can do it, so it must be possible. But I haven't tried to see if post-bus-fault there is any clue presented to the values. I will have a go tonight. I suspect it doesn't index to the instruction after. But it does give you the address of the faulting instruction - as you say this bit should be easy.

I now recall doing this in the 1980s on a Z280. Yes I had to decode the faulting instruction, sufficiently to determine its length i.e. where the next one started. And I was supporting only a DIV by zero fault.

As to why:

On this project we are short of RAM. The 128k+64k is used for all sorts of essential stuff, and then MbedTLS finished off what was left. But the ethernet code on this product is not performance critical.

The source code is available, but would probably need considerable hacking. Unless the SPI RAM was used as a "cache" i.e. one had say a local 16k buffer and merely transferred 16k blocks between that, and any number of 16k buffers in the SPI RAM. That would be a trivial DMA job.

And I don't want to change the CPU. Too much work has gone into it already.

There are CPUs (ESP32?) which implement SPI RAM, and it is pretty easy to do in hardware, on-chip. Some implement it just for code loading at startup.

Pavel A.
Evangelist III

There are QSPI RAMs such as 23LC1024. Maybe it can work in memory mapped mode like QSPI flash.

We used 23LC1024 recently in a project, but not in memory mapped mode, for simplicity.

S.Ma
Principal

First try to shrink the ram useage by using as much dynamic stack as possible, more local than heap or globals.

Second, if some variables are not used at the same time, union them. Third, can buffer be shrunk as RLE encoding?

If there are big buffers, and say TLS is a big buffer, use a page system to slice and transfer to and from the external memory.

Or if you used sw fifo or circular buffer or dma, plumb them to the external memory.

Using exception to sw memory map an external seems a maintenance burden.

Good luck.

PHolt.1
Senior III