View Single Post
Old 02 December 2018, 00:56   #57
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,415
Allright, I'll try.

Let's start at the beginning - you use self modifying code to write an address to jump to in your interrupt handler. That is a very, very bad idea. It can easily crash any 68020+ system. Apart from that, it's also completely unnecessary.

With this in mind, a cleaner version of the above would be:
Code:
	; Note that like your code, this is not 68020+ compatible.
	; It also probably won't work because it reads from the CIA ICR register, which can cause problems for the OS.
LEVEL2IADDR	EQU	$68
	lea.l	LEVEL2IADDR,a0
	move.l	(a0),level2_vector
	move.l	#level2i,(a0)
	...
	move.l	level2_vector,(a0)
	...

	; intr handler
level2i	btst	#3,$bfed01	; NOTE: this instruction does not work as intended (discussed below in post)
	beq	level2ie

	move.b	#1,key_ready

level2ie:
	lea	level2_vector,a2
	jmp	(a2)
	...

level2_vector	dc.l	0
More importantly, you setup your interrupt handler by changing the interrupt vector yourself and pointing back to the original vector afterwards with a jmp(). This is conform the Amiga OS guidelines (more like 'demands' in this case) about how to add interrupts and this is not the way described. There is simply put no guarantee whatsoever that the OS might not decide to change the vector later - and it won't point back to your vector if it does so. Note that I'm not saying it will do so, just that there is no guarantee it won't.

And even if it does happen to work by accident, I think it's not a good idea to ignore the OS. If you want to use the OS, use the OS for interrupts as well. It saves you mucking about with vectors and won't crash if someone decides to move the VBR to Fast RAM (and your code will crash in that case).

Your actual interrupt handler also contains a flaw - it tests a single bit in the CIA ICR register. This read action clears the CIA interrupt for all flags, not just the one you read. In other words, your interrupt handler can cause other interrupts to be cleared and thus not be handled.

Quote:
Originally Posted by Amiga Hardware Reference Manual on the CIA ICR register
When you read the DATA register, its contents are cleared (set to 0), and the IRQ line returns to a high state. Since it is cleared on a read, you must assure that your interrupt polling or interrupt service code can preserve and respond to all bits which may have been set in the DATA register at the time it was read. With proper preservation and response, it is easily possible to intermix polled and direct interrupt service methods.
However, there is a more fundamental problem - you are trying to work around the OS to get keyboard data read. The Amiga DOS function Read() is not intended for keyboard reading - it's intended for reading files. If you want to read from the keyboard using OS functions, you should look into either using input.device, or using keyboard.device.

I can't give you a working example as I don't have one ready. There is an example for keyboard.device over at http://amigadev.elowar.com/read/ADCD.../node01A0.html but it notes potential problems if input.device is also in use. AFAIK the 'OS legal way' of reading the keyboard is supposedly to use input.device.

Lastly, Read() does not cause character echo. If you see character echo in a shell/cli window that is because the OS is catching the keyboard and choosing to echo. It has nothing to do with Read().

Last edited by roondar; 02 December 2018 at 01:05.
roondar is offline  
 
Page generated in 0.07016 seconds with 11 queries