cpuport.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. * 2023-10-25 Shell Move ffs to cpuport, add general implementation
  9. * by inline assembly
  10. * 2024-01-18 Shell support rt_hw_thread_self to improve overall performance
  11. */
  12. #ifndef CPUPORT_H__
  13. #define CPUPORT_H__
  14. #include <armv8.h>
  15. #include <rtcompiler.h>
  16. #include <rtdef.h>
  17. #ifdef RT_USING_SMP
  18. /**
  19. * Spinlock
  20. */
  21. typedef struct
  22. {
  23. rt_uint32_t value;
  24. } rt_hw_spinlock_t;
  25. #endif /* RT_USING_SMP */
  26. #define rt_hw_barrier(cmd, ...) \
  27. __asm__ volatile (RT_STRINGIFY(cmd) " "RT_STRINGIFY(__VA_ARGS__):::"memory")
  28. #define rt_hw_isb() rt_hw_barrier(isb)
  29. #define rt_hw_dmb() rt_hw_barrier(dmb, ish)
  30. #define rt_hw_wmb() rt_hw_barrier(dmb, ishst)
  31. #define rt_hw_rmb() rt_hw_barrier(dmb, ishld)
  32. #define rt_hw_dsb() rt_hw_barrier(dsb, ish)
  33. #define rt_hw_wfi() rt_hw_barrier(wfi)
  34. #define rt_hw_wfe() rt_hw_barrier(wfe)
  35. #define rt_hw_sev() rt_hw_barrier(sev)
  36. #define rt_hw_cpu_relax() rt_hw_barrier(yield)
  37. #define rt_hw_sysreg_write(sysreg, val) \
  38. __asm__ volatile ("msr "RT_STRINGIFY(sysreg)", %0"::"r"((rt_uint64_t)(val)))
  39. #define rt_hw_sysreg_read(sysreg, val) \
  40. __asm__ volatile ("mrs %0, "RT_STRINGIFY(sysreg)"":"=r"((val)))
  41. void _thread_start(void);
  42. #ifdef RT_USING_CPU_FFS
  43. /**
  44. * This function finds the first bit set (beginning with the least significant bit)
  45. * in value and return the index of that bit.
  46. *
  47. * Bits are numbered starting at 1 (the least significant bit). A return value of
  48. * zero from any of these functions means that the argument was zero.
  49. *
  50. * @return return the index of the first bit set. If value is 0, then this function
  51. * shall return 0.
  52. */
  53. rt_inline int __rt_ffs(int value)
  54. {
  55. #ifdef __GNUC__
  56. return __builtin_ffs(value);
  57. #else
  58. __asm__ volatile (
  59. "rbit w1, %w0\n"
  60. "cmp %w0, 0\n"
  61. "clz w1, w1\n"
  62. "csinc %w0, wzr, w1, eq\n"
  63. : "=r"(value)
  64. : "0"(value)
  65. );
  66. return value;
  67. #endif
  68. }
  69. #endif /* RT_USING_CPU_FFS */
  70. #ifdef ARCH_USING_HW_THREAD_SELF
  71. rt_inline struct rt_thread *rt_hw_thread_self(void)
  72. {
  73. struct rt_thread *thread;
  74. __asm__ volatile ("mrs %0, tpidr_el1":"=r"(thread));
  75. return thread;
  76. }
  77. rt_inline void rt_hw_thread_set_self(struct rt_thread *thread)
  78. {
  79. __asm__ volatile ("msr tpidr_el1, %0"::"r"(thread));
  80. }
  81. #endif /* ARCH_USING_HW_THREAD_SELF */
  82. #endif /*CPUPORT_H__*/