You are on page 1of 69

REX

System Group

1.

Defines&Macros ...............................................5
1.1.
......................................................................................5
1.1.1.
TCB ..........................................................5
1.1.2.
timer.........................................................7
1.1.3.
Critical Section........................................7
1.1.4.
.................................................................7
1.2.
................................................................................8
1.2.1.
rex_curr_task ................................................................8
1.2.2.
rex_best_task................................................................8
1.2.3.
rex_task_list..................................................................8
1.2.4.
rex_num_tasks ..............................................................8
1.2.5.
rex_kernel_tcb ..............................................................8
1.2.6.
rex_sched_allow ...........................................................8
1.2.7.
rex_nest_depth..............................................................9
1.2.8.
rex_timer_list ................................................................9
1.2.9.
rex_null_timer ...............................................................9
1.2.10.
rex_irq_vector & rex_fiq_vector....................................9
1.3.
MACROS ...............................................................9
1.3.1.
REX_VERSION_NUMBER...............................................9
1.3.2.
.................................................................9
1.3.3.
REX_TASK_RUNNABLE(tcb) .......................................10
1.3.4.
..................................................................10
2.
TASK .................................................................................10
2.1.
....................................................................................11
2.1.1.
rex_def_task_internal() ...............................................11
2.2.
.....................................................................14
2.2.1. rex_task_preamble() ...........................................................14
2.3.
...........................................................................15
2.3.1.
rex_suspend_task().....................................................15
2.3.2.
rex_resume_task() ......................................................15
2.4.
....................................................................................16
2.4.1.
rex_remove_task() ......................................................16
2.4.2.
rex_kill_task_ext().......................................................16
2.5.
Others .....................................................................................19
2.5.1.
rex_self() .....................................................................19
2.5.2.
rex_get_pri() ................................................................19
2.5.3.
rex_set_pri() ................................................................19
2.5.4.
rex_task_pri() ..............................................................19

3.

Schedule................................................................21
3.1.
....................................................................................21
3.1.1.
rex_sched() .................................................................21
3.2.
rex_best_task....................................................................23

3.2.1.
rex_set_best_task().....................................................24
3.3.
/ .......................................................................24
3.3.1.
rex_task_lock()............................................................24
3.3.2.
rex_task_free() ............................................................25
3.3.3.
rex_tasks_are_locked()...............................................25

4.

Interrupts..............................................................25
4.1.
..............................................................................26
4.1.1.
rex_set_interrupt_vector () .........................................26
4.2.
PIC Trampoline Service...................26
4.2.1.
tramp_init()..................................................................26
4.2.2.
tramp_set_isr() ............................................................27
4.2.3.
tramp_isr()...................................................................29
4.3.
IRQ_handler.............................................................................33

5.

SignalsTimers......................37

5.1.
.......................................................................................37
5.1.1.
rex_wait() ....................................................................38
5.1.2.
rex_set_sigs() ..............................................................39
5.1.3.
rex_get_sigs()..............................................................39
5.1.4.
rex_clr_sigs()...............................................................40
5.2.
.......................................................................................40
5.2.1.
rex_init_timer_list() .....................................................41
5.2.2.
rex_insert_timer() .......................................................41
5.2.3.
rex_def_timer() ............................................................42
5.2.4.
rex_set_timer() ............................................................43
5.2.5.
rex_timed_wait() .........................................................44
5.2.6.
rex_clr_timer().............................................................44
5.2.7.
rex_get_timer()............................................................45
5.2.8.
rex_pause_timer() .......................................................46
5.2.9.
rex_resume_timer().....................................................46
5.2.10.
rex_delete_task_timers() ............................................47
5.2.11.
rex_decrement_timers() .............................................47
5.2.12.
rex_tick() .....................................................................49
5.3.
Others .....................................................................................49
5.3.1.
rex_sleep() ..................................................................49
6.
Critical Section ..............................................................50
6.1.
rex_init_crit_sect() ..................................................................51
6.2.
rex_enter_crit_sect()...............................................................51
6.3.
rex_leave_crit_sect_internals() ..............................................53
7.
APC&DPC ......................................................................................56
7.1.
DPC.................................................................................56
7.1.1.
rex_dpc_task() ............................................................56
7.1.2.
rex_execute_next_dpc() .............................................57

7.1.3.
rex_queue_dpc()..........................................................57
7.2.
APC.................................................................................58
7.2.1.
rex_queue_apc()..........................................................58
7.2.2.
rex_queue_apc_internal() ...........................................59
7.2.3.
rex_apc_prolog() .........................................................60
7.2.4.
rex_call_apc()..............................................................62
7.2.5.
rex_apc_epilog ............................................................63
8.
REX...............................................................63
8.1.
main() ......................................................................................64
8.2.
rex_init() ..................................................................................64
8.3.
rex_exit() .................................................................................67
8.4.
rex_get_version_number() ......................................................67
9.
...........................................................................................67
9.1.
rex_mem_init() ........................................................................67
9.2.
rex_malloc() ............................................................................67
9.3.
rex_calloc() .............................................................................68
9.4.
rex_realloc() ............................................................................68
9.5.
rex_free().................................................................................68

REXReal Time Executive

API
REX
REX 5k ROM RAM
k
REX IRQ

1. Defines&Macros

1.1.
rex.h REX

1.1.1.TCB
REX

typedef struct rex_tcb_struct {


void
*sp;
/* */
void
*stack_limit; /*
*/
unsigned long
slices;
/*
*/
rex_sigs_type
sigs;
/* */
rex_sigs_type
wait;
/*
*/
rex_priority_type
pri;
/* */
#if defined FEATURE_REX_PROFILE
unsigned long
time_samples; /* Profiling information */
unsigned long
max_intlock_time; /* Profiling Info */
#endif
#if defined TIMETEST
word
#endif

leds;

/* TIMETEST val

#if defined FEATURE_SOFTWARE_PROFILE


/* 32 bits counter, ~30 usec/tick, ~35 hours */
dword
numticks;

*/

#endif
#ifdef FEATURE_REX_APC
long
num_apcs;
#endif

/* APC */

/* rexarm.h */
rex_tcb_link_type
cs_link;
/* */
rex_crit_sect_type
*cs_stack[REX_CRIT_SECT_MAX]; /*
TCB */
rex_crit_sect_type
**cs_sp;
/* */
boolean
char

suspended;
/* */
task_name[REX_TASK_NAME_LEN + 1];

#if defined FEATURE_REX_EXTENDED_CONTEXT


void
*ext;
#endif
unsigned long
thread_id;
unsigned long
stack_size;
//task
#ifdef FEATURE_SI_STACK_WM
unsigned long
stack_wm;
#endif
//BSD socket
#if defined FEATURE_DS_SOCKETS_BSD
void
*bsdcb_ptr;
#endif
int
err_num;
/* Error code
*/
//taskDog
int
dog_report_val;
/* Dog Report Id
*/
int
autodog_enabled; /* Dog Report enabled? */
#if defined FEATURE_REX_CREATE_TASK || defined FEATURE_ZREX
boolean
is_dynamic;
#endif
#ifdef FEATURE_REX_IPC
rex_ipc_info_type ipc_info;
#endif
} rex_tcb_type;

1.1.2. timer
REX

typedef struct rex_timer_struct


{
struct
{
struct rex_timer_struct *next_ptr;
struct rex_timer_struct *prev_ptr;
} link;
rex_timer_cnt_type cnt;
/*
*/
rex_tcb_type
*tcb_ptr; /* TCB */
rex_sigs_type
sigs;
/*
*/
#ifdef FEATURE_REX_TIMER_EX
rex_timer_cb_type
cb_ptr; /* Function called when timer expires */
unsigned long
cb_param; /* Argument to callback function */
#endif
} rex_timer_type;

1.1.3. Critical Section

typedef struct {
byte
struct rex_tcb_struct
struct rex_tcb_struct
rex_priority_type
} rex_crit_sect_type;

lock_count; /* > 0 if crit sect is taken


*/
*owner;
/* TCB */
*tcb_link; /* */
orig_pri; /* */

1.1.4.
ARM
typedef PACKED struct {
rex_cpu_register_type spsr;
rex_cpu_register_type r[13]; /* r0-r7,r8-r12 */
rex_cpu_register_type lr;
/* r14
*/
rex_cpu_register_type pc;
/* r15
*/
} rex_context_frame_type;

1.2.
1.2.1. rex_curr_task
TCB
rex_tcb_type * rex_curr_task;
1.2.2. rex_best_task
ready task
rex_curr_task rex_best_task rex_sched()

ISR rex_sched()
rex_sched()rex_best_task
rex_best_task
rex_best_task rex_curr_task) ready
rex_best_task rex_best_task
rex_tcb_type * rex_best_task;
1.2.3. rex_task_list

rex_tcb_type rex_task_list;
1.2.4. rex_num_tasks

int rex_num_tasks = 0;
1.2.5. rex_kernel_tcb

Idle task
static rex_tcb_type rex_kernel_tcb;
rex_stack_word_type rex_kernel_stack[
sizeof(rex_stack_word_type) ];

REX_KERNEL_STACK_SIZE

1.2.6. rex_sched_allow

int rex_sched_allow = TRUE;

/* turns sched on/off */

1.2.7. rex_nest_depth

unsigned int rex_nest_depth = 0; /* supports nesting of TASKLOCK/


* FREE.*/
1.2.8. rex_timer_list

static rex_timer_type rex_timer_list;


1.2.9. rex_null_timer

static rex_timer_type rex_null_timer;


1.2.10. rex_irq_vector & rex_fiq_vector
ISR
void
void

(* rex_irq_vector) (void);
(* rex_fiq_vector) (void);

1.3. MACROS
1.3.1. REX_VERSION_NUMBER
#define REX_VERSION_NUMBER ((unsigned long) 403)
1.3.2.
REX_TASK_LIST_FRONT()

