Page 1 of 2
PIT not triggering an IRQ on VMWare.
Posted: Mon Jun 09, 2008 3:36 am
by mduft
Hi
i have a problem with the PIT not triggering an IRQ. I have all things set up (i hope correctly), but the interupt is simply not triggered. interupts work well alltogether, triggering the correspoding int manually using inline assembly works perfectly.
Also i have checked my PIT setup, but reading the timer count in a tight loop, giving me different values all the time, so it ticks...
IRQ0 is unmasked on the master PIC, so that shouldn't be a problem either.
is there a simple way to check wether any of the PIC triggered interupts are delivered?
my PIC setup is done like this:
Code: Select all
master_mask = _inp(SX_PIC_MASTER_DAT);
slave_mask = _inp(SX_PIC_SLAVE_DAT);
/* begin init, include ICW4 */
_outp(SX_PIC_MASTER_CMD, SX_PIC_ICW1_INIT | SX_PIC_ICW1_IC4);
_outp(SX_PIC_SLAVE_CMD, SX_PIC_ICW1_INIT | SX_PIC_ICW1_IC4);
/* set the interupt vector offsets */
_outp(SX_PIC_MASTER_DAT, SX_IRQ_BEGIN);
_outp(SX_PIC_SLAVE_DAT, SX_IRQ_BEGIN + 8);
/* now send the IRQ lines to connect the two PICs */
_outp(SX_PIC_MASTER_DAT, 4);
_outp(SX_PIC_SLAVE_DAT, 2);
/* now ICW4 */
_outp(SX_PIC_MASTER_DAT, SX_PIC_ICW4_8086);
_outp(SX_PIC_SLAVE_DAT, SX_PIC_ICW4_8086);
SxConPrint(" * IRQ's remapped to higher Interupts ...\n");
SxConPrint(" * Interupt Mask on PICs: Master: %bb Slave: %bb\n", master_mask, slave_mask);
_outp(SX_PIC_MASTER_DAT, master_mask);
_outp(SX_PIC_SLAVE_DAT, slave_mask);
and the timer setup is done like this:
Code: Select all
void SxTimerInit(sx_uint32 interval) {
sx_uint32 divisor = SX_PIT_FREQUENCY / interval;
sx_PitCommand cmd;
SxIrqHandlerSet(0, SxHandleTimerIRQ);
cmd.cmd.bcd = 0;
cmd.cmd.mode = SX_PIT_MODE_RATE;
_outp(SX_PIT_PORT_CMD, cmd.raw);
_outp(SX_PIT_PORT_CH0, divisor & 0xFF);
_outp(SX_PIT_PORT_CH0, (divisor>>8) & 0xFF);
SxConPrint(" * Timer divisor set to %d\n", divisor);
SxUnmaskPICInterupt(0);
}
hope thats enough but not too much information .....
Posted: Mon Jun 09, 2008 3:44 am
by AJ
Hi,
A few things to check:
1) You are reading in a 'tight loop'. Is the variable declared "volatile"?
2) Double check that you are sending an EOI at the end of the interrupt handler.
3) Double check your defines to ensure you really are setting a rate mode rather than fire once.
If you are using C and all is well in ASM, the most likely candidate is 1.
Cheers,
Adam
Posted: Mon Jun 09, 2008 3:54 am
by mduft
AJ wrote:
1) You are reading in a 'tight loop'. Is the variable declared "volatile"?
2) Double check that you are sending an EOI at the end of the interrupt handler.
3) Double check your defines to ensure you really are setting a rate mode rather than fire once.
thanks for the quick reply
1) hmm... nope, it wasn't volatile, but that one was just used to check wether _something_ happens.... i tried now with volatile, and get about the same results -> a long list of altering numbers
2) yes, i'm sending an EOI, but: it never gets there, since not a single interupt is triggered. thats my problem. i tried putting an "int 3" as first line of my interupt handler, to force a double/tripple fault, but nothing happened. the thing is that interupt handling works perfectly if i do "int 3" (or any other number of course), or provocate a div/0 exception... i seem to be completely lost here.
3) hmm... i think it's correct. heres what i have:
Code: Select all
#define SX_PIT_FREQUENCY 1193180
#define SX_PIT_PORT_CMD 0x43
#define SX_PIT_PORT_CH0 0x40
#define SX_PIT_PORT_CH1 0x41
#define SX_PIT_PORT_CH2 0x42
#define SX_PIT_MODE_IOTC 0 /* Interupt on Terminal Count */
#define SX_PIT_MODE_HWRTOS 1 /* Hardware re-triggerable one-shot */
#define SX_PIT_MODE_RATE 2 /* Rate generator */
#define SX_PIT_MODE_SQUARE 3 /* Square wave generator */
#define SX_PIT_MODE_STS 4 /* Software triggered strobe */
#define SX_PIT_MODE_HTS 5 /* Hardware triggered strobe */
and this is the union i use for more readability. i forgot that one above:
Code: Select all
typedef union {
struct {
sx_uint8 bcd : 1;
sx_uint8 mode : 3;
sx_uint8 access : 2;
sx_uint8 channel : 1;
} cmd;
sx_uint8 raw;
} sx_PitCommand;
thanks again for taking time for this!
Cheers, Markus
Posted: Mon Jun 09, 2008 4:26 am
by AJ
Hi,
Just looked at my code and I use mdoe 3 (Square wave generator) - does that make any difference? If not, I'll bow out and let someone else have a go!
Cheers,
Adam
Posted: Mon Jun 09, 2008 4:55 am
by mduft
AJ wrote:
Just looked at my code and I use mdoe 3 (Square wave generator) - does that make any difference? If not, I'll bow out and let someone else have a go!
Adam
no, it didn't make any difference
i just don't get an interupt.
Thanks anyway for taking time, maybe somebody else could help please?
Cheers, Markus
Posted: Mon Jun 09, 2008 5:08 am
by AJ
I'll have one more go
(sorry this is bitty, but I'm doing this in between a lot of work this morning!). I don't mean to be patronising, but you have done an "sti", haven't you?
Perhaps you could archive and post your code. When I get a chance, I'll have a more thorough look.
Cheers,
Adam
Posted: Mon Jun 09, 2008 5:27 am
by mduft
AJ wrote:I'll have one more go
(sorry this is bitty, but I'm doing this in between a lot of work this morning!). I don't mean to be patronising, but you have done an "sti", haven't you?
Perhaps you could archive and post your code. When I get a chance, I'll have a more thorough look.
Cheers,
Adam
hehe, i was wondering when this question comes up
yes i have done a sti, and it must have worked, since manually doing "int 32" works (which should be mapped to IRQ0 with the PIC setup i posted above, right?)...
right. i'll post the code. you'll need an installed Visual C++ 2008 (Express (which is free), or whatever up to Team System or so) to compile. I uses a network boot setup with pxegrub in vmware (the pxegrub with the lance driver for VMware is not included for size reasons (argl), but the menu.lst is use is). So if you want to use the same setup, you will want to have some external DHCP/BOOTP/TFTP server running (haneWIN DHCP is quite good for this). otherwise, this is a normal GRUB bootable multilib kernel, requiring nothing else than itself
no modules or black magic required to boot
Thanks for looking again.
Posted: Mon Jun 09, 2008 5:31 am
by mduft
err... ok another few words:
*) the code in question is mostly in sxTimer.{c,h} and in sxIntHandlers.{c,h}
*) in sxTimer.c i'm calling int 32 manually to test interupts now (so don't think its working
)
*) in sxMain.c at the end of SxCoreMain i call the SxTimerInit() and SxTimerTest() functions
all together it should be quite readable i think ...
Thanks in advance to anyone looking at my issue!
Cheers, Markus
Posted: Mon Jun 09, 2008 5:37 am
by mduft
another thing i forgot to mention (man...) is that the functions _inp, _outp, _enable and _disable are compiler intrinsics, but disassembling showed that the compiler DTRT:
Code: Select all
_SxInteruptsEnable:
00000290: 55 push ebp
00000291: 8B EC mov ebp,esp
00000293: FB sti
00000294: 5D pop ebp
00000295: C3 ret
00000296: CC int 3
i anyway believed this goes ok, since - as i said - manually triggered interupts are delivered...
thinking about this for a while now, i believe it's not the PIT but the PIC where things go wrong. i just can't tell why...
Cheers, Markus
Posted: Mon Jun 09, 2008 5:55 am
by mduft
STOP
shame on me.... somehow the SxInteruptsEnable call got lost! still i had a printf "enabling interupts", but the actual call was missing.
now things of course work perfectly! what i wonder about is, how could the "int 32" instruction work with interupts disabled?
sorry for taking up your time
now i have another question though.... how would you implement a simple sleep? is programming the PIT and doing "hlt" good? or are there better ways?
Cheers, Markus
Posted: Mon Jun 09, 2008 6:04 am
by AJ
mduft wrote:shame on me.... somehow the SxInteruptsEnable call got lost!
...
sorry for taking up your time
No probs - we've all done it!
how would you implement a simple sleep? is programming the PIT and doing "hlt" good? or are there better ways?
Personally, my scheduler deals with this. The sleep(msec) function ensures that a process is not scheduled until a given number of milliseconds have passed. It really depends what your design needs - if you are creating an RTOS, using this scheduler method would be horribly inaccurate. For my purposes, though, it's fine.
Of course, you need to decide whether you move the task to an 'inactive queue', whether the task gets immediate priority once woken and so on...
If you just program the PIT and HLT, what if someone hits the keyboard? What if another task needs to sleep for a different amount of time? (I'm assuming MT here...).
Cheers,
Adam
Posted: Mon Jun 09, 2008 6:07 am
by mduft
mhm... all good points to think about
also i saw that hlt'ing seems really slow
i'll have to think about it.
the thing i wanted to achieve is, that the vmware doesn't take up 100% cpu (which it of course does if i just - for now - run in a loop handling interupts as they arrive)
up until now i did { cli; hlt } but now i want things to continue working...
Posted: Mon Jun 09, 2008 7:55 pm
by pcmattman
how could the "int 32" instruction work with interupts disabled?
Common misconception here. The "int" instruction creates a software interrupt which will fire regardless of the IF. So running a cli instruction and then "int 32" will still fire interrupt 32.
Posted: Tue Jun 10, 2008 1:40 am
by mduft
pcmattman wrote:Common misconception here. The "int" instruction creates a software interrupt which will fire regardless of the IF. So running a cli instruction and then "int 32" will still fire interrupt 32.
thanks for clearing this up. i had never read this somewhere else before. maybe this would be a quite usefull information for beginners? if i knew that before, things would have been easier...
Posted: Tue Jun 10, 2008 1:44 am
by pcmattman
You should also note that it's not the same for exceptions. At least, not if I remember correctly. They are affected by the IF.
This though is where it gets a bit hazy, and I've got way too much schoolwork tonight to be able to test it right now.