Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2018 Linaro, Limited 3 : : * 4 : : * SPDX-License-Identifier: Apache-2.0 5 : : */ 6 : : 7 : : #include <kernel.h> 8 : : #include <kernel_internal.h> 9 : : 10 : : extern const int _k_neg_eagain; 11 : : 12 : : /* The 'key' actually represents the BASEPRI register 13 : : * prior to disabling interrupts via the BASEPRI mechanism. 14 : : * 15 : : * arch_swap() itself does not do much. 16 : : * 17 : : * It simply stores the intlock key (the BASEPRI value) parameter into 18 : : * current->basepri, and then triggers a PendSV exception, which does 19 : : * the heavy lifting of context switching. 20 : : 21 : : * This is the only place we have to save BASEPRI since the other paths to 22 : : * z_arm_pendsv all come from handling an interrupt, which means we know the 23 : : * interrupts were not locked: in that case the BASEPRI value is 0. 24 : : * 25 : : * Given that arch_swap() is called to effect a cooperative context switch, 26 : : * only the caller-saved integer registers need to be saved in the thread of the 27 : : * outgoing thread. This is all performed by the hardware, which stores it in 28 : : * its exception stack frame, created when handling the z_arm_pendsv exception. 29 : : * 30 : : * On ARMv6-M, the intlock key is represented by the PRIMASK register, 31 : : * as BASEPRI is not available. 32 : : */ 33 : 3 : int arch_swap(unsigned int key) 34 : : { 35 : : /* store off key and return value */ 36 : 3 : _current->arch.basepri = key; 37 : 3 : _current->arch.swap_return_value = _k_neg_eagain; 38 : : 39 : : #if defined(CONFIG_CPU_CORTEX_M) 40 : : /* set pending bit to make sure we will take a PendSV exception */ 41 : 3 : SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; 42 : : 43 : : /* clear mask or enable all irqs to take a pendsv */ 44 : 3 : irq_unlock(0); 45 : : #elif defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) 46 : : z_arm_cortex_r_svc(); 47 : : irq_unlock(key); 48 : : #endif 49 : : 50 : : /* Context switch is performed here. Returning implies the 51 : : * thread has been context-switched-in again. 52 : : */ 53 : 2 : return _current->arch.swap_return_value; 54 : : }