REX_TASK_LIST_NEXT( tcb_ptr )
REX_TASK_LIST_PREV( tcb_ptr )
REX_TASK_LIST_POP( tcb_ptr )
#define REX_TASK_LIST_FRONT() (&rex_task_list)
#define REX_TASK_LIST_NEXT( tcb_ptr ) ((rex_tcb_type *)
tcb_ptr->link.next_ptr )
#define REX_TASK_LIST_PREV( tcb_ptr ) ((rex_tcb_type *)
tcb_ptr->link.prev_ptr )

#define REX_TASK_LIST_POP( tcb_ptr )\


tcb_ptr->link.next_ptr->link.prev_ptr = tcb_ptr->link.prev_ptr;\
tcb_ptr->link.prev_ptr->link.next_ptr = tcb_ptr->link.next_ptr;
1.3.3. REX_TASK_RUNNABLE(tcb)
ready
123
4 APC
#define REX_TASK_RUNNABLE(tcb) ((tcb->suspended == FALSE) && \
(tcb->cs_link.next_ptr == NULL) && \
((tcb->wait
== 0)
|| \
(tcb->num_apcs > 0)))
1.3.4.
REX_PAUSE_DOG_MONITOR( tcb_ptr ) DOG
REX_RESUME_DOG_MONITOR( tcb_ptr ) DOG
#define REX_PAUSE_DOG_MONITOR( tcb_ptr ) \
{\
if ( ( tcb_ptr->autodog_enabled ) && ( tcb_ptr->dog_report_val >= 0 ) )\
{\
dog_monitor_pause( tcb_ptr->dog_report_val ); \
}\
}
#define REX_RESUME_DOG_MONITOR( tcb_ptr ) \
{\
if ( tcb_ptr->dog_report_val >= 0 ) \
{\
dog_monitor_resume( tcb_ptr->dog_report_val ); \
}\
}

2. TASK
REX task task
TCB

REX task
REX

TCB
TCB

2.1.
2.1.1. rex_def_task_internal()

TCB
rex_task_list
rex_best_task
void rex_def_task_internal(
rex_tcb_type
*p_tcb,
/* valid tcb for new task
*/
unsigned char*
p_stack,
/* stack for new task
*/
rex_stack_size_type p_stksiz,
/* stack size in bytes
*/
rex_priority_type
p_pri,
/* priority for new task
*/
rex_task_func_type p_task,
/* task startup function
*/
dword
p_param,
/* parameter for new task
*/
char
*p_tskname,
/* A/N string for task name
*/
boolean
p_susp,
/* is task initially suspended? */
void
*p_parent,
/* opaque handle to container
*/
boolean
p_dynamic, /* stack/tcb alloc'd via dyna mem */
int
dog_report_val /* Dog report value
*/
)
{
word
index
= 0;
byte
*stack_ptr = NULL;
rex_context_frame_type *cf_ptr
= NULL;
/*------------------------------------------------------** Task stack pointer points to the bottom of allocated
** stack memory. p_stksiz is the number of 8-bit bytes.
**-----------------------------------------------------*/
stack_ptr = (byte *)((unsigned long)p_stack + (unsigned long)p_stksiz sizeof(unsigned long) );
/*------------------------------------------------------** Creates room for the context.
** sp points to the top of the context frame.
**-----------------------------------------------------*/
stack_ptr -= sizeof( rex_context_frame_type );

/*------------------------------------------------------** Defines the initial context.


** pclrrex_task_preamble
** p_taskp_param
**-----------------------------------------------------*/
cf_ptr
= (rex_context_frame_type*)stack_ptr;
cf_ptr->spsr.val
= PSR_Supervisor | PSR_Thumb;
cf_ptr->r[0].task = p_task;
cf_ptr->r[1].arg
= p_param;
cf_ptr->r[10].arg = (unsigned long)p_stack;
cf_ptr->lr.preamble = rex_task_preamble;
cf_ptr->pc.preamble = rex_task_preamble;
/* -----------------------------------------------------** Initialize the task control block (TCB)
** ------------------------------------------------------ */
p_tcb->sp
=
stack_ptr;
p_tcb->stack_limit
=
p_stack;
p_tcb->stack_size
=
p_stksiz;
p_tcb->slices
=
0;
p_tcb->sigs
=
0;
p_tcb->wait
=
0;
p_tcb->pri
=
p_pri;
p_tcb->cs_link.next_ptr =
NULL;
p_tcb->cs_link.prev_ptr =
NULL;
p_tcb->cs_sp
=
p_tcb->cs_stack; - -p_tcb->cs_sp;
p_tcb->suspended
=
p_susp;
#ifdef FEATURE_SI_STACK_WM
rex_swm_init( p_tcb );
#endif /* FEATURE_SI_STACK_WM */
p_tcb->task_name[REX_TASK_NAME_LEN] = '\0';
if (p_tskname != NULL) /* copy task name if one was supplied */
{
/* copy bytes until /0 received or enough chars have been copied */
while ( (p_tcb->task_name[index] = p_tskname[index] ) &&
( index++ < REX_TASK_NAME_LEN ) );;
}
#if defined FEATURE_REX_APC
p_tcb->num_apcs = 0;
/* Number of queued APCs */
#endif

#if defined FEATURE_REX_PROFILE


p_tcb->time_samples = 0; /* Profiling information */
#endif
#if defined FEATURE_DS_SOCKETS_BSD
p_tcb->bsdcb_ptr = NULL;
#endif
#if defined FEATURE_SOFTWARE_PROFILE
p_tcb->numticks
= 0;
#endif
p_tcb->err_num = 0;
p_tcb->dog_report_val = dog_report_val;
p_tcb->autodog_enabled = FALSE;
#if defined FEATURE_REX_CREATE_TASK && !defined FEATURE_ZREX
p_tcb->is_dynamic = TRUE;
#endif
/*------------------------------------------------------** We are done if this is the idle task (kernel task) defined.
**-------------------------------------------------------*/
if (p_pri == 0) {
return;
}
/*------------------------------------------------------** Find the first task whose priority is lower than the
** new task and insert the new task in front of the
** lower priority task.
** rex_idle_task (the kernel task) is at the end of the list
** with priority 0 and therefore no need to check for null ptrs.
**-----------------------------------------------------*/
REX_INTLOCK();
{
rex_tcb_type *tcb_ptr;
tcb_ptr = rex_task_list.link.next_ptr;
while ((tcb_ptr->pri > p_pri) && (tcb_ptr != &rex_kernel_tcb)) {
tcb_ptr = tcb_ptr->link.next_ptr;
}

p_tcb->link.prev_ptr = tcb_ptr->link.prev_ptr;
p_tcb->link.next_ptr = tcb_ptr;
tcb_ptr->link.prev_ptr->link.next_ptr = p_tcb;
tcb_ptr->link.prev_ptr = p_tcb;
}
#ifdef FEATURE_REX_IPC
if (ipcns_node_register(p_tcb) == FALSE)
{
return;
}
#endif
/*--------------------------------------------------** Make this task the best task if it is higher
** priority than the present best task.
**---------------------------------------------------*/
/* Always compare with REX_BEST_TASK, not REX_CURR_TASK */
if ( (p_pri > rex_best_task->pri) && (p_tcb->suspended == FALSE) )
{
rex_best_task = p_tcb;
/* swap the task in */
rex_sched();
}
rex_num_tasks++;
REX_INTFREE();
return;
}
API
rex_def_taskrex_def_task_extrex_def_task_ext2

2.2.
2.2.1. rex_task_preamble()

REX
void rex_task_preamble(
void (*func_ptr)( dword arg ),
dword arg
)

{
func_ptr( arg );
/* if we return, kill the task */
rex_kill_task( rex_self() );
} /* END rex_task_preamble */

2.3.
2.3.1. rex_suspend_task()

void rex_suspend_task( rex_tcb_type *p_tcb)


{
p_tcb->suspended = TRUE;
REX_INTLOCK();
if ( ( p_tcb == rex_curr_task ) && !rex_is_in_irq_mode( ) )
{
rex_set_best_task( REX_TASK_LIST_FRONT() );
rex_sched( );
}
REX_INTFREE();
return;
} /* END rex_suspend_task */
2.3.2. rex_resume_task()

rex_best_task
void rex_resume_task( rex_tcb_type
*p_tcb)
{
REX_INTLOCK();
/* basic sanity check to see if we should even be here or not */
if (p_tcb->suspended == TRUE)
{
p_tcb->suspended = FALSE;
if ((p_tcb->pri > rex_best_task->pri) &&
REX_TASK_RUNNABLE(p_tcb))
{
rex_best_task = p_tcb;
rex_sched();
}

}
REX_INTFREE();
return;
} /* END rex_resume_task */

2.4.
2.4.1. rex_remove_task()
TCB rex_task_list
void rex_remove_task( rex_tcb_type *tcb_ptr
{
rex_tcb_type *prev_tcb_ptr;
rex_tcb_type *next_tcb_ptr;

/* pointer to tcb */)

prev_tcb_ptr = REX_TASK_LIST_PREV( tcb_ptr );


next_tcb_ptr = REX_TASK_LIST_NEXT( tcb_ptr );
if ( ( prev_tcb_ptr == NULL
||
prev_tcb_ptr->pri != tcb_ptr->pri ) &&
next_tcb_ptr != NULL
&&
next_tcb_ptr->pri == tcb_ptr->pri
)
{
/*
*/
rex_tcb_type *temp_tcb_ptr = next_tcb_ptr;
while ( temp_tcb_ptr->pri == tcb_ptr->pri )
{
temp_tcb_ptr->pri_rep_ptr = next_tcb_ptr;
temp_tcb_ptr = REX_TASK_LIST_NEXT( temp_tcb_ptr );
}
}
REX_TASK_LIST_POP( tcb_ptr );
tcb_ptr->link.prev_ptr = NULL;
tcb_ptr->link.next_ptr = NULL;
return;
} /* END rex_remove_task */
2.4.2. rex_kill_task_ext()
rex_task_list

DOG

