当前位置:首页 >> 计算机软件及应用 >>

threadX学习笔记(1)(2)

原链接: http://blog.chinaunix.net/uid-20767397-id-600146.html http://blog.chinaunix.net/uid-20767397-id-600145.html threadx 学习笔记(一) 2008-10-11 20:31:55 分类: tx_ill.s 文件用来处理初始化过程中的汇编语言,它是面向处理器和开发工具的。 Void_tx_initialize_low_level{ 1、CPSCR|= FIQ_ MODE,SET SP_fiq; 2、CPSCR|=IRQ_MODE,SET SP_irp; 3、CPSCR|=SVC_MODE,SET SP_svc; 4、设置中断向量表 IRQ_TABLE; 5 、 设 置 内 部 TIMER 线 程 的 堆 栈 起 始 地 址 , 堆 栈 大 小 和 优 先 级 : : tx_timer_stack_start,_tx_timer_stack_size,_tx_timer_priorit; 6、设置初始化后未使用内存地址的初始值_tx_initialize_unused_memory; } Tx_tcs.s 负责在中断发生时对上次的运行现场进行保存,它保存中断上下文,为了不覆 盖 R14_irq 离得中断返回地址,TCS 的返回是通过跳到__tx_irq_processing_return 地址做到 的。Tx_TCR.S 负责中断处理程序执行完后的处理。 Void _tx_thread_context_save{ 1、把表示中断嵌套个数的变量 _tx_thread_system_state++; 2 、 if _tx_thread_system_state>1,PUSH R0-R3,CPSR,R14 in IRQ stack,B __tx_irq_processing_return; 3 、 else if _tx_thread_current_ptr=0 判 断 是 否 有 线 程 正 在 运 行 , if not ,B _tx_irq_processing_return; 4、else,PUSH Context_irq in thread’s stack,SP_thread=new SP,B _tx_irq_processing_return; } 由于 R13 和 R14 在不同的 CPU 模式下对应的是不同的物理寄存器,所以若要得到中断 前的线程堆栈指针,需要先返回到该线程的运行模式,同时禁止中断,取值后再返回到终端 模式。R14_irq 保存的是终端发生时 PC 值+8,R14_svc 保存得失中断前线程自己的返回地 址。所以在中段上下文中,(R14_irq-4)应该存在中断地址,而 R14_svc 存在 R14 的位置。 Void _tx_thread_context_restore{ 1 、_tx_thread_system_state--,if _tx_thread_system_state>0,POP R0-R3,CPSR,R14 from IRQ stack,BX R14; 2、else if _tx_thread_current_ptr=0?if =0 CPSR|=VC_MODE,CPSR|=TX_INT_ENABLE, 跳到线程调度程序 B _tx_thread_schedule; 3 、 if!=0, 则 判 断 线 程 抢 占 是 否 禁 止 if _tx_thread_preempt_disable=0?if!=0,POP Context_irq from thread’s stack,BX R14; 4 、 if=0,_tx_timer_time_slice=new value,_tx_thread_current_ptr=0,CPSR|=SVC_MODE, 设置堆栈指针为系统指针 SP=SP_svc,CPSR|=TX_INT_ENABLE; 5、B _tx_thread_schedule; } Tx_tsr.s 用于从线程退回到系统态, 负责保存线程的最小语境并退回到 Threadx 的调度循 环状态。它保存的上下文是请求上下文。 Void _tx_thread_system_return{

