SPIN/ASM Driver lock up on code size greater than 480 longs?
Timothy D. Swieter
Posts: 1,613
Alright - same commercial project I am working through (i.e. can only post small portions of code). I have an object setup with several SPIN routines, then a data table in a DAT block, then an ASM routine in another DAT block. The SPIN code is for starting, stopping and sending commands to the ASM driver. The core of the driver is working and proven. However I started adding some additional SPIN code and commands. I am at a point where the driver appears to be locking up or isn't running properly, here is what I am seeing.
In the SPIN section is where the code was added. After review, commenting, uncommenting, etc I think what I am seeing is that the driver is locking up with the code size over a certain amount - 480 total longs. Now, again, remember the code I am adding is in the SPIN section, not the ASM section. When the driver is locking up and I get the Object Info - just the object (F8) I see the program is 471 longs, variables are 20 longs. When I comment out code (doesn't matter which SPIN code - any SPIN code - new code or old code - code that is being called or code that isn't implemented in the calling routines yet) and the program size drops to 460 longs or lower with 20 variable longs then the program/driver works fine. Futhermore, if I leave all the code in the SPIN section uncommented and take out portions of the data table to drop the size to 460 longs, 20 variables, the driver will still lockup, so it is as if the problem is in the SPIN section.
Again, it hasn't mattered which code I comment out or leave in. It appears to be the size. Am I barking up the wrong tree? What is happening here? Is this a symptom of a different problem?
FYI: In the ASM DAT section the status bar at the bottom of the Propeller Tool is telling me it is 491 bytes. So, I don't think it is a code size limit on a cog.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
In the SPIN section is where the code was added. After review, commenting, uncommenting, etc I think what I am seeing is that the driver is locking up with the code size over a certain amount - 480 total longs. Now, again, remember the code I am adding is in the SPIN section, not the ASM section. When the driver is locking up and I get the Object Info - just the object (F8) I see the program is 471 longs, variables are 20 longs. When I comment out code (doesn't matter which SPIN code - any SPIN code - new code or old code - code that is being called or code that isn't implemented in the calling routines yet) and the program size drops to 460 longs or lower with 20 variable longs then the program/driver works fine. Futhermore, if I leave all the code in the SPIN section uncommented and take out portions of the data table to drop the size to 460 longs, 20 variables, the driver will still lockup, so it is as if the problem is in the SPIN section.
Again, it hasn't mattered which code I comment out or leave in. It appears to be the size. Am I barking up the wrong tree? What is happening here? Is this a symptom of a different problem?
FYI: In the ASM DAT section the status bar at the bottom of the Propeller Tool is telling me it is 491 bytes. So, I don't think it is a code size limit on a cog.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com

