OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 5:57 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 4:51 am 
Offline
Member
Member

Joined: Thu Aug 18, 2016 12:54 pm
Posts: 25
Hello, all. Right now I am trying to write IDE driver for a minimal filesystem implementation in my OS. Since IDE configuration requires a sleep() function for a delay of 400ms, all the implementation that I have seen till now has Multitasking support and are stopping the currently running processes. It is correct to think as there should be some other process running for it to sleep. Can I implement sleep without multitasking or do I have to add multitasking support first?

_________________
drugstore-onlinecatalog.com


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 5:06 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
I'd implement multitasking first. But you can set a one-shot timer and a "hlt" instruction where you want to sleep. This will stop the processor until the interrupt from the timer.


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 5:18 am 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
Make an idle process which simply calls hlt as suggested by iansjack


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 5:28 am 
Offline
Member
Member

Joined: Thu Aug 18, 2016 12:54 pm
Posts: 25
Ch4ozz wrote:
Make an idle process which simply calls hlt as suggested by iansjack

Quote:
I'd implement multitasking first. But you can set a one-shot timer and a "hlt" instruction where you want to sleep. This will stop the processor until the interrupt from the timer.


I know that timer fires 18.222 per second, can I add something so that it delays for 400ms?
Code:
static void timer_callback(registers_t regs)
{
   tick++;
   if (tick % 18 == 0)
   {
      if (pit_handler_nest() != 0)
      {
         kprintf("PIT handler error");
      }
   }

}


Code:
void sleep(u32 ticks)
{
   u32 end = tick + ticks;
   while(tick < end);
}

_________________
drugstore-onlinecatalog.com


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 7:38 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

dream21 wrote:
I know that timer fires 18.222 per second, can I add something so that it delays for 400ms?


The PIT chip is left as 18.22 Hz by the BIOS (which is the slowest frequency the PIT chip supports); but it can and probably should be reprogrammed. By reprogramming the PIT chip you can set it to any frequency from 18.22 Hz to about 10 KHz, but (instead of having a fixed frequency) you can also set it to "one shot mode" where you set the delay to what you actually want. This gives you far better precision (e.g. "+/- 838 nanoseconds of precision" rather than the "+/- 1 millisecond" you'd get if you set the PIT to a fixed frequency of 1 KHz) and avoids IRQs you don't want (e.g. one IRQ after 400 ms rather than 400 IRQs with an IRQ every 1 ms).

Note that I'd also recommend abstracting the time source, so that it's trivial to add support for other time sources (HPET, local APIC timer, etc) later. With this in mind I'd keep track of time using something like "nanoseconds since boot" that is always the same regardless of time source (and wouldn't use something like "ticks since boot").

I'd also consider going one step further and using something similar for tracking real time (e.g. 64-bit nanoseconds since the year 2000) so you can do "current_time = nanoseconds_since_boot + time_at_boot".


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 9:47 am 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
dream21 wrote:
Hello, all. Right now I am trying to write IDE driver for a minimal filesystem implementation in my OS. Since IDE configuration requires a sleep() function for a delay of 400ms, all the implementation that I have seen till now has Multitasking support and are stopping the currently running processes. It is correct to think as there should be some other process running for it to sleep. Can I implement sleep without multitasking or do I have to add multitasking support first?

May I just comment that you might want to look at the specifications once more. That 400ms is probably 400ns (nano). A read from the Alt Status Register takes longer than this, so is a good delay.

However, you will need to implement a timer of some kind sooner or later (pun intended), so take the suggestions made here.
Ben


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 10:36 am 
Offline
Member
Member

Joined: Thu Aug 18, 2016 12:54 pm
Posts: 25
Brendan wrote:
Note that I'd also recommend abstracting the time source, so that it's trivial to add support for other time sources (HPET, local APIC timer, etc) later. With this in mind I'd keep track of time using something like "nanoseconds since boot" that is always the same regardless of time source (and wouldn't use something like "ticks since boot").

I'd also consider going one step further and using something similar for tracking real time (e.g. 64-bit nanoseconds since the year 2000) so you can do "current_time = nanoseconds_since_boot + time_at_boot".


Thank you for your suggestions sir but right now I am in more need of examples or refrences as I am new here. Surely your suggestions will help me make a more reliable RTC in the future.

_________________
drugstore-onlinecatalog.com


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Sat May 13, 2017 10:43 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

dream21 wrote:
Thank you for your suggestions sir but right now I am in more need of examples or refrences as I am new here. Surely your suggestions will help me make a more reliable RTC in the future.


There's example code for the PIT in the wiki page for the PIT, and example code for the RTC in the wiki page for the RTC ("Real Time Clock").


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Mon May 15, 2017 8:57 am 
Offline
Member
Member

Joined: Thu Aug 18, 2016 12:54 pm
Posts: 25
Brendan wrote:
There's example code for the PIT in the wiki page for the PIT, and example code for the RTC in the wiki page for the RTC ("Real Time Clock").


I looked at the RTC and CMOS tutorial and made a working implementation. My code is just a copy and goes like this.

