drv_timer.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-07-16 JasonHu first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtconfig.h>
  13. #include "board.h"
  14. /* PIT (Programmable Interval Timer)8253/8254 可编程中断计时器 */
  15. /*
  16. Port 40h, 8253 Counter 0 Time of Day Clock (normally mode 3)
  17. */
  18. #define PIT_COUNTER0 0x40
  19. /*
  20. Port 41h, 8253 Counter 1 RAM Refresh Counter (normally mode 2)
  21. */
  22. #define PIT_COUNTER1 0x41
  23. /*
  24. Port 42h, 8253 Counter 2 Cassette and Speaker Functions
  25. */
  26. #define PIT_COUNTER2 0x42
  27. /*
  28. Programmable interrupt timer, control word register:
  29. Port 43h, 8253 Mode Control Register, data format:
  30. |7|6|5|4|3|2|1|0| Mode Control Register
  31. | | | | | | | `---- 0=16 binary counter, 1=4 decade BCD counter
  32. | | | | `--------- counter mode bits
  33. | | `------------ read/write/latch format bits
  34. `--------------- counter select bits (also 8254 read back command)
  35. Read Back Command Format (8254 only)
  36. |7|6|5|4|3|2|1|0| Read Back Command (written to Mode Control Reg)
  37. | | | | | | | `--- must be zero
  38. | | | | | | `---- select counter 0
  39. | | | | | `----- select counter 1
  40. | | | | `------ select counter 2
  41. | | | `------- 0 = latch status of selected counters
  42. | | `-------- 0 = latch count of selected counters
  43. `----------- 11 = read back command
  44. Read Back Command Status (8254 only, read from counter register)
  45. |7|6|5|4|3|2|1|0| Read Back Command Status
  46. | | | | | | | `--- 0=16 binary counter, 1=4 decade BCD counter
  47. | | | | `-------- counter mode bits (see Mode Control Reg above)
  48. | | `----------- read/write/latch format (see Mode Control Reg)
  49. | `------------ 1=null count (no count set), 0=count available
  50. `------------- state of OUT pin (1=high, 0=low)
  51. */
  52. #define PIT_CTRL 0x43
  53. /* Mode Control Register */
  54. enum ctrl_mode_bits
  55. {
  56. /* Bits 76 Counter Select Bits */
  57. PIT_MODE_COUNTER_0 = (0), /* 00 select counter 0 */
  58. PIT_MODE_COUNTER_1 = (1 << 6), /* 01 select counter 1 */
  59. PIT_MODE_COUNTER_2 = (1 << 7), /* 10 select counter 2 */
  60. PIT_MODE_READ_BACK = ((1 << 6) | (1 << 7)), /* 11 read back command (8254 only, illegal on 8253, see below) */
  61. /* Bits 54 Read/Write/Latch Format Bits */
  62. PIT_MODE_LPCV = (0), /* 00 latch present counter value */
  63. PIT_MODE_MSB = (1 << 4), /* 01 read/write of MSB only */
  64. PIT_MODE_LSB = (1 << 5), /* 10 read/write of LSB only */
  65. PIT_MODE_MSB_LSB = ((1 << 4) | (1 << 5)), /* 11 read/write LSB, followed by write of MSB */
  66. /* Bits 321 Counter Mode Bits */
  67. /*
  68. 000 mode 0, interrupt on terminal count; countdown, interrupt,
  69. then wait for a new mode or count; loading a new count in the
  70. middle of a count stops the countdown
  71. */
  72. PIT_MODE_0 = (0),
  73. /*
  74. 001 mode 1, programmable one-shot; countdown with optional
  75. restart; reloading the counter will not affect the countdown
  76. until after the following trigger
  77. */
  78. PIT_MODE_1 = (1 << 1),
  79. /*
  80. 010 mode 2, rate generator; generate one pulse after 'count' CLK
  81. cycles; output remains high until after the new countdown has
  82. begun; reloading the count mid-period does not take affect
  83. until after the period
  84. */
  85. PIT_MODE_2 = (1 << 2),
  86. /*
  87. 011 mode 3, square wave rate generator; generate one pulse after
  88. 'count' CLK cycles; output remains high until 1/2 of the next
  89. countdown; it does this by decrementing by 2 until zero, at
  90. which time it lowers the output signal, reloads the counter
  91. and counts down again until interrupting at 0; reloading the
  92. count mid-period does not take affect until after the period
  93. */
  94. PIT_MODE_3 = ((1 << 1) | (1 << 2)),
  95. /*
  96. 100 mode 4, software triggered strobe; countdown with output high
  97. until counter zero; at zero output goes low for one CLK
  98. period; countdown is triggered by loading counter; reloading
  99. counter takes effect on next CLK pulse
  100. */
  101. PIT_MODE_4 = (1 << 3),
  102. /*
  103. 101 mode 5, hardware triggered strobe; countdown after triggering
  104. with output high until counter zero; at zero output goes low
  105. for one CLK period
  106. */
  107. PIT_MODE_5 = ((1 << 1) | (1 << 3)),
  108. /* Bits 0 Counter Mode Bits */
  109. PIT_MODE_BINARY = (0), /* 0 0= 16 binary counter */
  110. PIT_MODE_BCD = (1), /* 1 1= 4 decade BCD counter */
  111. };
  112. #define TIMER_FREQ 1193180 /* clock frequency */
  113. #define COUNTER0_VALUE (TIMER_FREQ / RT_TICK_PER_SECOND)
  114. static void rt_hw_timer_isr(int vector, void *param)
  115. {
  116. rt_tick_increase();
  117. }
  118. int rt_hw_timer_init(void)
  119. {
  120. outb(PIT_CTRL, PIT_MODE_2 | PIT_MODE_MSB_LSB |
  121. PIT_MODE_COUNTER_0 | PIT_MODE_BINARY);
  122. outb(PIT_COUNTER0, (rt_uint8_t) (COUNTER0_VALUE & 0xff));
  123. outb(PIT_COUNTER0, (rt_uint8_t) (COUNTER0_VALUE >> 8) & 0xff);
  124. rt_hw_interrupt_install(IRQ0_CLOCK, rt_hw_timer_isr, RT_NULL, "tick");
  125. rt_hw_interrupt_umask(IRQ0_CLOCK);
  126. return 0;
  127. }