📄 timer_interrupts.c
字号:
*(INTR_CLEAR) = 0x00;
stop_counter();
}
PciDio96_Cleanup(ihr, Clean);
print_interrupt_stat();
RtPrintf("\n Exit test (cardNumber=%d depth=%d)\n\n\n", cardNumber, initialized);
ExitProcess(0);
}
//
// respond: Respond to an interrupt
// Takes one interrupt and clears it.
//
BOOLEAN RTAPI respond(PVOID pdt)
{
int k=0, l, num=0;
BOOLEAN pass=TRUE;
ULONG status[10];
if ((IsrUsage == 0) && (is_my_interrupt() == 0)) // If IST only, then check for true
return PassToNextDevice; // board interrupt. If not true - pass to next device
if (pass_interrupt == 2) // If pass_interrupt_to_next() was not called by ISR yet
pass_interrupt = pass_interrupt_to_next(); // call it by yourself
// Introduce delay to let EOI reach IoApic:
if (pass_interrupt == 0) // Only if this IST is final
{ // introduce delay,
if (IsrUsage <= 3) // but only if IsrUsage does not instruct otherwise
{
for (k=0,l=0; k<10000; k++)
{ l += k; }
}
}
else // Case when either return irrelevant or no ISR and was set to pass interrupt.
pass = FALSE; // Will pass interrupt to next IST
status[0] = cardNumber; num++;
status[1] = *(PORTC_ADDR); num++;
status[2] = initialized; num++;
if ((pass_interrupt == 0) && (IsrUsage != 2)) // If final IST and interrupt was not cleared
clear_interrupt(); // clear it
if (append_interrupt_stat(num, status) == 0) // Accumulate statistic
IntDone = TRUE; // If buffer is full - set IntDone to print statistic and probably reset
pass_interrupt = 2; // Next time call pass_interrupt_to_next() again
return pass;
}
// ISR
RTFCNDCL fast_respond(PVOID arg)
{
if (is_my_interrupt() == 0) // If this is not my interrupt
return PassToNextDevice; // pass to next board
if ((pass_interrupt = pass_interrupt_to_next()) == 1) // If to pass interrupt
{ // to next application for the same board
pass_interrupt = 2; // Next time call pass_interrupt_to_next() again
return PassToNextDevice; // Pass to next board
}
if (IsrUsage == 2)
{
clear_interrupt();
return CallInterruptThread;
}
else if (IsrUsage >= 3)
{
respond(NULL);
return Dismiss;
}
return CallInterruptThread;
}
#define CNFG_VAL 0x99 // Port A Input Port B Output Port C Input
void initialize_board()
{
*(INTR_CTRL1) = 0x00;
*(INTR_CTRL2) = 0x00;
*(CNFG_ADDR) = CNFG_VAL; // Set PPI A to mode 0
}
ULONG start_counter(ULONG time)
{
ULONG time1, time2, k;
if (time <= 0)
return 0;
time *= 2; // Time in counter ticks (2MHz frequency).
if (time <= 0xFFFF) // If timer interval less then 0xFFFF ticks
{ // one counter is enough
time1=time; // First counter will do all job
time2 = 0; // No second counter
}
else // If bigger timer interval - we need the second counter
{ // but we will obtain the best possible resolution
time2 = time >> 1;
for (k=1; k<16; k++)
{
if (time2 <= 0xFFFF)
break;
time2 >>= 1;
}
time1 = 1 << k;
}
*(INTR_CTRL1) = 0x00;
*(INTR_CTRL2) = 0x00;
*(CLOCK_CTRL) = 0x34;
if (time2 == 0)
{
*(INTR_CTRL2) = 0x02;
*(INTR_CTRL2) = 0x06;
}
else
{
*(CLOCK_CTRL) = 0x74;
*(INTR_CTRL2) = 0x02;
*(INTR_CTRL2) = 0x07;
*(CLOCKB) = (UCHAR)(time2 & 0xFF);
*(CLOCKB) = (UCHAR)((time2 >> 8) & 0xFF);
}
*(CLOCKA) = (UCHAR)(time1 & 0xFF);
*(CLOCKA) = (UCHAR)((time1 >> 8) & 0xFF);
if (time2 == 0)
time = time1;
else
time = time2*time1;
return time;
}
void stop_counter()
{
*(CLOCK_CTRL) = 0x30;
*(INTR_CTRL1) = 0x00;
*(INTR_CTRL2) = 0x00;
}
#define TIME_DELTA 500 // +/- 500 mks
ULONG is_my_interrupt()
{
ULONG time;
RtGetClockTime(CLOCK_FASTEST, ¤t_time); // Get interrupt time
// Judje by time whether it is our interrupt:
time = (ULONG)((current_time.QuadPart-shared_board_data->previous_time.QuadPart)/5+TIME_DELTA);
if ((time%(shared_board_data->TimerDelay)) < 2*TIME_DELTA)
{
shared_board_data->previous_time = current_time;
return 1;
}
else
return 0;
}
void clear_interrupt()
{
*(INTR_CLEAR) = 0x00;
}
int append_interrupt_stat(int num, PULONG status)
{
int k;
ULONG *pl, *pl0=status;
COUNTER_STAT *data;
if (int_stat_num >= MAX_INT_STAT)
return -1;
data = int_stat+int_stat_num;
data->time = current_time;
for (k=0,pl=data->status,pl0=status; k<num; k++)
{ *pl++ = *pl0++; }
data->status_num = num;
int_stat_num++;
if (int_stat_num >= MAX_INT_STAT)
return 0;
return int_stat_num;
}
int print_interrupt_stat()
{
int k, m;
COUNTER_STAT *data;
ULONGLONG time0, time;
data = int_stat;
time0 = init_time.QuadPart;
RtPrintf("\n");
for (k=0; k<int_stat_num; k++, data++)
{
time = data->time.QuadPart;
RtPrintf("%d: time=%6u mks delta=%5u mks ", k,
(ULONG)(time-init_time.QuadPart)/10, (ULONG)(time-time0)/10);
for (m=0; m<data->status_num; m++)
{ RtPrintf(" 0x%X", data->status[m]); }
RtPrintf("\n");
time0 = time;
}
int_stat_num = 0;
return k;
}
HANDLE alloc_shared_memory(PVOID *mem)
{
HANDLE handle;
RtWaitForSingleObject(ShMemMutex, INFINITE);
if ((handle = RtCreateSharedMemory(0, 0, 1000, shared_mem_all_name, &pSharedMem)) == NULL)
{
RtReleaseMutex(ShMemMutex);
return NULL;
}
if (GetLastError() != ERROR_ALREADY_EXISTS)
initialize_shared_mem(pSharedMem);
RtReleaseMutex(ShMemMutex);
return handle;
}
void initialize_shared_mem(PVOID pmem)
{
int k;
SHARED_BOARDS_INFO *info = (SHARED_BOARDS_INFO *)pmem;
info->active_num = 0;
for (k=0; k<MAX_ACTIVE_BOARDS; k++)
{ info->boards[k].initialized = 0; }
}
int board_is_initialized(int number, BOARD_INIT_STRUCT *board)
{
ULONG init;
SHARED_BOARDS_INFO *info;
BOARD_INIT_STRUCT *boards;
RtWaitForSingleObject(ShMemMutex, INFINITE);
info = (SHARED_BOARDS_INFO *)pSharedMem;
boards = info->boards;
boards += number;
shared_board_data = boards;
boards->busy = 1;
if ((init = boards->initialized) == 0)
{
*boards = *board;
}
else
{
*board = *boards;
}
boards->initialized = init+1;
boards->busy = 0;
info->active_num++;
RtReleaseMutex(ShMemMutex);
return init;
}
int board_is_cleared(int number)
{
ULONG init;
SHARED_BOARDS_INFO *info;
BOARD_INIT_STRUCT *boards;
RtWaitForSingleObject(ShMemMutex, INFINITE);
info = (SHARED_BOARDS_INFO *)pSharedMem;
if (info->active_num == 0)
{
RtReleaseMutex(ShMemMutex);
return -1;
}
boards = info->boards;
boards += number;
boards->busy = 1;
if ((init = boards->initialized) == 0)
{
RtReleaseMutex(ShMemMutex);
return -2;
}
boards->initialized = init-1;
boards->busy = 0;
info->active_num--;
RtReleaseMutex(ShMemMutex);
return init-1;
}
ULONG pass_interrupt_to_next()
{
if ((IntPass == 0) || (shared_board_data->busy != 0) ||
(shared_board_data->int_serviced >= shared_board_data->initialized-1))
{
shared_board_data->int_serviced = 0;
return 0;
}
shared_board_data->int_serviced++;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -