📄 uk_kernel.c
字号:
/*******************************************************************************
File: uK_Kernel.c
Description:
This file implements uK-Kernel RTOS
Creation
Date: November 3, 2004
Author: Benjamin M. Kacenas
*******************************************************************************/
#include "uK_Kernel.h"
/*******************************************************************************
Function: main()
Description:
Provide initialization and the main Main Loop Component
Creation
Date: November 3, 2004
Author: Benjamin M. Kacenas
*******************************************************************************/
main()
{
// Disable all interrupts.
IEN0 = 0x00;
IEN1 = 0x00;
IP = 0x00;
// Turn off timers
TCON = 0x00;
T2CON = 0x00;
// Get the task queue ready
by_QueMax = 0; // For test purposes only
by_TaskQueHead = 0; // Initialize the task queue head and tail pointers
by_TaskQueTail = 0;
b_TaskQueEmpty = 0; // Set the queue to empty status
// Get the heartbeat and interval dispatcher ready
by_RTX_Counter = 0; // Clear the 4 msec event counter
ui_EventTask = 0; // Initialize all task slots to DISABLED
// Setup the heartbeat timer for 4.096 msec
TL0 = 0; // Preset timer 0 low byte to 0
TH0 = 0; // Preset timer 0 high byte to 0
TMOD &= 0xF0; // Set timer 0 to mode 0, 13 bit with 5 bit prescaler
PT0 = CLEAR; // Set timer 0 interrupt priority to low level
TF0 = CLEAR; // Clear any pending Timer 0 interrupts
ET0 = SET; // Enable Timer 0 overflow interrupts
// Start the heartbeat interrupt, let the kernel run
EA = SET; // Set master interrupt enable
TR0 = SET; // Set timer 0 to run
void (*fp)(void *);
while (TRUE)
{
// Start of task dispatcher
// Dispatch a task only if there is one pending
if (b_TaskQueEmpty == NOT_EMPTY)
{
// Dispatch the next task in the queue
fp = (void *)st_TaskQue[by_TaskQueTail].fp_Task;
fp(st_TaskQue[by_TaskQueTail].p_TaskData);
// If the tail is at the top of the queue set it back to 0
if (by_TaskQueTail == (TASK_QUE_SIZE - 1))
{
by_TaskQueTail = 0;
}
else // Else increment the tail index
{
by_TaskQueTail++;
}
EA = DISABLE; // Disable all interrupts
// If the tail index has reached the head index, no pending
if (by_TaskQueTail == by_TaskQueHead)
{
b_TaskQueEmpty = EMPTY;
}
EA = ENABLE; // Enable all interrupts
}
// Check for any timed repetitive tasks
sl_IntervalDispatcher();
// Place processes to be run from the main loop in this area
// ---------------------------------------------------------
// ---------------------------------------------------------
}
} // End of main()
/*******************************************************************************
Function: sl_RTX_Event()
Description:
Heartbeat interrupt service routine
Creation
Date: November 3, 2004
Author: Benjamin M. Kacenas
*******************************************************************************/
void sl_RTX_Event(void) interrupt 1
{
// This function gets called every 4.096 msec; when Timer 0
// overflows
byte by_Inx; //Simple iterator
// Loop through all delay timers
for (by_Inx = 0; by_Inx < NUM_DELAY_TIMERS; by_Inx++)
{
// If the delay counter register for this timer is 0,
// its not being used
if (st_SysDelay[by_Inx].i_DelayCounter != 0)
{
// Decrement the counter being used
st_SysDelay[by_Inx].i_DelayCounter--;
// Now test again to see if it has gone to 0, timed out
if (st_SysDelay[by_Inx].i_DelayCounter == 0)
{
// Queue that delay timer's task and test to see if the
// Task Queue can except the task
if (sl_QueTask(st_SysDelay[by_Inx].fp_Task,
st_SysDelay[by_Inx].p_TaskData) == TASK_QUE_FULL)
{
// The Task Queue could not except the task,
// Set the delay to try again next tick
st_SysDelay[by_Inx].i_DelayCounter = 1;
}
}
}
}
// Place code that will be executed every 4.096 msec in this area
// ----------------------------------------------------------------
// This stuff has no meaning, it just shows something in this slot
b_ResultFlag = 0;
if (b_TestFlag)
{
b_ResultFlag = 1;
}
// ----------------------------------------------------------------
ui_EventTask |= FLAG_4MSEC; // Set 4.096 msec event flag
by_RTX_Counter++;
if (by_RTX_Counter == 0)
{
return;
}
if (by_RTX_Counter % MSEC_40 == 0)
{
// Place code that will be executed every 40 msec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask |= FLAG_40MSEC; // Set 40 msec event flag
}
if (by_RTX_Counter % MSEC_100 == 0)
{
// Place code that will be executed every 100 msec in this area
// ------------------------------------------------------------
sl_QueTask(sl_100msecTask, NULL);
// ------------------------------------------------------------
ui_EventTask |= FLAG_100MSEC; // set 100 msec event flag
}
if (by_RTX_Counter % MSEC_200 == 0)
{
// Place codethat will be executed every 200 msec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask |= FLAG_200MSEC; // set 200 msec event flag
}
if (by_RTX_Counter % MSEC_500 == 0)
{
// Place code that will be executed every 500 msec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask |= FLAG_500MSEC; // set 500 msec event flag
}
if (by_RTX_Counter % MSEC_1000 == 0)
{
// Place code that will be executed every 1 sec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask |= FLAG_1000MSEC; // set 1000 msec event flag
}
// Reset counter to zero here at 1024 ms
if (by_RTX_Counter == RTX_COUNTER_LIMIT)
{
by_RTX_Counter = 0;
}
return;
} // End of sl_RTX_Event()
/*******************************************************************************
Function: sl_QueTask()
Description:
Task Queuing Service component
Creation
Date: November 3, 2004
Author: Benjamin M. Kacenas
*******************************************************************************/
byte sl_QueTask(FuncPoint fp_FunctionPointer, void *p_DataPointer)
{
EA = DISBALE; // Disable all interrupts
// Check to see if there is room for this request
if ((b_TaskQueEmpty == NOT_EMPTY) &&
by_TaskQueHead == by_TaskQueTail))
{
EA = ENABLE; // Enable all interrupts
return(TASK_QUE_FULL); // No room in the task queue
}
// Load the next location in the queue with the task pointer
st_TaskQue[by_TaskQueHead].fp_Task = fp_FunctionPointer;
// Load the next location in the queue with the task data pointer
st_TaskQue[by_TaskQueHead].p_TaskData = p_DataPointer;
// Increment the index head or wrap it back to zero
if (by_TaskQueHead == (TASK_QUE_SIZE - 1))
{
by_TaskQueHead = 0;
}
else
{
by_TaskQueHead++;
}
// This is for debug purposes only QueMax
if (by_TaskQueHead < by_TaskQueTail)
{
by_QueMax = MAX((TASK_QUE_SIZE - by_TaskQueTail +
by_TaskQueHead),by_QueMax);
}
else
{
by_QueMax = MAX((by_TaskQueHead - by_TaskQueTail), by_QueMax);
}
b_TaskQueEmpty = NOT_EMPTY; // Say that the queue is not empty
EA = ENABLE; // Enable all interrupts
// Tell the calling function that we have queued the task
return(NO_ERROR);
} // End of sl_QueTask()
/*******************************************************************************
Function: sl_IntervalDispatcher()
Description:
Interval Dispatcher component
Creation
Date: November 3, 2004
Author: Benjamin M. Kacenas
*******************************************************************************/
void sl_IntervalDispatcher(void)
{
if (ui_EventTask & TASK_4MSEC)
{
// Place code that will be executed every 4 msec in this area
// ------------------------------------------------------------
//check for incoming characters on serial port
SomeFunction();
// ------------------------------------------------------------
ui_EventTask &= ~TASK_4MSEC;
}
if (ui_EventTask & TASK_40MSEC)
{
// Place code that will be executed every 40 msec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask &= ~TASK_40MSEC;
}
if (ui_EventTask & TASK_100MSEC)
{
// Place code that will be executed every 100 msec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask &= ~TASK_100MSEC;
}
if (ui_EventTask & TASK_200MSEC)
{
// Place code that will be executed every 200 msec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask &= ~TASK_200MSEC;
}
if (ui_EventTask & TASK_500MSEC)
{
// Place code that will be executed every 500 sec in this area
// ------------------------------------------------------------
//process any waiting serial commands
AnotherFunction();
// ------------------------------------------------------------
ui_EventTask &= ~TASK_500MSEC;
}
if (ui_EventTask & TASK_1000MSEC)
{
// Place code that will be executed every 1 sec in this area
// ------------------------------------------------------------
// ------------------------------------------------------------
ui_EventTask &= ~TASK_1000MSEC;
}
} // End of sl_IntervalDispatcher()
/*******************************************************************************
Function: sl_RequestDelay()
Description:
Delay Timer Request component
Creation
Date: November 3, 2004
Author: Benjamin M. Kacenas
*******************************************************************************/
byte sl_RequestDelay(unsigned int i_Delay, FuncPoint p_FunctionPointer,
void *p_DataPointer)
{
byte by_Inx; // Simple iterator
EA = DISABLE; // Disable all interrupts
// Start the check for the first open Delay timer
for (by_Inx = 0; by_Inx < NUM_DELAY_TIMERS; by_Inx++)
{
// If the counter is 0, we have found an unused delay timer
if (st_SysDelay[by_Inx].i_DelayCounter == 0)
{
break;
}
}
// See if we have requested too many delay timers
if (by_Inx == NUM_DELAY_TIMERS)
{
EA = ENABLE; // Enable all interrupts
return(NO_DELAY_TIMER); // Return without assigning a timer
}
// Load up this delay timer structure with delay count, function
// pointer and data pointer
st_SysDelay[by_Inx].i_DelayCounter = i_Delay;
st_SysDelay[by_Inx].fp_Task = fp_FunctionPointer;
st_SysDelay[by_Inx].p_TaskData = p_DataPointer;
// Record the number of delay timers used maximum
if (by_Inx >= by_DelaysUsedMax)
{
by_DelaysUsedMax++;
}
EA = ENABLE; // Enable all interrupts
return(NO_ERROR); // Return with no error
} // End of sl_RequestDelay()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -