Emulating Linus Torvalds: create your own operating system from scratch (VII)

Welcome to another post about how to create our own operating system (Previous articles in the series: 1, 2, 3, 4, 5 y 6). It has been a long time since the last post, mainly due to a bug that I found in what we have today. We will see how to handle the clock on x86 architectures.

Previously we had activated the IRQs in a generic way, but there was a small problem since we did not activate them correctly and we passed extra data. We finally fix it carlosorta and I and I can continue to comment on how to continue.

Well, the clock is an IRQ, specifically the first. To configure it we will use the function that we defined previously to generically install the IRQs, the ND_IRQ_InstallHandler.

int ND_TIMER_TICKS = 0; void ND :: Timer :: Phase (int hz) {int divisor = 1193180 / hz; ND :: Ports :: OutputB (0x43,0x36); ND :: Ports :: OutputB (0x40, divisor & 0xFF); ND :: Ports :: OutputB (0x40, divisor >> 8); } void ND :: Timer :: Wait (int ticks) {unsigned long eticks; eticks = ND_TIMER_TICKS + ticks; while (ND_TIMER_TICKS <eticks) {void ND :: Timer :: Setup () {ND :: Screen :: SetColor (ND_SIDE_FOREGROUND, ND_COLOR_BLACK); ND :: Screen :: PutString ("\ nSetup timer ..."); ND_IRQ_InstallHandler (0, & ND_Timer_Handler); ND :: Screen :: SetColor (ND_SIDE_FOREGROUND, ND_COLOR_GREEN); ND :: Screen :: PutString ("done"); } extern "C" void ND_Timer_Handler (struct regs * r) {ND_TIMER_TICKS ++; if (ND_TIMER_TICKS% 18 == 0) {// ND :: Screen :: SetColor (ND_SIDE_FOREGROUND, ND_COLOR_BROWN); // ND :: Screen :: PutString ("\ nOne more second"); WE SHOULD DO A REFRESH SCREEN}}

The code runs as follows: the initialization system calls ND :: Timer :: Setup, which calls ND_IRQ_InstallHandler to insert in the first position, the IRQ0, a callback function when the event occurs, that is ND_Timer_Handler that increases the ticks. As we have set the clock speed to 18 Hz, as we will see later, if we divided it by 18 and gave us an integer, a second would have passed.

The function ND :: Timer :: Phase It helps us to adjust the speed of the timer, that extravagant number is 1.19 MHz which is a common value. Well, this function should be called if we want to change the speed of the timer, by default it goes to 18,22 Hz, a peculiar value that someone must have decided within IBM and it has remained to this day.

The function ND :: Timer :: Wait it's pretty simple, just wait with a loop while until the ticks necessary to continue.

In the image we can see that if we uncomment the code inside the ND_Timer_Handler we get this:

Seconds in NextDivel

In the next chapter we will see how to read keyboard input and make a little shell to interact with our system. As always, the code is available from GitHub under the license GNU GPL v2.


Leave a Comment

Your email address will not be published. Required fields are marked with *

*

*

  1. Responsible for the data: Miguel Ángel Gatón
  2. Purpose of the data: Control SPAM, comment management.
  3. Legitimation: Your consent
  4. Communication of the data: The data will not be communicated to third parties except by legal obligation.
  5. Data storage: Database hosted by Occentus Networks (EU)
  6. Rights: At any time you can limit, recover and delete your information.

  1.   Noah said

    Very interesting series of tutorials, personally I had not seen many about creating a Linux distribution from scratch, and even less in Spanish and so complete. I think you can learn a lot from this and as soon as I have time I hope to be able to do these tutorials.
    All I ask is that you do not get discouraged and finish the tutorial, since I have found many good tutorials that are never finished.
    Greetings and thanks :).

    1.    roader said

      It is not a linux distribution, it is a kernel 😛.

    2.    desikoder said

      You're wrong. Creating a linux distro does not imply programming anything, for example, in a linux from scratch you do not program, what you do is install (based on compiling), basic packages that make up a distro. This is very different. It is creating your own operating system. It has nothing to do with linux. This is what torvalds did in his day inspired by minix, and with that heated and popular discussion between torvalds and andrew s. tanenbaum on monolithic kernel vs microkernel.

      Greetings!

  2.   illukki said

    Thank you che. Until now I have not paid much attention to your post but I am in a project so I am going to take a look at them.
    Greetings.

  3.   roader said

    It is worth mentioning that other languages ​​can be used, such as Objective-C (++), C ++, D or Rust.

    1.    AdrianArroyoStreet said

      This is in C ++, not C. However, it is difficult to see the differences since many C ++ operators require a library backing, such as the new and delete operators. It would be very interesting to make an operating system in Rust. There is actually an IRC channel dedicated to operating systems on Rust (# rust-osdev on irc.mozilla.net). Anyone who compiles to machine code is really worth it, including Java if we use GCJ.

      1.    roader said

        Yes, indeed, Rust is a very interesting language for operating systems, because it is not only easier to learn than C or C ++ (it still continues with continuous changes, but it is easier), but it is much more secure.

  4.   roader said

    In the 70's it was quite common to program directly on the hardware, without OS.

  5.   Christopher said

    Excellent ... now I just need to understand: 3 ...

  6.   mmm said

    Hi. Thank you very much for these articles. But, if I don't have programming knowledge, I don't think I should do it, right? I mean, if not, it would be a «good, and now what do I copy and paste?» ... what a pity, I always wanted to know how to program so much and nothing, I'm more of a donkey!

    1.    desikoder said

      Don't blame yourself, you are no donkey. To begin with, not all programmers know how to write a kernel, it is a very little simple task, and in practice it is bigger. For example here the author creates generic drivers for the keyboard and the screen, manipulating the screen array, which is a method that is not used at all today. The tty in linux today are very, very complex, and do not depend on the x86 architecture having a screen array at its disposal. In addition, much of the code in C depends on the architecture, when the ideal is to make the architecture code in assembler and that the C code works on any processor. However, I do not detract from the author, because a kernel acquires the characteristics that today we consider normal in a linux kernel, for example, it is not an easy task, and rest assured that a single person is absolutely incapable of doing it. For something the big projects like linux, gcc, glibc, etc, are not made by a single person but there are many collaborators.

      Also, if you want to start programming you have quite a few guides on the web, although you have to be careful and select the good guides. I started programming in linux jumping into the pool with my head and without water (that is, with the beloved C language), although now I have some basic notions of python (which is also a very good language). There are some C books in which you give up on page 6 as much of the headache you get, but more than books these things are acquired from experience. It happens as with the OSI network model. The documentation about the osi model is absolutely impossible to understand for the newcomer, but if you find a site with a good explanation of the network layers, you quickly get the concepts to deal with technical documents such as RFCs.

      In short, there are good websites and manuals out there, it is a matter of getting down to it and finding good material.

      regards

  7.   Free_DOM said

    Hello, after trying so hard to solve the "error: no multiboot header found." and «error you need to load the kernel first», since I could not find anywhere the solution to the problem of the first article, which some like me had ... here is the solution, if it works for someone ...

    I don't know if my theory of the cause of the error is correct but anyway, the question is that when compiling the files in a 32-bit operating system, it did not generate the error, but since I have a 64-bit operating system (Gnu / Linux Debian 7), and that when compiling and testing it threw the error of "no multiboot header found", and there is a doubt, then in my opinion the error is due to the environment or architecture of the operating system in which we are compiling our files ... and well what I did is compile my files, specifying the environment or architecture of 32bits ..
    * sudo as -o kernel.o -c kernel.asm -32
    * sudo gcc -o NextKernel_Main.o -c NextKernel_Main.c -nostdlib -fPIC -ffreestanding -m32
    * sudo gcc -m32 -o START.ELF kernel.o NextKernel_Main.o -Tlink.ld -nostdlib -fPIC -ffreestanding
    The weird thing is that I have some doubts hahaha, then the operating system that we are creating step by step is for an x86 architecture or am I wrong ajajaj….

    PS: Someone to help me with the doubt, and excuse some spelling mistakes or my bad expression, and well I'm not perfect so "Perfection has its price" ... And most importantly, emulate a 32-bit operating system, holy solution … .Hahaha

    1.    martin villalba said

      Genius ! I really wanted to do this tutorial and I got off at the beginning with that mistake haha

  8.   Oscar said

    Congratulations, it is an excellent contribution. From now on I share with you that your good work through me and others will be extended;

    regards