void rex_kill_task_ext(
rex_tcb_type *p_tcb,
boolean
schedule_new_task
)
{
REX_INTLOCK();
TASKLOCK();
/* Task is alive only if it is still linked into TCB list.
*/
if ( (p_tcb->link.prev_ptr != NULL ) || (p_tcb->link.next_ptr != NULL) )
{
/* Remove TCB from the task list.
*/
rex_remove_task( p_tcb );
/* Remove REX timers associated with the task from the timer list.
*/
rex_delete_task_timers( p_tcb );
/* Tell Dog to stop monitoring this task.
*/
REX_PAUSE_DOG_MONITOR( p_tcb );
/* Check if we were holding or waiting on a critical section */
while (p_tcb->cs_sp >= p_tcb->cs_stack)
{
if ( p_tcb->cs_link.next_ptr == NULL) /* holding crit section */
{
/* free the crit section, but don't call rex_sched() yet */
rex_leave_crit_sect_internals( *p_tcb->cs_sp, p_tcb, FALSE);
}
else /* we were waiting on the list */
{
/* if item is first on the list, fix up list head */
if (p_tcb->cs_link.prev_ptr == REX_CRIT_SECT_FLAG)
{
(*p_tcb->cs_sp)->tcb_link = p_tcb->cs_link.next_ptr;
}
else /* fix up previous item on list */

{
p_tcb->cs_link.prev_ptr->cs_link.next_ptr =
p_tcb->cs_link.next_ptr;
}
/* if item is NOT the last on the list */
if (p_tcb->cs_link.next_ptr != REX_CRIT_SECT_FLAG)
{
p_tcb->cs_link.next_ptr->cs_link.prev_ptr =
p_tcb->cs_link.prev_ptr;
}
--p_tcb->cs_sp;
}
} /* END we needed to deal with crit section */
rex_num_tasks--;
if( schedule_new_task )
{
/* */
if (p_tcb == rex_curr_task)
{
if (rex_nest_depth > 0)
{
rex_nest_depth = 0;
rex_sched_allow = TRUE;
}
} /* end-if task was killing itself */
rex_set_best_task( REX_TASK_LIST_FRONT() );
rex_sched();
} /* END needed to reschedule */
} /* END TCB was still in active list */
TASKFREE();
REX_INTFREE();
return;
} /* END rex_kill_task_ext */
API
rex_kill_task

2.5. Others
2.5.1. rex_self()
TCB
rex_tcb_type *rex_self( void )
{
/*------------------------------------------------------** The currently running task is in rex_curr_task
**-----------------------------------------------------*/
return rex_curr_task;
} /* END rex_self */
2.5.2. rex_get_pri()

rex_priority_type rex_get_pri( void )


{
/*------------------------------------------------------** Just return the priority field of the current task
**-----------------------------------------------------*/
return rex_curr_task->pri;
} /* END rex_get_pri */
2.5.3. rex_set_pri()

rex_priority_type rex_set_pri(
rex_priority_type p_pri
/* the new priority */
)
{
/*------------------------------------------------------** A wrapper function that just calls rex_task_pri with
** the current task
**-----------------------------------------------------*/
return rex_task_pri(rex_curr_task, p_pri);
} /* END rex_set_pri */
2.5.4. rex_task_pri()

rex_priority_type rex_task_pri(
rex_tcb_type
*p_tcb,
/* tcb to set priority on
*/
rex_priority_type p_pri
/* the new priority
*/
)
{
rex_priority_type prev_pri = p_tcb->pri; /* the priority before the set */
boolean comp = FALSE;
/* Comparator */
REX_INTLOCK();
comp = (p_pri == p_tcb->pri);
REX_INTFREE();
/* Return if the priority is the same */
if( comp )
{
return prev_pri;
}
REX_INTLOCK();
/* */
p_tcb->link.next_ptr->link.prev_ptr = p_tcb->link.prev_ptr;
p_tcb->link.prev_ptr->link.next_ptr = p_tcb->link.next_ptr;
p_tcb->pri = p_pri;
/* rex_idle_task(the kernel task)
0 */
search_ptr = rex_task_list.link.next_ptr;
while(search_ptr->pri > p_pri) {
search_ptr = search_ptr->link.next_ptr;
}
p_tcb->link.prev_ptr = search_ptr->link.prev_ptr;
p_tcb->link.next_ptr = search_ptr;
search_ptr->link.prev_ptr->link.next_ptr = p_tcb;
search_ptr->link.prev_ptr = p_tcb;
/* readyrex_best_task */
if ( (p_pri > rex_best_task->pri) && ( REX_TASK_RUNNABLE(p_tcb) ) )
{

rex_best_task = p_tcb;
rex_sched();
}
REX_INTFREE();
return prev_pri;
} /* END rex_task_pri */

3. Schedule
REX 32
0 kernel task idle task
REX
REX ready
REX

ready
idle
REX

3.1.
3.1.1. rex_sched()

REX
REX best task
rex_sched current task best task
best task current task

LEAF_NODE rex_sched
mrs a3, CPSR
; Save the CPSR for later.
orr a1, a3, #PSR_Irq_Mask:OR:PSR_Fiq_Mask FIQ
msr CPSR_c, a1
;--------------------------------------------------------------------------;
;--------------------------------------------------------------------------and a1, a3, #PSR_Mode_Mask
cmp a1, #PSR_Supervisor ; If not in Supervisor mode do not swap
bne rex_sched_exit_1
; until we revert back to task level

