1、threadx学习笔记(一)tx_ill.s文献用来解决初始化过程中汇编语言,它是面向解决器和开发工具。Void_tx_initialize_low_level1、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_i
2、nitialize_unused_memory;Tx_tcs.s负责在中断发生时对上次运营现场进行保存,它保存中断上下文,为了不覆盖R14_irq离得中断返回地址,TCS返回是通过跳到_tx_irq_processing_return地址做到。Tx_TCR.S负责中断解决程序执行完后解决。Void _tx_thread_context_save1、把表达中断嵌套个数变量_tx_thread_system_state+;2、if _tx_thread_system_state1,PUSH R0-R3,CPSR,R14 in IRQ stack,B _tx_irq_processing_retur
3、n;3、else if _tx_thread_current_ptr=0判断与否有线程正在运营,if not ,B _tx_irq_processing_return;4、else,PUSH Context_irq in threads stack,SP_thread=new SP,B _tx_irq_processing_return;由于R13和R14在不同CPU模式下相应是不同物理寄存器,因此若要得到中断前线程堆栈指针,需要先返回到该线程运营模式,同步禁止中断,取值后再返回到终端模式。R14_irq保存是终端发生时PC值+8,R14_svc保存得失中断前线程自己返回地址。因此在中段上下文
4、中,(R14_irq-4)应当存在中断地址,而R14_svc存在R14位置。Void _tx_thread_context_restore1、_tx_thread_system_state-,if _tx_thread_system_state0,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_thr
5、ead_preempt_disable=0?if!=0,POP Context_irq from threads 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_ret
6、urn1、 PUSH Context_request:in threads 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_T
7、S.S负责调度和恢复就绪优先级最高线程最后语境。Void _tx_thread_schedule1、 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
8、 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_thre
9、ad_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
10、.s决定与否发生抢占,它是可选,大多数端口都用不到。TX_TIMIN.S负责解决定期中断。这两个函数只要将它们翻译成相应ARM汇编语言就可以了。threadx学习笔记(二)-1tx_kernel_enter();进入threadx核tx_kernel_enter()void tx_kernel_enter(void)所属文献调用者开关量demo.C启动代码无操作系统一方面从从量表直接进入该函数,在函数此前没有进行任何硬件及软件初始化!该函数重要包括_tx_initialize_low_level(),_tx_initialize_high_level(),tx_application_defi
11、ne(_tx_initialize_unused_memory),_tx_thread_schedule()。VOID _tx_initialize_kernel_enter(VOID)/*拟定编译器与否已经初始化过 */if (_tx_thread_system_state != TX_INITIALIZE_ALMOST_DONE)/* 没有初始化话执行下面程序 */* 设立系统状态变量来表达现正在解决过程中 注意该变量在后边中断嵌套中会使用*/_tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;/* 进行某些基本硬件设立,启动程序等 */
12、_tx_initialize_low_level();/*进行某些高档初始化*/_tx_initialize_high_level();/*设立系统状态变量来表达现正在解决过程中 注意该变量在后边中断嵌套中会使用*/_tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;/* 调用初始化中提供应用程序 把第一种未使用变量地址传送给它 */tx_application_define(_tx_initialize_unused_memory);/*设立系统壮伟进入线程调度做准备*/_tx_thread_system_state = TX_INITIA
13、LIZE_IS_FINISHED;/* 进入线程循环开始执行线程 */_tx_thread_schedule();_tx_initialize_low_level()void tx_kernel_enter(void)所属文献调用者开关量tx_till.s启动代码无该函数实现对FIQ、IRQ和SVC模式下sp寄存器初始化,并对定期堆栈基地址、大小和定期优先级变量进行初始化。/* 进行某些基本硬件设立,启动程序等 */*该函数在文献tx_ill.s文献中*/_tx_initialize_low_level();/* VOID _tx_initialize_low_level(VOID);EXPO
14、RT _tx_initialize_low_level_tx_initialize_low_level;/* 保存系统堆栈指针. */;/* _tx_thread_system_stack_ptr = (VOID_PTR) A7 (SP);*/;/*设立各个模式下sp(堆栈指针)*/;/* We must be in SVC mode at this point!*/;LDR a2,=|Image$ZI$Limit| ;Get end of non-initialized RAM areaLDR a3,pc,#FIQ_STACK_SIZE-.-8 ;获得FIO堆栈地址(这里没有弄明白,有待?)
15、MOV a1,#FIQ_MODE ;设立FIQ_MODEMSR CPSR_c,a1 ;进入FIQ模式ADD a2,a2,a3 ;计算FIQ堆栈开始BIC a2,a2,#3 ;将a2低两位清零保证堆栈开始为long对齐SUB a2,a2,#4 ;往回退一种字MOV sp,a2 ;建立FIQ 堆栈指针(即FIQ模式sp)MOV sl,#0 ;Clear sl(R10)MOV fp,#0 ;Clear fp(R11)LDR a3,pc,#SYS_STACK_SIZE-.-8 ;获得 IRQ (system stack size)MOV a1,#IRQ_MODE ;建立IRQ模式 CPSRMSR CP
16、SR_c,a1 ;进入IRQ模式ADD a2,a2,a3 ;计算IRQ stack开始BIC a2,a2,#3 ;将a2低两位清零保证堆栈开始为long对齐SUB a2,a2,#4 ;往回退一种字MOV sp,a2 ;建立 IRQ 堆栈指针MOV a1,#SVC_MODE ;建立SVC模式CPSRMSR CPSR_c,a1 ;进入 SVC模式LDR a4,pc,#SYS_STACK_PTR-.-8 ;获得stack 指针STR a2,a4,#0 ;保存系统堆栈;;/* Save the system stack pointer. */;_tx_thread_system_stack_ptr =
17、 (VOID_PTR) (sp);LDR a2,pc,#SYS_STACK_PTR-.-8 ;获得系统堆栈指针地址LDR a1,a2,#0 ;获得系统堆栈指针 ADD a1,a1,#4 ;增长一种long长度;;/* Pickup the first available memory address. */;;/* Allocate space for the timer threads stack. */;_tx_timer_stack_start = first_available_memory;;_tx_timer_stack_size = stack_size;;_tx_timer_p
18、riority = 0;LDR a2,pc,#TIMER_STACK-.-8 ;获得定期堆栈指针地址LDR a4,pc,#TIMER_STACK_SIZE-.-8 ;获得定期堆栈大小地址LDR a3,pc,#TIM_STACK_SIZE-.-8 ;获得实际定期堆栈大小STR a1,a2,#0 ;将定期堆栈基地址放在堆栈指针地址所相应内存中STR a3,a4,#0 ;存储定期器堆栈大小ADD a1,a1,a3 ;新空内存地址LDR a2,pc,#TIMER_PRIORITY-.-8 ;获得定期器优先级地址MOV a3,#0 ;获得定期器线程优先级STR a3,a2,#0 ;存储定期器线程优先级;
19、/*保存第一种变量内存地址. */;_tx_initialize_unused_memory = (VOID_PTR) System Stack + Timer Stack;LDR a3,pc,#UNUSED_MEMORY-.-8 ;获得没有使用内存指针地址STR a1,a3,#0 ;保存第一种空内存地址;/* 建立周期性定期中断. */STMDB LR/让lr入栈,保护lrBLTargetInit/TargetInit()为C语言编写中断定期函数LDMIA lr/让lr出栈在这里加上ARM定期器已实现周期性中断;/* Done,return to caller. */;MOV pc,lr ;
20、Return to caller;_tx_irq_handler所属文献调用者开关量tx_till.s IRQ中断无该函数是在定期中断后调用,该函数调用了_tx_thread_context_save函数(包括在tx_tcs.s中),该函数又调用到_tx_irq_processing_return函数处(包括在tx_till.s)EXPORT _tx_irq_handlerEXPORT _tx_irq_processing_return _tx_irq_handler;;/* 调用函数保存线程上下文环境. */B _tx_thread_context_save_tx_irq_processin
21、g_return;;/* At this point execution is still in the IRQ mode. The CPSR,point of;interrupt,and all C scratch registers are available for use. In ;addition,IRQ interrupts may be re-enabled - with certain restrictions -;if nested IRQ interrupts are desired. Interrupts may be re-enabled over;small code
22、 sequences where lr is saved before enabling interrupts and ;restored after interrupts are again disabled. */;;/* For debug purpose,execute the timer interrupt processing here. In;a real system,some kind of status indication would have to be checked;before the timer interrupt handler could be called
23、. */;BL clearflag;清除中断标志位很重要(自己移植时加,位置与否恰当?)BL _tx_timer_interrupt ;定期中断解决函数;;/* 系统线程上下文环境恢复函数 */B _tx_thread_context_restore_tx_timer_interrupt所属文献调用者开关量tx_timin.s启动代码无该函数重要是中断后将系统时钟加1,时间切片减1。定期某些比较多,没有完全看明白。IMPORT _tx_timer_time_sliceIMPORT _tx_timer_system_clockIMPORT _tx_timer_current_ptrIMPORT
24、_tx_timer_list_startIMPORT _tx_timer_list_endIMPORT _tx_timer_expired_time_sliceIMPORT _tx_timer_expiredIMPORT _tx_timer_threadIMPORT _tx_thread_current_ptrIMPORT _tx_thread_time_sliceIMPORT _tx_thread_resumeIMPORT _tx_thread_preempt_disable;PRESERVE8AREA |C$code|,CODE,READONLY|x$codeseg| DATA;VOID
25、_tx_timer_interrupt(VOID);EXPORT _tx_timer_interrupt_tx_timer_interrupt;;/* Upon entry to this routine,it is assumed that context save has already;been called,and therefore the compiler scratch registers are available;for use. */;;/* Increment the system clock. */;_tx_timer_system_clock+;LDR a2,pc,#
26、SYSTEM_CLOCK-.-8 ;获得系统时钟地址LDR a1,a2,#0 ;获得系统时钟ADD a1,a1,#1 ;将系统时钟加1STR a1,a2,#0 ;存储新系统时钟时间;;/* Test for time-slice expiration. */;if (_tx_timer_time_slice);;LDR a4,pc,#TIME_SLICE-.-8 ;获得链表中定期切片数地址LDR a3,a4,#0 ;获得定期切片数值CMP a3,#0 ;定期切片与否有效,0有效,=0无效BEQ _tx_timer_no_time_slice ;=0时,跳到_tx_timer_no_time_s
27、lice处;/* 时间切片减1. */;_tx_timer_time_slice-;SUB a3,a3,#1 ;时间切片值减1STR a3,a4,#0 ;存储新时间切片值;;/* 检查与否到期. */;if (_tx_timer_time_slice = 0);CMP a3,#0 ;0还是=0?BNE _tx_timer_no_time_slice ;如果0,;当没有定期切片时,将定期切片数标志位置1,表达链表中没有切片了。;/* Set the time-slice expired flag. */;_tx_timer_expired_time_slice = TX_TRUE;LDR a4,
28、pc,#EXPIRED_TIME_SLICE-.-8 ;获得定期切片数与否为0标志地址MOV a1,#1 ;将标志设为1STR a1,a4,#0 ;设立届时标志;;;_tx_timer_no_time_slice;;/* Test for timer expiration. */;if (*_tx_timer_current_ptr);;LDR a2,pc,#TIMER_CURRENT_PTR-.-8 ;获得是_tx_timer_current_ptr地址;而TIMER_DECLARE TX_INTERNAL_TIMER *_tx_timer_current_ptr;LDR a1,a2,#0
29、;获得当前_tx_timer_current_ptrLDR a3,a1,#0 ;获得定期列表入口定期切片指针CMP a3,#0 ;链表中与否有定期切片存在BEQ _tx_timer_no_timer ;不存在,调用_tx_timer_no_time将;_tx_timer_current_ptr+;;/* Set expiration flag. */;_tx_timer_expired = TX_TRUE;LDR a4,pc,#EXPIRED-.-8 ;Pickup expriation flag addressMOV a3,#1 ;Build expired valueSTR a3,a4,#
30、0 ;Set expired flagB _tx_timer_done ;Finished timer processing;;else;_tx_timer_no_timer;;/* No timer expired,increment the timer pointer. */;_tx_timer_current_ptr+;ADD a1,a1,#4 ;Move to next timer;;/* Check for wrap-around. */;if (_tx_timer_current_ptr = _tx_timer_list_end);LDR a4,pc,#LIST_END-.-8 ;
31、Pickup addr of timer list endLDR a3,a4,#0 ;Pickup list endCMP a1,a3 ;Are we at list end?BNE _tx_timer_skip_wrap ;No,skip wrap-around logic;;/* Wrap to beginning of list. */;_tx_timer_current_ptr = _tx_timer_list_start;LDR a4,pc,#LIST_START-.-8 ;Pickup addr of timer list startLDR a1,a4,#0 ;Set curren
32、t pointer to list start;_tx_timer_skip_wrap;STR a1,a2,#0 ;Store new current timer pointer;;_tx_timer_done;;/* See if anything has expired. */;if (_tx_timer_expired_time_slice) | (_tx_timer_expired);;LDR a4,pc,#EXPIRED_TIME_SLICE-.-8 ;Pickup addr of expired flagLDR a3,a4,#0 ;Pickup time-slice expired
33、 flagCMP a3,#0 ;Did a time-slice expire?BNE _tx_something_expired ;If non-zero,time-slice expiredLDR a2,pc,#EXPIRED-.-8 ;Pickup addr of other expired flagLDR a1,a2,#0 ;Pickup timer expired flagCMP a1,#0 ;Did a timer expire?BEQ _tx_timer_nothing_expired ;No,nothing expired;_tx_something_expired;STR l
34、r,sp,#-4!;Save the lr register on the stack;;/* Did a timer expire?*/;if (_tx_timer_expired);;LDR a2,pc,#EXPIRED-.-8 ;Pickup addr of expired flagLDR a1,a2,#0 ;Pickup timer expired flagCMP a1,#0 ;Check for timer expirationBEQ _tx_timer_dont_activate ;If not set,skip timer activation;;/* Increment the
35、 preempt disable counter in preparation for ;thread resumption. */;_tx_thread_preempt_disable+;LDR a4,pc,#PREEMPT_DISABLE-.-8 ;Pickup addr of preempt disable LDR a3,a4,#0 ;Pickup actual flagADD a3,a3,#1 ;Incrment the preempt disable countSTR a3,a4,#0 ;Store it back;;/* Activate the system timer thre
36、ad. */;_tx_thread_resume(&_tx_timer_thread);LDR a1,pc,#TIMER_THREAD-.-8 ;Get timer thread control block addrBL _tx_thread_resume ;Call thread resume to wake up the;timer thread;;_tx_timer_dont_activate;;/* Did time slice expire?*/;if (_tx_timer_expired_time_slice);;LDR a4,pc,#EXPIRED_TIME_SLICE-.-8
37、;Pickup addr of time-slice expired LDR a3,a4,#0 ;Pickup the actual flagCMP a3,#0 ;See if the flag is setBEQ _tx_timer_not_ts_expiration ;No,skip time-slice processing;;/* Time slice interrupted thread. */;if (!_tx_thread_time_slice();_tx_timer_time_slice = _tx_thread_current_ptr - tx_time_slice;BL _
38、tx_thread_time_slice ;Call time-slice processingCMP a1,#0 ;Check return statusBNE _tx_timer_not_ts_expiration ;If time-sliced,skip reset processingLDR a2,pc,#CURRENT_PTR-.-8 ;Pickup addr of current thread pointerLDR a1,a2,#0 ;Pickup thread pointerLDR a3,a1,#24 ;Pickup fresh time-slice for thread;(a
39、fresh time slice was setup in ;the _tx_thread_time_slice function)LDR a4,pc,#TIME_SLICE-.-8 ;Pickup addr of time-slice variableSTR a3,a4,#0 ;Setup new time-slice;;;_tx_timer_not_ts_expiration;LDR a4,pc,#EXPIRED_TIME_SLICE-.-8 ;Pickup address of expired time-slice flagMOV a1,#0 ;Clear valueSTR a1,a4,
40、#0 ;Clear time-slice expired flag;LDR lr,sp,#4 ;Recover lr register;;;_tx_timer_nothing_expired;MOV pc,lr ;Return to caller;TIME_SLICEDCD _tx_timer_time_sliceSYSTEM_CLOCKDCD _tx_timer_system_clockTIMER_CURRENT_PTRDCD _tx_timer_current_ptrLIST_STARTDCD _tx_timer_list_startLIST_ENDDCD _tx_timer_list_e
41、ndEXPIRED_TIME_SLICEDCD _tx_timer_expired_time_sliceEXPIREDDCD _tx_timer_expiredTIMER_THREADDCD _tx_timer_threadCURRENT_PTRDCD _tx_thread_current_ptrTHREAD_TIME_SLICEDCD _tx_thread_time_sliceRESUMEDCD _tx_thread_resumePREEMPT_DISABLEDCD _tx_thread_preempt_disableEND_tx_initialize_high_level()VOID _tx_initialize_high_level(VOID)所属文献调用者开关量tx_ihl.c启动代码无重要时对某些与硬件无关变量进行初始化,其中重要实现了线程初始化;定期初始化,这里定期也是一种线程,且优先级为最高0;尚有对信号量、队列、时间标志、块池、和字节池初始化。/*进行某些高档初始化*/_tx_initialize_high_level();VOID _tx_initialize_high_level(VOID)/* Initialize the event log,if enabled. */TX
©2010-2024 宁波自信网络信息技术有限公司 版权所有
客服电话:4008-655-100 投诉/维权电话:4009-655-100