Code:
u8 read_register(int reg)
{
   outb(reg, cmos_address);
   return inb(cmos_data);
}

int get_update_in_progress_flag()
{
   outb(0x0A, cmos_address);
   return (inb(cmos_data) & 0x80);
}
time_t rtc_handler()
{
   bool ready = read_register(0x0C) & 0x10;
   if (ready)
   {
      {
         current_time.second = read_register(0x00);
         current_time.minute = read_register(0x02);
         current_time.hour = read_register(0x04);
         current_time.month = read_register(0x08);
         current_time.year = read_register(0x09);
         current_time.day_of_week = read_register(0x06);
         current_time.day_of_month = read_register(0x07);
         current_time.century = read_register(0x32);
      }
   }   
   return current_time;
}
void rtc_install(void)
{
   unsigned char status;

   status = read_register(0x0B);
   status |= 0x02;         // 24 hour clock
   status |= 0x10;         // update ended interrupts
   status &= ~0x20;      // no alarm interrupts
   status &= ~ 0x40;      // no periodic interrupts
   bcd = !(status & 0x04);   // check if data type is BCD
   write_register(0x0B, status);

   read_register(0x0C);

   //register_interrupt_handler(40, &rtc_handler);
}


The problem is when I try to print the hour and minutes, it gives me incorrect results. Also I have to give a certain amount of delay between rtc_install and printing the values. What could be the reason for it?

_________________
drugstore-onlinecatalog.com


Top
 Profile  
 
 Post subject: Re: Multitasking for real time clock?
PostPosted: Mon May 15, 2017 9:52 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

dream21 wrote:
I looked at the RTC and CMOS tutorial and made a working implementation. My code is just a copy and goes like this.


This code:
Code:
u8 read_register(int reg)
{
   outb(reg, cmos_address);
   return inb(cmos_data);
}

needs some kind of protection around it, in case an IRQ or task switch happens causing something else to change "cmos_address" after it's been set but before "cmos_data" has been read.

This code:
Code:
int get_update_in_progress_flag()
{
   outb(0x0A, cmos_address);
   return (inb(cmos_data) & 0x80);
}

should use the "read_register()" function above instead for reading the register itself.


This code:
Code:
time_t rtc_handler()
{
   bool ready = read_register(0x0C) & 0x10;
   if (ready)
   {
      {
         current_time.second = read_register(0x00);
         current_time.minute = read_register(0x02);
         current_time.hour = read_register(0x04);
         current_time.month = read_register(0x08);
         current_time.year = read_register(0x09);
         current_time.day_of_week = read_register(0x06);
         current_time.day_of_month = read_register(0x07);
         current_time.century = read_register(0x32);
      }
   }   
   return current_time;
}

is extremely slow (every "read_register()" costs several thousand cycles of CPU time due to slow IO ports) and shouldn't be used anyway.

Typically an OS gets the current time from the RTC once during boot and convert it into some kind of "time since epoch" format (e.g. "seconds since 1970 in UTC", or "nanoseconds since 2000 in UTC" or ...), and then only does a "time_since_epoch += time_between_ticks" (e.g. when the update IRQ occurs) after that.

This code:
Code:
void rtc_install(void)
{
   unsigned char status;

   status = read_register(0x0B);
   status |= 0x02;         // 24 hour clock
   status |= 0x10;         // update ended interrupts
   status &= ~0x20;      // no alarm interrupts
   status &= ~ 0x40;      // no periodic interrupts
   bcd = !(status & 0x04);   // check if data type is BCD
   write_register(0x0B, status);

   read_register(0x0C);

   //register_interrupt_handler(40, &rtc_handler);
}

is broken. You can't change the way the RTC's time/date registers are configured (e.g. change them from 12-hour to 24-hour) without breaking the BIOS and ruining everything. Unlike most hardware, the RTC is battery backed and remembers how its time/date registers are configured even when the computer is turned off, which means that if you change it then turn the computer off, the next time the computer is turned on the BIOS sees all kinds of unexpected data in the time/date registers because the RTC was left in a state that the BIOS doesn't expect and doesn't support.

Instead; you need to leave the time/date register configuration "as is", and read the pre-existing configuration to figure out how to decode the time/date register values (e.g. convert from BCD to binary if it was using BCD, and convert from 12-hour to 24-hour if it was using 12-hour; so that you end up with "binary 24-hour" regardless of how the time/date registers are configured).

Note: If you do change the way the RTC's time/date registers are configured; then you also have to write corrected values into those registers. For example, if the RTC was configured as "12-hour BCD" and the "hour" register contains the value 0x82 (meaning 2 pm) and you change it to "24-hour BCD", then the "hour" register will still contain the value 0x82 (meaning 82 o'clock, which is pure nonsense).

dream21 wrote:
Also I have to give a certain amount of delay between rtc_install and printing the values. What could be the reason for it?


I have no idea - there's no code to print any of the values. Note that it should take up to 1 second before you get your first "update interrupt" (and if you're using an emulator, in some cases "1 virtual second" could take "10 actual seconds").


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: DotBot [Bot], SemrushBot [Bot] and 57 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group