Stuck on ASM problem :RESOLVED THANKS TO ALL
The following code snippit works fine if I have 2 (or more)·instructions inserted where shown. The instruction type does not seem to matter as even NOPs work.
This routine should use data read·out of a circular queue (it does) and eventually jump to some code to write a long to the hub ram and does if I have these 2 (or more) instructions added. If I remark them out, nothing is written to the hub ram.
The "CALL #TestWrite" does work as I can see the another HUB ram location change to the expected value.
My guess is that somehow the JMP to "StatusJumpTbl" gets screwed up without the 2 added instructions.
The address in the cog of the StatusJumpTbl is $1F (the address is $1D without the added instructions).
For testing,·the value of tmp_z is $0B (before it is added to the StatusJumpTbl address) and should force a jump to "ControllerCmd" which it does if
I have the··extra instuctions where shown.
If I just place 2 extra NOPs in the same location, then do a call #testwrite from the routine at "ControllerCmd" I get a value of $20 which is exactly what it should be. $0B-$0A = 1 plus the StatusJumpTbl address of $1F = $20. If the extra code is not present then it seems like "ControllerCmd" is
never jumped to.
Post Edited (Wurlitzer) : 2/24/2008 3:25:27 PM GMT
This routine should use data read·out of a circular queue (it does) and eventually jump to some code to write a long to the hub ram and does if I have these 2 (or more) instructions added. If I remark them out, nothing is written to the hub ram.
The "CALL #TestWrite" does work as I can see the another HUB ram location change to the expected value.
My guess is that somehow the JMP to "StatusJumpTbl" gets screwed up without the 2 added instructions.
The address in the cog of the StatusJumpTbl is $1F (the address is $1D without the added instructions).
For testing,·the value of tmp_z is $0B (before it is added to the StatusJumpTbl address) and should force a jump to "ControllerCmd" which it does if
I have the··extra instuctions where shown.
If I just place 2 extra NOPs in the same location, then do a call #testwrite from the routine at "ControllerCmd" I get a value of $20 which is exactly what it should be. $0B-$0A = 1 plus the StatusJumpTbl address of $1F = $20. If the extra code is not present then it seems like "ControllerCmd" is
never jumped to.
ParseQueData
mov DataByte2_z, QueReadData_Lng
and DataByte2_z, #$FF 'strip off everything except LSbyte
mov StatusByte_z,QueReadData_Lng
shr StatusByte_z, #16
mov tmp_z, StatusByte_z
shr tmp_z, #4 'removes Channel Nibble
and tmp_z, #$0F
'FOR SOME REASON I NEED 2 (OR MORE) INSTRUCTIONS BELOW. EVEN 2 NOPs WORK. WHY?
mov loopcounter, tmp_z 'REMOVE
call #testwrite'REMOVE
cmp tmp_z, #$0A wc,wz,nr
if_b jmp #MainLoop_z 'if < $0A then jump to main loop
cmp tmp_z, #$0F wc,wz,nr
if_a jmp #MainLoop_z 'if > $0F then jump to main loop
sub tmp_z, #$0A wc,wz'$0A points to the first entry in table.
add tmp_z, #StatusJumpTbl
jmp tmp_z 'jump to statusJumpTbl based upon value of StatusByte
'===================================================================================
StatusJumpTbl
jmp #MainLoop_z '$Ax NOT USED Aftertouch
jmp #ControllerCmd '$Bx Controller
jmp #ChannelMessage '$Cx Program change
jmp #mainLoop_z' '$Dx NOT USED Channel pressure
jmp #mainLoop_z 'NOT USED'$Ex Pitch wheel Transposer values
jmp #sysCommand_z '$Fx System command
Post Edited (Wurlitzer) : 2/24/2008 3:25:27 PM GMT

