passing arguments to P2 programs
flexspin supports CHAIN to start one program from another, but at the moment there's no defined way to pass data from the parent to the child. The obvious solution is to reserve a block of memory at the top of RAM and put the passed data there.
This seems like a place where having a standard of some sort would be useful. @Cluso99 , I assume you'll be doing something similar for your OS, and perhaps others will want to do it as well.
A simple standard might be to just say there's 256 bytes (or whatever size) just under the DEBUG area and that command line arguments for the new program will be placed there. This could be done WIndows style (just a 0 terminated ASCII string) or Unix style (an array of pointers to 0 terminated strings). The Windows style might be simpler, although it means parsing file names enclosed in quotes to allow strings in them... not a huge problem for SD cards (where you're not likely to have spaces in file names) but might be an issue for the host file system on the PC. Unix style would be more flexible but is conceptually trickier.
This same mechanism could be used by loadp2 to give arguments to the loaded program, so you could for example pass parameters to test programs. Or even better, give a file name to a flash / sd card copy program, so the P2 program can stream data from the host and write it to flash or to SD. This would get around the limitations of the current flash programmer in flexprop (where the data has to fit into memory).
Thoughts?
Comments
I've been thinking about ways to pass data into programs.
My approach would be a lot more complex for the loader, but really simple for the program itself. That is to store alongside the binary a list of addresses where the loader would patch in the runtime data. This could be shell arguments, but also pin assignments, video modes, etc.
I guess it would be a superset of your proposal.
You certainly want to avoid reading garbage as arguments, so I'd put a "magic value" up there, too. If this is not found, there are no arguments. The argument handling code would also erase it after it is done, so it doesn't mess stuff up if another program is loaded without clearing the area first.
I like the sound of having FlexProp pass startup arguments in, and I can see some benefits for controlling debugging, automating etc, without needing to necessarily build in a serial interpreter when some startup arguments change. Also I like the idea it can be used for filenames, or memory addresses etc. The scheme itself sounds reasonable, and high memory is probably the best place for it, but not all cases will always use the DEBUG area. I guess you need to assume it will be. Any decrementing type stack applications will need to be adjusted accordingly and be aware of this. It might be good to have the first value (highest memory long) define the length of this reserved area too, in case it needs to be over 256 bytes one day. Or even better maybe the final long value can just be a pointer to where this null terminated string begins, and 0 if unused. We can think of it as either an environment string area available at boot time or for command/startup arguments during chaining etc.
I am currently passing parameters to other programs/cogs in my formatter to the drivers which reside in other cog(s). I just pass a hub address of a parameter list via PTRA when the cog starts. This hub list contains as it's first parameter, another hub address where a big buffer resides. More parameters include I/O pins like an SD card's pins, a serial's pins, a vga's pins, any config data such as baud, etc.
Now for my OS, it will use just below the 16KB which actually means 512KB-16KB = just below the 496KB = just below $7C000. I will use, as I did with P1, an object file which is only a set of CON declarations with equates to hub addresses. This gets added as an object in every program (ie a binary) compiled. Now, of course, each cog needs to know where its' info resides. I gave each cog a set of 4 longs. You can do a lot with 4 longs, including using it as a single character buffer, or a buffer control. The data can depend on the type of program running in the cog, or it can be generic.
Currently my P2 drivers (multiportserial, SD, LCD, and coming VGA and Keyboard) all operate totally independantly, save for a parameter list which is passed as a hub address when the program (cog) starts. Each driver also has a buffer for transmit and a buffer for receive (if only transmit or receive then only one buffer), with the appropriate 4 long list(s) head, tail, start and end with the address of this list being passed in the main parameter list. It is currently working well. I have 16 slots (ie 16 buffers, and 16 pointer lists of head/tail/start/end) assigned, and they get allocated as required.
OK, I'll make a proposal then: that we reserve the top 4 longs $7BFF0 - $7BFFF for "command line" parameters, as follows:
The pointer at $7BFF8 gives where the command line arguments really are. This is a series of zero terminated strings, one after the other. The total number of strings is indicated by the long at $7BFF4 and (for now) must be in the range 0-$FF. So for example to pass two file names FLASH1.BIN and FLASH2.BIN to a format program the memory would contain bytes like the Spin2 DAT declaration:
and the memory at $7BFF0 would contain 4 longs:
Typically the arguments themselves (the actual strings) would also go in HUB memory up near $7BF00, but with this scheme we don't have to force that.
The ideal place for CGA-compatible video RAM is the 16K from $78000-7BFFF and I think it should not be anywhere else.
Would your proposal clash with CGA data in the top text page?
Eric,
Finally someone else is thinking about this
Don't know how many times I've tried.
May I suggest going a little further and allocate 8 longs to start with...
FWIW I didn't fine any need to pass the number of arguments between programs as I just pulled the args as needed from the buffer. So my buffer contained what was entered, less what had already been removed and actioned.
Just for reference, here is what I modelled almost 2 years ago, based on what I did for P1. Of course the upper 16KB is no longer available normally.
And here is what I use for my P1 OS
Intersting... I was thinking that the bottom of RAM would be the place to do this. But, I don't know exactly how all this works...
Doesn't flexprop start loading a program at $400?
What makes that 16K ideal for CGA compatible video RAM? Surely in real PCs the video RAM was at $B8000 rather than $78000, so no matter what we're already moving it.
@Cluso99 : Your 8 byte proposal seems fine to me as well. I had actually thought that we could walk down the memory starting at top of RAM and looking at magic numbers with different magic numbers for different things ("ARGV" for command line arguments, "OSIF" for OS info, "CLK_" for clock timing info, and so on) but that's probably more work than most people will want to take.
The clock frequency and mode are already in RAM so I'm not so sure about copying them up there. OTOH there's a big problem with where those should be, which probably deserves another thread.
No, the default load location is $0.
In the last version of spinix I reserved 176 bytes at the high end of hub RAM to hold the calling parameters. This worked OK for passing parameters to, but it did limit the total size of the parameters. Also, this only allowed for a single instance of a program that could use these parameters. In other versions of spinix I would pack the parameter list and place it just before the stack/heap space. This allowed for multiple programs to run at the same time, each with their own space for the parameter list.
If we are talking about establishing standards, then what about a standard colour text mode and where to put its VRAM?
The top 16K of hub RAM is out-of-bounds due to debugging and/or ROMification. Obvious next place is just below the top 16K. Note that the translation from $B8000 to $78000 is very simple.
How should this text mode be done? CGA-style character code followed by attribute byte seems good. How much RAM to use? 16K allows for four 80x25 pages, or fewer but larger pages.
Would this clash with your proposal? 80x25 needs 4000 bytes, not 4096, so the two could co-exist.
@TonyB_: I'm not sure I see any particular need for a CGA style graphics standard for P2. Many programs won't do video at all, and many of the ones that do will want higher resolutions than CGA provides, and/or will do pixel graphics rather than character based. In any case if your proposed 4000 byte buffer leaves 32 bytes free at the top of memory then it should co-exist fine with the argument passing stuff.
I think we should also reserve a long for Xtal Frequency too.