Assembler - язык неограниченных возможностей

         

Часы реального времени и CMOS-память


В каждом компьютере есть микросхема, отвечающая за поддержку текущей даты и времени. Для того чтобы они не сбрасывались при каждом выключении питания, на микросхеме расположена небольшая область памяти (от 64 до 128 байт), выполненная по технологии CMOS, позволяющей снизить энергопотребление до минимума (фактически энергия в таких схемах затрачивается только на зарядку паразитных емкостей при изменении состояния ячеек памяти). Вся эта микросхема получает питание от аккумулятора, расположенного на материнской плате, и не отключается при. выключении компьютера. Для хранения собственно времени достаточно всего четырнадцати байт такой энергонезависимой памяти, и остальная ее часть используется BIOS для хранения различной информации, необходимой для корректного запуска компьютера. Для общения с CMOS и регистрами RTC выделяются порты ввода-вывода от 70h до 7Fh, но только назначение портов 70h и 71h одинаково для всех материнских плат:

порт 70h для записи: индекс для выбора регистра CMOS:

бит 7: прерывание NMI запрещено на время чтения/записи

бит 6: собственно индекс

порт 71h для чтения и записи: данные CMOS

После записи в порт 70h обязательно надо выполнить запись или чтение из порта 71h, иначе RTC окажется в неопределенном состоянии. Содержимое регистров CMOS варьируется для разных BIOS, но первые 33h регистра обычно выполняют следующие функции:

00h: RTC — текущая секунда (00 – 59h или 00 – 3Bh) — формат выбирается регистром 0Bh, по умолчанию — BCD

01h: RTC — секунды будильника (00 – 59h или 00 – 3Bh или FFh (любая секунда))

02h: RTC — текущая минута (00 – 59h или 00 – 3Bh)

03h: RTC — минуты будильника (00 – 59h или 00 – 3Bh или FFh)

04h: RTC — текущий час:

0 – 23h/00 – 17h (24-часовой режим)




1 – 12h/01 – 1Ch (12-часовой режим до полудня)

81h – 92h/81 – 8Ch (12-часовой режим после полудня)

05h: RTC — часы будильника ( то же или FFh, если любой час)

06h: RTC — текущий день недели (1 – 7, 1 — воскресенье)

07h: RTC — текущий день месяца (01 – 31h/01h – 1Fh)

08h: RTC — текущий месяц (01 – 12h/01 – 0Ch)

09h: RTC — текущий год (00 – 99h/00 – 63h)

0Ah: RTC — регистр состояния А

бит 7: 1 — часы заняты (происходит обновление)

биты 4 – 6: делитель фазы (010 — 32 768 KHz — по умолчанию)

биты 3 – 0: выбор частоты периодического прерывания:

0000 — выключено

0011 — 122 микросекунды (минимум)

1111 — 500 миллисекунд

0110 — 976,562 микросекунды (1024 Hz)

0Bh: RTC — регистр состояния В

бит 7: запрещено обновление часов (устанавливают перед записью новых значений в регистры даты и часов)

бит 6: вызов периодического прерывания (IRQ8)

бит 5: вызов прерывания при срабатывании будильника

бит 4: вызов прерывания по окончании обновления времени

бит 3: включена генерация прямоугольных импульсов

бит 2: 1/0 — формат даты и времени двоичный/BCD

бит 1: 1/0 — 24-часовой/12-часовой режим

бит 0: автоматический переход на летнее время в апреле и октябре

0Ch только для чтения: RTC — регистр состояния С

бит 7: произошло прерывание

бит 6: разрешено периодическое прерывание

бит 5: разрешено прерывание от будильника

бит 4: разрешено прерывание по окончании обновления часов



0Dh только для чтения: регистр состояния D

бит 7: питание RTC/CMOS есть

0Eh: результат работы POST при последнем старте компьютера:

бит 7: RTC сбросились из-за отсутствия питания CMOS

бит 6: неверная контрольная сумма CMOS-конфигурации

бит 5: неверная конфигурация

бит 4: размер памяти не совпадает с записанным в конфигурации

бит 3: ошибка инициализации первого жесткого диска

бит 2: RTC-время установлено неверно (например, 30 февраля)

