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  * 2011-09-15     Bernard      first version
9  * 2018-11-22     Jesven       add rt_hw_cpu_id()
10  */
11 
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include <board.h>
15 
rt_hw_cpu_id(void)16 rt_weak int rt_hw_cpu_id(void)
17 {
18     int cpu_id;
19     __asm__ volatile (
20             "mrc p15, 0, %0, c0, c0, 5"
21             :"=r"(cpu_id)
22     );
23     cpu_id &= 0xf;
24     return cpu_id;
25 }
26 
27 #ifdef RT_USING_SMP
28 
rt_hw_spin_lock_init(rt_hw_spinlock_t * lock)29 void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
30 {
31     lock->slock = 0;
32 }
33 
rt_hw_spin_lock(rt_hw_spinlock_t * lock)34 void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
35 {
36     unsigned long tmp;
37     unsigned long newval;
38     rt_hw_spinlock_t lockval;
39 
40     __asm__ __volatile__(
41             "pld [%0]"
42             ::"r"(&lock->slock)
43             );
44 
45     __asm__ __volatile__(
46             "1: ldrex   %0, [%3]\n"
47             "   add %1, %0, %4\n"
48             "   strex   %2, %1, [%3]\n"
49             "   teq %2, #0\n"
50             "   bne 1b"
51             : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
52             : "r" (&lock->slock), "I" (1 << 16)
53             : "cc");
54 
55     while (lockval.tickets.next != lockval.tickets.owner) {
56         __asm__ __volatile__("wfe":::"memory");
57         lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner);
58     }
59 
60     __asm__ volatile ("dmb":::"memory");
61 }
62 
rt_hw_spin_unlock(rt_hw_spinlock_t * lock)63 void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
64 {
65     __asm__ volatile ("dmb":::"memory");
66     lock->tickets.owner++;
67     __asm__ volatile ("dsb ishst\nsev":::"memory");
68 }
69 #endif /*RT_USING_SMP*/
70 
71 /**
72  * @addtogroup ARM CPU
73  */
74 /*@{*/
75 
76 /** shutdown CPU */
rt_hw_cpu_shutdown(void)77 void rt_hw_cpu_shutdown(void)
78 {
79     rt_base_t level;
80     rt_kprintf("shutdown...\n");
81 
82     level = rt_hw_interrupt_disable();
83     while (level)
84     {
85         RT_ASSERT(0);
86     }
87 }
88 
89 #ifdef RT_USING_CPU_FFS
90 /**
91  * This function finds the first bit set (beginning with the least significant bit)
92  * in value and return the index of that bit.
93  *
94  * Bits are numbered starting at 1 (the least significant bit).  A return value of
95  * zero from any of these functions means that the argument was zero.
96  *
97  * @return return the index of the first bit set. If value is 0, then this function
98  * shall return 0.
99  */
__rt_ffs(int value)100 int __rt_ffs(int value)
101 {
102     return __builtin_ffs(value);
103 }
104 #endif
105 
rt_hw_interrupt_is_disabled(void)106 rt_bool_t rt_hw_interrupt_is_disabled(void)
107 {
108     int rc;
109     __asm__ volatile("mrs %0, cpsr" : "=r" (rc));
110     return !!(rc & 0x80);
111 }
112 
113 /*@}*/
114