rtc.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #include "rtc.h"
  2. #include <common/kprint.h>
  3. /*置位0x70的第7位,禁止不可屏蔽中断*/
  4. #define read_cmos(addr) ({ \
  5. io_out8(0x70, 0x80 | addr); \
  6. io_in8(0x71); \
  7. })
  8. enum CMOSTimeSelector
  9. {
  10. T_SECOND = 0x0,
  11. T_MINUTE = 0x2,
  12. T_HOUR = 0x4,
  13. T_DAY = 0x7,
  14. T_MONTH = 0x8,
  15. T_YEAR = 0x9,
  16. };
  17. int rtc_get_cmos_time(struct rtc_time_t *t)
  18. {
  19. // 为防止中断请求打断该过程,需要先关中断
  20. cli();
  21. uint8_t status_register_B = read_cmos(0x0B); // 读取状态寄存器B
  22. bool is_24h = ((status_register_B & 0x02) ? true : false); // 判断是否启用24小时模式
  23. bool is_binary = ((status_register_B & 0x04) ? true : false); // 判断是否为二进制码
  24. do
  25. {
  26. t->year = read_cmos(0x09);
  27. t->month = read_cmos(0x08);
  28. t->day = read_cmos(0x07);
  29. t->hour = read_cmos(0x04);
  30. t->minute = read_cmos(0x02);
  31. t->second = read_cmos(0x00);
  32. } while (t->second != read_cmos(0x00)); // 若读取时间过程中时间发生跳变则重新读取
  33. // 使能NMI中断
  34. io_out8(0x70, 0x00);
  35. if (!is_binary) // 把BCD转为二进制
  36. {
  37. t->second = (t->second & 0xf) + (t->second >> 4) * 10;
  38. t->minute = (t->minute & 0xf) + (t->minute >> 4) * 10;
  39. t->hour = ((t->hour & 0xf) + ((t->hour & 0x70) >> 4) * 10) | (t->hour & 0x80);
  40. t->month = (t->month & 0xf) + (t->month >> 4) * 10;
  41. t->year = (t->year & 0xf) + (t->year >> 4) * 10;
  42. }
  43. t->year += 2000;
  44. if ((!is_24h) && t->hour & 0x80) // 将十二小时制转为24小时
  45. t->hour = ((t->hour & 0x7f) + 12) % 24;
  46. sti();
  47. return 0;
  48. }