📄 cmx_init.c
字号:
/*********************************************************
Copyright (c) CMX Company. 1999. All rights reserved
*********************************************************/
/* version 5.30, adds the following:
1. counting semaphores
2. priority inversion on resources
3. highest priority task waiting on resource, is the one
that will get resource when it is released.
4. New pipe routine
*/
#define CMX_INIT_MODULE
#define CMXMODULE
#include <cxfuncs.h> /* get cmx include header file */
#include "cxconfig.h" /* get user configuration file */
#include <iom103.h> /* The chip to be used */
#if CMXTRACKER_ENABLE > 0
#include <cmxtrack.h> /* get cmx include header file */
#endif
#if C_PIPE_SIZE < 1 || C_PIPE_SIZE > 255
#error PIPE_SIZE MUST BE between 1 and 255
#endif
#if C_MAX_MESSAGES > 0
#define CMX_MAX_MESSAGES C_MAX_MESSAGES + 2
#endif
#if CMXBUG_ENABLE > 0 || CMXTRACKER_ENABLE > 0
#define CC_TASK_STK_SIZE (C_TASK_STK_SIZE + 128)
#define CC_TASK_SYSTEM_STK_SIZE (C_TASK_SYSTEM_STK_SIZE + 48)
#else
#define CC_TASK_STK_SIZE C_TASK_STK_SIZE
#define CC_TASK_SYSTEM_STK_SIZE C_TASK_SYSTEM_STK_SIZE
#endif
#if CMXBUG_ENABLE > 0 || CMXTRACKER_ENABLE > 0
#define CC_MAX_TASKS (C_MAX_TASKS + 1)
#else
#define CC_MAX_TASKS C_MAX_TASKS
#endif
/***********************************************************
WARNING: these are assumed to be initailized by the "C" compiler
start up code. Also all non-initialized CMX variables are assumed
to be zeroed out by the "C" compiler startup code. This is normally
done. If NOT, then the user must set the CMX_RAM_INIT define to 1.
See cxconfig.h (or equivalent file).
***********************************************************/
byte MAX_TASKS = CC_MAX_TASKS;
byte MAX_RESOURCES = C_MAX_RESOURCES;
byte MAX_CYCLIC_TIMERS = C_MAX_CYCLIC_TIMERS;
byte MAX_MAILBOXES = C_MAX_MAILBOXES;
byte MAX_QUEUES = C_MAX_QUEUES;
byte RTC_SCALE = C_RTC_SCALE;
byte MAX_SEMAPHORES = C_MAX_SEMAPHORES;
byte TSLICE_SCALE = C_TSLICE_SCALE;
/*******************************************************
The following sets up the necessary memory needed by CMX
*******************************************************/
/******************************************************
The cxvendor.h header file will actually add additional
CMX variables to ONLY this file. See that header file.
********************************************************/
struct _tcb cmx_tcb[CC_MAX_TASKS+1];
#if C_MAX_CYCLIC_TIMERS > 0
CYCLIC_TIMERS tcproc[C_MAX_CYCLIC_TIMERS];
#else
byte tcproc[1];
#endif
#if C_MAX_RESOURCES > 0
RESHDR res_que[C_MAX_RESOURCES];
#else
byte res_que[1];
#endif
#if C_MAX_MAILBOXES > 0
MAILBOX mail_box[C_MAX_MAILBOXES];
#else
byte mail_box[1];
#endif
#if C_MAX_MESSAGES > 0
MSG message_box[CMX_MAX_MESSAGES];
#else
byte message_box[1];
#endif
#if C_MAX_QUEUES > 0
QUEHDR queue[C_MAX_QUEUES];
#else
byte queue[1];
#endif
#if C_MAX_SEMAPHORES > 0
SEM sem_array[C_MAX_SEMAPHORES];
#else
byte sem_array[1];
#endif
struct {
word16 stack_space[CC_TASK_STK_SIZE / 2];
word16 dummy;
} stack_storage;
word16 *stack_blk;
struct {
word16 system_stack_space[CC_TASK_SYSTEM_STK_SIZE / 2];
word16 dummy;
} system_stack_storage;
word16 *system_stack_blk;
struct {
word16 interrupt_bytes[C_INTERRUPT_SIZE / 2];
word16 dummy;
} int_storage;
word16 *interrupt_stack;
struct {
word16 interrupt_bytes[C_SYSTEM_INTERRUPT_SIZE / 2];
word16 dummy;
} system_int_storage;
word16 *system_interrupt_stack;
word16 *stack_holder;
CYCLIC_LNK cyclic_buf;
CYCLIC_LNK *cyclic_lnk;
TSK_TIMER_LNK *tsk_timer_lnk;
TSK_TIMER_LNK tsk_timer_buf;
MSG *message_ptr;
word16 message_free;
/* Note the following are held in NEAR data space */
byte tslice_count;
byte SLICE_ON;
tcbpointer activetcb;
byte active_priority;
/* end of NEAR data space variables */
tcbpointer timertask;
byte rtc_count;
PIPE_STRUC *out_ptr;
PIPE_STRUC pipe[C_PIPE_SIZE];
#if CMX_RAM_INIT > 0
static void clear_ram(void *,word16);
static void init_cmx_variables(void);
#endif
#if CMXTRACKER_ENABLE > 0
byte CMXTRACKER_ACTIVE;
byte CMXTRACKER_ON;
tcbpointer previoustcb;
extern byte cmxtracker_slot;
extern void cmxtracker(void);
extern void cmxtracker_mode(byte,word16);
extern word16 cmxtracker_ctr;
extern byte *cmxtracker_in_ptr;
extern word16 num_records;
void init_cmxtracker(void);
byte cmxtracker_array[CMXTRACKER_SIZE];
#define LOG_DISPLAY_LEN 18
word16 rec_cnt[((sizeof (cmxtracker_array) / 4) / LOG_DISPLAY_LEN) + 2];
#endif
#if CMXBUG_ENABLE > 0
extern byte cmxbug_slot;
extern void cmxbug(void);
byte CMXBUG_ACTIVE;
#endif
#if CMXBUG_ENABLE > 0 || CMXTRACKER_ENABLE > 0
long stat_array[CC_MAX_TASKS+1];
char *task_name[CC_MAX_TASKS + 1];
byte BUG_WAIT_TICKS;
void setup_bug(void);
byte K_Bug_Getchr(byte *ptr);
void K_Bug_Putchr(char);
#else
char *task_name[1];
#endif
word32 cmx_tick_count; /* total number of CMX system ticks accumulated */
void K_OS_Init(void)
{
MSG *link; /* scratch pointer */
locked_out = 1; /* set lock so it will never goto K_I_Scheduler */
cmx_tick_count = 0; /* reset CMX long counter */
#if CMX_RAM_INIT > 0 /* Should we initialize CMX variables */
init_cmx_variables();
#endif
#if C_MAX_MESSAGES > 0
link = message_box; /* address of 1st block */
message_free = CMX_MAX_MESSAGES; /* use pipe_max to hold count */
while (message_free--)
{
message_ptr = link; /* point head at 1st block */
link++; /* compute addr of next block */
message_ptr->env_link = link; /* create link to it */
}
message_ptr->env_link = message_box; /* last link in chain is null */
message_ptr = message_box; /* point head at 1st block */
message_free = CMX_MAX_MESSAGES-2;
#endif
in_ctr = out_ctr = cmx_flag1 = 0;
pipe_slots_avail = C_PIPE_SIZE;
cyclic_lnk = &cyclic_buf; /* set up cyclic timers time link. */
cyclic_lnk->ftlink = cyclic_lnk->btlink = (struct _tcproc *)cyclic_lnk;
tsk_timer_lnk = &tsk_timer_buf; /* set up task timer link. */
tsk_timer_lnk->ftlink = tsk_timer_lnk->btlink = (tcbpointer)tsk_timer_lnk;
/* now set up stack block to release memory to task's stacks as
they are created. Also interrupt stack if used. */
stack_blk = &stack_storage.dummy;
interrupt_stack = &int_storage.dummy;
system_stack_blk = &system_stack_storage.dummy;
system_interrupt_stack = &system_int_storage.dummy;
activetcb = timertask = cmx_tcb; /* dummy tcb */
timertask->nxttcb = cmx_tcb; /* set up link. */
#if CMXBUG_ENABLE > 0 || CMXTRACKER_ENABLE > 0
setup_bug();
BUG_WAIT_TICKS = 10; /* Number of system ticks to wait, before checking
to see if the + (plus key) has been received
by UART. */
#endif
rtc_count = C_RTC_SCALE; /* number of timer ticks, before running
CMX task timer if needed. */
} /* K_OS_Init */
#if CMX_RAM_INIT > 0
static void init_cmx_variables(void)
{
MAX_TASKS = CC_MAX_TASKS;
MAX_RESOURCES = C_MAX_RESOURCES;
MAX_CYCLIC_TIMERS = C_MAX_CYCLIC_TIMERS;
MAX_MAILBOXES = C_MAX_MAILBOXES;
MAX_QUEUES = C_MAX_QUEUES;
MAX_SEMAPHORES = C_MAX_SEMAPHORES;
RTC_SCALE = C_RTC_SCALE;
TSLICE_SCALE = C_TSLICE_SCALE;
clear_ram(cmx_tcb,sizeof cmx_tcb);
clear_ram(&stack_storage.stack_space[0],sizeof stack_storage);
#if C_MAX_CYCLIC_TIMERS > 0
clear_ram(tcproc,sizeof tcproc);
#endif
#if C_MAX_RESOURCES > 0
clear_ram(res_que,sizeof res_que);
#endif
#if C_MAX_MAILBOXES > 0
clear_ram(mail_box,sizeof mail_box);
#endif
#if C_MAX_MESSAGES > 0
clear_ram(message_box,sizeof message_box);
#endif
#if C_MAX_QUEUES > 0
clear_ram(queue,sizeof queue);
#endif
#if C_MAX_SEMAPHORES > 0
clear_ram(sem_array,sizeof sem_array);
#endif
}
static void clear_ram(void *addr_ptr,word16 size)
{
byte *crap_ptr;
crap_ptr = addr_ptr;
while(size--)
{
*crap_ptr++ = 0;
}
}
#endif
#if CMXBUG_ENABLE > 0 || CMXTRACKER_ENABLE > 0
void setup_bug(void)
{
/* Do NOT change the "cmxbug_slot" or "cmxbug", for
CMXBug expects these names. You could change the priority
or stack size if need be, but we highly suggest you do not. */
#if CMXBUG_ENABLE > 0
K_Task_Create(1,&cmxbug_slot,cmxbug,128,32); /* create CMXBug task */
K_Task_Name(cmxbug_slot,"CMXBug"); /* Name for task */
K_Task_Start(cmxbug_slot); /* start CMXBug task */
#else
K_Task_Create(1,&cmxtracker_slot,cmxtracker,128,32); /* create CMXTracker task */
K_Task_Name(cmxtracker_slot,"CMXTracker"); /* Name for task */
K_Task_Start(cmxtracker_slot); /* start CMXBug task */
init_cmxtracker();
#endif
/* The following is for serial channel */
UBRR = 6; /* Bad tolerance - 9600 Baud using 1 MHz */
/* UBRR = 12; */ /* 4800 Baud using 1 MHz */
UBRR = 50; /* 1200 Baud using 1 MHz */
UCR = 0x18; /* enable transmitter/receiver */
}
#if CMXTRACKER_ENABLE > 0
void init_cmxtracker(void)
{
num_records = 0;
cmxtracker_in_ptr = cmxtracker_array;
cmxtracker_ctr = sizeof (cmxtracker_array);
}
#endif
byte K_Bug_Getchr(byte *ptr)
{
if ( USR & 0x80 )
{
*ptr = UDR & 0x7F;
return(1);
}
else
return(0);
}
void K_Bug_Putchr(char c)
{
while ( ! (USR & 0x20) )
;
UDR = c;
}
#endif
byte K_I_Intrp_Pipe_In(byte a, byte b, byte c, word16 d, void *mesg)
{
PIPE_STRUC *in_ptr;
#if CMXTRACKER_ENABLE > 0
if ((!(TEST_CMX_ACTIVE)) || (CMXTRACKER_ACTIVE))
return(K_ERROR);
#else
if (!(TEST_CMX_ACTIVE))
return(K_ERROR);
#endif
PROC_SAVE_INT; /* disable interrupts */
if (pipe_slots_avail)
{
in_ptr = &pipe[in_ctr];
--pipe_slots_avail;
if (++in_ctr == C_PIPE_SIZE)
in_ctr = 0;
PROC_RESTORE_INT; /* enable interrupts */
DO_INT_PIPE; /* Set the do interrupt pipe flag. */
in_ptr->identifier = a;
in_ptr->p1 = b;
switch(a) {
case 5:
case 6:
in_ptr->pipe_u.p3 = d;
break;
case 7:
in_ptr->pipe_u.p4 = mesg;
break;
case 8:
in_ptr->p2 = c;
in_ptr->pipe_u.p3 = d;
break;
}
return(K_OK);
}
else
{
PROC_RESTORE_INT; /* enable interrupts */
return(K_ERROR);
}
}
/*********************************************************************
The following function executes the functions that the interrupts
place into the interrupt pipe. called only by CMX K_I_Scheduler.
*********************************************************************/
void K_I_Intrp_Pipe_Out(void)
{
byte parm1;
byte parm2;
while(1)
{
#if CMXTRACKER_ENABLE
if (!CMXTRACKER_ACTIVE)
{
cmxtracker_in1(INT_ACTION);
}
#endif
out_ptr = &pipe[out_ctr];
switch (out_ptr->identifier) {
case 0:
K_Task_Wake(out_ptr->p1);
break;
case 1:
K_Task_Wake_Force(out_ptr->p1);
break;
case 2:
K_Task_Start(out_ptr->p1);
break;
case 3:
K_Timer_Stop(out_ptr->p1);
break;
case 4:
K_Timer_Restart(out_ptr->p1);
break;
case 5:
parm1 = out_ptr->p1;
K_Timer_Initial(parm1,out_ptr->pipe_u.p3);
break;
case 6:
parm1 = out_ptr->p1;
K_Timer_Cyclic(parm1,out_ptr->pipe_u.p3);
break;
case 7:
parm1 = out_ptr->p1;
K_Mesg_Send(parm1,out_ptr->pipe_u.p4);
break;
case 8:
parm1 = out_ptr->p1;
parm2 = out_ptr->p2;
K_Event_Signal(parm1,parm2,out_ptr->pipe_u.p3);
break;
case 9:
K_Semaphore_Post(out_ptr->p1);
break;
default:
/* What should we do here, possibly reset pipe ? to be beginning */
break;
}
PROC_DISABLE_INT; /* disable interrupts */
pipe_slots_avail++;
if (++out_ctr == C_PIPE_SIZE)
out_ctr = 0;
if (out_ctr == in_ctr)
{
CLR_DO_INT_PIPE; /* no, reset do interrupt pipe flag. */
break; /* exit. */
}
PROC_ENABLE_INT; /* re-enable interrupts and process more. */
}
PROC_ENABLE_INT; /* re-enable interrupts and exit. */
}
byte K_Task_Name(byte task_slot,char *name)
{
tcbpointer tcbptr;
if(K_I_Get_Ptr(task_slot,&tcbptr)) /* send address of pointer */
return(K_ERROR);
#if CMXBUG_ENABLE > 0 || CMXTRACKER_ENABLE > 0
task_name[task_slot] = name;
#else
task_name[0] = name;
#endif
return(K_OK);
}
byte K_OS_Task_Slot_Get(void)
{
return ((struct _tcb *)activetcb - cmx_tcb);
}
word32 K_OS_Tick_Get_Ctr(void)
{
return(cmx_tick_count);
}
/******************************************************************
K_OS_Tick_Update: Called from timer interrupt routine to signal that
the CMX task timer should execute if need be.
THIS CODE EXECUTES ONLY AT INTERRUPT LEVEL.
**********************************************************************/
void K_OS_Tick_Update(void)
{
if (TEST_CMX_ACTIVE) /* see if CMX OS has been entered. */
{
#if CMXBUG_ENABLE > 0
if (!CMXBUG_ACTIVE)
{
if (activetcb->tcbstate & RUNNING)
stat_array[activetcb - cmx_tcb] += 1;
else
stat_array[0] += 1;
}
#endif
cmx_tick_count++; /* increment long counter */
#if CMXTRACKER_ENABLE
if (!CMXTRACKER_ACTIVE)
{
#endif
if (!(--rtc_count)) /* converts hardware tics to CMX delay tics */
{
#if CMXTRACKER_ENABLE
cmxtracker_in1(CMX_TIC_CALL);
#endif
rtc_count = RTC_SCALE; /* reset counter with rtc prescaler */
/* the following will see if a task timer needs servicing or
a cyclic timer needs servicing. */
if ((tsk_timer_lnk->ftlink != (tcbpointer)tsk_timer_lnk) ||
(cyclic_lnk->ftlink != (struct _tcproc *)cyclic_lnk))
{
DO_TIMER_TSK; /* yes, set flag to indicate that CMX timer
task should execute. */
}
}
#if CMXTRACKER_ENABLE
}
#endif
if (TEST_SLICE_ENABLE) /* see if time slicing active. */
{
if (!(--tslice_count)) /* if so, decrement and test time slice
counter. */
{
DO_TIME_SLICE; /* set flag indicating time count expired. */
SLICE_DISABLE; /* disable time slicing. */
}
}
}
} /* K_OS_Tick_Update */
void K_I_Func_Return(void)
{
/* this function will decrement the task block (lock) counter.
Also see if the interrupt count is 0 and if so, will
test to see any of the CMX 5 flags are set, which will then call
the K_I_Scheduler to invoke possibly a task switch */
K_I_Enable_Sched();
}
/*****************************************************************
The following is the CPU reduced power function. The user
MUST write their own and they must ensure that the proceesor
returns to the caller, without modifying the stack.
NOTE: the CMX K_I_Scheduler calls this function which is in the assembly
module supplied. The user may find it necessary to modify the
assembly file, so every thing is correct when the CPU
comes out of the reduced power state. ALSO the CPU must let
the interrupts wake it up, out of the reduced power state
so as the task's timers and cyclic timers may have their
time counters decremented if need be.
*****************************************************************/
void K_OS_Low_Power_Func(void)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -