Shop OBEX P1 Docs P2 Docs Learn Events
My Bug or FPGA Image Interrupt Bug? — Parallax Forums

My Bug or FPGA Image Interrupt Bug?

I have a most peculiar effect with this pre-emptive multi-threading / tasking example. Not sure if it is me of the fpga image. The effect occurs on te 2 minute mark.

I think the RCR t0_C, #1 on line 86 doe not get executed at some point, possible because of the timer interrupt on SETINT1, which would result in carry being clear when I ROR t0_C, #1 WC , thus the conditional jump IF_NC JMP #task_0_loop would execute. The conditional execution is there to trap just this, to prove that Z & C flags are saved and restored on interrupt. They are, but I think an interrupt occuring at one position in the code causes an instruction to be missed? Is it the two JMPs? Is this related to Seairth's ISR Strangeness?

If you uncomment line 88 the error does not happen, well not at the same point, maybe later at some stage?

I've set up the file to output on pin b15:b0 of OUTB. Your help, will as ever, be greatly appreciated.

Comments

  • I'm not seeing a bug, if there is one. I'll keep looking. In the meantime, a few notes you may found helpful.

    1. Instead of
    if_c	setb 	TASKS_OUT, #12
    if_nc	clrb 	TASKS_OUT, #12
    

    you can do
    	setbc	TASKS_OUT, #12
    

    use SETBNC for the opposite effect. Similarly, you can use SETBZ and SETBNZ for the Z flag.

    2. To explicitly set C and/or Z, you can use
    	setcz #%11 wc, wz
    

    where bit 1 is c (only updated if WC) ant bit 0 is z (only updated if WZ)

    3. Instead of
    	add	curr_task_index, #1		' next task
    	and	curr_task_index, #$3		' in range 0 - 3
    

    you can do
    	incmod curr_task_index, #$3
    

    4. Though I'm guessing this code is actually part of something larger, you do not need the preamble code:
    		orgh $400
    		
    		org	0
    		coginit	#0, ##@cog_start
    self		jmp	#self
    

    The first cog starts in cog exec mode. The above code just ends up padding the image with 1024 zeros.
  • cgraceycgracey Posts: 14,152
    I see a problem here:
                    mov     modify, curr_task_index
                    add     modify, #task_ctrl_blk
                    altds   modify, #%000_100_000           ' replace D reg
                    mov     0-0, IRET1                      ' tcb[ task index]
    

    Before the ALTDS, you need to do a 'SHL modify,#9' to get the data up into the D field for the ALTDS.

    I think ALTDS could be improved to allow the lower 9 bits of the 'modify' to be put into the D field of the instruction after the ALTDS.
  • SeairthSeairth Posts: 2,474
    edited 2015-10-31 20:35
    cgracey wrote: »
    I see a problem here:
                    mov     modify, curr_task_index
                    add     modify, #task_ctrl_blk
                    altds   modify, #%000_100_000           ' replace D reg
                    mov     0-0, IRET1                      ' tcb[ task index]
    

    Before the ALTDS, you need to do a 'SHL modify,#9' to get the data up into the D field for the ALTDS.

    I think ALTDS could be improved to allow the lower 9 bits of the 'modify' to be put into the D field of the instruction after the ALTDS.

    Nicely spotted!
  • evanhevanh Posts: 15,915
    I think I remember wanting D to S transposing also.
  • Seairth wrote: »
    I'm not seeing a bug, if there is one. I'll keep looking. In the meantime, a few notes you may found helpful.

    1. Instead of
    if_c	setb 	TASKS_OUT, #12
    if_nc	clrb 	TASKS_OUT, #12
    

    you can do
    	setbc	TASKS_OUT, #12
    

    use SETBNC for the opposite effect. Similarly, you can use SETBZ and SETBNZ for the Z flag.

    2. To explicitly set C and/or Z, you can use
    	setcz #%11 wc, wz
    

    where bit 1 is c (only updated if WC) ant bit 0 is z (only updated if WZ)

    3. Instead of
    	add	curr_task_index, #1		' next task
    	and	curr_task_index, #$3		' in range 0 - 3
    

    you can do
    	incmod curr_task_index, #$3
    

    4. Though I'm guessing this code is actually part of something larger, you do not need the preamble code:
    		orgh $400
    		
    		org	0
    		coginit	#0, ##@cog_start
    self		jmp	#self
    

    The first cog starts in cog exec mode. The above code just ends up padding the image with 1024 zeros.

    Points 3 & 4 implemented in full.

    Thank you for the explanations in points 1 & 2. This looks an equally valid sequence utilising those instructions to set the output according to the C and Z flags:
      mov    my_reg, #0
      setbc  my_reg, #12
      setbz  my_reg, #13
      andn   TASKS_OUT,  ##1 << 13 | 1 << 12
      or     TASKS_OUT, myreg
    
  • cgracey wrote: »
    I see a problem here:
                    mov     modify, curr_task_index
                    add     modify, #task_ctrl_blk
                    altds   modify, #%000_100_000           ' replace D reg
                    mov     0-0, IRET1                      ' tcb[ task index]
    

    Before the ALTDS, you need to do a 'SHL modify,#9' to get the data up into the D field for the ALTDS.

    I think ALTDS could be improved to allow the lower 9 bits of the 'modify' to be put into the D field of the instruction after the ALTDS.

    You are quite correct, as always :smile: It looks like I was storing the current tasks return information at cog address 0 - 3, then loading the next tasks information from the correct table, albeit with what would be constant return address as the start of the task. At least the software counters were decremented occassionally! Is it any wonder I had wayward tasks!

    With your's and Seairth's comments applied, the demo has been running around 15 minutes and still behaving itself. On the plus side, this demo can run at 1MHz, but it is very slow due to the switching overhead.

    I will now update, again, my task switching thread. I will implement a similar program for referencing the hardware counters as you suggested yesterday, suggesting I look at using CMPM instruction.
Sign In or Register to comment.