0Fh: состояние, в котором находился компьютер перед последней перезагрузкой

00h — Ctr-Alt-Del

05h — INT 19h

0Ah, 0Bh, 0Ch — jmp, iret, retf на адрес, хранящийся в 0040h:0067h

Другие значения указывают, что перезагрузка произошла в ходе POST или в других необычных условиях

10h: тип дисководов (биты 7 – 4 и 3 – 0 — типы первого и второго дисковода)

0000: отсутствует

0001: 360 Кб

0010: 1,2 Мб

0011: 720 Кб

0100: 1,44 Мб

0101: 2,88 Мб

12h: тип жестких дисков (биты 7 – 4 и 3 – 0 — типы первого и второго жестких дисков, 1111, если номер типа больше 15)

14h: байт состояния оборудования

биты 7 – 6: число установленных жестких дисков минус один

биты 5 – 4: тип монитора (00, 01, 10, 11 — EGA/VGA, 40x25 CGA, 80x25 CGA, MDA)

бит 3: монитор присутствует

бит 2: клавиатура присутствует

бит 1: FPU присутствует

бит 0: дисковод присутствует

15h: младший байт размера базовой памяти в килобайтах (80h)

16h: старший байт размера базовой памяти в килобайтах (02h)

17h: младший байт размера дополнительной памяти (выше 1 Мб) в килобайтах

18h: старший байт размера дополнительной памяти (выше 1 Мб) в килобайтах

19h: тип первого жесткого диска, если больше 15



lAh:  тип второго жесткого диска, если больше 15

2Eh: старший байт контрольной суммы регистров 10h – 2Dh

2Fh: младший байт контрольной суммы регистров 10h – 2Dh

30h: младший байт найденной при POST дополнительной памяти в килобайтах

31h: старший байт найденной при POST дополнительной памяти в килобайтах

32h: первые две цифры года в BCD-формате

Данные о конфигурации, хранящиеся в защищенной контрольной суммой области, бывают нужны достаточно редко, а для простых операций с часами реального времени и будильником удобно использовать прерывание BIOS 1Ah. Однако, программируя RTC на уровне портов, можно активизировать периодическое прерывание — режим, в котором RTC вызывает прерывание IRQ8 с заданной частотой, что позволит оставить IRQ0 для работы системы, если вас удовлетворяет ограниченный выбор частот периодического прерывания. В качестве примера посмотрим, как выполняются чтение и запись в CMOS-память.

; rtctime,asm ; Вывод на экран текущей даты и времени из RTC ; .model tiny .code .186 ; для shr al,4 org 100h ; СОМ-программа start: mov al,0Bh ; CMOS OBh - управляющий регистр В out 70h,al ; порт 70h - индекс CMOS in al,71h ; порт 71h - данные CMOS and al,11111011b ; обнулить бит 2 (форма чисел - BCD) out 71h,al ; и записать обратно mov al,32h ; CMOS 32h - две старшие цифры года call print_cmos ; вывод на экран mov al,9 ; CMOS 09h - две младшие цифры года call print_cmos mov al,'-' ; минус int 29h ; вывод на экран mov al,8 ; CMOS 08h - текущий месяц call print_cmos mov al,'-' ; еще один минус int 29h mov al,7 ; CMOS 07h - день call print_cmos mov al,' ' ; пробел int 29h mov al,4 ; CMOS 04h - час call print_cmos mov al,'h' ; буква "h" int 29h mov al,' ' ; пробел int 29h mov al,2 ; CMOS 02h - минута call print_cmos mov al,':' ; двоеточие int 29h mov al,0h ; CMOS 00h - секунда call print_cmos ret

; процедура print_cmos ; выводит на экран содержимое ячейки CMOS с номером в AL ; считает, что число, читаемое из CMOS, находится в формате BCD print_cmos proc near out 70h,al ; послать AL в индексный порт CMOS in al,71h ; прочитать данные push ax shr al,4 ; выделить старшие четыре бита add al,'0' ; добавить ASCII-код цифры 0 int 29h ; вывести на экран pop ax and al,0Fh ; выделить младшие четыре бита add al,30h ; добавить ASCII-код цифры 0 int 29h ; вывести на экран ret print_cmos endp end start


Содержание раздела