1、 PUSH Context_request:in thread’s stack,CPSR|=TX_INT_DISABLE; 2、 _tx_thread_current_ptr->SP=SP,CPSR|=SVC_MODE; 3 、 设 置 堆 栈 指 针 为 系 统 指 针 SP=SP_svc , _tx_thread_current_ptr=0,CPSR|=TX_INT_ENABLE; 4、 B _tx_thread_schedule; } 由于用户模式不能直接更改 CPSR 来关断的,所以要通过 SWI 指令进入特权模式,而且 特权模式和用户模式的 SP 对应不同的物理寄存器,所以要在转入系统模式取得用户模式下 SP,最后再回到特权模式。 TX_TS.S 负责调度和恢复就绪的优先级最高的线程的最后语境。 Void _tx_thread_schedule{ 1、 while(_tx_thread_execute_ptr=0); 2、 CPSR|=TX_INT_DISABLE,_tx_threadx_current_ptr=_tx_thread_execute_ptr; 3、 _tx_thread_current_ptr->TX_run_count++,_tx_timer_time_slice=_tx_thread_current_ ptr->tx_time_slice; 4、 If 线程堆栈的中断类型=1,restore Context_irq,else restore Context_request; } Tx_tic.s 用于开中断和关中断。 Unint _tx_thread_interrupt_control(unint new _posture){ 1、 R1=CPSR; 2、 SWI; 3、 CPSR|=RO=new posture; 4、 R0=R1,R0 为返回值; } 移植该函数时,针对不同的处理器,应盖根据准热爱寄存器 CPSR 的中断禁止未来设置 开关中断向量,主要修改 TX_PORT.H 中的 TX_INT_ENABLE 和 TX_INT_DISABLE.R0 用 来传递的参数和结果。 Tx_tsb.s 负责创建每个线程的初始堆栈结构,这个初始的结构在线程创建时会引起中断 上下文返回到_tx_thread_shell_entry 函数的开头。然后这个函数调用指定线程入口函数。其 中断类型设置为 1,表示中断上下文。 Void _tx_thread_stack_build(TXTHREAD *thread_ptr,void (*function)(void)){ 1、 保证堆栈起始地址八字节对齐; 2、 中断地址存入线程调用的入口地址 PUSH function_ptr; 3、 R0-R12,R14 的初始值都设置为 0,PUSH 初始值; 4、 要 存 入 堆 栈 的 CPSR 值 设 置 为 用 户 模 式 , 开 中 断 , 标 志 位 清 零 , R1=USER_MODE,PUSH R1; 5、 Thread_ptr->sp=new SP; } 当处理一个低级的中断时,tx_tpc.s 决定是否发生抢占,它是可选的,大多数端口都用不 到。TX_TIMIN.S 负责处理定时中断。这两个函数只要将它们翻译成相应 ARM 汇编语言就 可以了。

threadx 学习笔记(二)-2