Comments
Other ideas?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
just a thought
The SPIN code isn't making any assumptions on memory or space for variables that I can see. There are a couple buffers declared as variables and those variables are strictly used with clear definitions (usually with variable[noparse][[/noparse]x] := value). There are various SPIN routines, and it hasn't mattered which ones are commented out or which lines are commented out - as long as the 460 longs program space isn't violated.
Kevin101 - good thought. The ASM driver reads configurations as the beginning of the driver initialization. Then, when a command is passed to the driver it reads the command plus four parameters. This is the same template idea that I have seen used in other drivers like graphics and float, and also in the LM9033A LCD driver I created. This new code works, I have tested and used it extensively, and it worked until I added SPIN code. There is one variable that is written to the HUB RAM an it is a value of zero written to the PAR address (clears the command after execution).
Here are more details after a little more investigation based on the above probing which triggers my thinking. Commenting or uncommenting the lines of SPIN are causing the ASM driver to function or not function properly. What I mean is, the ASM driver (with some lines commented out of SPIN) behaves as it should (it transmits and massages data - I am getting the data at the device that uses the data). I get great results and the driver is working. With those SPIN lines uncomments, it is like the ASM COG is locked up - not the calling COG or other cogs because I can still navigate on a menu structure (the calling COG), but the data sending isn't happening. So, the SPIN code isn't locking up, but the inclusion or exclusion of SPIN code is causing the ASM driver to function or not function.
So, why would commenting/uncommenting and size have to do with if the ASM code works properly or not? I will try and desensitize portions of the ASM code and publish that, but my thinking isn't that the problem is there.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
'*************************************** DAT '*************************************** '' Assembly language driver org '----------------------------------------------------------------------------------------------------- 'Start of assembly routine '----------------------------------------------------------------------------------------------------- Entry mov t0, par 'Load address of command into t0 (par contains the address of the command) 'Bring over the data for the pin and create the mask' add t0, #4 'Increment the address pointer by 4 bytes (skip over the command + parameter address) rdlong txPin, t0 'Read value of RF_tx mov txMask, #1 'Load the mask with a 1 shl txMask, txPin 'Create the mask for the proper I/O pin by shifting the 1 add t0, #4 'Increment the address pointer by 4 bytes rdlong ledPin, t0 'Read value of RF_led mov ledMask, #1 'Load the mask with a 1 shl ledMask, ledPin 'Create the mask for the proper I/O pin by shifting the 1 'Next set up the I/O with the masks and the direction register 'all I/O pins are set to output here. mov dira, txMask 'Set to an output and clears cog dira register or dira, ledMask 'Set to an output 'Set the initial state of the I/O, unless listed here, the output is initialized as off 'all outputs are initialized as off '----------------------------------------------------------------------------------------------------- 'Main loop 'wait for a command to come in, then process it. '----------------------------------------------------------------------------------------------------- CmdWait rdlong t0, par wz 'Check for a command being present if_z jmp #CmdWait 'If there is no command, jump to check again mov t1, t0 'Move the address of the command rdlong paramA, t1 'Get parameter A value add t1, #4 'Increment the address pointer by four bytes rdlong paramB, t1 'Get parameter B value add t1, #4 'Increment the address pointer by four bytes rdlong paramC, t1 'Get parameter C value add t1, #4 'Increment the address pointer by four bytes rdlong paramD, t1 'Get parameter D value shr t0, #16 wz 'Get the command cmp t0, #(_forceTX>>16)+1 wc 'Check for valid command if_z_or_nc jmp #:CmdExit 'Command is invalid so exit loop shl t0, #1 'Shift left, multiply by two add t0, #:CmdTable-2 'add in the "call" address" jmp t0 'Jump to the command 'The table of commands that can be called :CmdTable call #periodicTX 'Set or remove a flag for periodic transmitting of RF packet jmp #:CmdExit call #sendPCKTs 'Send x number of RF packets jmp #:CmdExit call #chngPCKcnt 'Change the numbe of packets sent in RF transmission jmp #:CmdExit call #forceTX 'Force the TX line to the transmitter IC to be on/off jmp #:CmdExit :CmdTableEnd 'End of processing a command :CmdExit wrlong _zero, par 'Clear the command status jmp #CmdWait 'Go back to waiting for a new commandAfter the above code is sub-routines for the various commands and sending data out. The behavour that I see when the driver behaves improperly is that no data is being sent and the LED I/O is stuck on.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
CON
VAR
OBJ - not used
PUBs/PRIs
DAT - table of values - Propeller Tool status bar says this section is 765 bytes
DAT - ASM routine (part of which is shown in the post above)
Are you suggesting moving the DAT(table) section above the PUBs/PRIs? I can certainly try it.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
Entry mov t0, par 'Load address of command into t0 (par contains the address of the command) ... CmdWait rdlong t0, par wz 'Check for a command being present if_z jmp #CmdWait 'If there is no command, jump to check again mov t1, t0 'Move the address of the commandThat looks odd. par holds the address of the command (Entry line). Then in CmdWait you actually load the command into t0 and then treat t0 as an address again (last quoted line)? Shouldn't that last line read mov t1,par?
This may be intentional if the command holds a pointer to its parameters but I just thought I point it out anyway.
Post Edited (kuroneko) : 3/17/2009 6:57:22 AM GMT
Then, the CMDWait section reads the CONTENTs of par into t0. So t0 is now the value of what par is pointing to in HUB RAM. If the value is zero, then the code checks again. If the value is non-zero then it moves on. t0 is copied to t1 for processing, because later I use t0 again - this avoids reading par and syncing with the HUB RAM again. The comments are confusing, I suppose you would have to see the spin code. The contents of PAR is a variable called Command. Command is then made up of a pointer and value in the upper 16 bits.
See Graphics.spin or Float32 (I think) or LM9033A LCD driver for more examples (complete with SPIN code) to see how the passing of a command and parameters are done in this method. It is sort of tricky until you write it out (or rewrite it and debug it) but boy is it a nice technique for creating drivers.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
Another thing I know is that the commands are being executed. Most of the SPIN code is structured to wait for the commands to be done before returning to the calling cog. Something like this, where 'a' is the start of four variables with parameters. You can see in the ASM code I posted that the par is written with zero after the command is processed, so the code waits for the command. The parameters are read near the start of the ASM.
I know this is working because it is not causing the calling cog to hang. Hmmm....maybe I can do more testing in this area because I would think that it should be hanging if the ASM cog is really walking off a cliff. Hmmm...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
Post Edited (Timothy D. Swieter) : 3/17/2009 7:33:19 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
But in your case in the command buffer you can have what ever you want without a problem. Because in your exit you always set the command back to zero and every waiting SPIN code will continue. Thats some kind of robust programming, but it's a program with Alzheimer as it simply forgets that there was an error.
In this case I'd place a errorbeat ;o) which is only executed in case of an erroneous command.
Isn't it a nice challenge to find those kind of bugs. I really miss my java debugger in these times. Step through the code, do code changes on the fly .... ;o)
Oh - I guess I also have an LED that gives some feedback under certain commands. I only have four commands right now, one sets/clears a flag, another changes a parameter for the other commands. yet another only forces I/O for testing purposes and finally there is the one command that does all the heavy lifting and sending of data. In the future this may be expanded to be multiple commands. First, get the SPIn processing and cog dysfunction working properly.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
Do you have a spare cog and 2 IO pins to communicate with the pc?
If so, you could use my debugger to trace the code, particularly if it occurs quickly. See my signature for link to the thread.
If you dont follow my debugger PM me and I'll give you my msn address.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBladeProp, SixBladeProp, website (Multiple propeller pcbs)
· Prop Tools under Development or Completed (Index)
· Emulators (Micros eg Altair, and Terminals eg VT100) - index
· Search the Propeller forums (via Google)
My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
You may already be doing this but do you ever check that the assembly cog actually starts either by checking the return value from the cognew or a led set in the asm cog?
"Command is then made up of a pointer and value in the upper 16 bits. "
Don't forget not all of the PAR variable actually gets passed into the cog.
Object table
Method Table
DAT section
PUB methods
PRI methods
VAR section
In this section
shr t0, #16 wz 'Get the command cmp t0, #(_forceTX>>16)+1 wc 'Check for valid command if_z_or_nc jmp #:CmdExit 'Command is invalid so exit loop shl t0, #1 'Shift left, multiply by two add t0, #:CmdTable-2 'add in the "call" address" jmp t0 'Jump to the commandshould t0 be t1? t0 just holds the contents of the PAR register.
Post Edited (stevenmess2004) : 3/17/2009 11:43:48 AM GMT
Good news is.......I think I found the problem. Bad news is......I don't understand why.
First, last night I was really getting bogged down thinking through this problem. I get like that after trying and trying and getting no where. Therefore I stopped working on the problem, that is why my posting stopped. I have gotten bogged down before and the lesson I learn is that I just need to walk away and stop thinking about it. I need to clear my head. After some time I return with a fresh mind - like I did this morning. I have a fresh mind and I start to reread everything I posted. I start to test assumptions. I review what I know and what I don't know. I retest to prove the problem or not. (of course I complicated matters yesterday by troubleshooting multiple bugs in multiple locations - which didn't help my focus).
So - this morning I think I found the problem. There is a piece of code I haven't posted yet. It is ASM code that has a flag and if the flag is set (non-zero) it branches to one direction and if the flag is not set (zero) it takes another path. The default, I was assuming, is not set and taking the "main path". The flag is reserved space at the end of the ASM routine. The flag was not initialized by the ASM code (I assumed this should be default to zero - no?). With all my SPIN code included (more than 460 longs), it appears that the flag was non-zero as it was getting stuck in that other path (a future feature half written). But, with some of my SPIN code commented out (doesn't matter which code, just as long as I am below 460) then the flag would be zero. Mind you, none of the commands/parameters at this time are manipulating the flag, it is only a reserved variable in ASM.
So, I am guessing that when I write something like:
That it isn't always initiated to zero - or at least doesn't appear to me to be that way based on my testing. Of course maybe there is some other bug that is clobbering the flag and I am looking for that now too. I also have my ASM routine initialized the flag to zero just after the I/O is initialized.
So - all of this to find a flag that is sometimes initialized as non-zero and other times is zero and the only way I can change between the two was how much SPIN code was present. Surely there is some thing else I haven't found yet.
So - all this talk here has helped me narrow down on the problem. Now if only I do why - I can spend sometime figuring it out, but I also need to move to the next coding task.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
periodicTXfg long 0
to define it at start up.
res reserves space for assembly code but that space is still available for spin or assembly code from other locations.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Need to make your prop design easier or secure? Get a PropMod has crystal, eeprom, and programing header in a 40 pin dip 0.7" pitch module with uSD reader, and RTC options.
I just checked the Propeller Manual regarding RES and it didn't mention that it is initialized to an indeterminante state. If this is true (and makes sense because there is also the other way of intializing a vriable) then it should get mentioned.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
The advantage of using res is the space gets reused over. very useful if your code is nearng the 32k limit. i almost always use the long, byte, or word opcode so I know for sure the start value.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Need to make your prop design easier or secure? Get a PropMod has crystal, eeprom, and programing header in a 40 pin dip 0.7" pitch module with uSD reader, and RTC options.