Comments
know if I need to but it's something worth trying. I cannot see any reason why it wouldn't work or why
adding extra 'nop' instructions make it work.
Thanks for looking at the code.
I knew I had to wait 7-22 cycles to assure the validity of the returned data but overlooked (possibly) playing with the address of the RDLONG instruction prior to the 7-22 cycles. This would make sense!
HOWEVER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
If that is the case, why would adding NOPs ·much further down in the code also work? From the RDLong I have 5 lines of code (minimum) prior to hitting the "ParseQueData" routine then 7 more instructions before I had added the extra code in my original post?
I just kept moving the extra NOPs further up stream until the code no longer functioned.
call #ParseQueData ' ' call #WriteParsedData jmp #MainLoop_z '============================================================================================== ReadQue rdlong QueReadData_Lng,CurrentQueHeadCtradd CurrentQueHeadCtr, #4 'make ready for next read cmp CurrentQueHeadCtr, QueBufferEnd wz,wc,nr 'is this past the end of the circular queue? if_be jmp #ReadQue_ret mov CurrentQueHeadCtr, QueBufferStart 'point to start of circular queue ReadQue_ret ret '================================================================================================= ParseQueData mov DataByte2_z, QueReadData_Lng and DataByte2_z, #$FF 'strip off everything except data byte 2 mov StatusByte_z,QueReadData_Lng shr StatusByte_z, #16 mov tmp_z, StatusByte_z shr tmp_z, #4 'removes Channel Nibble and tmp_z, #$0F 'FOR SOME REASON I NEED 2 INSTRUCTIONS HERE. EVEN 2 NOPs WORK. WHY? 'nop 'nop cmps tmp_z, #$0A wc,wz,nr if_b jmp #MainLoop_z 'if < $0A then jump to main loop cmps tmp_z, #$0F wc,wz,nr if_a jmp #MainLoop_z 'if > $0F then jump to main loop sub tmp_z, #$0A wc,wz'$add tmp_z, #StatusJumpTbl jmp tmp_z 'jump to statusJumpTbl based upon value of StatusByte'=================================================================================== StatusJumpTbl jmp #MainLoop_z''$Ax NOT USED Aftertouch jmp #ControllerCmd '$Bx Controller jmp #ChannelMessage '$Cx Program change jmp #mainLoop_z''$Dx NOT USED Channel pressure jmp #mainLoop_z'NOT USED'$Ex Pitch wheel Transposer values jmp #sysCommand_z '$Fx System commandDoes it make a difference that ReadQue returns sometimes and doesn't return at other times (jumps to mainLoop_z)? There's no stack, so the fact that ReadQue_ret is overwritten on the next call shouldn't matter.
Could the problem be one of code positioning rather than timing? By having two instructions, the following code is displaced forward in memory by two long words.
already anded that with $0F earlier. The 'cmp' before 'if_be' for adjusting the queue pointer might
also benefit from being a 'cmps'.
Is it worth posting your entire code in case it's something elsewhere we are not seeing which is having
an effect on behaviour ? Not that I can see any obvious reason why adding the NOP's fixes whatever
problem there is. Do they really fix the problem, or is that simply masking whatever's actually going
wrong ?
Thanks for the insite on how the COG waits as I was unsure if I played with the address before the RDLONG finished what would happen. Based upon your reply I do not have to be concerned as nothing happens until the RDLONG is finished.
The strange thing is the value read from the RDLONG is correct regardless if the rest of the code is working or not. I can see that in the HUB Ram.
Thank you for taking the time to look at the code.
"Could the problem be one of code positioning rather than timing? By having two instructions, the following code is displaced forward in memory by two long words."
Good thought! That is why I verified the JMP to StatusJumpTbl addressing. It seemed correct!
While I believe every variable in this assembly routine has been declared as a long, your comment merits some investigation. I would expect strange results like this·if I had not been careful with declaring bytes at improper boundaries.
·I will play with the number of inserted instructions to see if there is a pattern. I have tried 1,2,3 and 1 does not work but 2 or 3 does.
This assembly routine is one of 2 in the same SPIN file if that makes any difference. I have checked for declaration conflicts and different entry points etc. SIDE COMMENT: Is there any way to have just assembly code in its own file rather than some SPIN calling 1 or more assembly routines. I understand the need for at least one spin routine but I would like separate files for pure assembly.
Mike & Hippy let me play with this some more and if I cannot spot the issue, I'll post the code. As it is under development I would want to add comments as to where the functioning code ends and the under development starts. Right now I just plant a bunch of JMP #MainLoop_z around to bypass the under development code.
Thanks again to both of you for taking the time to review this.
The compiler will align items to their proper boundaries with instructions on long word boundaries.
It may well be that there's an error in the assembly code that you left out, but it's manifesting itself in what you've shown.
only a suggestion: You could optimize your code easily to have a deterministic execution time of ReadQue. This would perhaps avoid unnecessary waiting on RDLONG.
ReadQue rdlong QueReadData_Lng,CurrentQueHeadCtr add CurrentQueHeadCtr, #4 'make ready for next read cmp CurrentQueHeadCtr, QueBufferEnd wz,wc,nr 'is this past the end of the circular queue? ' if_be jmp #ReadQue_ret 'not necessary if you would use an opposed condition on the next statement if_a mov CurrentQueHeadCtr, QueBufferStart 'point to start of circular queue ReadQue_ret retDid you have used any assembly debugger to analyse your trouble?
Thomas
add tmp_z, #foo jmp tmp_zI wonder if maybe the JMP instruction has been pre-fetched into the pipeline and maybe tmpz has as well, so you've got a stale version of tmpz in addition to the jump. That would suggest that adding a nop between the add and the jmp should make it reliable but I've not tried that.
--Chuck
The insertion of the 2 NOPs is now located in the ReadQue routine on the 2nd and 3rd lines right after the rdlong instruction. All my testing seems to point to the an improper jump to the #StatusJumpTbl near the bottom of the ParseQueData routine if these added instructions are not in the program.
I have read the tutorial numerous times but, while very helpful, I obviously have not picked up on my error. There also seems to be 2 schools of thought, based upon some responses, as to what cautions need to be taken immediately after a HUB based instruction. At this point the code runs so fast I am not dwelling on perfect optimization.
DAT org entry_z call #Initialize_ParseMidi MainLoop_z rdlong CurrentQueTailAddr,QueTailPtrAddr 'read location of current queue tail address cmp CurrentQueTailAddr,CurrentQueHeadCtr wc,wz,nr 'if different read current head value if_e jmp #MainLoop_z 'Working:no new data go back to main loop call #ReadQue 'Working: data waiting to be read call #ParseQueData ' ' ' call #WriteParsedData jmp #MainLoop_z '============================================================================================== ReadQue rdlong QueReadData_Lng,CurrentQueHeadCtr nop 'ADDED CODE TO FIX UNKNOWN PROBLEM nop 'ADDED CODE TO FIX UNKNOWN PROBLEM add CurrentQueHeadCtr, #4 'make ready for next read cmp CurrentQueHeadCtr, QueBufferEnd wz,wc,nr 'is this past the end of the circular queue? if_be jmp #ReadQue_ret mov CurrentQueHeadCtr, QueBufferStart 'point to start of circular queue ReadQue_ret ret '================================================================================================= ParseQueData mov DataByte2_z, QueReadData_Lng and DataByte2_z, #$FF 'strip off everything except data byte 2 mov StatusByte_z,QueReadData_Lng shr StatusByte_z, #16 mov tmp_z, StatusByte_z shr tmp_z, #4 'removes Channel Nibble and tmp_z, #$0F cmps tmp_z, #$0A wc,wz,nr if_b jmp #MainLoop_z 'if < $0A then jump to main loop cmps tmp_z, #$0F wc,wz,nr if_a jmp #MainLoop_z 'if > $0F then jump to main loop sub tmp_z, #$0A wc,wz' add tmp_z, #StatusJumpTbl jmp tmp_z 'jump to statusJumpTbl based upon value of StatusByte '=================================================================================== StatusJumpTbl jmp #MainLoop_z''$Ax NOT USED Aftertouch jmp #ControllerCmd '$Bx Controller jmp #ChannelMessage '$Cx Program change jmp #mainLoop_z''$Dx NOT USED Channel pressure jmp #mainLoop_z'NOT USED'$Ex Pitch wheel Transposer values jmp #sysCommand_z '$Fx System command '================================================================================== :ChannelMessage jmp #mainLoop_z 'Add if needed '=============================== Control Message ================================= 'Parse out Swell (B0_07_dd) or Transposer messages (B0_07_dd) then handle stop/piston messages ControllerCmd '$Bx received mov tmp_z,QueReadData_Lng shr tmp_z,#8 'strip off byte 0 cmp tmp_z, SwellCmdMsg wc,wz,nr '$B0_07_xx if_e jmp #SwellMessage cmp tmp_z, TransposeCmdMsg wc,wz,nr '$B0_06_xx if_e jmp #TransposeCmd 'Not a Swell or Transpose Command process further jmp #mainloop_z'REMOVE mov tmp_z, StatusByte_z and tmp_z, #$0F 'leaves Channel #. This is used to set the 'appropriate bit mov StopHubBytePntr, StopOffset 'StopOffset is starting address of stops in Hub add StopHubBytePntr, DataByte2_z 't1_z = Address in Hub for this stop byte 'NOTE METHOD TO READ JUST A BYTE NEEDED mov StopTablePtr, #tblStopMsg0 'First byte address in table add StopTablePtr, DataByte2_z 'Point to proper table btye movs ReadStopTable, StopTablePtr ReadStopTable mov StopTableValue, 0-0 '0-0 is replaced by the table address ' muxc outa, OutPinPointer jmp #mainLoop_z'REMOVE TEST ONLY ' jmp #ControllerJmpTbl sysCommand_z 'Needs to be written ParseQueData_ret WriteParsedData 'Needs to be written nop WriteParsedData_ret ret TransposeCmd '$B0_06_xx wrbyte DataByte2_z, TransposerAddr_z jmp #MainLoop_z 'Done SwellMessage '$B0_07_xx wrbyte DataByte2_z, SwellAddr_z jmp #MainLoop_z 'Done testwrite 'REMOVE TEST ONLY wrlong loopcounter,QueHeadPtrAddr'REMOVE TEST ONLY nop nop testwrite_ret ret 'REMOVE TEST ONLY Initialize_ParseMidi mov QueBufferStart, par add QueBufferStart,QueBufferStartOffset 'adds the hub starting addr to the buffer start mov QueBufferEnd, par add QueBufferEnd,QueBufferEndOffset 'adds the hub starting addr to the buffer end mov QueHeadPtrAddr,par add QueHeadPtrAddr, QueHeadPtrAddrOffset 'points to loc in Hub ram for current head address mov QueTailPtrAddr,par add QueTailPtrAddr, QueTailPtrAddrOffset 'points to loc in Hub ram for current head address mov TransposerAddr_z,par add TransposerAddr_z, iniTransposerOffset mov SwellAddr_z, par add SwellAddr_z, iniSwellOffset mov StopOffset, par add StopOffset, #64 'points to beginning of current stop data rdlong CurrentQueHeadCtr,QueHeadPtrAddr 'read location of current queue tail address cogid loopcounter 'REMOVE call #testwrite 'REMOVE Initialize_ParseMidi_ret ret fit DataByte3_z_MASK long %11111111_00000000_00000000 'The following table converts byte 3 of a B0, 80/81 message to the appropriate stop byte to change tblStopMsg0 long $01_28_08_00 'HUB_StopStart + tblStopMsg, byte 0-4 current Stop byte in hub ram tblStopMsg1 long $29_19_31_11 'In a B0 message, byte 3 will = 0-84 which points to a byte index in this table tblStopMsg2 long $01_48_18_0A 'xxxx_xxdd dd points to the byte in these longs to use and the 6MSbits are tblStopMsg3 long $39_31_11_09 'the Long index from tblStopMsg0 tblStopMsg4 long $29_21_19_41 tblStopMsg5 long $1A_12_11_49 tblStopMsg6 long $18_4A_2A_22 tblStopMsg7 long $08_00_58_13 tblStopMsg8 long $01_20_28_10 tblStopMsg9 long $39_31_11_09 tblStopMsg10 long $29_21_19_41 tblStopMsg11 long $12_0A_02_49 tblStopMsg12 long $14_2A_22_1A tblStopMsg13 long $50_15_13_0B tblStopMsg14 long $58_60_70_68 tblStopMsg15 long $78_78_78_63 tblStopMsg16 long $78_78_78_78 tblStopMsg17 long $09_01_79_79 tblStopMsg18 long $70_70_50_31 tblStopMsg19 long $79_31_11_00 tblStopMsg20 long $79_79_79_79 tblStopMsg21 long $7B_7B_7B_7A tblStopMsg22 long $00_00_00_7B iniTransposerOffset long 6272 'Byte address Offset in Hub RAM iniSwellOffset long 6273 QueBufferEndOffset long 6688 QueBufferStartOffset long 6292 QueHeadPtrAddrOffset long 6284 QueTailPtrAddrOffset long 6288 TransposeCmdMsg long $B0_06 SwellCmdMsg long $B0_07 NoTranspose_z long 64 QueBufferEnd res 1 'Buffer End address after Hub offset applied QueBufferStart res 1 'Buffer Start address after Hub offset applied QueHeadPtrAddr res 1 'Loc in Hub Ram which stores the current Head address QueTailPtrAddr res 1 'Loc in Hub Ram which stores the current Tail address CurrentQueHeadCtr res 1 CurrentQueTailAddr res 1 QueReadData_Lng res 1 TransposerAddr_z res 1 SwellAddr_z res 1 StopOffset res 1 t1_z res 1 tmp_z res 1 RankPointer_z res 1 HUB_RAM_StartAddr_z res 1 StopHubBytePntr res 1 TransposerValue_z res 1 StopTablePtr res 1 StopTableValue res 1 BitPointer_z res 1 OutPinPointer_z res 1 ReadOffset_z res 1 tmpQue_Data_z res 1 StatusByte_z res 1 ReadAddr_z res 1 Byte1 res 1 Byte2 res 1 DataByte2_z res 1 HUB_Cur_Stop_Addr_z res 1 BytePointer_z res 1 tmpStopByte res 1 tstAddr res 1'REMOVE LoopCounter res 1The full code (minus today's edits) is in the previous post.
loopcounter is only used for the TestWrite routine
In the code below, with the mov instruction remarked out I get the·bottom image (attached). When I leave this dummy mov instruction in I get the·top image (attached)
What is supposed to happen is I capture from the Circular Queue, starting @ 1573 on the attached image "B0_07_xx" with xx being the variable in this message.
In 1571 you "SHOULD" see a $0B which is written by the TestWrite routine.
In 1568 you "SHOULD" see the variable from the B0_07_xx message in 1573 placed in the byte 1 position and byte 0 is left at its original value (it is)
You will notice when I do NOT get the $0B in 1571 I do get the proper result in 1568 (makes no sense at all). I cannot explain where the $04 is generated.
When I do not get the $0B I do get the byte written into 1568 as expected (again this makes not sense)
I have moved the testwrite before and after the SUB tmp_z, #$0A and have yet to·see a "1" which should be the correct result as tmp_z = $0B.
ParseQueData mov DataByte2_z, QueReadData_Lng and DataByte2_z, #$FF 'strip off everything except data byte 2 mov StatusByte_z,QueReadData_Lng shr StatusByte_z, #16 mov tmp_z, StatusByte_z shr tmp_z, #4 'removes Channel Nibble 'BELOW IS THE DUMMY INSTRUCTION I EITHER LEAVE IN OR REMARK OUT 'mov loopcounter,tmp_z 'REMOVE TEST ONLY sub tmp_z, #$0A' wc,wz' mov loopcounter, tmp_z 'REMOVE TEST ONLY call #testwrite 'This should write the value of tmp_z to 1571 (in my master array) add tmp_z, #StatusJumpTbl jmp tmp_z 'jump to statusJumpTbl based upon value of StatusByte '=================================================================================== StatusJumpTbl jmp #MainLoop_z''$Ax NOT USED Aftertouch jmp #ControllerCmd '$Bx Controller jmp #ChannelMessage '$Cx Program change jmp #mainLoop_z''$Dx NOT USED Channel pressure jmp #mainLoop_z'NOT USED'$Ex Pitch wheel Transposer values jmp #sysCommand_z '$Fx System command . . .snip testwrite 'REMOVE TEST ONLY wrlong loopcounter,QueHeadPtrAddr'REMOVE TEST ONLY nop nop testwrite_ret ret 'REMOVE TEST ONLYPlease note the different values I receive depending upon the placement of Call #TestWrite
All I did was to cut and paste the mov and call to testwrite in 3 different places. In the code below I describe the values observed.
ParseQueData mov DataByte2_z, QueReadData_Lng and DataByte2_z, #$FF 'strip off everything except data byte 2 mov StatusByte_z,QueReadData_Lng shr StatusByte_z, #16 mov tmp_z, StatusByte_z shr tmp_z, #4 'removes Channel Nibble 'STARTING RIGHT HERE tmp_z SHOULD = $0B mov loopcounter, tmp_z 'test 1 call #testwrite 'If placed here TestWrite never writes anything sub tmp_z, #$A' mov loopcounter, tmp_z 'test 2 call #testwrite 'If placed here TestWrite writes a $04 when it should be a $01 add tmp_z, #StatusJumpTbl mov loopcounter, tmp_z 'test 3 call #testwrite 'If placed here TestWrite writes a $01 jmp tmp_z 'jump to statusJumpTbl based upon value of StatusByteIf I add the 2 NOPs shown, I can place the "mov wtf, tmp_z" anywhere in the lines of code shown and see the proper value in PropTerm and the rest of my code works. The jump to StatusJumpTbl works exactly as expected.
I even loaded the latest IDE 1.06 since my last post with no change in results.
I cannot base a project on something this flakey (assuming for just a moment it is not my code). The question was and remains, "why are 2 NOPs required after a SHR instruction"
This is back to where I started this thread.
ParseQueData mov DataByte2_z, QueReadData_Lng and DataByte2_z, #$FF 'strip off everything except data byte 2 mov StatusByte_z,QueReadData_Lng shr StatusByte_z, #16 mov tmp_z, StatusByte_z shr tmp_z, #4 'removes Channel Nibble. for this test tmp_z = $0B at this point nop' if these 2 NOPs are added after the line above, the entire program works and the value of wtf is correct. nop 'if I move the NOPs before the "shr tmp_z, #4" I get a completely bogus value for tmp_z and wtf and the code does not work sub tmp_z, #$0A' add tmp_z, #StatusJumpTbl mov wtf, tmp_z 'REMOVE TEST ONLY call #testwrite 'Writes the value of wtf into master array 1571 REMOVE TEST ONLY jmp tmp_z 'jump to statusJumpTbl based upon value of StatusByteI thought of your issue yesterday, when I wrote "...one unsolved due to the missung FULL code ..."
But you posted your full code don't you? No!
See, as soon as the COG is loaded with your code nothing can harm it any longer.... but before, it can!
I - and most likely others as well - have thoroughly looked through it. It was obvious from the beginning that this all had nothingti do with timing or so
(And no, there are no "two schools of thinking"
The first idea - before you posted this greater part of your program - was some misfit of RES, maybe a preset variable behing a RES,
which can happen very easily. However this was not the case, your total amount of machine code was rather low, and that left me with only
one solution: Your main program overwrites some of the assembly code before it is copied to the COG!
I am especially unhappy with these lines from your code here:
Such things scvhould not exist at all... They are bound to give you trouble, if not immediately then later...
Sorry I can't help more.... An idea to check this:
Just before the ORG 0 of your COG code, add a LONG 0[noparse][[/noparse]300]. If the smptoms disappear, then we are on the right track!
Post Edited (deSilva) : 2/23/2008 6:06:18 PM GMT
I think reality is that it is your code, even if not the code where the problem appears to be. I've seen
no inherent flakiness in the Propeller although I'm quite sure all of us have been convinced that our
problems must be down to hardware faults and not our software at some time.
Adding the NOP's doesn't identify the underlying problem nor resolve it, but simply masks it. I think
you are too focused on that fix and not on the bigger picture which is where the problem originates.
There's nothing fundamentally wrong with the PASM code which adding NOP would fix as best anyone
who has looked at the code can tell ( deSilva has a good point about hard-wired constants ), so the
obvious conclusion to me is that the underlying problem must be elsewhere.
The only suggestions I have are to use some debugging within the code ( difficult if moving things
around alters how it works ) or take a deep breath, stop digging one hole and move on to digging
another. Rip up all you've done and implement again using what you've learned along the way. A
rewrite is often not the painful experience it may look to be and can often be implemented quite
quickly and the result is often better for it.
As frustrating as it is, you won't be the first person up a blind-alley who has 'ballsed-up their code'
with no idea as to how or where they've done that. It's all part of the programmer's territory as is
knowing when to stop banging ones head against the wall and to move to a different approach or to
start again. Been there, done that, I have a whole drawer full of T-shirts.
While I did post all of the offending COG code·I did·not post the entire Spin object which contained 2 Dat statements hence 2 separate assembly program segments.
I thought I was saving everyone's time in not sending code that was 100% operational and "SHOULD" not have been related to the problem. I value your time as much as my own. In fact, I wasted your time. Sorry!
This morning I remarked out the entire offending code and created a separate spin file and place the code there with the associated spin code to launch the assembly portion and with one notable exception it compiled properly and ran fine. No added NOPs required.
In the StatusJumpTbl there was a JMP #ChannelMessage which was a section of code not yet developed and only had a JMP #MainLoop_z so I never expected any problem there.
However, the actual label was :ChannelMessage but when this code was in its original place with the other assembly program the compiler never complained about the mismatch as in the other assembly program there was a label "ChannelMessage".
As my problem code "SHOULD" have never jumped to ChannelMessage under these testing conditions I did not pay attention to the label conflict.
One last request guys! I would rather not face this issue again so I want to keep the assembly programs as completely separate as possible.
I have 1 spin program and 6 assembly routines. What is the safest way to launch all of these without tying up cogs with "helper" spin objects to launch all the assembly programs?
·
Of course I loaded your code into the PropellerTool and it complained!
I silently fixed that!
I thought: " some experimenting of Wulitzer... Never expected he send me anything functional anyhow..."
Would not have been this idiotic quarrel with Mosquite the other day, you should have received
a sharp remark from me, and we would have solved this puzzle already the day before yesterday
Post Edited (deSilva) : 2/24/2008 3:26:23 PM GMT
The normal way to initiate an assembly program in a cog while packaging up the assembly program in a object is to have a single Spin start routine in that object that simply does a COGNEW and returns a zero (false) if there are no free cogs or the number of the cog + 1 if a cog is started. This takes only a few bytes:
Sorry, my little idea here does not work!!
Post Edited (deSilva) : 2/24/2008 5:02:59 PM GMT
Jumping from on Cog into another Cog ... yes, somewhere round here I have that T-Shirt
Glad you got it sorted.
Segregation is not free of charge...
In contrast to what Mike implied (sorry Mike, I know you did not say it!) is that a PASM COG need not be initiated from the same object!
That is just a constraint for SPIN-COGs due to heavy internal workings (we now understand better than before).
Whenever you've got an address, you can "cog" it!
Hoewever you cannot easily get an address out of an Object
So the alternative to Mike's "standard procedure" is:
No real advantage in fact, but maybe interesting in some other context!
Note that the compiler distinguishes the both kinds of COGNEW by whether it gets a routine or a variable as first argument..
So COGNEW(modul.getAsmAddr,..)
is no good at all
Post Edited (deSilva) : 2/24/2008 5:21:49 PM GMT
The reason I was attempting to place 2 assembly routines in a single spin file was I thought I might get to the point where I had 7 cogs running and launching another assembly program using another spin object would not be possible.
I know now that while 2 assembly routines can reside in a single spin file I have to be 100% positive there are no duplicate labels. The compiler does not catch my stupid mistakes with labels.
Thanks again for you input.
No, there is no INSTANCE OF SPIN. this all works by one and the same SPIN interpreter in your main COG.
STOP will stop the assembly routines you so carefully have set up a moment ago
You most likely need no stop at all in the first place
STOP will stop the assembly routines you so carefully have set up a moment ago
You most likely need no stop at all in the first place
"
What I did, to completely eliminate the possibility of dup labels or variable names was from the top object:
Public Main
'then launch· spin file object MidiIn.
MidiIn.Start(26, @MasterArray) 'this object file contains minimal spin just to launch assembly program #1
'wait·enough time to allow this spin file to launch the assembly program·then stop the MidiIn spin object.
MidiIn.stop 'this only stops the spin portion the assembly continues to run. I made sure I stopped the right cog
'then launch a·2nd spin file object.
MidiParse.Start(26,@MasterArray) 'this object file contains minimal spin just to launch assembly program #2
'wait·enough time to allow this spin file to launch the assembly program·then stop the MidiIn spin object.
MidiParse.Stop 'again making sure the "cog stop", stopped the proper cog.
etc, etc until all the required cogs (minus 1) are merrily running their respective assembly routines.
Then finally 'launch the· assembly routine in the top object file
This seems to work well.
This may not be the best way to do this, but after the last week I wanted to make sure I did not duplicate the same problem.
But reading it again... No, I do not understand it...
How do your "STOP" routines look like???.
Post Edited (deSilva) : 2/25/2008 5:54:43 PM GMT