所属文件 调用者 开关量 tx_tc.c 启动代码或者是线程建立时 无 UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name, VOID (*entry_function)(ULONG), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start) { TX_INTERRUPT_SAVE_AREA REG_1 TX_THREAD_PTR tail_ptr; /* 建立用来保存尾指针的指针变量 */ #ifndef TX_DISABLE_STACK_CHECKING /* 分配一段内存空间给线程堆栈 */ memset(stack_start, TX_STACK_FILL, stack_size);/*在堆栈中填充 0xEF*/ #endif /* 再把线程加入以创建链表中以前先对该线程初始化 */ /* 用提供的参数对线程控制块的进行赋值 */ thread_ptr -> tx_thread_name = name; thread_ptr -> tx_thread_entry = entry_function; thread_ptr -> tx_entry_parameter = entry_input; thread_ptr -> tx_stack_ptr = TX_NULL; //用来保存线程的寄存器等的内存开始指针 thread_ptr -> tx_stack_start = stack_start;//线程堆栈的开始指针 thread_ptr -> tx_stack_size = stack_size;//线程堆栈的大小 thread_ptr -> tx_stack_end = (VOID_PTR) (((CHAR_PTR) stack_start) + (stack_size-1)); thread_ptr -> tx_priority = priority & TX_THREAD_PRIORITY_MASK; thread_ptr -> tx_preempt_threshold= preempt_threshold & TX_THREAD_PRIORITY_MASK; thread_ptr -> tx_time_slice = time_slice; thread_ptr -> tx_new_time_slice = time_slice; /* 填充线程初始化所需要的值 */ thread_ptr -> tx_run_count = 0; thread_ptr -> tx_state = TX_SUSPENDED; thread_ptr -> tx_delayed_suspend = TX_FALSE; thread_ptr -> tx_suspending = TX_FALSE; /* 对线程定时器模块的必要部分进行赋值. */

thread_ptr -> tx_thread_timer.tx_timeout_function = _tx_thread_timeout;//线程超时函数 thread_ptr -> tx_thread_timer.tx_timeout_param = (ULONG) thread_ptr;//超时函数的参数 thread_ptr -> tx_thread_timer.tx_list_head = TX_NULL; thread_ptr -> tx_thread_timer.tx_re_initialize_ticks = 0; /* 清除挂起信息 */ thread_ptr -> tx_suspend_cleanup = TX_NULL; thread_ptr -> tx_suspend_control_block = TX_NULL; thread_ptr -> tx_suspended_next = TX_NULL; thread_ptr -> tx_suspended_previous= TX_NULL; /*建立优先级比特图,第几 bit 位为 1 表示优先级为几! */ thread_ptr -> tx_priority_bit = (((ULONG) 1) << (priority & TX_THREAD_PRIORITY_MAS K)); /* 建立线程堆栈(用来存储各个线程寄存器的值) */ _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry); /* 准备将该线程加入已建线程列表,禁止中断. */ TX_DISABLE /* Load the thread ID field in the thread control block. */ thread_ptr -> tx_thread_id = TX_THREAD_ID; /* 将线程加入已建列表. 首先检查是否为空表 。注意循环链表,第一个的前一个即为最后 一个*/ if (_tx_thread_created_ptr) { /* 获得已建线程列表的尾线程指针. */ tail_ptr = _tx_thread_created_ptr -> tx_created_previous; /* 将新线程加入意见列表中 */ _tx_thread_created_ptr -> tx_created_previous = thread_ptr; tail_ptr -> tx_created_next = thread_ptr; thread_ptr -> tx_created_previous = tail_ptr; thread_ptr -> tx_created_next = _tx_thread_created_ptr; } else {

/* 如果以创建线程列表为空,则将新线程加到以创建列表中 */ _tx_thread_created_ptr = thread_ptr; thread_ptr -> tx_created_next = thread_ptr; thread_ptr -> tx_created_previous = thread_ptr; } /*已创建线程计数器增加 1 */ _tx_thread_created_count++; /* 无效优先级增加 1. */ _tx_thread_preempt_disable++; /* Register thread in the thread array structure. */ TX_EL_THREAD_REGISTER(thread_ptr); /* Log this kernel call. */ TX_EL_THREAD_CREATE_INSERT //这里不太明白什么意思,没有找到关于_cpp_exception_init()函数 /* Green Hills specific code. */ /* { #pragma weak __cpp_exception_init extern void __cpp_exception_init(void **); static void (*const cpp_init_funcp)(void **) = __cpp_exception_init; if (cpp_init_funcp) __cpp_exception_init(&(thread_ptr->tx_eh_globals)); } */ /* End of Green Hills specific code. */ /*恢复中断 */ TX_RESTORE /*确定是自动开始还是创建后处于挂起状态. 如果为自动开始调用 resume 函数并且检查线 程抢占条件 */ if (auto_start) { /* Call the resume thread function to make this thread ready. Upon return, check for a preemption condition caused by creating a thread of higher priority. */ if (_tx_thread_resume(thread_ptr)) /* A preemption condition exists, pass control back to the

