Shop OBEX P1 Docs P2 Docs Learn Events
Examples: ISR in COG/LUT/HUB — Parallax Forums

Examples: ISR in COG/LUT/HUB

mindrobotsmindrobots Posts: 6,506
edited 2015-10-30 01:31 in Propeller 2
A simple counter based ISR entirely in COG space - all COG EXEC
con
main_led	=	0
isr_led		=	1

dat
		orgh	0

		org

start
		setb	dirb,#main_led
		setb	dirb,#isr_led
		getct	isrticks
		addct1	isrticks,isr_wait
		mov	ijmp1,#isr
		setint1	#1

blink		
		notb	outb,#main_led		'flip its output state
		waitx	main_wait		' WAITX blocks interrupts
		jmp	#blink		'do it again

isr_wait	long	25_000_000
main_wait	long	5_000_000

isrticks	long	1

isr
		notb	outb,#isr_led
		addct1	isrticks,isr_wait
		reti1


A simple counter based ISR that has its ISR code in LUT space (interrupt is LUT EXEC, main is COG EXEC).

EDIT: A few posts below, is an updated version of this with changes suggested by Chip to better handle the LUT address references.
con
main_led	=	0
isr_led		=	1

dat
		orgh	0

		org	0

start
		loc	adra,#@isr
		setq2	#3
		rdlong	0,adra
		setb	dirb,#main_led
		setb	dirb,#isr_led
		getct	isrticks
		addct1	isrticks,isr_wait
		mov	ijmp1,##isr>>2
		setint1	#1

blink		
		notb	outb,#main_led		'flip its output state
		waitx	main_wait		'wait that many clocks
		jmp	#blink		'do it again
		

isr_wait	long	50_000_000
main_wait	long	5_000_000
isrticks	long

		orgh	$200
isr
		notb	outb,#isr_led
		addct1	isrticks, isr_wait
		reti1

A simple counter based ISR that has its code in HUB space (interrupt is HUB EXEC, main is COG EXEC).
con
main_led	=	0
isr_led		=	1

dat
		orgh	0

		org	0

start
		setb	dirb,#main_led
		setb	dirb,#isr_led
		getct	isrticks
		addct1	isrticks,isr_wait
		loc	adra,#@isr
		mov	ijmp1,adra
		setint1	#1

blink		
		notb	outb,#main_led		'flip its output state
		waitx	main_wait		' WAITX blocks interrupts
		jmp	#blink		'do it again
		

isr_wait	long	50_000_000
main_wait	long	5_000_000
isrticks	long	0
isr_in_hub	long	0

		orgh	$400
isr
		notb	outb,#isr_led
		addct1	isrticks, isr_wait
		reti1

I just wanted to get these up as examples if anyone is playing and wants some quickies to try.

I intend to better document these and provide a narrative if anyone thinks they will be useful for the P2 examples library.