;--------------------------------------------------------------------------;
;--------------------------------------------------------------------------; test for TASKLOCK
ldr a2, =rex_sched_allow
; load scheduling flag
ldr a2, [a2]
; dereference sched. flag
cmp a2, #0
; compare with FALSE
beq rex_sched_exit_1
; return
;--------------------------------------------------------------------------; rex_best_task rex_curr_task
;--------------------------------------------------------------------------ldr a2, =rex_best_task
; load the best task into a2
ldr a2, [a2]
; dereference best task
ldr a4, =rex_curr_task
; load the current task into a4
ldr a1, [a4]
; dereference current task
cmp a2, a1
; if current task == best task just return
beq rex_sched_exit_1
;--------------------------------------------------------------------------; Set the curr_task to the new value
;--------------------------------------------------------------------------str a2, [a4]
; set rex_curr_task=rex_best_task
mov a4, a1
; a4 points now to the last (former current) task
;--------------------------------------------------------------------------; Increment the slice count.
;--------------------------------------------------------------------------ldr a1, [a2, #REX_TCB_SLICES_OFFSET] ; load up the slice count
add a1, a1, #1
; increment it
str a1, [a2, #REX_TCB_SLICES_OFFSET]
; store it
; -------------------------------------------------------------------; CPU
; -------------------------------------------------------------------stmfd sp!, {lr}
; Return address.
sub
sp, sp, #8
; no need to store r12,r14 in task context.
stmfd sp!, {r4-r11}
sub
sp, sp, #16
; Subtract a1-a4 location
stmfd sp!, {a3}
; First line on rex_sched saves CPSR in a3!!!
;--------------------------------------------------------------------------; Save the context on stack

;--------------------------------------------------------------------------str
sp, [a4, #REX_TCB_STACK_POINTER_OFFSET]
mov
a1, a2
; a1 = the current task
;--------------------------------------------------------------------------; rex_start_task_1 void rex_start_task(rex_tcb_type *)
; a1 rex_curr_task TCB
;--------------------------------------------------------------------------rex_start_task_1
; -------------------------------------------------------------------; Restore the user state, note this may not be the state saved above
; since the call the rex_sched may have changed which stack the handler is
working on. Note, a context switch will happen here.
; -------------------------------------------------------------------ldr
sp, [a1, #REX_TCB_STACK_POINTER_OFFSET]
; Load the
stack pointer
ldmfd sp!, {a1}
; Restore SPSR (in a1)

msr
msr
mov
add
ldmfd

SPSR_f, a1
; Load SPSR
SPSR_c, a1
; Load SPSR
a1, sp
; Load sp in a1.
sp, sp, #REX_CF_SIZE - 4 ; adjust sp
a1, {r0-r12,lr,pc}^
; Load and return, sp already adjusted.

; -------------------------------------------------------------------;
; -------------------------------------------------------------------rex_sched_exit_1
msr CPSR_f, a3
msr CPSR_c, a3

; Restore interrupts as prior to rex_sched


; Restore interrupts as prior to rex_sched

LEAF_NODE_END
; END rex_sched

3.2. rex_best_task
rex_best_task ready

3.2.1. rex_set_best_task()
ready
rex_best_task
void rex_set_best_task(rex_tcb_type *start_tcb)
{
rex_tcb_type *candidate_task;
ASSERT( start_tcb != NULL );
candidate_task = start_tcb->link.next_ptr;
ASSERT( candidate_task != NULL );
/* find first runnable task */
while ( REX_TASK_RUNNABLE(candidate_task) == FALSE)
{
candidate_task = candidate_task->link.next_ptr;
ASSERT( candidate_task != NULL );
}
rex_best_task = candidate_task;
return;
} /* END rex_set_best_task */
3.3. /
3.3.1. rex_task_lock()
IRQ

FALSE

void rex_task_lock( void )


{
if ( !rex_is_in_irq_mode( ) )
{
REX_INTLOCK();
rex_sched_allow = FALSE;
rex_nest_depth++;
REX_INTFREE();
}
} /* END rex_task_lock */
REX_INTLOCK()INTLOCK()

3.3.2. rex_task_free()
IRQ

0 rex_sched()

void rex_task_free( void )


{
if ( !rex_is_in_irq_mode( ) )
{
REX_INTLOCK();
if (rex_nest_depth > 0)
rex_nest_depth--;
if (rex_nest_depth == 0)
{
rex_sched_allow = TRUE;
rex_sched();
}
REX_INTFREE();
}
} /* END rex_task_free */
REX_INTFREE()INTFREE()
3.3.3. rex_tasks_are_locked()
TRUE FALSE
int rex_tasks_are_locked( void )
{
return !rex_sched_allow;
} /* END rex_tasks_are_locked */

4. Interrupts
REX
ready
Programmable Interrupt ControllerPIC
PIC TRAMPOLINE SERVICES

4.1.
4.1.1. rex_set_interrupt_vector ()
ISR IRQFIQ

tramp_set_isr()

void rex_set_interrupt_vector (
rex_vect_type v,
/* Vector
*/
void (*fnc_ptr)( void )
/* *function to be installed */
)
{
if (v == P_IRQ_VECT)
{
rex_irq_vector = fnc_ptr;
}
else
{
rex_fiq_vector = fnc_ptr;
}
} /* END rex_set_interrupt_vector */

4.2. PIC Trampoline Service


4.2.1. tramp_init()
ISR
PIC
tramp_isr() IRQ
void tramp_init( void )
{
uint8 i;
/* all isr to default */
for ( i = 0; i < TRAMP_NUM_INTS; i++ )
{
isr_func_tbl[i].isr_ptr = tramp_default_isr;
}
/* init hardware */
tramp_init_hardware();

#ifdef FEATURE_TRAMP_QUEUED_CALLS
/* Initialize the interrupt call queue.
*/
(void) q_init( &tramp_call_q );
#endif /* FEATURE_TRAMP_QUEUED_CALLS */
/* tramp_isr()IRQ ISRIRQ */
/* no FIQ ISR for now */
rex_set_interrupt_vector( P_IRQ_VECT, tramp_isr );
} /* end tramp_init */
4.2.2. tramp_set_isr()
ISR
void tramp_set_isr
(
/* */
tramp_isr_type int_num,
/* ISR to be installed for this interrupt */
isr_ptr_type
isr_ptr
)
{
/* Address of priority register corresponding to this interrupt */
uint32 prio_address;
/* Address of the Enable registers: IRQ_ENABLE_0 and IRQ_ENABLE_1 */
uint32 mask_reg_address;
/* Address of the Clear registers: IRQ_ENABLE_0 and IRQ_ENABLE_1 */
uint32 clear_reg_address;
/* Interrupt mask to set in the enable register */
uint32 mask_val;
/* Mask to clear bit in the CLEAR register */
uint32 clear_val = 0;
/* disable interrupts while changing table and PIC registers */
INTLOCK();
/* ISR if passed-in ISR is NULL, change it to tramp_default_isr */
if (isr_ptr == NULL)
{
isr_ptr = tramp_default_isr;

}
/* load our local table with the function ptr */
isr_func_tbl[int_num].isr_ptr = isr_ptr;
/* PIC32PRIO_BASE
4 */
prio_address = PRIO_BASE + ((unsigned int)int_num << 2);
outpdw( prio_address, (uint32) (isr_func_tbl[int_num].priority &
MAX_PRIO_VAL));
/* mask register */
if ( int_num >= NUM_INT_BITS_IN_REG)
{
mask_reg_address = HWIO_ADDR(IRQ_ENABLE_1);
mask_val
= HWIO_IN(IRQ_ENABLE_1);
clear_reg_address= HWIO_ADDR(IRQ_CLEAR_1);
/* convert to bit offset in register */
int_num -= NUM_INT_BITS_IN_REG;
}
else
{
mask_reg_address = HWIO_ADDR(IRQ_ENABLE_0);
mask_val
= HWIO_IN(IRQ_ENABLE_0);
clear_reg_address= HWIO_ADDR(IRQ_CLEAR_0);
}
/* bit */
if (isr_ptr == tramp_default_isr)
{
mask_val &= ~((unsigned int)1 <<int_num); /* set that bit to zero,
turning off INT */
/* clear the status bit of this interrupt */
clear_val = (1 << int_num);
}
else
{
mask_val |= ((unsigned int)1 << int_num); /* set bit to one, turning on
INT */
}

/* mask register */
outpdw( mask_reg_address, mask_val);
/* status
registerThis is because INT STATUS = INT ENABLE MASK & INT_SRC(s) */
if (isr_ptr == tramp_default_isr)
{
/* unset bit in the CLEAR register => clears bit in STATUS register */
outpdw( clear_reg_address, clear_val );
}
INTFREE();
} /* end tramp_set_isr */
4.2.3. tramp_isr()
IRQ IRQ_handler
PIC IRQ_VEC_INDEX_RD
ISR NON_VECTOR
IRQ_ENABLE
1) ISR
2) ISR ISR
void tramp_isr( )
{
/* vector index from PIC register */
uint32 vect_idx;
/* for our local tbl */
uint32 tbl_idx;
/* Mask of the occurring interrupt */
uint32 mask_val;
/* Address of the IRQ_ENABLE register */
uint32 mask_reg_address;
/* Address of the IRQ_CLEAR register */
uint32 clear_reg_address;
/*IRQ_VEC_INDEX_RD
ARMtramp_isr()
ISR*/
/* ARMISR

IRQ_VEC_INDEX_RDARM
IRQ_VEC_INDEX_PEND_RD
NON_VECTOR*/
boolean irq_from_arm = TRUE;

#ifdef FEATURE_DEBUG_TRAMP_EXECUTION
TRAMP_DEBUG_IN_ISR = 1;
#endif
/* */
for (;;) /* forever */
{
if (irq_from_arm)
{
/* IRQ_VEC_INDEX_RD
smart functionTASKIRQ

PICISR
ISR*/
tbl_idx = vect_idx = HWIO_INM(IRQ_VEC_INDEX_RD,
IRQ_VEC_INDEX_RD_RMSK );
irq_from_arm = FALSE;
#ifdef FEATURE_TRAMP_QUEUED_CALLS
nested_int_cnt++;
#endif
}
else
{
/* Lock interrupt before reading index register */
(void) rex_int_lock();
tbl_idx = vect_idx = HWIO_INM(IRQ_VEC_INDEX_PEND_RD,
IRQ_VEC_INDEX_PEND_RD_RMSK);
}
/* NON_VECTOR */
if (vect_idx == NON_VECTOR)
{
/* No more interrupt to process for the time being.
*/
#ifdef FEATURE_TRAMP_QUEUED_CALLS
/* Since everything else is done, handle queued calls
*/
if (nested_int_cnt == 1)
{
tramp_call_ptr_type *call_ptr;
/* */
while ( (call_ptr = (tramp_call_ptr_type *) q_get( &tramp_call_q )) !=

NULL )
{
/* call_ptrcall_ptr*/
if (call_ptr->call_ptr)
{
#ifdef FEATURE_DEBUG_TRAMP_EXECUTION
TRAMP_DEBUG_IN_ISR_QUEUED_CALL = 1;
/*save call for debugging*/
TRAMP_DEBUG_QUEUED_CALL_FUNC_PTR = (void*)
call_ptr->call_ptr;
#endif
(void) rex_int_free();
(*(call_ptr->call_ptr))( call_ptr->arg.arg_int4,
call_ptr->arg.arg_ptr );
(void) rex_int_lock();
call_ptr->in_use = FALSE;

#ifdef FEATURE_DEBUG_TRAMP_EXECUTION
TRAMP_DEBUG_IN_ISR_QUEUED_CALL = 0;
#endif
}
else
{
ERR_FATAL("Invalid call_ptr in tramp_handle_int_calls", 0, 0, 0);
}
}
}
/*
ISR */
nested_int_cnt--;
#endif /* FEATURE_TRAMP_QUEUED_CALLS */
#ifdef FEATURE_DEBUG_TRAMP_EXECUTION
if (nested_int_cnt==0)
{
/*all isrs finished*/
TRAMP_DEBUG_IN_ISR = 0;
}
#endif

return;
}
/* ISRISR */
(void) rex_int_free();
/* determine which clear register to write to */
if ( vect_idx >= NUM_INT_BITS_IN_REG)
{
clear_reg_address = HWIO_ADDR(IRQ_CLEAR_1);
mask_reg_address = HWIO_ADDR(IRQ_ENABLE_1);
/* adjust bit offset if it's in different register */
vect_idx -= NUM_INT_BITS_IN_REG;
}
else
{
clear_reg_address = HWIO_ADDR(IRQ_CLEAR_0);
mask_reg_address = HWIO_ADDR(IRQ_ENABLE_0);
}
/* */
#ifdef FEATURE_DEBUG_TRAMP_EXECUTION
TRAMP_DEBUG_ISR_NUM = tbl_idx;
#endif
/* Case 1. ISR */
if ( isr_func_tbl[tbl_idx].clr_when == CLR_BEF)
{
outpdw( clear_reg_address, (1 << vect_idx) ); /* clear the int */
#ifdef TIMETEST
TIMETEST_ISR_ID( isr_func_tbl[tbl_idx].id );
#endif
if (isr_func_tbl[tbl_idx].isr_ptr==NULL)
{
ERR_FATAL("NULL ISR ptr",0,0,0);
}
(isr_func_tbl[tbl_idx].isr_ptr) (); /* call the registered ISR */
}
/* case 2. ISR */
else

{
#ifdef TIMETEST
TIMETEST_ISR_ID( isr_func_tbl[tbl_idx].id );
#endif
if (isr_func_tbl[tbl_idx].isr_ptr==NULL)
{
ERR_FATAL("NULL ISR ptr",0,0,0);
}
/* ISR */
(isr_func_tbl[tbl_idx].isr_ptr) ();
/* clear the bit */
outpdw( clear_reg_address, (1 << vect_idx) );
}
} /* end for(;;) */
} /* end tramp_isr */

4.3. IRQ_handler
IRQ

IRQ
TIMETEST
ISR

no_switch
task_swapped
no_switch
no_switch
task_swapped
EXPORT IRQ_Handler
ALIGN
ROUT
IRQ_Handler
sub
lr, lr, #4
; adjust return address (ARM requirement)
; -------------------------------------------------------------------; C
SPSR
; -------------------------------------------------------------------stmfd sp!, {r0-r3, r10, r12, r14}

mrs
r0, SPSR
stmfd sp!, {r0}
; -------------------------------------------------------------------; Increment the nesting level counter.
; -------------------------------------------------------------------ldr
r0, =rex_int_nest_level
ldrh
r1, [r0]
add
r1, r1, #1
strh
r1, [r0]
; -------------------------------------------------------------------; Switch to System Mode and save r14 on stack.
; -------------------------------------------------------------------msr
CPSR_c, #PSR_System:OR:PSR_Irq_Mask
stmfd sp!, {r14}
; -------------------------------------------------------------------;
; -------------------------------------------------------------------ldr
r3, =rex_irq_vector
; tramp_isr()
ldr
r3, [r3]
blatox r3
; -------------------------------------------------------------------; Pop r14 from stack and switch to IRQ Mode.
; -------------------------------------------------------------------ldmfd sp!, {r14}
msr
CPSR_c, #PSR_Irq:OR:PSR_Irq_Mask
; -------------------------------------------------------------------; Decrement the nesting level counter.
; -------------------------------------------------------------------ldr
r0, =rex_int_nest_level
ldrh
r1, [r0]
subs
r1, r1, #1
; Notice it is subs. Set Z flag if r1==0
strh
r1, [r0]
; ---------------------------------------------------------------; Set timetest_isr_level to the new value
; ---------------------------------------------------------------#ifdef TIMETEST_PROF
ldr
r0, =timetest_isr_level
strb
r1, [r0]
#endif
;--------------------------------------------------------------------; Branch if rex_int_nest_level <> 0.
; The Z flag was set (or not set) by the subs instruction above.
;--------------------------------------------------------------------bne
nested_interrupt

;--------------------------------------------------------------------; curr task best task


;--------------------------------------------------------------------ldr
r0, =rex_curr_task
ldr
r0, [r0]
ldr
r1, =rex_best_task
ldr
r1, [r1]
cmp
r0, r1
beq
task_swap_not_required
;--------------------------------------------------------------------; If a TASKLOCK is in effect, then we do not need to even consider
; swapping tasks.
;--------------------------------------------------------------------; test for TASKLOCK in effect
ldr
r2, =rex_sched_allow
ldr
r2, [r2]
cmp
r2, #0
beq
task_swap_not_required
;--------------------------------------------------------------------; Restore the SPSR from stack.
;--------------------------------------------------------------------ldmfd
sp!, {r0}
msr
SPSR_f, r0
msr
SPSR_c, r0
;--------------------------------------------------------------------; Restore the registers from IRQ mode stack.
;--------------------------------------------------------------------ldmfd
sp!, {r0-r3, r10, r12, r14}
;--------------------------------------------------------------------;
;--------------------------------------------------------------------msr
CPSR_c, #PSR_Supervisor:OR:PSR_Irq_Mask
sub
stmfd
sub
mov
ldr

sp, sp, #4
sp!, {r0-r12,lr}
sp, sp, #4
r1, sp
r0, =rex_curr_task

; Space for Return address (pc)


; Other registers
; Space for SPSR

; Save sp of outgoing task into TCB.

ldr
str

r2, [r0]
;
r1, [r2, #REX_TCB_STACK_POINTER_OFFSET]

msr

CPSR_c, #PSR_Irq:OR:PSR_Irq_Mask ; change to IRQ mode


; save Return address into context frame.
r14, [r1, #REX_INTERRUPT_FRAME_PC_OFFSET]
r3, SPSR
; save SPSR into context frame.
r3, [r1, #REX_INTERRUPT_FRAME_SPSR_OFFSET]

str
mrs
str

msr

; Back to Supervisor
CPSR_c, #PSR_Supervisor:OR:PSR_Irq_Mask

;--------------------------------------------------------------------;
;--------------------------------------------------------------------; Reminder ... r0 = address of rex_curr_task variable.
;--------------------------------------------------------------------ldr
r1, =rex_best_task
ldr
r1, [r1]
str
r1, [r0]
; curr_task <- best_task
ldr sp,
ldmfd
msr
msr
mov
add
ldmfd

[r1, #REX_TCB_STACK_POINTER_OFFSET]
; Stack pointer
sp!, {r0}
; Get SPSR
SPSR_f, r0
SPSR_c, r0
; Restore SPSR.
a2, sp
sp, sp, #REX_CF_SIZE - 4 ; adjust sp
a2, {r0-r12, r14, pc}^
; Load and return
; This will also restore CPSR.
;--------------------------------------------------------------------; Control comes here when a task swap is not required.
;--------------------------------------------------------------------task_swap_not_required
;--------------------------------------------------------------------; Restore the SPSR from stack.
;--------------------------------------------------------------------ldmfd
sp!, {r0}
msr
SPSR_f, r0
msr
SPSR_c, r0
;----------------------------------------------------------------; Load saved registers and return
; This will also restore CPSR.
;-----------------------------------------------------------------

ldmfd

sp!, {r0-r3, r10, r12, pc}^

;--------------------------------------------------------------------; Control comes here when a nested interrupt continues.


;--------------------------------------------------------------------nested_interrupt
;--------------------------------------------------------------------; Restore the SPSR from stack.
;--------------------------------------------------------------------ldmfd
sp!, {r0}
msr
SPSR_f, r0
msr
SPSR_c, r0
;----------------------------------------------------------------; Load saved registers and return
; This will also restore CPSR.
;----------------------------------------------------------------ldmfd sp!, {r0-r3, r10, r12, pc}^
IRQ_Handler_end

IRQ_handler clk
driver/clk/clkm2p.cclk_init()
//5ms
MSM_OUT( SLEEP_TIMER_0_CNT, TS_SLEEP_TMR_0_CNT_5MS );
// ISRclk_tick_isr() rex_tick() rex timers
tramp_set_isr( SLEEP_TIMER_INT0, clk_tick_isr );
5msREX

5. SignalsTimers
5.1.
32 TCB

32
32
5.1.1. rex_wait()
IRQ

rex_sigs_type rex_wait( rex_sigs_type p_sigs/* sigs to wait on */)


{
rex_sigs_type sigs = 0;
ASSERT( !rex_is_in_irq_mode( ) );
ASSERT( !TASKS_ARE_LOCKED( ) );
REX_INTLOCK( );
/*------------------------------------------------------** if no signals are set, wait, and reschedule
**-----------------------------------------------------*/
if( (rex_curr_task->sigs & p_sigs) == 0 )
{
/*------------------------------------------------------** Set the sigs the task should wait upon
**-----------------------------------------------------*/
rex_curr_task->wait = p_sigs;
/* Tell Dog to stop monitoring this task.
*/
REX_PAUSE_DOG_MONITOR( rex_curr_task );
/*ready*/
rex_set_best_task( REX_TASK_LIST_FRONT() );
rex_sched();
}
/*------------------------------------------------------** return with the signal mask of the current task
**-----------------------------------------------------*/
sigs = rex_curr_task->sigs;
INTFREE( );
return sigs;
} /* END rex_wait */

5.1.2. rex_set_sigs()

DOG
ready rex_best_task

rex_sigs_type rex_set_sigs(
rex_tcb_type *p_tcb,
rex_sigs_type p_sigs
)
{
rex_sigs_type prev_sigs = 0;

/* tcb for which the sigs will be set */


/* the sigs to set
*/

/* the sigs before setting */

REX_INTLOCK();
prev_sigs = p_tcb->sigs;
p_tcb->sigs = p_tcb->sigs | p_sigs;
/*rex_best_task
*/
if((p_tcb->wait & p_sigs) != 0)
{
p_tcb->wait = 0;
/* DOG */
REX_RESUME_DOG_MONITOR( p_tcb );
if ((p_tcb->pri > rex_best_task->pri) &&
REX_TASK_RUNNABLE(p_tcb))
{
rex_best_task = p_tcb;
rex_sched();
}
}
REX_INTFREE();
return prev_sigs;
} /* END rex_set_sigs */
5.1.3. rex_get_sigs()

rex_sigs_type rex_get_sigs(
rex_tcb_type *p_tcb
)
{
return p_tcb->sigs;
} /* END rex_get_sigs */

/* tcb for which sigs will be returned */

5.1.4. rex_clr_sigs()

rex_sigs_type rex_clr_sigs(
rex_tcb_type *p_tcb,
/* tcb for which the signals will be cleared
*/
rex_sigs_type p_sigs
/* which signals to clear
*/
)
{
rex_sigs_type prev_sigs = 0; /* holds the signals prior to the clear */
REX_INTLOCK();
#ifdef FEATURE_REX_IPC
/* Don't clear IPC Receive Signal if a message is pending */
if ((p_sigs & p_tcb->ipc_info.receive_signal) &&
pq_is_empty(p_tcb->ipc_info.mq_ptr))
{
p_sigs &= ~p_tcb->ipc_info.receive_signal; /* IPCDEFI_RECEIVE_SIG */
}
#endif
p_sigs = ~p_sigs;
prev_sigs = p_tcb->sigs;
p_tcb->sigs = p_tcb->sigs & p_sigs;
REX_INTFREE();
return prev_sigs;
} /* END rex_clr_sigs */

5.2.

REX

5.2.1. rex_init_timer_list()
rex_timer_list
0
rex_null_timer UINT_MAX
void rex_init_timer_list( void )
{
rex_timer_list.cnt
rex_null_timer.tcb_ptr
rex_null_timer.sigs

= 0;
= NULL;
= 0x0;

rex_null_timer.cnt
rex_null_timer.tcb_ptr
rex_null_timer.sigs

= UINT_MAX;
= NULL;
= 0x0;

rex_null_timer.link.next_ptr
rex_null_timer.link.prev_ptr
rex_timer_list.link.next_ptr
rex_timer_list.link.prev_ptr

= NULL;
= &rex_timer_list;
= &rex_null_timer;
= NULL;

return;
} /* END rex_init_timer_list */

5.2.2. rex_insert_timer()
rex_timer_list

void rex_insert_timer(
rex_timer_type
*timer_ptr, /* pointer to a valid timer structure */
rex_timer_cnt_type tmo
/* Timeout for the timer */
)
{
rex_timer_type *next_timer_ptr = rex_timer_list.link.next_ptr;
/*

*/
while( tmo > next_timer_ptr->cnt )
{
REX_ASSERT( next_timer_ptr != NULL );
tmo -= next_timer_ptr->cnt;
next_timer_ptr = next_timer_ptr->link.next_ptr;
}
timer_ptr->cnt = tmo;
timer_ptr->link.prev_ptr = next_timer_ptr->link.prev_ptr;
timer_ptr->link.next_ptr = next_timer_ptr;
next_timer_ptr->link.prev_ptr->link.next_ptr = timer_ptr;
next_timer_ptr->link.prev_ptr = timer_ptr;
if ( next_timer_ptr != &rex_null_timer)
{
next_timer_ptr->cnt -= timer_ptr->cnt;
}
return;
} /* END rex_insert_timer */

5.2.3. rex_def_timer()
TCB
void rex_def_timer(
rex_timer_type *p_timer,
/* pointer to a valid timer structure */
rex_tcb_type
*p_tcb,
/* tcb to associate with the timer
*/
rex_sigs_type
sigs
/* sigs to set upon timer expiration */
)
{
p_timer->link.next_ptr = NULL;
p_timer->link.prev_ptr = NULL;
p_timer->cnt
= 0;
p_timer->tcb_ptr
= p_tcb;
p_timer->sigs
= sigs;
#ifdef FEATURE_REX_TIMER_EX
p_timer->cb_ptr
= NULL;
p_timer->cb_param = 0;
#endif
return;
} /* END rex_def_timer */
API
rex_def_timer_ex()

5.2.4. rex_set_timer()

rex_timer_list
0 rex_timer_list
rex_timer_list
0
rex_timer_cnt_type rex_set_timer(
rex_timer_type
*p_timer, /* pointer to timer to set */
rex_timer_cnt_type cnt
/* value to set the timer */
)
{
rex_timer_cnt_type prev_value; /* the value before the set */
INTLOCK();
/*------------------------------------------------------** Remove the timer from the timer list and insert it back
** if necessary.
**-----------------------------------------------------*/
prev_value = rex_clr_timer( p_timer );
if (cnt > 0)
{
rex_insert_timer( p_timer, cnt );
(void) rex_clr_sigs( p_timer->tcb_ptr, p_timer->sigs );
}
else
{
/*------------------------------------------------------** If the user passed in 0, set the signals or call the
** callback function.
**-----------------------------------------------------*/
do {
#ifdef FEATURE_REX_TIMER_EX
/* APC
*/
if ( p_timer->cb_ptr != NULL )
{
if ( !rex_queue_apc(
p_timer->cb_ptr,
p_timer->tcb_ptr,
p_timer->cb_param
))
{

/* APC
*/
rex_insert_timer( p_timer, 0 );
}
break;
}
#endif /* FEATURE_REX_TIMER_EX */
if ( p_timer->sigs != 0 )
{
(void)rex_set_sigs( p_timer->tcb_ptr , p_timer->sigs );
}
} while (0);
}
INTFREE();
return prev_value;
} /* END rex_set_timer */
5.2.5. rex_timed_wait()

rex_sigs_type rex_timed_wait(
rex_sigs_type
sigs,
/* sigs to wait on
*/
rex_timer_type
*p_timer,
/* timer to set and wait on */
rex_timer_cnt_type cnt
/* timer to wait
*/
)
{
REX_ASSERT( !rex_is_in_irq_mode( ) );
/*------------------------------------------------------** A call to rex_set_timer and rex_wait will perform a
** timed wait
**-----------------------------------------------------*/
(void) rex_set_timer(p_timer, cnt);
return rex_wait(sigs);
} /* END rex_timed_wait */
5.2.6. rex_clr_timer()

0
rex_timer_cnt_type rex_clr_timer(
rex_timer_type *timer_ptr
/* timer to clear */
)
{
rex_timer_cnt_type prev_value = 0;
/* previous count */
rex_timer_type
*next_timer_ptr = &rex_timer_list;
INTLOCK( );
REX_ASSERT(timer_ptr!=NULL);
if( timer_ptr->link.next_ptr != NULL )
{
while ( next_timer_ptr != timer_ptr )
{
next_timer_ptr = next_timer_ptr->link.next_ptr;
REX_ASSERT( next_timer_ptr != NULL );
prev_value += next_timer_ptr->cnt;
}
timer_ptr->link.prev_ptr->link.next_ptr = timer_ptr->link.next_ptr;
timer_ptr->link.next_ptr->link.prev_ptr = timer_ptr->link.prev_ptr;
if ( timer_ptr->link.next_ptr != &rex_null_timer)
{
timer_ptr->link.next_ptr->cnt += timer_ptr->cnt;
}
timer_ptr->link.next_ptr = NULL;
timer_ptr->cnt = 0;
}
INTFREE( );
return prev_value;
}
5.2.7. rex_get_timer()

0
rex_timer_cnt_type rex_get_timer(
rex_timer_type *timer_ptr
/* pointer to the timer to get */
)

{
rex_timer_cnt_type prev_value = 0;
/* previous count */
rex_timer_type
*next_timer_ptr = &rex_timer_list;
INTLOCK( );
REX_ASSERT(timer_ptr!=NULL);
if( timer_ptr->link.next_ptr != NULL )
{
while ( next_timer_ptr != timer_ptr )
{
next_timer_ptr = next_timer_ptr->link.next_ptr;
REX_ASSERT( next_timer_ptr != NULL );
prev_value += next_timer_ptr->cnt;
}
}
INTFREE( );
return prev_value;
}
5.2.8. rex_pause_timer()

void rex_pause_timer(rex_timer_type *timer_ptr)


{
timer_ptr->cnt = rex_clr_timer( timer_ptr );
return;
} /* END rex_pause_timer */
5.2.9. rex_resume_timer()

void rex_resume_timer(rex_timer_type *timer_ptr)


{
rex_set_timer( timer_ptr, timer_ptr->cnt );
return;
} /* END rex_resume_timer */

5.2.10. rex_delete_task_timers()

void rex_delete_task_timers(rex_tcb_type *tcb_ptr)


{
rex_timer_type *timer_ptr;
rex_timer_type *next_timer_ptr;
INTLOCK( );
for( timer_ptr = rex_timer_list.link.next_ptr;
timer_ptr != &rex_null_timer;
timer_ptr = next_timer_ptr )
{
next_timer_ptr = timer_ptr->link.next_ptr;
if ( timer_ptr->tcb_ptr == tcb_ptr )
{
rex_clr_timer( timer_ptr );
}
}
INTFREE( );
return;
} /* END rex_delete_task_timers */
5.2.11. rex_decrement_timers()

rex_set_sigs()

INLINE static void rex_decrement_timers(


rex_timer_cnt_type p_ticks /* number of rex ticks to decrement by */
)
{
rex_timer_type *ptr;
/* points to current timer */
rex_timer_type *next_ptr;
/* points to next timer
*/
#ifdef FEATURE_REX_TIMER_EX
unsigned long apc_queued;
#endif
/*
*/
for(ptr = rex_timer_list.link.next_ptr;
ptr != &rex_null_timer;

ptr = next_ptr
)
{
REX_ASSERT(ptr!=NULL);
next_ptr = ptr->link.next_ptr;
if( ptr->cnt <= p_ticks )
{
rex_clr_timer( ptr );
#ifdef FEATURE_REX_TIMER_EX
/* APC
*/
if ( ptr->cb_ptr != NULL )
{
if ( rex_is_in_irq_mode( ) )
{
apc_queued = rex_queue_apc(
ptr->cb_ptr,
ptr->tcb_ptr,
ptr->cb_param
);
}
else
{
apc_queued = rex_queue_apc_internal(
(unsigned long) ptr->cb_ptr,
(unsigned long) ptr->tcb_ptr,
ptr->cb_param
);
}
if ( !apc_queued )
{
/* APC
*/
rex_insert_timer( ptr, 0 );
}
continue;
}
#endif /* FEATURE_REX_TIMER_EX */
/* ready

Noteptr->sigs 0
*/

if ( ptr->sigs != 0 )
{
(void) rex_set_sigs(ptr->tcb_ptr, ptr->sigs);
}
}
else
{
/**/
ptr->cnt -= p_ticks;
break;
}
}
return;
} /* END rex_decrement_timers */
5.2.12. rex_tick()
REX
clr_tick_isr()5ms

void rex_tick(
rex_timer_cnt_type p_ticks
/* number of rex ticks to decrement
everything by */
)
{
{
rex_decrement_timers( p_ticks );
#if defined( FEATURE_REX_PROFILE )
&& !defined( FEATURE_HIGH_RES_PROFILE )
rex_self( )->time_samples += p_ticks;
rex_total_time_samples += p_ticks;
#endif
}
return;
} /* END rex_tick */

5.3. Others
5.3.1. rex_sleep()

void rex_sleep(unsigned long ms)


{
boolean
sleeping = TRUE;
boolean
sig_set = FALSE;
unsigned long tmo
= ms;
rex_timer_type sleep_timer;
rex_def_timer(
&sleep_timer,
rex_self(),
0x80000000
);
while( sleeping )
{
rex_timed_wait( 0x80000000, &sleep_timer, tmo );
REX_INTLOCK();
if( (tmo = rex_get_timer( &sleep_timer )) == 0 )
{
sleeping = FALSE;
}
else
{
sig_set = TRUE;
}
REX_INTFREE();
}
if( sig_set )
{
rex_set_sigs( rex_self(), 0x80000000 );
}
return;
} /* END rex_sleep */

6. Critical Section

6.1. rex_init_crit_sect()

void rex_init_crit_sect(
rex_crit_sect_type *crit_sect
)
{
crit_sect->lock_count = 0;
crit_sect->tcb_link = REX_CRIT_SECT_FLAG;
crit_sect->orig_pri = -1;
crit_sect->owner
= REX_CRIT_SECT_FLAG;
return;
} /* END rex_init_crit_sect */
6.2. rex_enter_crit_sect()

void rex_enter_crit_sect(rex_crit_sect_type *crit_sect)


{
ASSERT( !TASKS_ARE_LOCKED( ) );
ASSERT( !rex_is_in_irq_mode( ) );
REX_INTLOCK();
/* mark the TCB with the critical section that we want */
ASSERT( rex_curr_task->cs_sp <
rex_curr_task->cs_stack + REX_CRIT_SECT_MAX - 1 );
/* */
if ( crit_sect->lock_count > 0 &&
rex_curr_task == crit_sect->owner)
{
ASSERT( crit_sect->lock_count < 0xff );
crit_sect->lock_count++;
}
else
{
/* */
++rex_curr_task->cs_sp;
*rex_curr_task->cs_sp = crit_sect;

/* */
if ( crit_sect->lock_count == 0 )
{
crit_sect->lock_count = 1;
crit_sect->owner
= rex_curr_task;
crit_sect->tcb_link

= REX_CRIT_SECT_FLAG;

/* */
crit_sect->orig_pri = rex_curr_task->pri;
}
else
{
/* */
/* previous first element's prev_ptr needs to point to us */
if (crit_sect->tcb_link != REX_CRIT_SECT_FLAG)
{
crit_sect->tcb_link->cs_link.prev_ptr = rex_curr_task;
}
/* set our next ptr to what the crit sect var previously pointed to */
rex_curr_task->cs_link.next_ptr = crit_sect->tcb_link;
/* we are the new head, so make crit sect var point to us, and set
our prev_ptr to the flag value. */
crit_sect->tcb_link = rex_curr_task;
rex_curr_task->cs_link.prev_ptr = REX_CRIT_SECT_FLAG;
/*
*/
if ( rex_curr_task->pri > crit_sect->owner->pri )
{
rex_task_pri( crit_sect->owner, rex_curr_task->pri );
}
/* Tell Dog to stop monitoring this task.
*/
REX_PAUSE_DOG_MONITOR( rex_curr_task );
/* Schedule the best runnable task.
*/
rex_set_best_task( REX_TASK_LIST_FRONT() );
rex_sched();

}
}
REX_INTFREE();
return;
} /* END rex_enter_crit_sect */
6.3. rex_leave_crit_sect_internals()

A rex_kill_task()
B B rex_kill_task()

rex_kill_task() rex_sched()

API rex_leave_crit_sect()
static void rex_leave_crit_sect_internals(
rex_crit_sect_type *crit_sect,
rex_tcb_type
*p_tcb,
boolean
resched_allowed
)
{
rex_tcb_type *index_ptr = NULL;
rex_tcb_type *save_ptr = NULL;
rex_priority_type best_pri;
/* No INTLOCK - calling function is responsible */
/* */
if ( (p_tcb->cs_sp < p_tcb->cs_stack) ||
(crit_sect->owner != p_tcb)
||
(p_tcb->cs_link.next_ptr != NULL) )
{
/* calling task is not holding this lock */
ASSERT( 0 );
return;
}
/* */
if ( crit_sect->lock_count > 1 )
{
--crit_sect->lock_count;
return;
}

if (*p_tcb->cs_sp != crit_sect)
{
/* Caller is trying to release critical sections in something other
** than LIFO order. We do not support this.
*/
ASSERT( 0 );
return;
}
/* mark that we are no longer holding/waiting-in this crit section */
--p_tcb->cs_sp;
/* */
if ( crit_sect->orig_pri != p_tcb->pri )
{
rex_task_pri( p_tcb, crit_sect->orig_pri );
}
/* If there are no waiting tasks, we can simply unlock and proceed */
if ( crit_sect->tcb_link == REX_CRIT_SECT_FLAG )
{
crit_sect->lock_count = 0;
crit_sect->owner
= REX_CRIT_SECT_FLAG;
crit_sect->orig_pri = -1;
}
else
{
/* */
best_pri = 0;
for( index_ptr = crit_sect->tcb_link;
index_ptr != REX_CRIT_SECT_FLAG;
index_ptr = index_ptr->cs_link.next_ptr
)
{
if ( index_ptr->pri > best_pri )
{
best_pri = index_ptr->pri;
save_ptr = index_ptr;
}
}
/* */

/* If found task is the first on the list, fix up list head */


if ( save_ptr->cs_link.prev_ptr == REX_CRIT_SECT_FLAG )
{
crit_sect->tcb_link = save_ptr->cs_link.next_ptr;
}
else /* fix up previous element */
{
save_ptr->cs_link.prev_ptr->cs_link.next_ptr =
save_ptr->cs_link.next_ptr;
}
/* look to next element*/
/* if found task is NOT the last item on the list */
if ( save_ptr->cs_link.next_ptr != REX_CRIT_SECT_FLAG )
{
save_ptr->cs_link.next_ptr->cs_link.prev_ptr =
save_ptr->cs_link.prev_ptr;
}
/* cs_link
*/
save_ptr->cs_link.next_ptr = save_ptr->cs_link.prev_ptr = NULL;
/* mark the crit section appropriately */
crit_sect->owner
= save_ptr;
crit_sect->orig_pri = save_ptr->pri;
/* Tell Dog to resume monitoring the found task.
*/
REX_RESUME_DOG_MONITOR( save_ptr );
/* */
/* Always compare with REX_BEST_TASK, not REX_CURR_TASK! */
if ( ( resched_allowed
) &&
( save_ptr->pri > rex_best_task->pri ) &&
( !save_ptr->suspended
) )
{
rex_best_task = save_ptr;
rex_sched();
}
}

/* No INTFREE - calling function is responsible */


return;
} /* END rex_leave_crit_sect_internals */
API
rex_leave_crit_sect()

7. APC&DPC
APC (Asynchronous Procedure Calls)
APC

DPC (Deferred Procedure Calls)REX


DPC DPC
APC DPC

7.1. DPC
7.1.1. rex_dpc_task()
DPC
REX_DPC_SIG DPC
void rex_dpc_task(unsigned long param /*lint -esym(715,param)*/)
{
for(;;)
{
/* Block waiting for a DPC to be ready
*/
(void) rex_wait( REX_DPC_SIG );
rex_clr_sigs( rex_self( ), REX_DPC_SIG );
/* Execute DPC's until the ring buffer is empty
*/
REX_INTLOCK( );
while( rex_execute_next_dpc( ) == TRUE );
INTFREE( );
}
} /* END rex_dpc_task */

7.1.2. rex_execute_next_dpc()
DPC
REX
static boolean rex_execute_next_dpc( void )
{
rex_dpc_func_type *dpc_ptr;
unsigned long
dpc_param1;
unsigned long
dpc_param2;
unsigned long
dpc_param3;
if( rex_dpc_rd_index != rex_dpc_wr_index )
{
dpc_ptr
= rex_dpc_ring[ rex_dpc_rd_index ].dpc_ptr;
dpc_param1 = rex_dpc_ring[ rex_dpc_rd_index ].dpc_param1;
dpc_param2 = rex_dpc_ring[ rex_dpc_rd_index ].dpc_param2;
dpc_param3 = rex_dpc_ring[ rex_dpc_rd_index ].dpc_param3;
rex_dpc_rd_index = (rex_dpc_rd_index+1) & REX_DPC_RING_MASK;
if( dpc_ptr != NULL )
{
dpc_ptr( dpc_param1, dpc_param2, dpc_param3 );
}
return TRUE;
}
return FALSE;
} /* END rex_execute_next_dpc */
7.1.3. rex_queue_dpc()
DPC
boolean rex_queue_dpc(
rex_dpc_func_type *dpc_ptr,
/* Pointer to the function to call
*/
unsigned long
param1,
/* Parameter to pass to the dpc
*/
unsigned long
param2,
/* Parameter to pass to the dpc
*/
unsigned long
param3
/* Parameter to pass to the dpc
*/

)
{
boolean ret_status = 0;
if ( dpc_ptr == NULL )
{
return 0;
}
REX_INTLOCK( );
/* Make sure there is space in the ring buffer, add the DPC to the
** ring and signal the DPC task.
*/
if( ((rex_dpc_wr_index+1) & REX_DPC_RING_MASK) !=
rex_dpc_rd_index )
{
rex_dpc_ring[ rex_dpc_wr_index ].dpc_ptr
= dpc_ptr;
rex_dpc_ring[ rex_dpc_wr_index ].dpc_param1 = param1;
rex_dpc_ring[ rex_dpc_wr_index ].dpc_param2 = param2;
rex_dpc_ring[ rex_dpc_wr_index ].dpc_param3 = param3;
rex_dpc_wr_index = (rex_dpc_wr_index+1) &
REX_DPC_RING_MASK;
rex_set_sigs( &rex_dpc_tcb, REX_DPC_SIG );
ret_status = 1;
}
else
{
ret_status = 0;
}
INTFREE( );
return ret_status;
} /* END rex_queue_dpc */

7.2. APC
7.2.1. rex_queue_apc()
APC
APC ready tcb_ptr->num_apcs = 0
APC
APC FIFO

APC

ABCD pri of A < pri of B < pri of C < pri of DAC ready
C
C B APC
B ready C B B C B
APC B B
B A
C D APC
D ready APC D
D C
boolean rex_queue_apc(
rex_apc_func_type apc,
rex_tcb_type
*tcb_ptr,
unsigned long
param
)
{
if ( ( apc == NULL ) || ( tcb_ptr == NULL ) )
{
return 0;
}
/* DPCrex_queue_apc_internal
apctcb */
return rex_queue_dpc(
rex_queue_apc_internal,
(unsigned long) apc,
(unsigned long) tcb_ptr,
param
);
} /* END rex_queue_apc */
7.2.2. rex_queue_apc_internal()
APC
REX ISR
rex_queue_apc() DPC
boolean rex_queue_apc_internal(
unsigned long apc_handle,
unsigned long tcb_handle,
unsigned long param

)
{
boolean
ret_status = FALSE;
rex_apc_func_type apc
= (rex_apc_func_type) apc_handle;
rex_tcb_type
*tcb_ptr
= (rex_tcb_type *) tcb_handle;
ASSERT( apc
!= NULL );
ASSERT( tcb_ptr != NULL );
ASSERT( !rex_is_in_irq_mode( ) );
/*
APC*/
if ( tcb_ptr == rex_curr_task )
{
/* APC */
apc( param );
ret_status = TRUE;
}
else if( rex_apc_stack_avail( tcb_ptr ) )
{
REX_INTLOCK( );
rex_apc_prolog( apc, param, tcb_ptr );
tcb_ptr->num_apcs++;
/* Schedule the task for which the APC is being queued, if
** necessary.
*/
if ( ( tcb_ptr->pri > rex_best_task->pri ) &&
REX_TASK_RUNNABLE( tcb_ptr ) )
{
rex_best_task = tcb_ptr;
rex_sched( );
}
ret_status = TRUE;
INTFREE( );
}
return ret_status;
} /* END rex_queue_apc_internal*/
7.2.3. rex_apc_prolog()
APC

r0APC
r1APC
LR PC rex_apc_epilog()
PC rex_call_apc() rex_apc_epilog() APC
APC CPU
PC rex_call_apc()r0r1
REX
ISR
static void rex_apc_prolog(
rex_apc_func_type apc,
unsigned long
param,
rex_tcb_type
*tcb_ptr
)
{
char
*stack_ptr;
rex_context_frame_type *context_frame_ptr;
ASSERT(
ASSERT(
ASSERT(
ASSERT(

apc != NULL );
tcb_ptr != NULL );
tcb_ptr != rex_curr_task );
!rex_is_in_irq_mode( ) );

/* TCB */
stack_ptr = (char *) tcb_ptr->sp - sizeof(rex_context_frame_type);
ASSERT( (unsigned long) stack_ptr <
(unsigned long) tcb_ptr->stack_limit +
tcb_ptr->stack_size );
memset( (void *) stack_ptr, 0x00, sizeof(rex_context_frame_type) );
context_frame_ptr = (rex_context_frame_type *) stack_ptr;
context_frame_ptr->spsr.val =
(((rex_context_frame_type *) tcb_ptr->sp)->spsr.val &
PSR_Mode_Mask) | PSR_Thumb ;
/* If spsr_val indicates user mode, set it to supervisor mode.
*/
if ( (context_frame_ptr->spsr.val & PSR_Mode_Mask) == PSR_User )
{
context_frame_ptr->spsr.val &= ~PSR_Mode_Mask;
context_frame_ptr->spsr.val |= PSR_Supervisor;
}

context_frame_ptr->r[0].arg = (unsigned long) apc;


context_frame_ptr->r[1].arg = param;
context_frame_ptr->r[10].val = (unsigned long) tcb_ptr->stack_limit;
context_frame_ptr->lr.arg = (unsigned long) rex_apc_epilog;
context_frame_ptr->pc.arg = (unsigned long) rex_call_apc;
tcb_ptr->sp = stack_ptr;
return;
} /* rex_apc_prolog */
7.2.4. rex_call_apc()
APC
APC APC

APC
rex_apc_prolog()
rex_apc_prolog() PC
rex_call_apc() CPU
rex_apc_prolog() LR rex_apc_epilog()
rex_apc_epilog()
void rex_call_apc(
rex_apc_func_type apc,
unsigned long
param
)
{
ASSERT( apc != NULL );
/* APC */
apc( param );
/*best tasknum_apcs0.
**
** NOTErex_apc_epilog()
rex_apc_epilog()CPU
rex_apc_epilog()CPU
*/
rex_int_lock( );
rex_curr_task->num_apcs--;
ASSERT( rex_curr_task->num_apcs >= 0 );
rex_set_best_task( REX_TASK_LIST_FRONT() );

return;
} /* END rex_call_apc */
7.2.5. rex_apc_epilog
rex_call_apc() APC
1. best task
CPU

2.

TCB
APC CPU
best taskbest task

LEAF_NODE rex_apc_epilog
ldr
ldr
ldr
ldr
cmp
beq
str
str
ldr

a1, =rex_curr_task
a2, [a1]
; Load curr task into a2.
a3, =rex_best_task
a3, [a3]
; Load best task into a3.
a3, a2
; Check if curr_task = best_task.
rex_apc_epilog_after_swap
sp, [a2, #REX_TCB_STACK_POINTER_OFFSET]
; Update stack pointer in TCB.
a3, [a1]
; Set curr task to best task.
sp, [a3, #REX_TCB_STACK_POINTER_OFFSET]
; Load the new stack pointer.

rex_apc_epilog_after_swap
ldmfd sp!, {a2}
msr
msr
mov
add
ldmfd

SPSR_f, a2
SPSR_c, a2
a2, sp
sp, sp, #REX_CF_SIZE - 4
a2, {r0-r12, r14, pc}^

; Restore SPSR (in a2).


; Load SPSR.
; Load SPSR.
; Load sp in a2.
; Adjust sp.
; Load and return
; sp already adjusted.

LEAF_NODE_END

8. REX
main()services/task/mobile.c

8.1. main()
int main(void)
{
setlocale(LC_ALL, "C");
rex_init( (void *)irq_stack, /* Interrupt stack
*/
/* Interrupt stack size
*/
IRQ_Stack_Size,
&tmc_tcb,
/* Task TCB of the main control task
*/
(void *)tmc_stack, /* Stack for the main control task
*/
TMC_STACK_SIZ, /* Main control task stack size
*/
TMC_PRI,
/* Main control task priority
*/
tmc_task,
/* Entry point for the main control task */
0L );
/* Parameter to pass the main control task */
/* Never fall through main.*/
return 0;
}
8.2. rex_init()
REX
kernel task(idle task) p_task
void rex_init(
void *
p_istack,
/* interrupt stack
*/
rex_stack_size_type p_istksiz,
/* interrupt stack size */
rex_tcb_type
*p_tcb,
/* task control block */
void *
p_stack,
/* stack
*/
rex_stack_size_type p_stksiz,
/* stack size
*/
rex_priority_type p_pri,
/* task priority
*/
void
(*p_task)( dword ), /* task function
*/
dword
p_param
/* task parameter
*/
)
{
/*------------------------------------------------------** Change to Supervisor mode
**-----------------------------------------------------*/
(void)rex_set_cpsr( PSR_Supervisor | PSR_Irq_Mask | PSR_Fiq_Mask );

#if defined ( FEATURE_REX_DYNA_MEM )


rex_mem_init( );
#endif

/*------------------------------------------------------** Setup the interrupt stack.


**-----------------------------------------------------*/
REX_INTLOCK();
/* Point to the top of the stack */
rex_int_stack = (rex_stack_word_type *) p_istack;
/* 0 */
rex_int_nest_level = 0;
/**/
rex_init_timer_list( );
/**/
rex_task_list.link.next_ptr = &rex_kernel_tcb;
rex_task_list.link.prev_ptr = NULL;
rex_kernel_tcb.link.next_ptr = NULL;
rex_kernel_tcb.link.prev_ptr = &rex_task_list;
/* rex_curr_task rex_best_task */
rex_curr_task = &rex_kernel_tcb;
rex_best_task = &rex_kernel_tcb;
#ifdef TIMETEST
rex_kernel_tcb.leds = TIMETEST_REX_TASK_ID;
#endif
/* kernel taskidle task */
rex_def_task_ext(
&rex_kernel_tcb,
/* tcb
*/
(unsigned char *) &rex_kernel_stack[0],
/* stack
*/
REX_KERNEL_STACK_SIZE,
/* stack size */
0,
/* priority */
rex_idle_task,
/* function */
0,
/* arguments */
"REX Idle Task",
/* task name */
FALSE
/* suspended */
);
rex_kernel_tcb.pri = 0xFFFFFFFF;
#ifdef FEATURE_REX_DPC

#ifdef TIMETEST
rex_dpc_tcb.leds = TIMETEST_DPC_TASK_ID;
#endif
/* DPC task */
rex_def_task_ext(
&rex_dpc_tcb,
(unsigned char *) rex_dpc_stack,
REX_DPC_STACK_SIZE,
REX_DPC_THREAD_PRI,
rex_dpc_task,
0,
"REX DPC Task",
FALSE
);
#endif
rex_kernel_tcb.pri = 0;
/* rex_curr_task rex_best_task */
rex_curr_task = p_tcb;
rex_best_task = p_tcb;
/*Main Task*/
rex_def_task_ext(
p_tcb,
/* tcb
*/
(unsigned char *)p_stack,
/* stack
*/
p_stksiz*sizeof(rex_stack_word_type),
/* stack size */
p_pri,
/* priority */
p_task,
/* function */
p_param,
/* arguments */
"Main Task",
/* name
*/
FALSE
);
INTFREE( );
/* rex_best_task */
rex_set_best_task( REX_TASK_LIST_FRONT() );
rex_curr_task = rex_best_task;
rex_start_task( rex_best_task );
} /* END rex_init */

8.3. rex_exit()
REX REX assertion fails
REX
void rex_exit(int condition)
{
static int err_cond;
err_cond = condition;
return;
} /* END rex_exit */
8.4. rex_get_version_number()
REX
unsigned long rex_get_version_number(void)
{
return REX_VERSION_NUMBER;
} /* END rex_get_version_number */

9.
REX utils memheap
9.1. rex_mem_init()
REX
void rex_mem_init( void )
{
mem_init_heap(
&rex_heap,
rex_mem_buffer,
sizeof( rex_mem_buffer ),
NULL
);
return;
} /* END rex_mem_init */
9.2. rex_malloc()
REX

void *rex_malloc(unsigned long num_bytes)


{
ASSERT( !rex_is_in_irq_mode( ) );
return mem_malloc( &rex_heap, num_bytes );
} /* END rex_malloc */
9.3. rex_calloc()

void *rex_calloc(
unsigned long num_blocks,
unsigned long block_size
)
{
ASSERT( !rex_is_in_irq_mode( ) );
return mem_calloc( &rex_heap, num_blocks, block_size );
} /* END rex_calloc */
9.4. rex_realloc()

void *rex_realloc(
void
*ptr,
/* Block previously allocated via REX allocation call */
unsigned long size
/* New size (in bytes) */
)
{
ASSERT( !rex_is_in_irq_mode( ) );
return mem_realloc( &rex_heap, ptr, size );
} /* END rex_calloc */
9.5. rex_free()
rex_malloc()
void rex_free(void *mem_ptr)
{
ASSERT( !rex_is_in_irq_mode( ) );
mem_free( &rex_heap, mem_ptr );

return;
} /* END rex_free */

You might also like