Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
I decided to start my OS based on broken thorn's OS dev series. I modified the interface to my liking and changed file names a little bit. I also added debug messages to the kernel startup to diagnose problems. I can run it fine in virtual box because it quickly goes to the prompt after initializing HAL, interrupts, ect. However, when I run it on a real hardware it just hangs at initializing the HAL code. I can't seem to figure out why
This is indeed the result one would expect. You did not expect it to run on real hardware on first attempt, do you?
Some common problem on running test OS (especially tutorials) real hardware is having assumptions - assume hardware(eg. PS2 controller, A20) exists, or accessible at special location.
If it hangs, it should be trivial to find out at which instruction it hangs. Even in a programme 1 million lines long you should be able to use a 'divide and conquer' method and find your problem within 20 guesses. Have you done that yet ?
From there, it should be simple to see what's wrong and fix it.
If a trainstation is where trains stop, what is a workstation ?
Like gerryg400 suggested use some output functionality (like printf(), or even an LED would do) to determine at which of those 6 points it "hangs". Then recursively apply that strategy to the functions being called until you end up at the exact instruction it all goes wrong.
ponyboy wrote:It appears to hang on enabling interrupts, or when returning back to init() in the kernel.
You can place an output function call right in front of the return in hal_initialize() and then another one right after the call to hal_initialize() in init(). That way you can figure out whether it is either or.
The error is most probably the interrupt handler for the PIT itself. The typical censuses is to write the actual interrupt handler in assembly language rather then C to prevent problems caused by the compiler and increases portability (no need for odd stack manipulation that can break between compiler versions or compiler extensions.) If you really prefer to use C for the interrupt handler, though, I recommend making it a naked function and getting rid of your stack changes:
/* note: __declspec(naked) is MSVC specific. It is better to write
this in assembler, or use a generic ISR stub in assembler that calls your C handler */
__declspec(naked) void _cdecl i86_pit_irq () {
//! increment tick count
_pit_ticks++;
//! tell hal we are done
interruptdone(0);
}
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}