tx_kernel_enter();进入threadx核
tx_kernel_enter()
void tx_kernel_enter(void)
所属文件 调用者 开关量
demo.C 启动代码 无
操作系统首先从从量表直接进入该函数,在函数以前没有进行任何的硬件及软件的初始化!该函数主要包含_tx_initialize_low_level(),_tx_initialize_high_level(),tx_application_define(_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;
/* 进行一些基本硬件设置,启动程序等 */
_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_INITIALIZE_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)
;{
EXPORT _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 area
LDR a3, [pc, #FIQ_STACK_SIZE-.-8] ; 获得FIO堆栈地址(这里没有弄明白,有待?)
MOV a1, #FIQ_MODE ; 设置FIQ_MODE
MSR 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模式的 CPSR
MSR CPSR_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模式的CPSR
MSR 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 = (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 thread's stack. */
; _tx_timer_stack_start = first_available_memory;
; _tx_timer_stack_size = stack_size;
; _tx_timer_priority = 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] ; 存储定时器线程优先级
; /*保存第一个变量内存地址. */
; _tx_initialize_unused_memory = (VOID_PTR) System Stack + Timer Stack;
;
LDR a3, [pc, #UNUSED_MEMORY-.-8] ;获得没有使用的内存指针地址
STR a1, [a3, #0] ; 保存第一个空内存地址
; /* 建立周期性的定时中断. */
STMDB {LR} //让lr入栈,保护lr
BL TargetInit //TargetInit()为C语言编写的中断定时函数
LDMIA {lr} //让lr出栈
在这里加上ARM定时器已实现周期性的中断
; /* Done, return to caller. */
;
MOV pc, lr ; 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_handler
EXPORT __tx_irq_processing_return
__tx_irq_handler
;
; /* 调用函数保存线程上下文环境. */
B _tx_thread_context_save
__tx_irq_processing_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 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. */
;
BL clearflag ;清除中断标志位很重要(自己移植时加的,位置是否恰当?)
BL _tx_timer_interrupt ; 定时中断处理函数
;
; /* 系统线程上下文环境恢复函数 */
B _tx_thread_context_restore
_tx_timer_interrupt
所属文件 调用者 开关量
tx_timin.s 启动代码 无
该函数主要是中断后将系统时钟加1,时间切片减1。定时部分比较多,没有完全看明白。
IMPORT _tx_timer_time_slice
IMPORT _tx_timer_system_clock
IMPORT _tx_timer_current_ptr
IMPORT _tx_timer_list_start
IMPORT _tx_timer_list_end
IMPORT _tx_timer_expired_time_slice
IMPORT _tx_timer_expired
IMPORT _tx_timer_thread
IMPORT _tx_thread_current_ptr
IMPORT _tx_thread_time_slice
IMPORT _tx_thread_resume
IMPORT _tx_thread_preempt_disable
;
PRESERVE8
AREA |C$$code|, CODE, READONLY
|x$codeseg| DATA
;VOID _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, #SYSTEM_CLOCK-.-8] ; 获得系统时钟地址
LDR a1, [a2, #0] ; 获得系统时钟
ADD a1, a1, #1 ; 将系统时钟加1
STR 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_slice处
; /* 时间切片减1. */
; _tx_timer_time_slice--;
;
SUB a3, a3, #1 ; 时间切片值减1
STR 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, [pc, #EXPIRED_TIME_SLICE-.-8] ; 获得定时切片数是否为0标志地址
MOV a1, #1 ; 将标志设为1
STR 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] ; 获得当前的_tx_timer_current_ptr
LDR 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 address
MOV a3, #1 ; Build expired value
STR a3, [a4, #0] ; Set expired flag
B __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] ; Pickup addr of timer list end
LDR a3, [a4, #0] ; Pickup list end
CMP 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 start
LDR a1, [a4, #0] ; Set current 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 flag
LDR a3, [a4, #0] ; Pickup time-slice expired flag
CMP a3, #0 ; Did a time-slice expire?
BNE __tx_something_expired ; If non-zero, time-slice expired
LDR a2, [pc, #EXPIRED-.-8] ; Pickup addr of other expired flag
LDR a1, [a2, #0] ; Pickup timer expired flag
CMP a1, #0 ; Did a timer expire?
BEQ __tx_timer_nothing_expired ; No, nothing expired
;
__tx_something_expired
;
;
STR lr, [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 flag
LDR a1, [a2, #0] ; Pickup timer expired flag
CMP a1, #0 ; Check for timer expiration
BEQ __tx_timer_dont_activate ; If not set, skip timer activation
;
; /* Increment the 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 flag
ADD a3, a3, #1 ; Incrment the preempt disable count
STR a3, [a4, #0] ; Store it back
;
; /* Activate the system timer thread. */
; _tx_thread_resume(&_tx_timer_thread);
;
LDR a1, [pc, #TIMER_THREAD-.-8] ; Get timer thread control block addr
BL _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] ; Pickup addr of time-slice expired
LDR a3, [a4, #0] ; Pickup the actual flag
CMP a3, #0 ; See if the flag is set
BEQ __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 _tx_thread_time_slice ; Call time-slice processing
CMP a1, #0 ; Check return status
BNE __tx_timer_not_ts_expiration ; If time-sliced, skip reset processing
LDR a2, [pc, #CURRENT_PTR-.-8] ; Pickup addr of current thread pointer
LDR a1, [a2, #0] ; Pickup thread pointer
LDR a3, [a1, #24] ; Pickup fresh time-slice for thread
; (a fresh time slice was setup in
; the _tx_thread_time_slice function)
LDR a4, [pc, #TIME_SLICE-.-8] ; Pickup addr of time-slice variable
STR 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 flag
MOV a1, #0 ; Clear value
STR a1, [a4, #0] ; Clear time-slice expired flag
;
LDR lr, [sp], #4 ; Recover lr register
;
; }
;
__tx_timer_nothing_expired
;
MOV pc, lr ; Return to caller
;
;}
TIME_SLICE
DCD _tx_timer_time_slice
SYSTEM_CLOCK
DCD _tx_timer_system_clock
TIMER_CURRENT_PTR
DCD _tx_timer_current_ptr
LIST_START
DCD _tx_timer_list_start
LIST_END
DCD _tx_timer_list_end
EXPIRED_TIME_SLICE
DCD _tx_timer_expired_time_slice
EXPIRED
DCD _tx_timer_expired
TIMER_THREAD
DCD _tx_timer_thread
CURRENT_PTR
DCD _tx_thread_current_ptr
THREAD_TIME_SLICE
DCD _tx_thread_time_slice
RESUME
DCD _tx_thread_resume
PREEMPT_DISABLE
DCD _tx_thread_preempt_disable
END
_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_EL_INITIALIZE
/* 调用线程初始化函数. */
_tx_thread_initialize();
/* 调用定时初始化函数 */
_tx_timer_initialize();
/* 调用信号量初始化函数 */
_tx_semaphore_initialize();
/* 调用队列初始化函数 */
_tx_queue_initialize();
/* 调用事件标志初始化函数. */
_tx_event_flags_initialize();
/* 调用block pool 初始化函数. */
_tx_block_pool_initialize();
/* 调用byte pool初始化函数. */
_tx_byte_pool_initialize();
}
/* 调用线程初始化函数. */
_tx_thread_initialize();
VOID _tx_thread_initialize(VOID)
所属文件 调用者 开关量
tx_ti.c 启动代码 无
此函数主要实现对与线程有关的一些变量进行初始化。
VOID _tx_thread_initialize(VOID)
{
REG_1 UINT i; /* Working index variable */
REG_2 UCHAR set_bit; /* Lowest set bit */ H
REG_3 UINT temp; /* Working shift variable */
REG_4 UCHAR *lowest_set_ptr; /* Pointer in set bit array */
REG_5 TX_THREAD_PTR *priority_list_ptr; /* Pointer in priority list */
/* Note: the system stack pointer and the system state variables are
initialized by the low and high-level initialization functions,
respectively. */
/* 初始化当前线程指针为空 */
_tx_thread_current_ptr = TX_NULL;
/* 初始化要执行线程指针为空. */
_tx_thread_execute_ptr = TX_NULL;
/* 初始化优先级信息 */
_tx_thread_priority_map = 0;
_tx_thread_preempted_map = 0;
_tx_thread_highest_priority = TX_MAX_PRIORITIES;
/* 初始化the lowest-set bit 表. 这被用来当线程被挂起和从新启动时寻找下一个准备执行的线程 */
_tx_thread_lowest_bit[0] = 0;
lowest_set_ptr = &_tx_thread_lowest_bit[1];
for (i = 1; i < TX_THREAD_MAX_BYTE_VALUES; i++)
{
/*将当前序号给临时变量 */
temp = i;
/* 寻找字节中的最低比特位设置,即在一个字节中的最高优先级 */ r
set_bit = 0;
while (!(temp & 1))
{
/*把序号往右移动一位.并且增加set-bit 的位置. */
temp = temp >> 1;
set_bit++;
}
/* 预先求出对应的线程优先级byte值所对应的优先级最高的的bit位*/ *(lowest_set_ptr++) = set_bit;
/*例如priorityb_byte的值为5即0x101那么所对应的优先级最高为0,则
lowest_set_ptr[priorityb_byte]=0*/
}
/*当优先级字节的值为i时,我们很快可以知道该字节的高优先级为第_tx_thread_lowest_bit[i]bit位。*/
/* 初始化优先级头指针队列. 即将线程块对应的空间都初始化为空 */
priority_list_ptr = &_tx_thread_priority_list[0];
for (i = 0; i < TX_MAX_PRIORITIES; i++)
*(priority_list_ptr++) = TX_NULL;
/* I初始化以创建线程列表的头指针和以创建线程的个数*/
_tx_thread_created_ptr = TX_NULL;
_tx_thread_created_count = 0;
/* Clear the global preempt disable variable. ???*/
_tx_thread_preempt_disable = 0;
}
VOID _tx_timer_initialize(VOID)
所属文件 调用者 开关量
tx_timi.c 启动代码 无
主要实现有定时器有关的一些变量的初始化,并建立了一个线程专门由于定时管理。
/* 调用定时初始化函数 */
_tx_timer_initialize();
VOID _tx_timer_initialize(VOID)
{
REG_1 UINT i; /* Working index variable */
REG_2 TX_INTERNAL_TIMER **timer_ptr; /* Working timer pointer */
/* 初始化系统时钟为 0. */
_tx_timer_system_clock = 0;
/*初始化时间切片的值为0以确保它是无效的 ?? */
_tx_timer_time_slice = 0;
/* 清除时间期限终止标志位 */
_tx_timer_expired_time_slice = TX_FALSE;
_tx_timer_expired = TX_FALSE;
/* 初始化线程并且定时管理控制结构的应用 */
/*首先初始化定时指针列表,即将列表中存储的指针都赋为空 */
timer_ptr = &_tx_timer_list[0];
for (i = 0; i < TX_TIMER_ENTRIES; i++)
*timer_ptr++ = TX_NULL;
/* 初始化所有列表指针. */
_tx_timer_list_start = &_tx_timer_list[0];
_tx_timer_current_ptr = &_tx_timer_list[0];
/* 设置定时列表的尾指针为实际定时列表的的指针再加1, 事件中断处理在前面的汇编语言中已经定义过了 (就是_tx_irq_handler) */
_tx_timer_list_end = &_tx_timer_list[TX_TIMER_ENTRIES-1];
_tx_timer_list_end = _tx_timer_list_end + 1;
/* 创建一个系统定时线程 这个线程处理所有的定时期限终止和从新调度. 它的堆栈和优先级在前面的low-level initialization component已经定义过了(从新回去看)*/
_tx_thread_create(&_tx_timer_thread, "System Timer Thread", _tx_timer_thread_entry,
(ULONG) TX_TIMER_ID, _tx_timer_stack_start, _tx_timer_stack_size,
_tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE,TX_DONT_START);
/*_tx_timer_stack_start, _tx_timer_stack_size,_tx_timer_priority,是在tx_ill.s中进行了初始化,其中_timer_stack_size=1024,_tx_timer_priority=0*/
/*初始化已建定时列表的指针 */
_tx_timer_created_ptr = TX_NULL;
/* 初始化已建定时数为0 */
_tx_timer_created_count = 0;
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。