weird problem with rdlong
Larry Martin            
            
                Posts: 104            
            I am having a weird problem with rdlong. It dereferences one pointer correctly but fails on the next one. I think I'm handling both pointers the same, and could use an extra eye or two on the problem.
This is the PASM and the output of a SPIN diagnostic. The left column is diagnostics and the right column is the real code. Ft* are function temps.

On the red boxed line showing the contents of address $6210 (aCycleTraceBufferStart), you can see that ft1 in PASM read address 4B8C, and ft3 correctly got the value $BEEFDEAD at the end of that buffer. Ft3 correctly got the address $4C44, which you can verify two lines above. But when I do "rdlong ft2,ft3", ft2 gets the wrong value! The last value in paragraph $6210 is $01FC, which is incorrect. The correct value is $07F4, as shown in the dump two lines above, and the line above that with the '?' mark. I know the read value is incorrect because the following code does the wrong things, so it's not just an indication error.
Thinking that the variable is changing when I read it, I first made a shadow, which is why there are two identical values at $4C40. At one time, I also had stabilization code in PASM that forced made the code loop until it read the same value twice in a row. The ft* variables are at the end of PASM right before FIT, and there are 5 longs left in the cog.
Can some kind soul point out my error?

                            
Comments
Hi,
Without seeing the actual code it might be difficult to understand what is going on.
This is as much as I can show (edited: replaced indented diagnostic code in ShiftSpinHistory):
CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 'Algorithms depend on code being >> faster than data CLK_FREQ = ((_CLKMODE-xtal1)>>6)*+_xinfreq MS_CNT = CLK_FREQ / 1_000 CC16ParamsReady = $01 'limit constants to 8 bits for Assembly CC16ResultValid = $02 'use for Feig as well since it has its own flag word 'ToDo: move this out of common memory and into each cog's memory. Needs access methods. kTxBuffSize = 128 'BUFSIZE we only need about 96 bytes, but the mask scheme demands a power of 2 kTxBuffMask = $7F 'BUFSIZE kRxBuffSize = 256 '128 'BUFSIZE we only need about 96 bytes, but the mask scheme demands a power of 2 kRxBuffMask = $FF '$7F 'BUFSIZE kLogSlots = $20 VAR long cog 'cog flag/id ... long lSlotReaderHistoryOfTag_p '96 long lTagHistoryAlloc_p '100 ... ''These methods execute in caller's address space and cog ''Only the assembler code below executes in a separate cog PUB start(rxpin, txpin, mode, baudrate, pCmdBuf_p, pCmdLen_p, pStartMs, pGapCount_p, pCmdBufFlags_p, pIndex, pHist_p, pActive_p) : okay | bix stop repeat bix from @rx_head to @tx_buffer BYTE[bix] ~ 'bytefill(@rx_buffer, 0, kRxBuffSize) CmdBufFlags_p := pCmdBufFlags_p longmove(@rx_pin, @rxpin, 3) 'bit_ticks may be marginal for 115200. Scope shows bit detection drifting into end of bit time bit_ticks := clkfreq / baudrate 'clqfreq is $04C4B400 == 80,000,000 'should be 694.4 at 115200 baud buffer_ptr := @rx_buffer ' read by PASM INIT rxtx_mode := mode 'GlueLogix: mode not saved in published module kTICK_CNT := CLKFREQ / 1_000 CmdBuf_p := pCmdBuf_p CmdLen_p := pCmdLen_p lCycleTraceNumSlots := kLogSlots 'for ASM lCycleTraceGuardWord := $EFBEEDFE 'comes out FEEDBEEF in dump, good landmark for rx queue StartMs := pStartMs RetryFlags := $00000004 ' default retries, no flags Index := pIndex ' & $01 'aug20 back to alternate gaps GapCount_p := pGapCount_p lSlotReaderHistoryOfTag_p := pHist_p lTagHistoryAlloc_p := pActive_p okay := cog := cognew(@entry, @rx_head) + 1 '@entry is the assembly driver below ... DAT '****************************************** '* Assembly language computation "driver" * '****************************************** org ' ' ' Entry ' entry ... mov pSlotReaderHistoryOfTag_p,par add pSlotReaderHistoryOfTag_p,#96 mov pTagHistoryAlloc_p,par add pTagHistoryAlloc_p,#100 ... computations ... fast_gap 'FastGap 'Dec2020 Use global GapCount from CompuCog via pointers rdlong t1,aGapCountAddress_p cmp t1,GapCountLocal wz if_z jmp #fast_gap_done mov GapCountLocal,t1 'Jul2020 select edges by index ' see also "180 degree trigger" Jan21 in CompuCog PASM and main SPIN. mov t3,GapCountLocal 'STAGGER: every 4 gaps 'and t3,#$03 ' quickie //= 4 'cmp t3,pasmIndex wz 'STAGGER: every 2 gaps xor t3,pasmIndex and t3,#$01 wz ' //= 2 'end edge selection 'STAGGER: comment to go every time: 'if_nz jmp #:fast_gap_save 'end select edges by index :checkSpinShift 'Sep2021 avoid race condition in SPIN history. CompuCog is full, so do it in the first active reader call #ShiftSpinHistory 'ASSUME this balis out on null pointer :cmdchain_go 'set up for the command chain 'mov lCycleTraceOpcode, #$B3 'call #CycleTraceAppend test SerialStatus,kTxingSequence wz 'if_nz mov lCycleTraceOpcode, #$97 'processing command sequence at gap time 'if_nz call #CycleTraceAppend if_z jmp #:tryEnqueue 'ok so we are still in a sequence. Report Overrun mov SpinCmdFlags,#0 rdlong t1,aGapCountAtRead 'save the low nibble of starting gap count and t1,#$0F or SpinCmdFlags,t1 shl SpinCmdFlags,#4 or SpinCmdFlags,pkC2cTidReadOverrun 'set the bad flag call #CmdFlagBufEnqueue jmp #:fast_gap_save 'Mar21: ALWAYS jump away, never send command if reader is still working :tryEnqueue xor SpinLengthCursor,SpinLengthCursor xor SpinCmdCursor,SpinCmdCursor 'mov lCycleTraceOpcode, #$91 'Edge, new command 'call #CycleTraceAppend call #EnqueueNextCommand 'sets kTxingSequence in SerialStatus wrlong GapCountLocal,aGapCountAtRead 'save the gap count at which the read started :fast_gap_save 'mov LastInA, ThisInA fast_gap_done ... jmp #computations '''''END MAIN ASM LOOP ShiftSpinHistory 'FUNCTION rdlong ft1,pSlotReaderHistoryOfTag_p wz 'cmp ft1,#0 wz if_z jmp #ShiftSpinHistory_Ret mov ft4,aCycleTraceBufferStart wrlong ft1,ft4 add ft4,#4 mov ft2,ft1 add ft2,#$80 rdlong ft3,ft2 wrlong ft3,ft4 rdlong ft3,pTagHistoryAlloc_p wz 'cmp ft3,#0 wz if_z jmp #ShiftSpinHistory_Ret nop nop nop 'tried nop since OP rdlong ft2,ft3 add ft4,#4 wrlong ft2,ft4 '<<<<< WRONG VALUE, SEE SCREENSHOT ABOVE mov ft3,#32 'kTagHistoryNumElem :ssh_loop_top test ft2,#1 wz if_z jmp #:ssh_loop_next 'commenting this works but all the values shift to 0 rdlong ft4,ft1 shl ft4,#4 wrlong ft4,ft1 :ssh_loop_next shr ft2,#1 add ft1,#4 djnz ft3,#:ssh_loop_top :ssh_loop_done ShiftSpinHistory_Ret 'Assembler checks for label <funcname>_RET ret ... pSlotReaderHistoryOfTag_p res 1 pTagHistoryAlloc_p res 1 ft1 res 1 ft2 res 1 ft3 res 1 ft4 res 1 FIT 'Compile-time error if previous instructions/data exceed AddressShiftSpinHistory (diagnostic lines removed here) is called when FastGap sees a new sensor edge. It relies on initial setup of pointers to SPIN variables lSlotReaderHistoryOfTag and lTagHistoryAlloc. lTagHistoryAlloc tells what elements of lSlotReaderHistoryOfTag need to be shifted. If "if_z jmp #:ssh_loop_next " is commented, everything gets shifted every time. If it is not commented, the wrong cells get shifted because ft2 is wrong.
This is the SPIN diagnostic:
Fourrdrs.Hex(K4RdrHost, lTagHistoryAlloc, 8) 'deleteme Fourrdrs.Tx(K4RdrHost, "?") 'deleteme DumpMemoryToHost(@lTagHistoryAlloc, 8) 'deleteme DumpMemoryToHost(UidTid.GetLadderLogBufferAddress, 16) 'deleteme DumpMemoryToHost(@lSlotReaderHistoryOfTag, 33*4) 'deletemeJust a shot in the dark, but do you have any bytes or words declared above lSlotReaderHistoryOfTag_p and lTagHistoryAlloc_p?
You're passing the address of rx_head through par, then adding offsets to get the pointers to pSlotReaderHistoryOfTag_p and pTagHistoryAlloc_p.
(edited 13Sep21) There are roughly 24 longs before lSlotReaderHistoryOfTag_p, spacing that variable out to address 96. That's the point of the ellipses and the comments '96 and '100. There are no variables of other sizes declared.
The diagnostic screenshot shows that pSlotReaderHistoryOfTag_p ($4B8C) and its dereference ($beefdead at offset $80) are correct, and that the pointer to pTagHistoryAlloc_p ($4C44 in ft3) is correct as well. Only the dereference of the second pointer is bad: "rdlong ft2,ft3" places $0000_01FC in ft2, where the SPIN diagnostic shows that location holding $0000_07F4.
Is there another way to share addresses between SPIN and PASM? All the PASM examples I have seen do it more or less like that.
I should add that ShiftSpinHistory works correctly in that all 32 longs get shifted and the guard value $beefdead at the end is not touched. The point of *pTagHistoryAlloc_p in ft2 would be to shift only the currently allocated array cells, so I can inspect the data later to see status when the resource was consumed. That means an awful lot of things have already come together. It's just "rdlong ft2,ft3" messing up. I'm hoping someone will explain a condition where you can only rdlong so many times in a row or something. Although I added NOPs and they did not help.
Hi Larry,
I have to admit, that I do not understand, what your code is doing. And that I did not invest too much time.
As I never have heard, that rdlong does not work, I would search in other directions. Like silly things, which have happend to silly me.
I would try to go back to a simpler more direct way for debugging. For example load a 9bit constant into a register and wrlong this value to a known fixed destination. And I would try a second set of hardware...
Good luck.
Thanks for trying, Christof.
Hi, I seem to remember, that there was some issue with "FIT" at some time. So does your code reach $1F0 in cog ram?
In the debug screenshot, the last line, commented, is "__testmem res 5". If I uncomment that, compile works. if I change 5 to 6, compile fails. I think that means that the DAT section is 5 longs smaller than $1F0. I moved the FT* variables further up and it did not help.
I commented FIT and it did not help.
This is what It's doing today:
I changed the PASM code to look at an array of ID lengths rather than the old bitmap, which expresses the nonzero lengths in the same array. My code captures several views of the data as it comes in, to save time when reporting (up to 33 times/sec: right now the system is running around half speed to allow time for debug prints). Note the pattern at the end of $6454. That is the result of "rdlong ft2,ft3" written to ft4. It is 4 bytes of $0C in a row. That can happen if my read from $60e8 really read from $60EA (or $60E9 or $60EB). I can't think of other memory in my application that would have that pattern. The book says that the address for rdlong is always rounded for you. The "E8 60 00 00" on line $6454 is the value of FT3, showing the correct address. So what can make rdlong "miss its target"?
Should I replace the propeller 1 chip?
Just a general observation after more than 50 years experience: it's virtually never the hardware.
-Phil
I'll second Phil's observation. Some general things to watch for:
(1) Using "res" is a bit risky, it creates uninitialized variables and is also a trap if you happen to put anything after it. Try changing "res 5" to "long 0[5]", at least until everything is debugged.
(2) On the P1, rdlong expects a long address. If the lower 2 bits of the address are not 0, they'll be forced to 0.
(3) Look carefully in the assembly code for missing "#" (especially on jumps, but sometimes on "mov" and other instructions). Also check all "cmp" instructions to make sure they set the flags. flexspin will help with detecting some of these kinds of bugs, but not all.
there is a Propeller Simulator named GEARS (written in C#) maybe you can try this one to single step your program.
Else I think @Cluso99 wrote a simple debugger for PASM.
sorry, have no links,
Mike
Thanks for all the suggestions, folks. I am going on travel tomorrow morning and will not be able to try anything for a week.
For the record, I never resolved this. Just rewrote the function a different way. If I was doing something stupid, it's lost now. Never did get GEAR to work at this level. Thanks again to the group for trying to help.