very close in time and, as a result, your program can behave unexpectedly
Is the unexpected behavior a result of interference with the read/write cycle, or is it just that things are happening so quickly?
I think I've come to a realization: cognew isn't really launching a method into a cog, what it really does is launch the whole object: it's just specifying which method to start with first. Is this a correct analysis?
1) Unexpected behavior is just that. You write your program for one cog forgetting that there's another cog possibly changing a variable's value during the execution of a single statement so the same variable has two different values so "a + a" may not be the same as "2 * a".
2) COGNEW (in your case) actually launches the Spin interpreter which starts with a call to a particular method that you've specified. The COGNEW sets up the new stack as if the call in the COGNEW statement has just occurred and the new copy of the Spin interpreter is given the same information that an ordinary method call would be given (along with a return address effectively to a COGSTOP statement).
1) So the unexpected behavior is not a result of a bad value due to overlapping read/write, it's from modifying the value with one cog between reads in another cog. Okay, I can program around that. Thanks for the heads up.
2) Ahhh....
I think I get it (at least a little more)! On to more programming practice. If I develop any more questions, I'll post them here. Thanks for the tips.
I'm passing an object the address of some variables that it is to use when storing data. In this case, I'm passing the address of an array for storing Ping distance measurements. My question is: how do I access the next elements of the array? Since I just passed the address of the first element, how do I get to subsequent elements? I tried to do something like
LONG[noparse][[/noparse]startAddress + 1]
but I don't think that works in spin. Do I have to say something like
LONG[noparse][[/noparse]startAddress + 32]
I'm guessing that this is the problem, since when I print out the array it shows the first group of numbers to be some value, then all the rest to be 0. Also can I do something like the following (on a single line):
You can use either LONG[noparse][[/noparse]startAddress], LONG[noparse][[/noparse]startAddress+4], LONG[noparse][[/noparse]startAddress+8], etc. or
LONG[noparse][[/noparse]startAddress][noparse][[/noparse] 0 ], LONG[noparse][[/noparse]startAddress][noparse][[/noparse] 1 ], LONG[noparse][[/noparse]startAddress][noparse][[/noparse] 2 ], etc.
For words, it would be the equivalent with elements every 2 bytes. You can also do this with bytes.
Mike Green said...
1) Unexpected behavior is just that. You write your program for one cog forgetting that there's another cog possibly changing a variable's value during the execution of a single statement so the same variable has two different values so "a + a" may not be the same as "2 * a".
2) COGNEW (in your case) actually launches the Spin interpreter which starts with a call to a particular method that you've specified. The COGNEW sets up the new stack as if the call in the COGNEW statement has just occurred and the new copy of the Spin interpreter is given the same information that an ordinary method call would be given (along with a return address effectively to a COGSTOP statement).
Mike, just a newbie question:
is this unexpected behavior just a spin problem (because of latency in interpreting the bytecode while the sliding hub window is avaiable to other cogs). If I have understood corectly this is not true in pasm because even if more than one cog access the same location it can not do at the same time (because of the hub access window) isn't it ?
This is an issue with any programming (Spin or assembly or C or Forth or whatever) using multiple processors like the Propeller. The issue is that you're either making a local copy of some shared variable, doing some kind of arithmetic on it, then storing the changed local copy back or you're making two local copies of a shared variable and another processor sneaks in and changes the shared variable between your two accesses. The Propeller's hub simply makes sure that individual accesses are indivisible so another processor (cog) can't change a memory location while a read or write is going on which might result in some bits being correct and some not correct.
The fix for this problem is to either avoid it (by using "2 * a" instead of "a + a" when you expect this sort of thing) or use the LOCKxxx instructions to ensure that only one processor is accessing the variable(s) at a time (by agreement among the processors). The "single producer-consumer" is one example of a special case of multiprocessor programming that, if done correctly, doesn't need the use of a semaphore (LOCKxxx) to ensure correctness. There are discussions of this in any introductory book on multiprocessor programming.
When one object is 'shared' across multiple files, and two cogs try to access a single method at the same time, what happens? I can see two potential areas where this might be of interest: one where the method only uses variables that you pass in, so there might not be a conflict, and the other when the method uses global variables.
The code for a method is read-only and the local variables are stored on the stack that's unique to each cog. The only way you'll get in trouble is the shared (global) variables (VAR and DAT). You'll need to use a LOCKxxx whenever you access the shared variables. Any methods called by the method in question also will need to follow the same rules.
Is there a way to 'dynamically allocate' memory at runtime? I know that in C++ (for example) you can use 'new' and it will find a place to put that object on the heap. Anything similar to that in spin? Mostly, I don't want to write a value to a position, and have another value overwrite the first accidentally.
Can I create new instances of objects at runtime? For example, if I had a 'cat' class that had two data members of 'Cat number' and 'age', could I create an array of cats and have the memory for the member variables be safely stowed away?
As a frame of reference, I thought it might be fun (and original?) to make a linked list implementation for Spin with the List object, ListNode, and List iterator subclasses.
There is no built-in way to 'dynamically allocate' memory at run-time. I've written several programs that do this, often by allocating areas from the "top" of RAM downwards towards the top of the stack. There was an object that I think is in the Object Exchange that provides for dynamic memory allocation. Since the stack extends upwards from the end of the program to the end of memory, you do have the potential of the stack overwriting items that are allocated at the end of RAM. There's no checking for stack overflow built-into Spin.
You can't really allocate new instances of objects at runtime. It would be possible to "patch" some of the internal object tables at runtime to use a different area for the instance's variables. It's not really supported in Spin in any way.
A hardware question: I seem to remember reading somewhere that you can input a higher voltage than 3.3 volts (something like 5 volts?) on one of the propeller I/O pins, and it will still be safe for the chip. I'm making a button that has a ~10 mega Ohm pull up resistor (with 9-15 volts on the positive side), with the switch on the other side. So, the maximum current is on the order of 1 micro amp. Is this safe for the propeller pins, even though there may be up 6 volts on the I/O pin?
9-15 volts -----\/\/~10 mega Ohm\/\/\/---+TO I/O pin+----o \/\/\/Switch(~1 to 5 mega Ohm)\/\/\/\/ o------ GND
Sort of ... A Propeller I/O pin has two protective diodes, one connected to Vdd, the other connected to Vss (ground). Any voltage more than one diode drop (about 0.7V) above Vdd (like 4.0V) gets connected to Vdd through the diode and any voltage more than one diode drop below Vss (-0.7V) gets connected to Vss through the other diode. The diodes can handle about 500uA, so any input above Vdd or below Vss has to have its current limited to that by a resistor or other mechanism. If 15V is the absolute maximum attached (through the resistor) to the switch, you could use a 24K resistor to protect the I/O pin. 15V - 3V = 12V. 12V / 24K = 500uA by Ohm's Law.
Doesn't the 10 mega ohm resistor limit the current into the I/O pin? Measuring with my multimeter from where the I/O pin connects (in the diagram above) to GND I get less than 2 uA. What am I missing here?
As a side note, if the current into the pin is limited to less than 500 uA, is there any limit on the maximum voltage on the pin? On the datasheet, it lists VDD+.3 volts as the maximum, but if we can put in at least 5, that seems to null and void that statement.
For the example I gave from your situation, any resistor at least 24K in value would work. As you get higher resistances (like 10M), you start to get RC time delays and leakage effects. Unless you have a particular reason for that sort of resistance, I'd stick with something lower, no more than 100K.
As long as the current is limited, you should be fine. With high voltages, you can get leakage in some cheap resistors, particularly in high humidity environments. Normally, the I/O pin doesn't see a voltage higher than 4V. That's the whole reason for the diodes. The diodes conduct the current needed for the resistor to drop the voltage needed to keep the I/O pin voltage within limits.
Does your "switch" really has 1..5 MOhm when closed? I don't know if this can be called switch.
With such high resistors it is save for the Propeller, but the Prop will not recognize a closed "switch":
The thershold input voltage of a Propeller pin is around 1.4V and with 15V, 10MOhm Pullup and and 1..5MOhm switch resistance, you get a higher
voltage at the pin.
Well, the variable resistance (1 to 5 mega Ohms) is from the human body. I've figured out that the ideal VIN is 8 volts: that gives 3.3 volts as a high, and close to zero for the low. However, up to 15 volts + VIN it still gives below 1.4 volts. So, it's not perfect, but it should work.
@Mike
Is the leakage due to water coating the resistor and providing a circuit along the body, instead of through? I seem to remember that is why high power lines have all those curves on the insulators.
Well, I've tried to make my first propeller soldered board (with a DIP prop), and it doesn't seem to work. So, as a Propeller general question, what does successful download indicate? My board can successfully have it's RAM or EEPROM programmed (according to the Propeller Tool), so I assumed that there isn't a problem with the design. However when I downloaded a program to simply spit information back to a terminal, nothing happened. So, does a successful program indicate a working chip and EEPROM, or does it mean something else?
Unfortunately, the dreaded blown PLL failure behaves as you're indicated. The Propeller can be identified and can download to RAM or EEPROM because it's working off the internal clock. As soon as you try to execute something that requires the PLL, it all grinds to a halt. You can use a crystal clock or an external clock without the PLL and you can use the internal slow and fast clocks. The internal clocks are not accurate enough or stable enough to do serial I/O. The way to test for this is to try a program using the supplied crystal without the PLL. If that works, then you've found the problem. If it doesn't work, then check the crystal and the wiring for it.
Once you mentioned crystal, I immediately took a look and yep, it was a bad connection. I made a quick change, and it worked. Thanks for the heads up. As a side note, if the internal clock isn't accurate enough for serial communications, how can data be downloaded from the Propeller Tool? I know it must be possible (it works!), but the 'why' illudes me.
Another question: I'm taking my first steps into assembly, and I'm having trouble finding documentation on the octothorpe (#) operator. It seems everything uses it, but it's not listed anywhere! What exactly does it mean? I've been working with the assumption that it means "literally this label", but is that true?
1) In the source field (as the first character) it sets the "immediate" bit in the instruction. This makes the source field an immediate value where the source address becomes the source value itself. It's the normal mode for jump instructions, but still has to be present there. If the octothorpe is not present, the source field is used as the address of a cog memory location which is used as the source. In the case of jump instructions, you're doing an indirect jump (to the address contained in the addressed location).
2) The item <objectName>#<constantName> indicates that the constant name is to be found in the named object and the constant's value is to be used.
I have been looking for this for several days, but does PASM have the NOT instruction!? I can't find it in the manual, it doesn't highlight in prop tool... Assuming that there isn't a not, what is the best way to NOT a variable? I have been using ANDN, but that requires three instructions and a negative one register.
Comments
Is the unexpected behavior a result of interference with the read/write cycle, or is it just that things are happening so quickly?
I think I've come to a realization: cognew isn't really launching a method into a cog, what it really does is launch the whole object: it's just specifying which method to start with first. Is this a correct analysis?
2) COGNEW (in your case) actually launches the Spin interpreter which starts with a call to a particular method that you've specified. The COGNEW sets up the new stack as if the call in the COGNEW statement has just occurred and the new copy of the Spin interpreter is given the same information that an ordinary method call would be given (along with a return address effectively to a COGSTOP statement).
2) Ahhh....
I think I get it (at least a little more)! On to more programming practice. If I develop any more questions, I'll post them here. Thanks for the tips.
I'm passing an object the address of some variables that it is to use when storing data. In this case, I'm passing the address of an array for storing Ping distance measurements. My question is: how do I access the next elements of the array? Since I just passed the address of the first element, how do I get to subsequent elements? I tried to do something like
LONG[noparse][[/noparse]startAddress + 1]
but I don't think that works in spin. Do I have to say something like
LONG[noparse][[/noparse]startAddress + 32]
I'm guessing that this is the problem, since when I print out the array it shows the first group of numbers to be some value, then all the rest to be 0. Also can I do something like the following (on a single line):
LONG[noparse][[/noparse]apingSpinCount] ++
Thanks.
LONG[noparse][[/noparse]startAddress][noparse][[/noparse] 0 ], LONG[noparse][[/noparse]startAddress][noparse][[/noparse] 1 ], LONG[noparse][[/noparse]startAddress][noparse][[/noparse] 2 ], etc.
For words, it would be the equivalent with elements every 2 bytes. You can also do this with bytes.
is this unexpected behavior just a spin problem (because of latency in interpreting the bytecode while the sliding hub window is avaiable to other cogs). If I have understood corectly this is not true in pasm because even if more than one cog access the same location it can not do at the same time (because of the hub access window) isn't it ?
Dario
The fix for this problem is to either avoid it (by using "2 * a" instead of "a + a" when you expect this sort of thing) or use the LOCKxxx instructions to ensure that only one processor is accessing the variable(s) at a time (by agreement among the processors). The "single producer-consumer" is one example of a special case of multiprocessor programming that, if done correctly, doesn't need the use of a semaphore (LOCKxxx) to ensure correctness. There are discussions of this in any introductory book on multiprocessor programming.
Is there a way to 'dynamically allocate' memory at runtime? I know that in C++ (for example) you can use 'new' and it will find a place to put that object on the heap. Anything similar to that in spin? Mostly, I don't want to write a value to a position, and have another value overwrite the first accidentally.
Can I create new instances of objects at runtime? For example, if I had a 'cat' class that had two data members of 'Cat number' and 'age', could I create an array of cats and have the memory for the member variables be safely stowed away?
As a frame of reference, I thought it might be fun (and original?) to make a linked list implementation for Spin with the List object, ListNode, and List iterator subclasses.
Thanks.
You can't really allocate new instances of objects at runtime. It would be possible to "patch" some of the internal object tables at runtime to use a different area for the instance's variables. It's not really supported in Spin in any way.
You can allocate but not free memory with it ....
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
As a side note, if the current into the pin is limited to less than 500 uA, is there any limit on the maximum voltage on the pin? On the datasheet, it lists VDD+.3 volts as the maximum, but if we can put in at least 5, that seems to null and void that statement.
As long as the current is limited, you should be fine. With high voltages, you can get leakage in some cheap resistors, particularly in high humidity environments. Normally, the I/O pin doesn't see a voltage higher than 4V. That's the whole reason for the diodes. The diodes conduct the current needed for the resistor to drop the voltage needed to keep the I/O pin voltage within limits.
Does your "switch" really has 1..5 MOhm when closed? I don't know if this can be called switch.
With such high resistors it is save for the Propeller, but the Prop will not recognize a closed "switch":
The thershold input voltage of a Propeller pin is around 1.4V and with 15V, 10MOhm Pullup and and 1..5MOhm switch resistance, you get a higher
voltage at the pin.
Andy
@Mike
Is the leakage due to water coating the resistor and providing a circuit along the body, instead of through? I seem to remember that is why high power lines have all those curves on the insulators.
Thanks for any and all replies.
sounds like you got power, reset, and eeprom connections set otherwise
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Parallax Forums - If you're ready to learn, we're ready to help.
1) In the source field (as the first character) it sets the "immediate" bit in the instruction. This makes the source field an immediate value where the source address becomes the source value itself. It's the normal mode for jump instructions, but still has to be present there. If the octothorpe is not present, the source field is used as the address of a cog memory location which is used as the source. In the case of jump instructions, you're doing an indirect jump (to the address contained in the addressed location).
2) The item <objectName>#<constantName> indicates that the constant name is to be found in the named object and the constant's value is to be used.