Propeller Program loading trick
Beau Schwabe
Posts: 6,568
Ok, so a recent thread "What is save binary for?" and something Jeff Martin·re-iterated in a webinar that I already knew got me thinking.
·
I'll post details on this later, because·I think this might open some doors for many of you running·large Propeller applications.· Here is how I would use something like this.· Suppose I have MANY assembly "snippets" that I want to use that I have functionally compiled over a period of time.· Each snippet is capable of standalone operation and is useful in it's own way.· Suppose I have a large project that would benefit from several of these code snippets working together, but·the problem is that I don't have enough memory left to contain all of the functions that I want to use. What do I do?·· The technique I have discovered would allow you to dynamically load a dedicated cog from any external EEPROM capable of holding all of·the code snippets, and run them as if it were an original part of the Propeller’s·boot memory without having to re-boot.· The same dedicated cog could be re-programmed on the fly from the main cog by fetching the data from the external memory and self-modifying the data·within·the dedicated cog.
·
Instead of saving the Original program as binary, I have saved the Original program as EEPROM.· From there I have written a small external program to parse the EEPROM file and create the "byte section" you see in the Tokenized Program below.· This eliminates the·need to transcribe the data.· But if you will notice doing an F8 on both programs below will yield slightly different tokenized code.· There is a reason for this and I will elaborate on this later.
·
Original Program:
Tokenized Program:
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/27/2009 5:10:51 AM GMT
·
I'll post details on this later, because·I think this might open some doors for many of you running·large Propeller applications.· Here is how I would use something like this.· Suppose I have MANY assembly "snippets" that I want to use that I have functionally compiled over a period of time.· Each snippet is capable of standalone operation and is useful in it's own way.· Suppose I have a large project that would benefit from several of these code snippets working together, but·the problem is that I don't have enough memory left to contain all of the functions that I want to use. What do I do?·· The technique I have discovered would allow you to dynamically load a dedicated cog from any external EEPROM capable of holding all of·the code snippets, and run them as if it were an original part of the Propeller’s·boot memory without having to re-boot.· The same dedicated cog could be re-programmed on the fly from the main cog by fetching the data from the external memory and self-modifying the data·within·the dedicated cog.
·
Instead of saving the Original program as binary, I have saved the Original program as EEPROM.· From there I have written a small external program to parse the EEPROM file and create the "byte section" you see in the Tokenized Program below.· This eliminates the·need to transcribe the data.· But if you will notice doing an F8 on both programs below will yield slightly different tokenized code.· There is a reason for this and I will elaborate on this later.
·
Original Program:
CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 PUB start cognew(@Assembly_DEMOBoard_BlinkTest, 0) DAT Assembly_DEMOBoard_BlinkTest mov t1, #1 shl t1, #16 mov dira, t1 mov outa, t1 mov t2, clkf shr t2, #2 mov t3, cnt add t3, t2 Loop waitcnt t3, t2 xor outa, t1 jmp #Loop clkf long 80_000_000 t1 res 1 t2 res 1 t3 res 1
Tokenized Program:
CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 PUB start cognew(@Assembly_DEMOBoard_BlinkTest, 0) DAT Assembly_DEMOBoard_BlinkTest byte $00,$B4,$C4,$04,$6F,$A4,$10,$00,$78,$00,$80,$00,$70,$00,$84,$00 byte $68,$00,$02,$00,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 byte $00,$00,$00,$00,$00,$00,$00,$00,$01,$2C,$FC,$A0,$10,$2C,$FC,$2C byte $16,$EC,$BF,$A0,$16,$E8,$BF,$A0,$15,$2E,$BC,$A0,$02,$2E,$FC,$28 byte $F1,$31,$BC,$A0,$17,$30,$BC,$80,$17,$30,$BC,$F8,$16,$E8,$BF,$6C byte $12,$00,$7C,$5C,$00,$B4,$C4,$04,$34,$87,$08,$35,$2C,$32,$00,$00
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/27/2009 5:10:51 AM GMT
Comments
Is it not posible edit EEPROM file that skip spin code section and only save in "MyCOG-Pasm.Cog" file DAT section.
Then in MySpin program.
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
PUB start
cognew(@CogProg, 0)
DAT
CogProg 'The Transient Program Area
.............. file "MyCOG-Pasm.Cog" ' assembly "snippet"
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nothing is impossible, there are only different degrees of difficulty.
For every stupid question there is at least one intelligent answer.
Don't guess - ask instead.
If you don't ask you won't know.
If your gonna construct something, make it·as simple as·possible yet as versatile as posible.
Sapieha
Essentially that's what I'm doing, but there are some pointer offset considerations that you must take into account in your original program. I too originally thought it would be a straight copy, but it's not.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
I wil compile only PASM with BSTC with first 8 Longs that have vectors to Places in HUB of my VARIABLES with COG comunikation.
Then LOAD that snipet.
And in my spin section only use them 8 Longs to point to HUB variables and discard rest of "Snipet"
Ps Maybe 16 Longs
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nothing is impossible, there are only different degrees of difficulty.
For every stupid question there is at least one intelligent answer.
Don't guess - ask instead.
If you don't ask you won't know.
If your gonna construct something, make it·as simple as·possible yet as versatile as posible.
Sapieha
Maybe since you are thinking about it people will be more warm to the idea [noparse]:)[/noparse] No doubt, I do look forward to your contribution.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
The eeprom would contain multiple relocatables and a directory for finding them by name.· The program in the master cog would include a simple loader/linker/relocater subroutine·to load'em up and get'em going.
Relocatable modules could include encoded references (by name) to other relocatable code.· The loader/linker would·notice these references·as it was loading the code, and in the same operation also load any required subs, replacing the encoded references with actual as-loaded addresses.
Nothing of this is a new idea, of course -- mainframes did it as early as the 1950s -- but no one has done it on a Prop, I think.· It'd be a fun project, not terribly tough, and it'd be a start on a real operating system, too.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Assembly_DEMOBoard_TokenTest.ZIP - contains everything (attached)
·
···· Assembly_DEMOBoard_TokenTest.spin - Main DEMO program
···· Assembly_DEMOBoard_BlinkTest.zip- BlinkTest Assembly source code and EEPROM dump
···· Assembly_Pin_HIGH_Test.zip - PinHIGH Assembly source code and EEPROM dump·
···· Assembly_Pin_Pan_Test.zip - PinPan Assembly source code and EEPROM dump
Demonstrates "safe" COG entry and exit after Assembly code completion
Demonstrates COG entry and continued execution
Demonstrates that Spin in original COG has not been compromised and continues to work properly
Demonstrates that you can affectively move data around·from one location to another.
·Note : - This can be an external memory source
·········· - And you don't need to move the entire 32K block, just the portion that pertains
············ to the Assembly code.
An example of copying/moving a tokenized routine from one location to the next and then executing the routine
Updated version below - files removed
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/27/2009 5:14:04 AM GMT
You talk about large programs to run on the Prop. So the goal is to save tons of PASM-programs on a SD-card and load them when needed. You can easyly use the target propeller to store the stuff on the card. Just a little host program which utilizes the SD driver and contains the or some PASM code that has to be stored.
With the @ spin and pasm know where to find the compiled PASM code. So, instead of running it with cognew let the SD driver store the code on SD. Later on it in the real program it can be loaded into a buffer and run from there.
This is just a proof of concept. Instead of the longmove the 'storer' would write the PASM to SD and the big program would use the SD driver to load it into a buffer and run it from there.
The only problem I currently have is the adress operator. I'd like to do something like
length := @[url=mailto:movable_end-@movable]movable_end-@movable[/url]
to calculate the size of the PASM code. But it does not work. Is it my mistake? How can you store a adress in a variable?
I come from the idea that the main program is in Spin and calls the Assembly subroutines to aid in the overall program functionality. This may be my own fault, but it stems from years of writing code in QuickBasic4.5 and running "In-Line Assembly" from within Quickbasic4.5. Your method is not entirely different from mine in the sense of determining where the PASM is, but yours seems to live completely in PASM. Another thing I'm not clear on, is that it seems that your code must load the entire 512 longs into the buffer which is not the case with the code I have posted.
As far as your questions...
"The only problem I currently have is the address operator. I'd like to do something like ... length := @movable_end-@movable"
This would work if you changed ... "movable_end res 1" ... so that it reads ..."movable_end long 0"
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
length:=@movable_end-@movable
longmove( @load_buffer, @movable, length )
I have not been aware that the label of a RES is treated differently from a label of a LONG ... but sure ... the REServed long is only available for PASM.
Of course you are right. My code was written having in mind to move store/load PASM code and no Spin code. But if Spin code is relocateable that's a nice to have as well. But shouldn't that work with the longmove & labels as well? I'll try that.
My main point is: I don't know why you use an external program and use some tricks to mark the start and the end of code, if you can let a propeller do the job?
Post Edited (MagIO2) : 3/26/2009 11:02:47 PM GMT
For external PASM drivers that would be loadable on demand, tokenizing or some organizational form is necessary to extract the different DAT sections ... often people use tables that are not part of the PASM.
It is an interesting idea to load and run certain PASM snippets on demand ... too bad you couldn't just point a custom spin interpreter to the newly loaded code and say go. While slower and obviously limited, you could pack more instruction features·in the cog memory.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230
Sorry if I not understand it.
But You start COGNEW with HEADER position and NOT with real PASM code position.
My Question is WHY?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nothing is impossible, there are only different degrees of difficulty.
For every stupid question there is at least one intelligent answer.
Don't guess - ask instead.
If you don't ask you won't know.
If your gonna construct something, make it·as simple as·possible yet as versatile as posible.
Sapieha
When I point directly to the PASM code, the pointers within the PASM code are not correct. I've noticed that if the PASM code does not have any jumps or calls it works, but that's not a realistic code approach. I'd like to get rid of the Header myself, but I don't think it's a possibility, since it contains information as far as how big the PASM code is (i.e. bytes 10 and 11 indicate the PSAM code size) and other information that is normally setup during compile time that you normally don't see. Perhaps I'm missing something, I am always open for suggestions.
Scratch that... I just figured something else out ... update to follow
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/27/2009 4:09:30 AM GMT
Your absolutely right... for some reason I was not getting my head around how the assembly program is entered... I essentially replaced the Header with all Zero's and it still compiled just fine. This makes things much easier, even in the Assembly code. No header required at all. I will update the post and clean things up with the revision.
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Sapieha·had pointed something out that I had overlooked.· In the previous version there was a Header requirement.· In this version the·Header has been removed.· What remains is the Footer, but this is mainly just a cue to a parsing program I use to generate the stand-alone EEROM dumps that I can later use in Spin in sort of an in-line assembly coding approach.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/27/2009 5:29:26 AM GMT
But could you please confirm or unconfirm my understanding:
In this thread we talk about a way to have at least PASM code snippets·(Spin snippets would be nice as well)·which get loaded during runtime as needed. For example we have devices A, B and C attached to the Propeller. All 3 are never used together and are only needed from time to time. Then there is no need to waste 3 COGs for the drivers AND no need to have the driver code in the HUB RAM for all the time.
Or we have a menu based system and depending on the selected menu entry code is loaded to do the job.
Or we want to implement a YALMM (Yet another LMM ;o) which runs a subsequence of the code with size of COG RAM at full speed and then reloads the next 512 LONGs and so on.
What I still don't understand is the advantage of having a external tool which needs header and footer to find the PASM code in the EEPROM-file.
My suggestion is to have a minimal storing system around the PASM code snippets. So, in PropTool you open at least 2 tabs for writing an extended program. One which is used to edit the main program and one which includes the storing system that can have (32k - size of storing system itself)Bytes of different PASM-code-snippets. The main function of the storing system of course would change a lot as it can be used to test the PASM modules. If tests have been passed successfully, you'd replace the test code with a call of the SD driver, which stores the PASM-code on the SD-card.
In the main program you now can load this module in a buffer, start it in the COG and use the buffer for loading the next module or use it otherwise.
This is not working code, but an outline of the idea:
SnippetStoringSystem
Program which uses the snippets:
As you see there is no external program needed to find the PASM snippets and store it on a SD card. A testing environment is needed anyway. No need to deal with EEPROM-files. The Propeller can handle that allone. (Beau, you should have more confidence in your controller ;o)
Having a byte array which represents the PASM is not needed for (what I think is) our goal and I guess it's been used as a proof of concept, isn't it?
Post Edited (MagIO2) : 3/27/2009 8:00:44 AM GMT
You are correct, you don't need to deal with an EEPROM file if you have an SD card or other memory form attached, just have the Propeller write data to the SD card and be done with it.· In light of that, because of my minimalist hardware approach, I don't have an SD card attached and my way of extraction during this preliminary proof of concept debugging stage is to use an EEPROM dump ... I suppose I could send the data serially to the PC, that would be a real BIG storage reservoir, and that would more closely resemble an SD card or other external memory, but I'm an old DOS guy at heart and like to visually DEBUG·HEX code.· - smirk
"But could you please confirm or unconfirm my understanding:
In this thread we talk about a way to have at least PASM code snippets (Spin snippets would be nice as well) which get loaded during runtime as needed. For example we have devices A, B and C attached to the Propeller. All 3 are never used together and are only needed from time to time. Then there is no need to waste 3 COGs for the drivers AND no need to have the driver code in the HUB RAM for all the time.
Or we have a menu based system and depending on the selected menu entry code is loaded to do the job.
Or we want to implement a YALMM (Yet another LMM ;o) which runs a subsequence of the code with size of COG RAM at full speed and then reloads the next 512 LONGs and so on."
Yes, I agree with all of this and to add, an effective O/S could easily be achieved using a method like this.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.