cpu.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-09-15 Bernard first version
  9. * 2019-07-28 zdzn add smp support
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #include <board.h>
  14. #include "cp15.h"
  15. #ifdef RT_USING_SMP
  16. void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
  17. {
  18. lock->slock = 0;
  19. }
  20. #define TICKET_SHIFT 16
  21. void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
  22. {
  23. unsigned int tmp;
  24. struct __arch_tickets lockval, newval;
  25. asm volatile(
  26. /* Atomically increment the next ticket. */
  27. " prfm pstl1strm, %3\n"
  28. "1: ldaxr %w0, %3\n"
  29. " add %w1, %w0, %w5\n"
  30. " stxr %w2, %w1, %3\n"
  31. " cbnz %w2, 1b\n"
  32. /* Did we get the lock? */
  33. " eor %w1, %w0, %w0, ror #16\n"
  34. " cbz %w1, 3f\n"
  35. /*
  36. * No: spin on the owner. Send a local event to avoid missing an
  37. * unlock before the exclusive load.
  38. */
  39. " sevl\n"
  40. "2: wfe\n"
  41. " ldaxrh %w2, %4\n"
  42. " eor %w1, %w2, %w0, lsr #16\n"
  43. " cbnz %w1, 2b\n"
  44. /* We got the lock. Critical section starts here. */
  45. "3:"
  46. : "=&r"(lockval), "=&r"(newval), "=&r"(tmp), "+Q"(*lock)
  47. : "Q"(lock->tickets.owner), "I"(1 << TICKET_SHIFT)
  48. : "memory");
  49. rt_hw_dmb();
  50. }
  51. void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
  52. {
  53. rt_hw_dmb();
  54. asm volatile(
  55. " stlrh %w1, %0\n"
  56. : "=Q"(lock->tickets.owner)
  57. : "r"(lock->tickets.owner + 1)
  58. : "memory");
  59. }
  60. #endif /*RT_USING_SMP*/
  61. /**
  62. * @addtogroup ARM CPU
  63. */
  64. /*@{*/
  65. /** shutdown CPU */
  66. void rt_hw_cpu_shutdown()
  67. {
  68. rt_uint32_t level;
  69. rt_kprintf("shutdown...\n");
  70. level = rt_hw_interrupt_disable();
  71. while (level)
  72. {
  73. RT_ASSERT(0);
  74. }
  75. }
  76. /*@}*/