最近一直忙于工作,现在空一点继续写这个议题。(本文原创转载请注明出处 http://blog.youkuaiyun.com/rickleaf)
stm32既然属于cortexm3体系结构,那么它的线程上下文切换必然要采用cortexm3的方式
打开
packages\hal\cortexm\arch\current\src\context.S
//==========================================================================
// Context switch
//
// R0 contains a pointer to the SP of the thread to load, R1 contains
// a pointer to the SP of the current thread.
.globl hal_thread_switch_context
.thumb
.thumb_func
.type hal_thread_switch_context, %function
hal_thread_switch_context:
push {r0-r12,lr} // Push all savable register
mov r2,#2 // Set state type == thread
mrs r3,basepri // Get priority base register
mov r4,sp // Get SP (for info only)
push {r2-r4} // Push them
str sp,[r1] // Save SP
// Fall through
//--------------------------------------------------------------------------
// Load context
//
// This is used to load a thread context, abandoning the current one. This
// function is also the second half of hal_thread_switch_context.
.globl hal_thread_load_context
.thumb
.thumb_func
.type hal_thread_load_context, %function
hal_thread_load_context:
ldr sp,[r0] // Load SP
pop {r2-r4} // Pop type, basepri and SP (discarded)
msr basepri,r3 // Set BASEPRI
pop {r0-r12,pc} // Pop all register and return
//==========================================================================
我们可以看到与ARM9的上下文切换相比,cortexm体系机构更为简洁。
在eCos的cortexm移植中:
R2保存当前任务的状态,比如R2=2来表示由thread进入上下文切换。
R3表示线程优先级
R4表示栈的状态
然后我们再浏览一下ARM9的上下文切换函数
packages\hal\arm\arch\current\src\context.S
// ----------------------------------------------------------------------------
// hal_thread_switch_context
// Switch thread contexts
// R0 = address of sp of next thread to execute
// R1 = address of sp save location of current thread
// Need to save/restore R4..R12, R13 (sp), R14 (lr)
// Note: this is a little wasteful since r0..r3 don't need to be saved.
// They are saved here though so that the information can match the
// HAL_SavedRegisters
FUNC_START_ARM(hal_thread_switch_context, r2)
mov ip,sp
sub sp,sp,#(ARMREG_SIZE - armreg_lr - 4) // skip svc_sp, svc_lr, vector, cpsr, and pc
stmfd sp!,{ip,lr}
stmfd sp!,{r0-r10,fp,ip}
mrs r2,cpsr
str r2,[sp,#armreg_cpsr]
str sp,[r1] // return new stack pointer
#ifdef __thumb__
b hal_thread_load_context_ARM // skip mode switch stuff
#endif
# Now load the destination thread by dropping through
# to hal_thread_load_context
// ----------------------------------------------------------------------------
// hal_thread_load_context
// Load thread context
// R0 = address of sp of next thread to execute
// Note that this function is also the second half of
// hal_thread_switch_context and is simply dropped into from it.
FUNC_START_ARM(hal_thread_load_context, r2)
ldr fp,[r0] // get context to restore
mrs r0,cpsr // disable IRQ's
orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r0
ldr r0,[fp,#armreg_cpsr]
msr spsr,r0
ldmfd fp,{r0-r10,fp,ip,sp,lr}
#ifdef __thumb__
mrs r1,spsr // r1 is scratch
// [r0 holds initial thread arg]
msr cpsr,r1 // hopefully no mode switch here!
bx lr
#else
movs pc,lr // also restores saved PSR
#endif
ARM9中如果要保存连续的寄存器不能像cortexm这样才有push和pop,需要使用下面的两条指令完整类似的功能。
stmfd
ldmfd
简单的理解一下底层的上下文保存方法更让我们方便理解两个不同体系结构是如何与操作系统接口的。
笔者将在后面的文章中通过介绍eCos的ticker继续深入的了解cortexm体系结构如何使用eCos