flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > IRQ only fires once? |
Author |
|
newport 23 Nov 2014, 00:45
First, let me say that I did my research and have read every pertaining thread within this board and searched extensively on the net for an answer before posting...
After achieving a working IDT thanks to everyone who commented on my last thread, I've got the keyboard interrupt working. However, it will only fire once.. I have no idea what is wrong.. There's way too much code to paste within here, so I am including a re-organized copy of my working OS for download to examine the code... I would appreciate any help I could get on this one.. Thanks in advance!
|
|||||||||||
23 Nov 2014, 00:45 |
|
BAiC 23 Nov 2014, 09:44
I forgot to mention you also need to read the keyboard data.
Code: in al, 0x60;keyboard controller data port. so the code should look like this: Code: isr33: push eax in al, 0x60;read the keyboard controller data port mov al, 0x60+1 out 0x20, al mov[0xB8000], word 10 shl 8 + 'a' pop eax iret |
|||
23 Nov 2014, 09:44 |
|
BAiC 23 Nov 2014, 14:32
the following will show the code works by printing the character to the screen:
Code: isr33: push eax edi in al, 0x60;read the keyboard controller data port to get the scancode. test al, al js @f ;convert the scancode to ASCII. movzx eax, byte [eax+normal_keymap] add eax, 10 shl 8 ;calculate the pointer in memory. mov edi, 2 xadd[.idx],edi ;write the ASCII character to memory. mov[edi],ax @@: ;respond to the interrupt controller. mov al, 0x60+1 out 0x20, al pop edi eax iret align 4 .idx dd 0xB8000+ 160*3 _________________ byte me. |
|||
23 Nov 2014, 14:32 |
|
newport 23 Nov 2014, 20:28
I do appreciate your help very much BAiC, but I tried your suggestions and I can't get them to work either. In fact I receive an invalid opcode error. My updated code reflects the following... the string "Keyboard Interrupt Handled" appears on the screen upon striking a key, however, it's only executed once...
Code: align 4 ;int33 irq1: pushad push ds push es push fs push gs call newLine mov esi, imsg call printString pop gs pop fs pop es pop ds in al, 0x60;read the keyboard controller data port mov al, 0x60+1 out 0x20, al popad iret thanks again for your help CORRECTION: ok... i got it working.. the pushad and popad was affecting the outcome.. I replaced this with push eax ebx ecx edx edi and was still having issues. It was not until I did not push or pop esi and edi that it worked... thanks.. so you were right all along!!! my apologies... the corrected working code is as follows... Code: align 4 ;int33 irq1: ;pushad push eax ebx ecx edx push ds push es push fs push gs call newLine mov esi, imsg call printString pop gs pop fs pop es pop ds in al, 0x60;read the keyboard controller data port mov al, 0x60+1 out 0x20, al ;popad pop edx ecx ebx eax iret |
|||
23 Nov 2014, 20:28 |
|
smiddy 23 Nov 2014, 21:02
Check this page out, it may provide more details into why things are not working as expected: http://www.brokenthorn.com/Resources/OSDevPic.html
In reviewing my own code I don't do this: Code: mov al,0x60+1 out 0x20, al I do this: Code: .FinishUp: mov al,20h ; Load EOI into AL out 20h,al ; Send to first PIC port Looking around, I have no idea why you would do 0x60+1. The page link I just sent wrote: Sending End of Interrupt (EOI) Based on this set of information, 0x61 (effectively) is not an option...maybe I'm missing something. Last edited by smiddy on 23 Nov 2014, 21:04; edited 1 time in total |
|||
23 Nov 2014, 21:02 |
|
newport 23 Nov 2014, 21:04
For all those entering into the world of x86 Assembly OS programming, I have included my working example for anyone who wishes to study the code. It has taken me nearly 2 years of on/off studying of assembly and the help of the wonderful people in these forums just to get to the point I am at now. Please make sure you understand how and why the code works the way it does, and not simply just copy it to use in your own OS. The zip file includes a two-stage bootloader with a very minimilistic kernel and a working keyboard interrupt. All organized in 4 simple and easy to read files. While it is not perfect and very far from being a complete OS, it does provide useful studying information nonetheless. Enjoy!
|
|||||||||||
23 Nov 2014, 21:04 |
|
newport 23 Nov 2014, 21:18
smiddy wrote: Check this page out, it may provide more details into why things are not working as expected: http://www.brokenthorn.com/Resources/OSDevPic.html I have read the same thing you did smiddy and tried your example yet it doesn't work the way I(we) think it would.. but, doing it BAiC's way works.. this is something I'm still trying to research and grasp the concept for myself...back to the intel docs... lol |
|||
23 Nov 2014, 21:18 |
|
BAiC 24 Nov 2014, 03:32
smiddy wrote: Check this page out, it may provide more details into why things are not working as expected: http://www.brokenthorn.com/Resources/OSDevPic.html there are two options to issuing an interrupt response: 1) tell the PIC which interrupt you're responding to directly (in the low 3 bits, corresponding to ints 0-7). this is the 0x60+INT message. 2) tell the PIC to respond to the highest priority interrupt that is currently running. this is the 0x20 message. just imagine multiple (at least two) higher priority interrupts occurring while the current interrupt is running: you'll end up responding to the highest priority interrupt (not the current) and cause the middle one to begin executing. the fact that it's only the controller being responded to means the device will likely just issue another interrupt (this is usually true for 'line' interrupts and usually false for 'edge' interrupts). - Stefan _________________ byte me. |
|||
24 Nov 2014, 03:32 |
|
smiddy 24 Nov 2014, 11:25
BAiC wrote:
Now I am even more confused. Although, I think I get what you're saying. So, no matter what bit 5 has to be set on the Operation Command Word (OCW) (ala 0x20 or 0x60, etcetera). The fact that you use 0x60 says you're wishing to end a specific interrupt. Bit 0, of the OCW says which interrupt level in which to react to, in this case an L0, which I'm not sure of, because 'line' triggered doesn't make sense to me. Where 'level' triggered would, being that there are three bits, L0 thru L2, that correspond to 0 to 7 levels, depending on the bits used. This is what must be confusing me. You're saying that since the keyboard ISR is 1, you set L0 = 1, and the bits 5 and 6 being set says, only react to the end of this L0. The L0 thru L2 correspond to the ISRs, in this case should be set for each ISR's number (for each PIC). The jargon used is confusing, since I get "line" now, where level is being used in the data sheet. So, the fact that mine works is only likely because I only have it and the timer running, it gets much more complicated if I have more items running, and I would run into collisions as you must be saying. Is that correct? |
|||
24 Nov 2014, 11:25 |
|
BAiC 24 Nov 2014, 16:38
first of all: using the term "line" was an error on my part. the term "Level" is what I meant. I haven't used the term in awhile so I honestly forgot.
secondly for the edge/level thing: the hardware may use either but it doesn't change the response to the interrupt controller: you always need to send an End of Interrupt. you configure the Edge/Level when you initialize the controller for a specific interrupt pin. btw: the configuration ports for Edge/Level are at 0x4D0 (master) and 0x4D1 (slave). the ports are readable so you might get some insight into the current BIOS configuration of your computer by looking at it. as for the EOI: I've seen the 0x20 on every example I've ever read concerning the PIC as well as the documentation. I only learned about the Specific EOI by reading the documentation. I made a judgment call to ignore the non-specific EOI to avoid the race condition. I have interrupts for keyboard(int1),soundblaster(int5, not used any more), floppy(int6), rtc(int8), mouse(int12), ATA HardDrive/Optical(int14 and int15). all of them work as expected using the Specific Interrupt method so I have no reason to use the non-specific mode. Quote: So, no matter what bit 5 has to be set on the Operation Command Word (OCW) bit 5 is set for both methods but I think it's a coincidence. this is what I understand of the OCW situation: when you write to port 0x20 the device looks at bit 4 first. if bit 4 is 1 then it's an Initialize Command Word. if it's a 0 then bit 3 specifies which OCW it is (2 or 3, OCW1 is the Interrupt Mask which is at address 0x21 rather than 0x20). - Stefan _________________ byte me. |
|||
24 Nov 2014, 16:38 |
|
smiddy 24 Nov 2014, 18:13
Thanks, I like the specific EOI.
I'm a "hardware guy" learning to code, for fun, which is what confused me on the edge/level. I do a lot of analysis in that realm developing systems. I hope to have timer, keyboard, and HDDs setup by years end, if I can find time to ring out my memory mapping, and usage. But that's another topic for another time. I appreciate your insight, thanks! Smiddy |
|||
24 Nov 2014, 18:13 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.