Propeller General Questions
SRLM
Posts: 5,045
Okay, I've been sitting on these for a while, in the hopes that I could find the answer somewhere. They haven't shown up, so here goes.
Is there a single reference for memory and how to access it? I can look at the Propeller diagram (the one with the cogs as squares, and the four lines below and IO pins to the right) and see the basics of how memory is allocated. Yet, what's the difference between cog RAM and hub RAM? Is is access capabilities? How do I differentiate between the two? To access the EEPROM memory, do I need to start up an I2C object, or can I just reference it with a simple command?
Second: when I create an object (in the OBJ block), do I launch that into a new cog, or is it simply a way to import more code into the current cog? If it's not automatically launched, how do I put it into a new cog? COGSTART only works with a method, right?
What is the most efficient way to exchange data between cogs? Address? Passing by value?
Thanks for any insights...
Is there a single reference for memory and how to access it? I can look at the Propeller diagram (the one with the cogs as squares, and the four lines below and IO pins to the right) and see the basics of how memory is allocated. Yet, what's the difference between cog RAM and hub RAM? Is is access capabilities? How do I differentiate between the two? To access the EEPROM memory, do I need to start up an I2C object, or can I just reference it with a simple command?
Second: when I create an object (in the OBJ block), do I launch that into a new cog, or is it simply a way to import more code into the current cog? If it's not automatically launched, how do I put it into a new cog? COGSTART only works with a method, right?
What is the most efficient way to exchange data between cogs? Address? Passing by value?
Thanks for any insights...
Comments
What is referred to as "hub" memory is a completely separate block of 32K RAM (and 32K ROM) that is accessible from each of the 8 cogs using a commutator (or hub mechanism) and a group of special instructions for reading (RDBYTE/RDWORD/RDLONG) and writing (WRBYTE/WRWORD/WRLONG). Think of this memory as an I/O device rather than conventional memory.
2) The EEPROM attached to I/O pins 28/29 is one of the possible sources of information to be initially loaded into the hub memory by a bootloader in ROM, the other being an attached PC using a special protocol. Once the hub is initially loaded, these I/O pins (and the EEPROM) are no longer needed. The EEPROM can be accessed using a variety of routines available from the Propeller Object Exchange. Some of these are written in assembly language and would run in a separate cog. Some of these are written in Spin and can be incorporated into your own program as the individual subroutines (methods) or referenced as objects.
3) Objects do not automatically start up routines in separate cogs. Objects are just ways to package up a set of subroutines and functions along with private data. Some of these objects need to start up a separate cog to do their "thing" and these will generally provide a start routine, possibly with some parameters, that will do this for you.
4) Sharing data between cogs is normally done by sharing variables. If the cog code is in Spin and all the routines involved are in one object, you can literally just use the same variables in both sets of routines. If the cog code is in a separate object, you will probably have to pass the address of the shared area to the separate object. There are plenty of examples in the Object Exchange of sharing simple scalar variables to complex buffers and their pointers. "Most efficient" depends on what you're doing, how you've organized it, and what you intended.
An example:
Say I launch OPERATE, and operate calls ADD and SUBTRACT. Are those methods ported to the new cog too? Also, does the same thing happen for objects in that objects OBJ block (like the debug object)?
4a) So, in the above example, if I were to use the OPERATE method to launch the ADD method into a new cog they would both be able to manipulate Value at the same time?
4b) Do the addresses of COG ram restart at 0 (or an identical value) for each cog, or do they build (cog 0 is 0 - 511, cog 1 is 512-1023, ...)
4c) Can one cog use a variable address to access another cogs data?
Thanks
Sincerely,
Ron
·
The bootloader, spin interpreter, font tables, and math tables are all stored in 32K of masked ROM on the Propeller chip at addresses $8000 to $FFFF in the hub address space (32K of RAM is at addresses $0000 to $7FFF).
You're correct in that 8 cogs x 2K bytes for a unique cog ram content per cog equals 16K. Typically, cog programs don't take the full 2K and the rest of the cog is loaded with whatever comes after the actual code from the hub memory (this is typically ignored or used for uninitialized data areas).
You can't do bank switching because there are no banks to switch. What you can do is to load other code into the cog from hub memory (fastest) or external EEPROM as an overlay.
You can use an EEPROM larger than 32K. They're available in sizes up to 128K bytes and you can use up to 4 of these. Only the first 32K is recognized by the bootloader and the Propeller Tool, but you can store programs and data there by using any of several programs that act as an operating system. The first 32K is assumed to contain the program to be started up on a reset, but any EEPROM past the end of the program can be used for data although it's erased the next time a program is downloaded from the PC to the EEPROM.
SRLM,
Objects and cogs are separate concepts. You can have routines all contained in one object that execute in different cogs. You can have objects that contain routines that never use additional cogs. You can have all sorts of combinations as well.
The 8 cog ram areas are completely separate and, as I said, are only accessible from the associated cog. Each of the cogs is a separate processor with its own memory and arithmetic/logic unit. The cog's ram cannot be accessed by another cog or any other part of the chip.
Spin is executed by an interpreter (a program) written in Propeller assembly language and stored in ROM. When the chip is reset, a copy of this interpreter is loaded into one of the cogs and executed (after the bootloader has finished). It is this interpreter program that "executes" the Spin program stored in hub memory. The Spin source file is compiled into a bytecode format and this is what is downloaded into the Propeller's ram on a reset from the Propeller Tool running on a PC. The bootloader can copy the program from ram to the EEPROM and that copy is what's used when a PC is not present.
quote -->
You're correct in that 8 cogs x 2K bytes for a unique cog ram content per cog equals 16K. Typically, cog programs don't take the full 2K and the rest of the cog is loaded with whatever comes after the actual code from the hub memory (this is typically ignored or used for uninitialized data areas).
<--quote
1) So, was my assumption that there·is 16K of hub ram free, which is not used as the source for loading cog ram, correct?· Can this ram be used for any other purpose I want in my program?
2) How can I determine how much cog memory is used, and how much can be used for other purposes.· Sorry if that's in the manual.
3) Say I declare an array, for example, in cog ram.· If I use only symbolic names, no physical addresses, does the compiler handle all the memory mapping?· What if the size of the array exceeds available ram?
quote-->
You can't do bank switching because there are no banks to switch. What you can do is to load other code into the cog from hub memory (fastest) or external EEPROM as an overlay.
<--quote
4) Say I have a cog program which is using 1K of memory, leaving 1K free.· If that program is doing a supervisory role and switching overlays in and out, how would I go about loading the overlay, then having it execute, then returning control to the supervisor?
quote-->
You can use an EEPROM larger than 32K. They're available in sizes up to 128K bytes and you can use up to 4 of these. Only the first 32K is recognized by the bootloader and the Propeller Tool, but you can store programs and data there by using any of several programs that act as an operating system. The first 32K is assumed to contain the program to be started up on a reset, but any EEPROM past the end of the program can be used for data although it's erased the next time a program is downloaded from the PC to the EEPROM.
<--quote
5) How would I hook up more eeproms?· Do they attach to the same circuits and the existing eeprom on the Prop demo board?· How are they addressed?· Are they using I2C to communicate?· How would I load them?
6) It sounds like you're saying I would have to load the program with the propeller tool, which erases all? the eeproms.· Then I would have to reload the eeproms.· Then they would be accessible to the program.· Would they still be accessible beyond 32K after a reset, assuming I don't reprogram?
quote-->
Spin is executed by an interpreter (a program) written in Propeller assembly language and stored in ROM. When the chip is reset, a copy of this interpreter is loaded into one of the cogs and executed (after the bootloader has finished). It is this interpreter program that "executes" the Spin program stored in hub memory. The Spin source file is compiled into a bytecode format and this is what is downloaded into the Propeller's ram on a reset from the Propeller Tool running on a PC. The bootloader can copy the program from ram to the EEPROM and that copy is what's used when a PC is not present.
<--quote
7) Which cog will the interpreter load into, if there is only one?· I understand that the interpreter loads in any cog which is running any spin code.· Is that correct?
8) How much cog ram does the interpreter take?
9) Does the spin code get stored· in cog ram, or only hub ram?· If hub ram, does that mean a spin instruction can only execute every time the hub ram·becomes accessible to that cog?· I understand that the assembly instructions can execute at 20 MIPS with an 80 MHz clock.· How many spin instructions can execute per second?
10) I think I read somewhere that some spin code must exist in at least one cog, even if the application is all assembly.· Is that correct?
11) I think I also read that it is possible to have all assembly in a cog, if it is kickstarted by spin in another cog.· Is that correct?
Thanks for the help.· There are many implications to this architecture, which are initially difficult to wrap one's brain around.
Sincerely,
Ron
I understand where you are coming from. I can see where you misunderstand some of the Propellers properties just as I did and still do. I have tried to download and read everything I can find as I run into each thing I need to do. I am interfacing a lot of different devices one at a time and just try to learn as I go along. Its much the same as I had to do about a hundred years ago with the 8080 and Altair. Nobody that knew anything was talking so I just had to learn on my own.
Unfortunately, I have not found much involving learning assembly for the Prop. The manual gives some explanation for the instructions but nothing like it does for Spin.
I am sure there is a wealth of information here iin the forum but it takes so long to find it. The search engine is worthless. I know because it can't find stuff I know is there. And there is only one forum with no breakdown by subject type.
I am currently having problems trying to pass parameters between objects. I have done it for a couple of items using the same ethod I have seen in other programs but have found no real explanation for it anywhere. I cannot find any tutorial on using the @ for passing mutilple parameters or how to use the @stack.
Like you say, the memory model is not very well explained. Although it is stated that a mix of spin and assembly is used in each cog, that is not the case. When assembly code is loaded into a cog, it starts at org 0. There is no place for the spin code to reside. It doesn't state where that is. All parameters are passed between the cog memory and main memory. I do know that the cogs operate independantly at the same time and only "slow" down if waiting to transfer data to/from main memory. Thats when it has to wait for its time slot. It seems that you can run either spin or assembly in a cog but not both at the same time.
Yes you can load different programs into cogs. You can start a cog with a certain function and when finished, stop the cog which releases it for any other method that needs it.
I am not very good at explaining the items you mentioned especially when I am also tring to learn the same things. I am sure there are much more qualified people on the forum to do that. I'm also sure the questions are not new and the answers are probably here if we could just find them.
Good Luck,
Donald
Where is that stated?
1) Lets back up a moment first. The Spin compiler puts out a "binary" file which gets downloaded to the Propeller's hub ram (and perhaps the attached EEPROM). This file consists of several different things: a) Spin interpretive bytecodes for the "main program" and routines that it calls; b) assembly language instructions to be loaded into some cogs when needed; c) global variables and constants. Spin is a stack-based environment, so there's a run-time stack that starts at the end of the loaded program and extends upward in memory as needed. This stack is used for subroutine (method) calls including local variables. If you start another copy of the Spin interpreter in another cog, that requires its own stack space which is usually an array variable declared somewhere in the program. What's left of the 32K hub ram can be used for other things. Some of the display drivers use this space for a display buffer, particularly the TV bitmapped graphics driver(s).
2) We're only talking about 496 words here. The compiler does have a FIT directive to check that a chunk of code will fit into a cog with a specified amount of memory remaining (for buffers, etc.) Other than that, there's no checking.
3) Again, cog ram is used only for assembly language. There's no high level structure like arrays. The compiler doesn't allocate variables in cog ram.
4) You write your supervisory routine to do what you want. There are instructions to read from hub memory to cog memory and, once a block of data is copied, you can jump to the beginning of the block.
5) It sounds like you need to learn how I2C EEPROMs work and how they're connected. More can be connected to the same I/O pins as the existing one or they can be connected to other I/O pins. As far as the Propeller is concerned, one I/O pin is just the same as any other. There are standard routines available for I2C I/O.
6) The Propeller Tool erases the 1st 32K of EEPROM when a program is downloaded. It doesn't access any EEPROM beyond 32K.
7) It doesn't matter. All the cogs are identical. Normally, the hardware picks a stopped (idle) cog to use (see the COGNEW instruction description).
8) All of it
9) Spin code is stored in hub ram. The execution time for Spin bytecodes is variable (because they do things of widely varying complexity), but generally is on the order of microseconds.
10) When a program is started, the Spin interpreter is always the first thing executed by the bootloader. As a result, a program must consist of at least a short stub that just replaces the Spin interpreter with a user supplied assembly program. This can be done with a 16 byte program prefix.
11) I think you need to work through some of the tutorials. There's a set of them that are intended for use with the Propeller Education Kit and there are some other tutorials, all linked from the "sticky" (permanent) forum threads at the beginning of the Propeller forum thread list. Most applications are written entirely in Spin and, as far as the user is concerned, that's the programming language. There are all sorts of library routines (objects) in the Propeller Object Exchange that take care of most high speed I/O and parts of these are written in assembly language that the user doesn't normally see or have to worry about. These include video display drivers, PS/2 keyboard, asynchronous serial I/O, servo motor control, analog to digital conversion, and objects for handling specific external devices. Download some of these and look at the demo/example programs that are included.
Sorry if I misspoke
Keep in mind that objects are not loaded into cogs. Objects are just a way of organizing code and providing data encapsulation so code can more easily be re-used. Cogs run either PASM code or a separate SPIN execution process with the interpreter. SPIN code is never loaded into a cog directly. It is read statement by statement from HUB RAM by the SPIN interpreter as it executes.
Since SPIN is executed directly from HUB RAM, all SPIN processes have global scope, even if launched on a separate cog. PASM, however, runs in it's own little world (cog memory) so it needs to access HUB RAM using the HUB access statements (rdlong, wrlong, etc.).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."
- Bjarne Stroustrup
Post Edited (Ken Peterson) : 11/19/2008 5:56:04 PM GMT
http://forums.parallax.com/forums/default.aspx?f=25&m=209237
Although English is not his first language, he covers the material in great depth and does so with enthusiasm and a bit of dry humor. I found it to be a good read.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."
- Bjarne Stroustrup
I will second, third and sponsor that recommendation. I also wish he'd get over it and come back. He is greatly missed.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pull my finger!
Ron
Donald
Also, how do I assign an address to a variable (what it the syntax)?
here is what I want to do:
@variable1 := @variable2
so that whatever changes I make to variable1 are reflected in variable2, and vice versa.
Okay, I may be off here, but if they've got the same address, how can they be two different variables? Is it just that you want to call a variable by two different names?
There's no provision to access cog memory in spin. You can access the 16 SPRs (special purpose registers) in each cog by using SPR[noparse][[/noparse]idx], but there's no way to access the entire cog memory. I believe hippy was able to obtain cog memory access through some very sneaky coding, but it is unrealistic for real applications. Accessing cog memory wouldn't get you anything other than the interpreter source code since no user code is loaded into a spin cog. All user variables are stored in HUB memory.
There are no pointer variables in spin. You can get the HUB address of a variable via @symbol, but you cannot assign an address to a variable. The method of choice to share variables using memory addresses is to use the long[noparse][[/noparse]hubaddr], word[noparse][[/noparse]hubaddr], byte[noparse][[/noparse]hubaddr] 'arrays' in spin.
Basically you would do something like this:
You wouldn't use it as such. But you might want to pass a variable to a child object which would modify the value of that variable. The only way you can do that is by passing the address of the variable because the variable name is not in scope within that child object.
There is no access to cog memory directly except by the code running within the cog. If you want access outside of that cog, you have to provide a means within the code running in the cog to access it. There are many ways of doing this. The simplest and most obvious is to copy values to HUB periodically or when needed, to make those values available to other cogs.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."
- Bjarne Stroustrup
Post Edited (Ken Peterson) : 11/22/2008 4:13:03 AM GMT
I'm still wondering about inter-object variable sharing. To me, it seems the most logical to have a spot on the heap that both programs look at, one to read and one to write.
My background on this is that I want to make a program to pulsout servos: I launch this into a cog and it sends the pulse every 20 ms. In order to update the pulse width, it should read a spot in memory that is updated by the main program. This way, I never have to do a call (from main) like
Rather, I could just do something like
Thanks for all the help!
http://obex.parallax.com/objects/51/
Thanks to all.
Jim-
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Signature space for rent, only $1.
Send cash and signature to CannibalRobotics.
Oh, and thanks for all the answers!
The spin code lives in hub. The spin interpreter (interpreters if more than 1 cog running spin) lives in cog ram and is written in pasm. Each byte is fetched from hub by the pasm interpreter and decoded and a routine (set of pasm instructions) executed, depending on the bytecode.
Loading the bytecode may take up to 16 cycles to fetch each byte. The pasm code decodes (interprets) the bytecode(s) and executes a set of pasm instructions (resident within the cog) to perform this. This is common to all interpreted languages. The variables and stack are located in hub, but pointers to these bases are held in cog ram.
If you wish to investigate further I suggest you look at my articles Faster Spin Interpreter and Spin and Pasm Debugger with Zero Footprint. If you download my demo you can see how many pasm instructions are executed for each spin instruction - it will trace these instructions (pasm and/or spin).
How do I do the timing? It seems difficult to do when I don't know how much assembly is generated from a Spin command (that is what it does, right?)
So if the spin is always interpreted, why not "pre-interpret" it before loading it onto the chip? Isn't that what a compiler does?
Edit: Cluso99 Can you provide a link? Google couldn't seem to find a literal for the titles you provided...
Post Edited (SRLM) : 11/24/2008 6:15:13 AM GMT
The assembly code is not generated by the Spin commands, it stays already in the cog. And the proper timing has been done by the author of the interpreter (Chip himself). You can see the Interpreter cog as a virtual CPU which executes bytecode from the Hub RAM.
The bytecode is the "pre-interpreted" result of the Spin compiler. Spin is a combination of compiler and interpreter: The compiler generates the intermediate bytecode, and the "interpreter" executes this bytecode. The reason for this is:
1) the bytecode is much compacter as a generated assembly code (important because of the limited Hub-RAM size).
2) Assembly code can not be executed directly from the Hub RAM, and the cog RAM is too small for bigger programs.
Another methode (used by the C compiler) is LMM, where the compiler generates assembly instructions in the Hub RAM, which are loaded and then directly executed by a LMM interpreter in a cog. This is faster than Spin bytecode, but uses much more RAM for the same functions.
Andy
PASM and SPIN debug with Zero Footprint http://forums.parallax.com/forums/default.aspx?f=25&m=290946
Spin Interpreter - Faster??? http://forums.parallax.com/forums/default.aspx?f=25&m=273607
This is where I find them:
Prop Tools under Development (Index) http://forums.parallax.com/forums/default.aspx?f=25&m=296149&p=1
Open Office file which contains an index of all Propeller Forum postings http://forums.parallax.com/forums/default.aspx?f=25&m=305797
As Ariba says, the interpreter runs a set of predefined pasm instructions for each bytecode (or sequence of bytecodes).
pulse := LONG[noparse][[/noparse]newPulseAddress]
My question is: can I be writing at this address the same time as I'm reading it? I think this may be the part about the hub going around in a round robin fashion...