SPI ram
Dr_Acula
Posts: 5,484
Attached is the config file for the 23LC1024 spi ram chip. (configured to run on propeller pins 4,5,6,7)
I understand there are some clever ways of telling GCC where to store data and it is even possible to store some data in hub and some in external ram. I think this is a split mode.
However, the only option that will compile and run is XMMC.
Is there a way of tweaking this file so it can run in split mode as well? Any help would be most appreciated
I understand there are some clever ways of telling GCC where to store data and it is even possible to store some data in hub and some in external ram. I think this is a split mode.
However, the only option that will compile and run is XMMC.
Is there a way of tweaking this file so it can run in split mode as well? Any help would be most appreciated
cfg
323B
Comments
Ok, I tried it with xmm-single and it doesn't do anything. Compiles and downloads fine but the program doesn't run. Same program in XMMC mode works fine.
Am I doing something wrong? Is there a setting that needs changing in the config file? Or is this a "hard" problem to solve?
(My little coding experiment - I think it might be possible to build a faster CP/M emulator but for that it needs to use the 24LC1024 chip to store both the C code and also set aside a 64k block for the 8080/Z80 ram. I want at least half the propeller ram devoted to a graphics buffer)
Indeed I may be running out of space. It works fine for a Hello World in both XMMC and XMMC-Single. But the larger program is not running in XMMC-Single.
Only thing is that the program that isn't working is only a little bit bigger:
The 'main' part of the program is just creating an array and printing a value from it
It is a Spin program that has gone through spin2cpp, maybe that is an issue?
I may need to strip it back even further to try to find the bug. Maybe there are things going on behind the scenes with the tv text driver after it runs through spin2cpp and it is putting the TV buffer into external ram instead of hub ram? Maybe it is actually running, but it is the TV output that is not working? So I need to simplify it more. A "Hello World" using the serial port and stdio works fine, so maybe I need to add that for debugging purposes, and then add in the TV part?
My hardware is very simple at the moment - 4 pins to talk to the sram, and 3 pins to a TV.
Re common hardware, do any of the commercial boards out there use the 23LC1024?
I'd like to have a driver for it, so I'll have to see what you have here...
BTW: If you're doing an 8080 emulator, I'd like to see that too.
I've tried getting the Toledo one going, but no luck so far...
To this:
C opens up more possibilities, but it may not be possible to mindlessly copy spin objects and run them through spin2cpp.
The vast majority of programs only load cogs once. So maybe there is a way of loading up all the cogs first, then overwrite all that hub ram with something else? Having said that, Spin wasn't really designed to do this.
I suppose where this is heading is a group of C objects, optimised for C. So that TV object, well maybe the cog part and the higher level language part need to be decoupled?
Thinking aloud, one needs to take advantages of C, but not lose the vast library of code that exists in the Spin Obex. But like you say, still maintain access to the hub parameters like the ones passed in PAR.
Thinking about this more, this does appear to be a fundamental problem in porting Spin objects over to C.
In Spin, all memory is in hub so this issue never came up. But take a typical Spin program and run it through Spin 2cpp and it ends up maybe twice as big, so many Spin program are going to run out of memory if they are ported to C. So - we add external memory.
But now we need some way of telling the program where to put data. In a simplistic sense, take that TV driver. Most of the code can live in external ram. But there are the PAR values that will need to live in hub ram.
Are variants on Spin allowed? In the purest sense, no, but there are a number of programs out there that will only compile on BST and won't compile on the Proptool because they use things like #ifdef. So if we allow new spin commands... could we think about a command, in Spin, that explicitly tells the compiler that this variable needs to be in hub? Or external memory for that matter. So maybe you might have a command #memory_hub and #end_memory that you wrap around the variable declaration.
Then the next thing is to add this to Spin2cpp.
Then it makes the job of translating all the obex easier. Go through a Spin program and note the variables that are definitely going to need to be in hub. It might only be the PAR list, so that could be quite easy to do. Then run that through spin2cpp which will (presumably) collect such variables from all the objects and they will probably end up as a group in hub.
I'm interested to see what you have done with your p2load program too. I've never really liked the way almost half of the hub in a typical spin program is used up with cog code, which gets loaded once and then the ram is never used again. With external memory, there is no need to do it this way and there ought to be enough information for a compiler to work out ways automatically to load data. So the cog data could be in external ram, if any cog code is detected the compiler reserves 2k of hub ram, then if a cogstart comes up, that runs a routine that transfers the 2k of data from external ram to hub ram and does a cogstart as per normal.
Such a system could be completely transparent to the user. Take a typical spin program with 7 cogs to load (14k), check a box that says "store cog data in external memory" and if the compiler is set to xmmc or other external memory models, suddenly 12k (14-2) becomes available in hub.
Thoughts would be most appreciated!
Maybe it could work with a buffer in hub memory that is overwritten with the cog data from external ram ?
declare a 2k buffer
HUBDATA uint8_t cogcode[2048];
copy the cog code from external ram:
memcpy(cogcode, _external_cog_code, 2048);
cogstart(cogcode, par)
wait the time needed to load the code so it won't get overwritten.
This will use 2k for all cog drivers. Maybe using dynamic allocation with malloc/free could allow to reuse the 2k block for other data (never tested).
My opinion, supported by my recent experience in porting Spin code to C, is that automated programs like spin2cpp should be used as an hint (o quick way) to port the code. Manual editing is always needed. Manual porting is the preferred way to make the code more compact and efficient.
Re manual editing, I guess one place to start would be by taking the original spin code and collecting up all the variables that are going to be hub variables and trying to put them all in one group? Maybe with a VAR declaration at the beginning rather than having them declared throughout the code. I'll have a think about that some more.
Addit - several types of variables come to mind. There is the PAR group. Also there are large common buffers that the cog needs to access, eg the graphics buffer for a display, or the circular buffer for a serial port driver. There might be a third group hidden in some objects. Pulling apart the TV object will be a good place to start
We actually do this now. The best example is in the gas_toggle demo: https://code.google.com/p/propgcc/source/browse/demos/toggle/gas_toggle/toggle.c
The ecog thing David mentions reads PASM binaries from EEPROM and loads them. For this to be beneficial, 2 or 3 PASM blobs need to be used. It is the easiest solution for a simple self-contained "embedded" program. We have a demo for this too although the latest SimpleIDE does not support it (0-8-5 does) : https://code.google.com/p/propgcc/source/browse/#hg%2Fdemos%2Fcog_loader
We have discussed 2 phase loader methods for starting all cogs before loading/running the main C program. My goal is to not carry the LMM/CMM kernel at all in HUB RAM. The problem is that the kernel code needs to live somewhere for multiple COG processes (gcc cogstart) to work like the Spin cognew command. Spin has an advantage because it's interpreter lives in ROM.
We have considered these solutions: 1) pre-load all unused cogs with kernels to be used as required with a small number of re-init bytes in HUB RAM - can't use cogstop, 2) COG cloning where a reserved COG will hold a version of the kernel, and 3) keep the kernel in EEPROM - since most boards have a 64KB EEPROM, this is more viable, but it's still a non-starter for things like the Propeller Demoboard.
For the 2 phase loader to be useful, there must be an agreement on PASM mailboxes. Ross uses a registry definition. Others in the P2 thread have ignored that and come up with another solution. Both of those seem inflated to me, but the P2 proposal seems simpler although it lacks any form of identification like a cookie word. Providing O/S (operating system) like features where one can run any number of programs one at a time (using registry connections between the application and the PASM driver services) is not my goal. I know others want this kind of O/S thing, but how important is it?
Yes I agree. Defining mailboxes for things that are never used seems a waste. Plus, it isn't necessary anyway. Kyedos has no mailboxes or registry entries. Values can be passed between programs with standard command line parameters, and each program is fully independent and can use all of hub ram in whatever way it wants.
I'm working through the practicalities of rebuilding a typical Spin object for use with external memory. Attached is the standard TV object from the Obex.
It comes in three parts. The demo program, then the sub program TV_Text and that has a subprogram TV. In TV_text are two areas that will need to be in hub ram - the first is the VAR declaration which includes the screen buffer and all the parameters passed via PAR. Then at the end is a DAT section. So one needs a way of marking both VAR and DAT sections as being hub and not external ram.
Then there is the cog driver which is in tv.spin. So using the model we are proposing, this DAT section stays in external ram. But we will need a pointer to mark the beginning of that section, and somehow the value of that pointer needs to be passed out to the main program so we know how to do the memcopy(). I'm not sure about that bit.
Finally the program will need the common 2k block in hub for cogloads, and that would be part of the main program and it only needs to be defined once, no matter how many objects get added.
tv_text.spin and tv.spin are really one object so it may be best to run those two through spin2cpp and then start marking blocks of data for hub ram in the output file?
Re HUBDATA, does this put all the following data in hub up till the next }
so the cog driver for the tv is going to be this
I'm not sure what is happening to the screen buffer - I need to study the C code more as it seems to have disappeared. This is the spin code and this is (I think) the C
The screensize is 40x13 so should have produced a bigger array than that. Or is it in the .h file?
It should. Eric?
Wish I had time to help! This week is super hecktic.