ec_timestamp.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright (c) 2025, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "ec_master.h"
  7. #ifndef CONFIG_EC_TIMESTAMP_CUSTOM
  8. #if defined(__riscv) || defined(__ICCRISCV__)
  9. #define READ_CSR(csr_num) ({ uint32_t v; __asm volatile("csrr %0, %1" : "=r"(v) : "i"(csr_num)); v; })
  10. #define CSR_MCYCLE (0xB00)
  11. #define CSR_MCYCLEH (0xB80)
  12. static inline uint64_t riscv_csr_get_core_mcycle(void)
  13. {
  14. uint64_t result;
  15. uint32_t resultl_first = READ_CSR(CSR_MCYCLE);
  16. uint32_t resulth = READ_CSR(CSR_MCYCLEH);
  17. uint32_t resultl_second = READ_CSR(CSR_MCYCLE);
  18. if (resultl_first < resultl_second) {
  19. result = ((uint64_t)resulth << 32) | resultl_first; /* if MCYCLE didn't roll over, return the value directly */
  20. } else {
  21. resulth = READ_CSR(CSR_MCYCLEH);
  22. result = ((uint64_t)resulth << 32) | resultl_second; /* if MCYCLE rolled over, need to get the MCYCLEH again */
  23. }
  24. return result;
  25. }
  26. static uint32_t g_clock_time_div;
  27. void ec_timestamp_init(void)
  28. {
  29. g_clock_time_div = ec_get_cpu_frequency() / 1000000;
  30. uint64_t start_cycle = ec_timestamp_get_time_ns();
  31. ec_osal_msleep(10);
  32. EC_ASSERT_MSG((ec_timestamp_get_time_ns() - start_cycle) >= 9000000, "Timestamp timer not running\n");
  33. }
  34. EC_FAST_CODE_SECTION uint64_t ec_timestamp_get_time_ns(void)
  35. {
  36. return (riscv_csr_get_core_mcycle() * 1000) / g_clock_time_div;
  37. }
  38. #elif defined(__arm__) || defined(__ICCARM__) || defined(__ARMCC_VERSION)
  39. #define DWT_CR (*(volatile uint32_t *)0xE0001000)
  40. #define DWT_CYCCNT (*(volatile uint32_t *)0xE0001004)
  41. #define DEM_CR (*(volatile uint32_t *)0xE000EDFC)
  42. #define DEM_CR_TRCENA (1 << 24)
  43. #define DWT_CR_CYCCNTENA (1 << 0)
  44. static volatile uint32_t g_dwt_high = 0;
  45. static volatile uint32_t g_dwt_last_low = 0;
  46. static uint32_t g_clock_time_div;
  47. static inline uint64_t arm_dwt_get_cycle_count(void)
  48. {
  49. uint32_t current_low = DWT_CYCCNT;
  50. if (current_low < g_dwt_last_low) {
  51. g_dwt_high++;
  52. }
  53. g_dwt_last_low = current_low;
  54. return ((uint64_t)g_dwt_high << 32) | current_low;
  55. }
  56. void ec_timestamp_init(void)
  57. {
  58. g_clock_time_div = ec_get_cpu_frequency() / 1000000;
  59. g_dwt_high = 0;
  60. g_dwt_last_low = 0;
  61. DEM_CR |= (uint32_t)DEM_CR_TRCENA;
  62. DWT_CYCCNT = (uint32_t)0u;
  63. g_dwt_last_low = 0;
  64. DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
  65. uint64_t start_cycle = ec_timestamp_get_time_ns();
  66. ec_osal_msleep(10);
  67. EC_ASSERT_MSG((ec_timestamp_get_time_ns() - start_cycle) >= 9000000, "Timestamp timer not running\n");
  68. }
  69. EC_FAST_CODE_SECTION uint64_t ec_timestamp_get_time_ns(void)
  70. {
  71. return (arm_dwt_get_cycle_count() * 1000) / g_clock_time_div;
  72. }
  73. #else
  74. #error "Unsupported architecture"
  75. #endif
  76. #endif