system in order to get the higher priority thread running. */ _tx_thread_system_return(); } else { /* 中断禁止 */ TX_DISABLE /* Remove temporary disable preemption. */ _tx_thread_preempt_disable--; /* 恢复中断 */ TX_RESTORE } /* 总是返回成功 */ return(TX_SUCCESS); } _tx_thread_interrupt_control 所属文件 调用者 开关量 tx_tic.s TX_DISABLE 和 TX_RESTORE 宏 无 该 函 数 主 要 是 实 现 中 断 的 禁 止 与 允 许 功 能 。 对 于 TX_DISABLE 宏 定 义 为 _tx_thread_interrupt_control(TX_INT_DISABLE),其返回值为存在变量 interrupt_save,将该 变量作为 TX_RESTORE 宏定义_tx_thread_interrupt_control(interrupt_save)的参数。 两个宏定义 TX_DISABLE 和 TX_RESTORE 分别实现中断禁止和恢复中断的功能,它们都 是通过调用汇编语言的_tx_thread_interrupt_control(parameter)函数来实现的,只是两次的 参数不同,TX_RESTORE 所用的参数为 TX_DISABLE 所返回的值,它们一般是成对出现 的! #define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save; #defined TX_INT_DISABLE 0xc0 #define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); #define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); #defined INT_MASK 0x3F EXPORT _tx_thread_interrupt_control _tx_thread_interrupt_control ; ; /* Pickup current interrupt lockout posture. */ ; MRS a4, CPSR ; 获得 CPSR 的值,将其存入 a4 中 MOV a3, #INT_MASK ; 将中断禁止掩码放入 a3

AND a2, a4, a3 ; 按位逻辑与以后 FIQ 和 IRQ 中断位为 0 ORR a2, a2, a1 ; 其中 a1 的值为参数(TX_INT_DISABLE)逻辑或以后中断禁止位置 1 ; ; /* Apply the new interrupt posture. */ ; MSR CPSR_c, a2 ;建立新的 CPSR 禁止中断 BIC a1, a4, a3 ; 返回先前的中断掩码(将值返回给 interrupt_save) MOV pc, lr ; ;}

