| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-07-16 JasonHu first version
- */
- #include <rthw.h>
- #include <rtthread.h>
- #include <rtconfig.h>
- #include "board.h"
- /* PIT (Programmable Interval Timer)8253/8254 可编程中断计时器 */
- /*
- Port 40h, 8253 Counter 0 Time of Day Clock (normally mode 3)
- */
- #define PIT_COUNTER0 0x40
- /*
- Port 41h, 8253 Counter 1 RAM Refresh Counter (normally mode 2)
- */
- #define PIT_COUNTER1 0x41
- /*
- Port 42h, 8253 Counter 2 Cassette and Speaker Functions
- */
- #define PIT_COUNTER2 0x42
- /*
- Programmable interrupt timer, control word register:
- Port 43h, 8253 Mode Control Register, data format:
- |7|6|5|4|3|2|1|0| Mode Control Register
- | | | | | | | `---- 0=16 binary counter, 1=4 decade BCD counter
- | | | | `--------- counter mode bits
- | | `------------ read/write/latch format bits
- `--------------- counter select bits (also 8254 read back command)
- Read Back Command Format (8254 only)
- |7|6|5|4|3|2|1|0| Read Back Command (written to Mode Control Reg)
- | | | | | | | `--- must be zero
- | | | | | | `---- select counter 0
- | | | | | `----- select counter 1
- | | | | `------ select counter 2
- | | | `------- 0 = latch status of selected counters
- | | `-------- 0 = latch count of selected counters
- `----------- 11 = read back command
- Read Back Command Status (8254 only, read from counter register)
- |7|6|5|4|3|2|1|0| Read Back Command Status
- | | | | | | | `--- 0=16 binary counter, 1=4 decade BCD counter
- | | | | `-------- counter mode bits (see Mode Control Reg above)
- | | `----------- read/write/latch format (see Mode Control Reg)
- | `------------ 1=null count (no count set), 0=count available
- `------------- state of OUT pin (1=high, 0=low)
- */
- #define PIT_CTRL 0x43
- /* Mode Control Register */
- enum ctrl_mode_bits
- {
- /* Bits 76 Counter Select Bits */
- PIT_MODE_COUNTER_0 = (0), /* 00 select counter 0 */
- PIT_MODE_COUNTER_1 = (1 << 6), /* 01 select counter 1 */
- PIT_MODE_COUNTER_2 = (1 << 7), /* 10 select counter 2 */
- PIT_MODE_READ_BACK = ((1 << 6) | (1 << 7)), /* 11 read back command (8254 only, illegal on 8253, see below) */
- /* Bits 54 Read/Write/Latch Format Bits */
- PIT_MODE_LPCV = (0), /* 00 latch present counter value */
- PIT_MODE_MSB = (1 << 4), /* 01 read/write of MSB only */
- PIT_MODE_LSB = (1 << 5), /* 10 read/write of LSB only */
- PIT_MODE_MSB_LSB = ((1 << 4) | (1 << 5)), /* 11 read/write LSB, followed by write of MSB */
- /* Bits 321 Counter Mode Bits */
- /*
- 000 mode 0, interrupt on terminal count; countdown, interrupt,
- then wait for a new mode or count; loading a new count in the
- middle of a count stops the countdown
- */
- PIT_MODE_0 = (0),
- /*
- 001 mode 1, programmable one-shot; countdown with optional
- restart; reloading the counter will not affect the countdown
- until after the following trigger
- */
- PIT_MODE_1 = (1 << 1),
- /*
- 010 mode 2, rate generator; generate one pulse after 'count' CLK
- cycles; output remains high until after the new countdown has
- begun; reloading the count mid-period does not take affect
- until after the period
- */
- PIT_MODE_2 = (1 << 2),
- /*
- 011 mode 3, square wave rate generator; generate one pulse after
- 'count' CLK cycles; output remains high until 1/2 of the next
- countdown; it does this by decrementing by 2 until zero, at
- which time it lowers the output signal, reloads the counter
- and counts down again until interrupting at 0; reloading the
- count mid-period does not take affect until after the period
- */
- PIT_MODE_3 = ((1 << 1) | (1 << 2)),
- /*
- 100 mode 4, software triggered strobe; countdown with output high
- until counter zero; at zero output goes low for one CLK
- period; countdown is triggered by loading counter; reloading
- counter takes effect on next CLK pulse
- */
- PIT_MODE_4 = (1 << 3),
- /*
- 101 mode 5, hardware triggered strobe; countdown after triggering
- with output high until counter zero; at zero output goes low
- for one CLK period
- */
- PIT_MODE_5 = ((1 << 1) | (1 << 3)),
- /* Bits 0 Counter Mode Bits */
- PIT_MODE_BINARY = (0), /* 0 0= 16 binary counter */
- PIT_MODE_BCD = (1), /* 1 1= 4 decade BCD counter */
- };
- #define TIMER_FREQ 1193180 /* clock frequency */
- #define COUNTER0_VALUE (TIMER_FREQ / RT_TICK_PER_SECOND)
- static void rt_hw_timer_isr(int vector, void *param)
- {
- rt_tick_increase();
- }
- int rt_hw_timer_init(void)
- {
- outb(PIT_CTRL, PIT_MODE_2 | PIT_MODE_MSB_LSB |
- PIT_MODE_COUNTER_0 | PIT_MODE_BINARY);
- outb(PIT_COUNTER0, (rt_uint8_t) (COUNTER0_VALUE & 0xff));
- outb(PIT_COUNTER0, (rt_uint8_t) (COUNTER0_VALUE >> 8) & 0xff);
- rt_hw_interrupt_install(IRQ0_CLOCK, rt_hw_timer_isr, RT_NULL, "tick");
- rt_hw_interrupt_umask(IRQ0_CLOCK);
- return 0;
- }
|