Comments

  • I put all three examples together: ISR in COG space, ISR in LUT space, ISR in HUB space.

    As discussed in another thread, the WAITX I use in my examples BLOCKS interrupts. This code is not a best practices for how to code a mainline but it does give you structure and how to set up a simple ISR and how to get the proper address references (that still causes me trouble).

    Enjoy...or not.....
  • jmgjmg Posts: 15,173
    These are cool examples.
    mindrobots wrote: »
    As discussed in another thread, the WAITX I use in my examples BLOCKS interrupts. This code is not a best practices for how to code a mainline ...

    If WAITx is not best practices, it might pay to change to POLL form for the examples ?

    I guess if someone really wanted last-ns precision, they could combine polling, with an INT disable and a very short wait. viz poll to within some few cycles, then use fine delay if needed.

  • cgraceycgracey Posts: 14,152
    edited 2015-10-30 00:05
    Mindrobots,

    In the middle example, change 'ORGH $200' to 'ORG $200'. ORG allows two ranges, $000..$1FF for cog and $200..$3FF for lut.

    One other thing... Change 'mov ijmp1,##isr>>2' to 'mov ijmp1,##isr'.
  • Chip,

    Thanks! I think I tried that and it wasn't working. I'll go back and try again and see where I messed up or what was getting complaints. PNUT didn't like the org at first until I got very explicit with 'org 0,$1ff' and then 'org $200' once i got that squared away, I think my LUT load sequence was having issues. But I'll go bang away at it more and report back.
  • jmg wrote: »
    These are cool examples.
    mindrobots wrote: »
    As discussed in another thread, the WAITX I use in my examples BLOCKS interrupts. This code is not a best practices for how to code a mainline ...

    If WAITx is not best practices, it might pay to change to POLL form for the examples ?

    I guess if someone really wanted last-ns precision, they could combine polling, with an INT disable and a very short wait. viz poll to within some few cycles, then use fine delay if needed.

    Thanks! I'm not sure anybody has best practices yet. I mostly wanted to post these for the memory structure and organization. How to structure and reference things still doesn't jump out at me when I start playing with COG, LUT and HUB all tied together. I also wanted to test interrupts going back and forth across execution modes.

    I do have a 2 ISR version that has a WAITINT in the main path. It's fun to watch the slightly out of sync blinkies beat against each other and the the main led that has no timing control of its own.

  • jmgjmg Posts: 15,173
    cgracey wrote: »
    In the middle example, change 'ORGH $200' to 'ORG $200'. ORG allows two ranges, $000..$1FF for cog and $200..$3FF for lut.

    It may be better to have ?
    ORGH
    ORGC
    ORGL

    to make it clear where-you-are, and then the tools can check you are not trying to do stuff illegal in that code area.

  • cgracey wrote: »
    Mindrobots,

    In the middle example, change 'ORGH $200' to 'ORG $200'. ORG allows two ranges, $000..$1FF for cog and $200..$3FF for lut.

    One other thing... Change 'mov ijmp1,##isr>>2' to 'mov ijmp1,##isr'.

    Chip,

    To get your changes to work, the only additional thing I needed to do was insert 'orgf $200' before the 'org $200'. Without the orgf, PNUT doesn't generate the code to fill out to $200. Ctrl-M looks a bit empty. With the orgf, you get zeroes out to byte 800 before the LUT code starts.

    This is the final result for the middle program above:
    con
    main_led	=	0
    isr_led		=	1
    
    dat
    		orgh	0
    
    		org	0
    
    start
    		loc	adra,#@isr
    		setq2	#3
    		rdlong	0,adra
    		setb	dirb,#main_led
    		setb	dirb,#isr_led
    		getct	isrticks
    		addct1	isrticks,isr_wait
    		mov	ijmp1,##isr
    		setint1	#1
    
    blink		
    		notb	outb,#main_led		'flip its output state
    		waitx	main_wait		'wait that many clocks
    		jmp	#blink		'do it again
    		
    
    isr_wait	long	50_000_000
    main_wait	long	5_000_000
    isrticks	long	0
    		orgf	$200
    		org	$200 
    isr
    		notb	outb,#isr_led
    		addct1	isrticks, isr_wait
    		reti1
    

    If anyone thinks the 'orgf $200' followed by 'org $200' seems redundant, if you remove the 'org $200', PNUT tells you the 'Cog origin exceeds limit.'
  • mindrobots wrote: »
    cgracey wrote: »
    Mindrobots,

    In the middle example, change 'ORGH $200' to 'ORG $200'. ORG allows two ranges, $000..$1FF for cog and $200..$3FF for lut.

    One other thing... Change 'mov ijmp1,##isr>>2' to 'mov ijmp1,##isr'.

    Chip,

    To get your changes to work, the only additional thing I needed to do was insert 'orgf $200' before the 'org $200'. Without the orgf, PNUT doesn't generate the code to fill out to $200. Ctrl-M looks a bit empty. With the orgf, you get zeroes out to byte 800 before the LUT code starts.

    This is the final result for the middle program above:
    con
    main_led	=	0
    isr_led		=	1
    
    dat
    		orgh	0
    
    		org	0
    
    start
    		loc	adra,#@isr
    		setq2	#3
    		rdlong	0,adra
    		setb	dirb,#main_led
    		setb	dirb,#isr_led
    		getct	isrticks
    		addct1	isrticks,isr_wait
    		mov	ijmp1,##isr
    		setint1	#1
    
    blink		
    		notb	outb,#main_led		'flip its output state
    		waitx	main_wait		'wait that many clocks
    		jmp	#blink		'do it again
    		
    
    isr_wait	long	50_000_000
    main_wait	long	5_000_000
    isrticks	long	0
    		orgf	$200
    		org	$200 
    isr
    		notb	outb,#isr_led
    		addct1	isrticks, isr_wait
    		reti1
    

    If anyone thinks the 'orgf $200' followed by 'org $200' seems redundant, if you remove the 'org $200', PNUT tells you the 'Cog origin exceeds limit.'

    I'm pretty sure you shouldn't need the orgf. I think you're doing something wrong. Check your "loc adra, #@isr". What if you replace it with "mov adra, ##@isr", since you probably want an absolute hub address in this case and loc is generally for resolving relative addresses?

  • I'm pretty sure you shouldn't need the orgf. I think you're doing something wrong. Check your "loc adra, #@isr". What if you replace it with "mov adra, ##@isr", since you probably want an absolute hub address in this case and loc is generally for resolving relative addresses?

    Yup! That works! I can get rid of the orgf. Thanks!!

    Accidentally, I tried 'mov adra,#@isr' also worked.....which is just in this case and would soon break as my COG image grows. The address references are still making me scratch my head sometimes.

  • OK, absolutely on reason to do this. One ISR in COG, one ISR in LUT, one ISR in HUB and the main code bounces back and forth between COG exec and HUB exec as it waits for interrupts. Just for added stress, I put a big block of filler code in HUB to exercise the FIFO.

    I got rid of the WAITX in the main code. It has no timer, it just toggles LED0 on and off as it gets notified that an interrupt has occurred.
    con
    main_led	=	0
    isr1_led	=	1
    isr2_led	=	2
    isr3_led	=	3
    
    dat
    		orgh	0
    
    		org	0
    
    start
    		setb	dirb,#main_led
    		setb	dirb,#isr1_led
    		setb	dirb,#isr2_led
    		setb	dirb,#isr3_led
    
    	' isr1 is in COG RAM
    		getct	isr1_ticks
    		addct1	isr1_ticks,isr1_wait
    		mov	ijmp1,#isr1
    		setint1	#1
    
    	' isr2 is in LUT RAM
    		mov	adra,##@isr2
    		setq2	#3
    		rdlong	0,adra
    		getct	isr2_ticks
    		addct2	isr2_ticks,isr2_wait
    		mov	ijmp2,##isr2
    		setint2	#2
    
    	' isr3 is in HUB RAM
    		getct	isr3_ticks
    		addct3	isr3_ticks,isr3_wait	
      		loc	adra,#@isr3
    		mov	ijmp3,adra
    		setint3	#3
    
    blink		
    		notb	outb,#main_led		'flip its output state
    		waitint	
    		jmp	#@hblink		' go to HUB exec
    
    isr1_wait	long	12_400_000
    isr2_wait	long	12_500_000
    isr3_wait	long	12_600_000
    isr1_ticks	long	0
    isr2_ticks	long	0
    isr3_ticks	long	0
    scratch		long	0
    scratch2	long	0
    
    isr1
    		notb	outb,#isr1_led
    		addct1	isr1_ticks,isr1_wait
    		reti1
    
    		org	$200
    isr2
    		notb	outb,#isr2_led
    		addct2	isr2_ticks,isr2_wait
    		reti2
    
    		orgh	$1000
    
    hblink		notb	outb,#main_led	' toggle the LED
    
    	'	just a bunch of filler instructions to exercise HUB FIFO
    		mov	scratch,#1
    		add	scratch,#1
    		mov	scratch2, scratch
    		add	scratch2,#3
    		mov	scratch,#1
    		add	scratch,#1
    		mov	scratch2, scratch
    		add	scratch2,#3
    		mov	scratch,#1
    		add	scratch,#1
    		mov	scratch2, scratch
    		add	scratch2,#3
    		mov	scratch,#1
    		add	scratch,#1
    		mov	scratch2, scratch
    		add	scratch2,#3
    		mov	scratch,#1
    		add	scratch,#1
    		mov	scratch2, scratch
    		add	scratch2,#3
    		mov	scratch,#1
    		add	scratch,#1
    		mov	scratch2, scratch
    		add	scratch2,#3
    	
    	' wait for one of the interrupts to happen
    		waitint
    		jmp	#blink		' go back to COG exec
    
    isr3
    		notb	outb,#isr3_led
    		addct3	isr3_ticks,isr3_wait
    		reti3
    

  • jmgjmg Posts: 15,173
    mindrobots wrote: »
    If anyone thinks the 'orgf $200' followed by 'org $200' seems redundant, if you remove the 'org $200', PNUT tells you the 'Cog origin exceeds limit.'

    A warning / error sort of makes sense because you do not want to casually cross the COG-LUT bondary.

    ( IIRC aren't the SFRs there anyway - you should be warned when you bump into those ?)

    It does make a better case for ORGL to explicitly move into LUT area. Using the same ORG for two of three areas is just confusing.
  • jmgjmg Posts: 15,173
    mindrobots wrote: »
    The address references are still making me scratch my head sometimes.
    Yes, hopefully these can be cleaned up by making the tools a little more aware.

Sign In or Register to comment.