_tx_thread_stack_build 所属文件 调用者 开关量 tx_tsb.s TX_DISABLE 和 TX_RESTORE 宏 无 每个线程都有这样的一块堆栈,用来保存每个线程的寄存器值。(Interrupt stack frame type (中断堆栈堆类型)、CPSR、R0-R1) EXPORT _tx_thread_stack_build _tx_thread_stack_build ; /* Build a fake interrupt frame. The form of the fake interrupt stack ; on the ARM7 should look like the following after it is built: ; ; Stack Top: 1 Interrupt stack frame type ; CPSR Initial value for CPSR ; a1 (r0) Initial value for a1 ; a2 (r1) Initial value for a2 ; a3 (r2) Initial value for a3 ; a4 (r3) Initial value for a4 ; v1 (r4) Initial value for v1 ; v2 (r5) Initial value for v2 ; v3 (r6) Initial value for v3 ; v4 (r7) Initial value for v4 ; v5 (r8) Initial value for v5 ; sb (r9) Initial value for sb ; sl (r10) Initial value for sl ; fp (r11) Initial value for fp ; ip (r12) Initial value for ip ; lr (r14) Initial value for lr ; pc (r15) Initial value for pc ; 0 For stack backtracing ;

; Stack Bottom: (higher memory address) */ ; LDR a3, [a1, #16] ; 从(Thread Struct) tx_stack_end 获得堆栈的尾地址 BIC a3, a3, #3 ; 使得 long 对齐 SUB a3, a3, #72 ; 分配堆栈空间 ; ; /* Actually build the stack frame. */ ; MOV a4, #1 ; 将中断类型赋给寄存器 a4 STR a4, [a3, #0] ; 将中断类型保存在堆栈中 MOV a4, #INITIAL_CPSR ; INITIAL_CPSR EQU 13 Supervisor mode, ints enabled 将其值赋 给寄存器 a4 STR a4, [a3, #4] ; 将 INITIAL_CPSR 存储在堆栈中 MOV a4, #0 ;将寄存器初始化的值 0 存入寄存器 a4 中 STR a4, [a3, #8] ; 用寄存器 a4 值初始化 a1 STR a4, [a3, #12] ; 用寄存器 a4 值初始化 a2 STR a4, [a3, #16] ; 用寄存器 a4 值初始化 a3 STR a4, [a3, #20] ; 用寄存器 a4 值初始化 a4 STR a4, [a3, #24] ; 用寄存器 a4 值初始化 v1 STR a4, [a3, #28] ; 用寄存器 a4 值初始化 v2 STR a4, [a3, #32] ; 用寄存器 a4 值初始化 v3 STR a4, [a3, #36] ; 用寄存器 a4 值初始化 v4 STR a4, [a3, #40] ; 用寄存器 a4 值初始化 v5 STR a4, [a3, #44] ; 用寄存器 a4 值初始化 sb\v6 LDR a4, [a1, #12] ; 获得堆栈的开始地址(tx_stack_Ptr),将值赋给寄存器 a4 STR a4, [a3, #48] ; 用寄存器 a4 值(堆栈开始地址)初始化 sl\v7 MOV a4, #0 ; 将寄存器初始化的值 0 存入寄存器 a4 中 STR a4, [a3, #52] ; 用寄存器 a4 值初始化 fp STR a4, [a3, #56] ; 用寄存器 a4 值初始化 ip STR a4, [a3, #60] ; 用寄存器 a4 值初始化 lr STR a2, [a3, #64] ; 用寄存器 a4 值初始化 pc STR a4, [a3, #68] ; 0 for back-trace???? ; ; /* Setup stack pointer. */ ; thread_ptr -> tx_stack_ptr = a3; ; STR a3, [a1, #8] ; 将保存寄存器的开始地址保存在从(Thread Struct) tx_stack_Ptr MOV pc, lr ;} UINT _tx_thread_resume(TX_THREAD *thread_ptr) 所属文件 调用者 开关量 tx_tr.c 任务或者初始化代码 无 该函数主要是线程第一次启动或者挂起后重新启动是调用。

UINT _tx_thread_resume(TX_THREAD *thread_ptr) { TX_INTERRUPT_SAVE_AREA UINT preemption; /* Preempt condition flag */ REG_1 UINT priority; /* Thread priority */ REG_2 TX_THREAD *head_ptr; /* Thread priority head pointer */ REG_2 TX_THREAD *tail_ptr; /* Thread priority tail pointer */

/*初始化占用标志为 TX_FALSE. */ preemption = TX_FALSE; /* 当线程重新恢复时,禁止中断 */ TX_DISABLE /* Decrease the preempt disabled count. */ _tx_thread_preempt_disable--; /* 确定线程是否处于挂起过程 如果线程控制块已经处于链表中就不用做什么了?*/ if (thread_ptr -> tx_suspending) { /* 确定该函数没有完成没有终止 。如果是其中任何一种情况不对中断挂起做任何处理. */ if ((thread_ptr -> tx_state != TX_COMPLETED) && (thread_ptr -> tx_state != TX_TERMINATED)) { /* 清除中断标志 */ thread_ptr -> tx_suspending = TX_FALSE; /*恢复状态准备 */ thread_ptr -> tx_state = TX_READY; } } /* 如果线程没有回复到准备状态 TX_READY. */ else if (thread_ptr -> tx_state != TX_READY) { /* 检查是否有一个延迟挂起标志. */ if (thread_ptr -> tx_delayed_suspend) {

/* 清除延迟挂起标志并改变状态 */ thread_ptr -> tx_delayed_suspend = TX_FALSE; thread_ptr -> tx_state = TX_SUSPENDED; } else { /* Log the thread status change. */ TX_EL_THREAD_STATUS_CHANGE_INSERT(thread_ptr, TX_READY); /* Make this thread ready. */ /* 将状态改为 TX_READY */ thread_ptr -> tx_state = TX_READY; /* 获得线程的优先级. */ priority = thread_ptr -> tx_priority; /* 确定在同优先级是否有其它已准备的线程 */ head_ptr = _tx_thread_priority_list[priority]; if (head_ptr) { /*在该优先级已经存在其他准备好的线程 */ /* 把该线程加入到优先级列表中,每个优先级都有一个准备好的线程循环链表 */ tail_ptr =head_ptr -> tx_ready_previous; tail_ptr -> tx_ready_next = thread_ptr; head_ptr -> tx_ready_previous =thread_ptr; thread_ptr -> tx_ready_previous = tail_ptr; thread_ptr -> tx_ready_next =head_ptr; } else { /* 这是该优先级第一个准备好的线程 把该线程加到链表的最前面 */ _tx_thread_priority_list[priority] = thread_ptr; thread_ptr -> tx_ready_next = thread_ptr; thread_ptr -> tx_ready_previous = thread_ptr; /* 将该线程的优先级 bit 放到线程优先级 map 中 */ _tx_thread_priority_map = _tx_thread_priority_map | thread_ptr -> tx_priority_bit; /* 和当前执行的优先级比较看是否比当前优先级高. */

if (_tx_thread_execute_ptr == TX_NULL) { /* 当前没有其它准备好的线程,将该线程设为_tx_thread_execute_ptr ,将该线程 的优先级设为最高优先级*/ _tx_thread_execute_ptr = thread_ptr; _tx_thread_highest_priority = priority; } else if (priority < _tx_thread_highest_priority) { /* 已有_tx_thread_execute_ptr 线程,但该线程比准备好的线程优先级要高. */ /* 更新最高优先级变量 */ _tx_thread_highest_priority = priority; /* 确定该线程是否能够占用 cpu, 线程优先级应高于已准备好的线程优先级门槛 _tx_thread_execute_ptr -> tx_preempt_threshold */ if (priority < _tx_thread_execute_ptr -> tx_preempt_threshold) { if (_tx_thread_execute_ptr -> tx_preempt_threshold != _tx_thread_execute_ptr -> tx_priority) { /* 注意,一个线程只能被优先级高于其门槛优先级的线程占用 */ _tx_thread_preempted_map = _tx_thread_preempted_map |_tx_thread_execute_ ptr -> tx_priority_bit; } /* 将该线程改为_tx_thread_execute_ptr */ _tx_thread_execute_ptr = thread_ptr; } } } } } /* 恢复中断 */ TX_RESTORE /* 确定中是否应该发生 */ if ((_tx_thread_current_ptr != _tx_thread_execute_ptr) && (_tx_thread_system_state == 0))

/*设置优先占用标志 */ preemption = TX_TRUE; /* 返回该标志,如果可以占有返回 TX_TRUE;如果不可以返回 TX_FALSE */ return(preemption); }

VOID _tx_thread_schedule(VOID) 所属文件 调用者 开关量 tx_ts.s 任务或者初始化代码 无 该函数主要实现对线程的调度 Tx_ts.s 该汇编文件重要实现 VOID _tx_thread_schedule(VOID)这个函数,其功能为实现函数 调度. ENABLE_CPSR EQU 0x13 ; Supervisor mode, ints enabled DISABLE_CPSR EQU 0x93 ; Supervisor mode, ints disabled ; ; IMPORT _tx_thread_execute_ptr IMPORT _tx_thread_current_ptr IMPORT _tx_timer_time_slice ; ; AREA |C$$code|, CODE, READONLY |x$codeseg| DATA ;VOID _tx_thread_schedule(VOID) ;{ EXPORT _tx_thread_schedule _tx_thread_schedule ; ; /* Enable interrupts. */ ; MOV a1, #ENABLE_CPSR ;将 ENABLE_CPSR 的值放入 a1,该值能使 cpu 进入管理模式, 并且中断使能 MSR CPSR_c, a1 ; 中断使能 ; ; /* Wait for a thread to execute. */ ; do ;{ LDR a2, [pc, #EXECUTE_PTR-.-8] ; 获得未准备好的线程指针的地址(类似于指针的指针, 即双指针) ;

__tx_thread_schedule_loop ;该循环在寻找一个可以执行的线程指针 ; LDR a1, [a2, #0] ; 获得下个一个要准备好的线程的指针 CMP a1, #0 ; 判断其是否为空 BEQ __tx_thread_schedule_loop ; 如果为空从新调度 ; ;} ; while(_tx_thread_execute_ptr == TX_NULL); ; ; /* Yes! We have a thread to execute. Lockout interrupts and ; transfer control to it. */ ; MOV a3, #DISABLE_CPSR ; 将 DISABLE_CPSR 的值放入 a1, 该值能使 cpu 进入管理模式, 并且中断禁止 MSR CPSR_c, a3 ; 中断禁止 ; ; /* Setup the current thread pointer. */ ; _tx_thread_current_ptr = _tx_thread_execute_ptr; ; LDR a2, [pc, #CURRENT_PTR-.-8] ; 获得当前线程的指针的地址 STR a1, [a2, #0] ; 将刚才获得的准备好的线程指针放到当前线程的指针地址所对应的空间 里 ; ; /* 将该线程的运行次数加 1 */ ; _tx_thread_current_ptr -> tx_run_count++; ; LDR a3, [a1, #4] ; 获得线程运行次数 LDR a4, [a1, #24] ; 获得该线程的时间切片 ADD a3, a3, #1 ;将线程运行次数加 1 STR a3, [a1, #4] ; 存储线程的运行次 ; /* Setup time-slice, if present. */ ; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_time_slice; ; LDR a3, [pc, #TIME_SLICE-.-8] ; 获得定时切边的地址 LDR sp, [a1, #8] ;将堆栈指针赋给 cpu 的 sp 寄存器 STR a4, [a3, #0] ;将该线程的定时切片赋给_tx_timer_time_slice ; /* Switch to the thread's stack. */ ; sp = _tx_thread_execute_ptr -> tx_stack_ptr; ; ; /* Determine if an interrupt frame or a synchronous task suspension frame ; is present. */ ; LDMIA {a1, a2} ; Pickup the stack type and saved CPSR CMP a1, #0 ; Check for synchronous context switch

MSR SPSR_cxsf, a2 ; Setup SPSR for return LDMEQIA {v1-fp, pc}^ ; Return to thread synchronously ; Otherwise, LDMIA {a1-ip, lr, pc}^ ; Return to point of thread interrupt ; ;} ; EXECUTE_PTR DCD _tx_thread_execute_ptr CURRENT_PTR DCD _tx_thread_current_ptr TIME_SLICE DCD _tx_timer_time_slice END

所属文件 调用者 开关量 tx_tsr.s 无 ;VOID _tx_thread_system_return(VOID) ;{ EXPORT _tx_thread_system_return _tx_thread_system_return ; ; /* Save minimal context on the stack. */ ; MOV a1, #0 ; Build a solicited stack type MRS a2, CPSR ; 获得 CPSR 的值 STMDB {a1-a2, v1-fp, lr} ; 保存最小环境上下文 ; ; /* Lockout interrupts. */ ; MOV a3, #DISABLE_CPSR ; 简历中断禁止值 MSR CPSR_c, a3 ; 设置中断禁止 LDR a4, [pc, #CURRENT_PTR-.-8] ; 获得当前线程指针地址 LDR a1, [a4, #0] ; 获得当前指针 LDR a3, [pc, #TIME_SLICE-.-8] ; 获得全局定时切片地址 LDR a2, [a3, #0] ; 获得全局定时切片值 ; ; /* 保存当前堆栈并且切换到系统堆栈. */ ; _tx_thread_current_ptr -> tx_stack_ptr = sp; ; sp = _tx_thread_system_stack_ptr; ; STR sp, [a1, #8] ; 保存线程堆栈指针

; ; /* Determine if the time-slice is active. */ ; if (_tx_timer_time_slice) ;{ ; MOV v1, #0 ; Build clear value CMP a2, #0 ; 时间切片是否有效 BEQ __tx_thread_dont_reset_ts ; No, don