OSDev

для всех
Текущее время: 29 мар 2024, 04:22

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 6 ] 
Автор Сообщение
СообщениеДобавлено: 15 сен 2015, 15:10 

Зарегистрирован: 15 сен 2015, 14:42
Сообщения: 5
Всем привет!

Таймер срабатывает только один раз.

Проверка работы:

вызов из main.c
Код:
void kernel_main()
{
    asm volatile ("sti"); // включить прерывания
    init_timer(50);
}


В терминале увидим однократное срабатывание. А должно повторяться с частотой 50Hz
Код:
    Timer tick counter=0


если вызвать прерывание самостоятельно, допустим, три раза
Код:
void kernel_main()
{
    // 0x20 = 32 = IRQ0
    asm volatile ("int $0x20");
    asm volatile ("int $0x20");
    asm volatile ("int $0x20");
}


Уто успех :) это означает, что каллбэк работает, а вот с делителем частоты что-то не то.
Код:
    Timer tick counter=0
    Timer tick counter=1
    Timer tick counter=2


Код(JamesM's kernel development tutorials)
Код:
/*----------------------------------------------
// Обработчик прерывания IRQ0
//--------------------------------------------*/
static void timer_callback(registers_t regs)
{
    print_text("Timer tick counter=");
    print_dec_value tick);
    tick++;
}

/*----------------------------------------------
// Инициализация таймера
//--------------------------------------------*/
void init_timer(u32int frequency)
{

    u32int divisor; /* Делитель частоты */
    u8int low;      /* Младший байт делителя */
    u8int high;     /* Старший байт делителя */

    /* Регистрируем в системе обработчик для IRQ0 */
    register_interrupt_handler(IRQ0, &timer_callback);

    /* Расчитываем делитель по заданной частоте */
    divisor = 1193180/frequency;

    /* Задаем режим работы таймера */
    outb(0x43, 0x36);

    /* Разбираем делитель на байты */
    low = (u8int) (divisor & 0xFF);
    high = (u8int) ((divisor >> 8) & 0xFF);

    /* Отсылаем делитель в канал 0 PIT */
    outb(0x40, low);
    outb(0x40, high);
}



Использую qemu-system-i386 и VirtualBox


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 сен 2015, 21:45 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1126
Существенных ошибок не видно.
Из не существенных тут отсутствует проверка на переполнение.
divisor = 1193180/frequency;
Если frequency=1, то divisor выйдет за 65535.

То, что осталось за кадром.
Должен быть бесконечный цикл.
EOI должен быть отправляться в нужный PIC, иначе внешние прерывания не будут генерироваться.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 сен 2015, 23:31 

Зарегистрирован: 15 сен 2015, 14:42
Сообщения: 5
pavia писал(а):
Должен быть бесконечный цикл.
EOI должен быть отправляться в нужный PIC, иначе внешние прерывания не будут генерироваться.

Ничего из этого не понял, но на всякий случай добавил в kernel_main()
Код:
while(true){}

и все заработало.
Эпично я сфейлил.
Правда пришлось выключить -O2 оптимизацию у gcc - с ней тоже не работает, ну тут я представляю куда копать и дизассемблер мне в помощь.

Спасибо, pavia!


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 сен 2015, 10:33 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1126
1) Первую строчку вы поняли. То что нужен бесконечный цикл
Код:
while(true){}


А вообще вы не внимательно прочитали 2 статью. Там этот цикл есть.
Код:
start:
   push    ebx                   ; Load multiboot header location

   ; Execute the kernel:
   cli                         ; Disable interrupts.
   call main                   ; call our main() function.
   jmp $                       ; Enter an infinite loop, to stop the processor
                               ; executing whatever rubbish is in the memory
                               ; after our kernel!

Последней строчкой jmp $ входим в бесконечный цикл, для предотвращения выполнения мусора лежащего в памяти после ядра.

2) Что касается второй строчки про EOI. В 5 главе всё описано:
http://www.jamesmolloy.co.uk/tutorial_h ... 20PIT.html

Система прерываний в персональных компьютерах довольно сложная и запутанная.
Существует два PIC контролёра. Которые расположены в северном мосте. Они отвечают за внешние прерывания процессора от устройств: таймер, COM-порт, USB-контролер хоста и тд. Если есть внешние, то есть и внутренние. Такие как исключение при деление на 0, ошибка защиты, конец стека, страничная ошибка и тд.


Так вот PIC буферизирует прерывания от внешних устройств. Как только он отправил сигнал о прерывании в процессор PIC начинает блокировать все оставшиеся прерывания. Ждет пока процессор не освободиться. Как только процессор освободиться он должен послать сигнал EOI (End-of-Interupt) - конец прерывания. Если его не послать, то вы не получите больше прерываний. При этом проверка с Int 20h будет работать. Так как в данном случае это будет уже внутреннее прерывание.

И как я говорил что контроллеров PIC два, то нужно отправить в нужный. А работают они каскадом. Поэтому в одном случае конец прерывания посылается ведущему. Во втором случае ведущему затем ведомому.

3) Помимо того что контроллер прерываний PIC работает с блокировкой. Внешние устройства точно также работают с блокировкой, не все. Им тоже надо послать сигнал о конце прерывания.
У таймера это делать не нужно, так как мы выбрали такой режим где нет блокировки
outb(0x43, 0x36); Тут младшая цифра - отвечает за режим.

Код:
6d=0110b
   ^^^- 3 режим


http://ru.osdev.wikia.com/wiki/Программируемый_интервальный_таймер

У контроллера i8042, сброс совмещён с чтением сканкода 60h.
И так далее.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 сен 2015, 15:04 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
pavia писал(а):
Существует два PIC контролёра. Которые расположены в северном мосте


Контроллеры прерываний расположены в южном мосте, а не в северном. Северный мост -- это сопряжение между процессором, памятью и системной шиной (PCI Express на сколько-нибудь современных ПК), сейчас он является составной частью микросхемы процессора. Ну а южный -- всяческая периферия (контроллеры SATA, USB и т.д. и т.п.), в том числе PICи.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 сен 2015, 15:36 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1126
У нас сейчас холодно. Вот и попутал.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB