irq.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-02-24 Bernard first version
  9. * 2006-05-03 Bernard add IRQ_DEBUG
  10. * 2016-08-09 ArdaFu add interrupt enter and leave hook.
  11. * 2018-11-22 Jesven rt_interrupt_get_nest function add disable irq
  12. * 2021-08-15 Supperthomas fix the comment
  13. * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to irq.c
  14. * 2022-07-04 Yunjie fix RT_DEBUG_LOG
  15. * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
  16. * 2024-01-05 Shell Fixup of data racing in rt_interrupt_get_nest
  17. * 2024-01-03 Shell Support for interrupt context
  18. */
  19. #include <rthw.h>
  20. #include <rtthread.h>
  21. #define DBG_TAG "kernel.irq"
  22. #define DBG_LVL DBG_INFO
  23. #include <rtdbg.h>
  24. #if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
  25. static void (*rt_interrupt_enter_hook)(void);
  26. static void (*rt_interrupt_leave_hook)(void);
  27. /**
  28. * @ingroup group_hook
  29. *
  30. * @brief This function set a hook function when the system enter a interrupt
  31. *
  32. * @note The hook function must be simple and never be blocked or suspend.
  33. *
  34. * @param hook the function point to be called
  35. */
  36. void rt_interrupt_enter_sethook(void (*hook)(void))
  37. {
  38. rt_interrupt_enter_hook = hook;
  39. }
  40. /**
  41. * @ingroup group_hook
  42. *
  43. * @brief This function set a hook function when the system exit a interrupt.
  44. *
  45. * @note The hook function must be simple and never be blocked or suspend.
  46. *
  47. * @param hook the function point to be called
  48. */
  49. void rt_interrupt_leave_sethook(void (*hook)(void))
  50. {
  51. rt_interrupt_leave_hook = hook;
  52. }
  53. #endif /* RT_USING_HOOK */
  54. /**
  55. * @addtogroup group_kernel_core
  56. */
  57. /**@{*/
  58. #ifdef RT_USING_SMP
  59. #define rt_interrupt_nest rt_cpu_self()->irq_nest
  60. #else
  61. volatile rt_atomic_t rt_interrupt_nest = 0;
  62. #endif /* RT_USING_SMP */
  63. #ifdef ARCH_USING_IRQ_CTX_LIST
  64. void rt_interrupt_context_push(rt_interrupt_context_t this_ctx)
  65. {
  66. struct rt_cpu *this_cpu = rt_cpu_self();
  67. rt_slist_insert(&this_cpu->irq_ctx_head, &this_ctx->node);
  68. }
  69. void rt_interrupt_context_pop(void)
  70. {
  71. struct rt_cpu *this_cpu = rt_cpu_self();
  72. rt_slist_pop(&this_cpu->irq_ctx_head);
  73. }
  74. void *rt_interrupt_context_get(void)
  75. {
  76. struct rt_cpu *this_cpu = rt_cpu_self();
  77. return rt_slist_first_entry(&this_cpu->irq_ctx_head, struct rt_interrupt_context, node)->context;
  78. }
  79. #endif /* ARCH_USING_IRQ_CTX_LIST */
  80. /**
  81. * @brief This function will be invoked by BSP, when enter interrupt service routine
  82. *
  83. * @note Please don't invoke this routine in application
  84. *
  85. * @see rt_interrupt_leave
  86. */
  87. rt_weak void rt_interrupt_enter(void)
  88. {
  89. rt_atomic_add(&(rt_interrupt_nest), 1);
  90. RT_OBJECT_HOOK_CALL(rt_interrupt_enter_hook,());
  91. LOG_D("irq has come..., irq current nest:%d",
  92. (rt_int32_t)rt_atomic_load(&(rt_interrupt_nest)));
  93. }
  94. RTM_EXPORT(rt_interrupt_enter);
  95. /**
  96. * @brief This function will be invoked by BSP, when leave interrupt service routine
  97. *
  98. * @note Please don't invoke this routine in application
  99. *
  100. * @see rt_interrupt_enter
  101. */
  102. rt_weak void rt_interrupt_leave(void)
  103. {
  104. LOG_D("irq is going to leave, irq current nest:%d",
  105. (rt_int32_t)rt_atomic_load(&(rt_interrupt_nest)));
  106. RT_OBJECT_HOOK_CALL(rt_interrupt_leave_hook,());
  107. rt_atomic_sub(&(rt_interrupt_nest), 1);
  108. }
  109. RTM_EXPORT(rt_interrupt_leave);
  110. /**
  111. * @brief This function will return the nest of interrupt.
  112. *
  113. * User application can invoke this function to get whether current
  114. * context is interrupt context.
  115. *
  116. * @return the number of nested interrupts.
  117. */
  118. rt_weak rt_uint8_t rt_interrupt_get_nest(void)
  119. {
  120. rt_uint8_t ret;
  121. rt_base_t level;
  122. level = rt_hw_local_irq_disable();
  123. ret = rt_atomic_load(&rt_interrupt_nest);
  124. rt_hw_local_irq_enable(level);
  125. return ret;
  126. }
  127. RTM_EXPORT(rt_interrupt_get_nest);
  128. RTM_EXPORT(rt_hw_interrupt_disable);
  129. RTM_EXPORT(rt_hw_interrupt_enable);
  130. rt_weak rt_bool_t rt_hw_interrupt_is_disabled(void)
  131. {
  132. return RT_FALSE;
  133. }
  134. RTM_EXPORT(rt_hw_interrupt_is_disabled);
  135. /**@}*/