Skip to content

Commit

Permalink
Add math interrupt test program
Browse files Browse the repository at this point in the history
  • Loading branch information
MJoergen committed Oct 29, 2020
1 parent 2e5172c commit ac7cd4d
Showing 1 changed file with 139 additions and 0 deletions.
139 changes: 139 additions & 0 deletions c/test_programs/test_math_isr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// This is a test program to verify that math operations are interrupt safe.
//
// The program runs for approximately 10 seconds and can be interrupted by
// pressing any key.
//
// The expected output (when running on the hardware) is:
// Finished!
// cycles = 7665 (ca.)
// loop_count = 712451 (ca.)
// isr_count = 500000
// error_count1 = 0
// error_count2 = 0
// isr_results = 68041169, 135708334, 203148773, 269872203, 336269884, 404026614, 470963936,
//
// The idea in the program is to generate random numbers (which use the EAE) in the ISR,
// and to sum the results of these together, so the calculation can be verified.
// In the main loop various math operations are performed in such a way so that the
// results can be verified.

#include <stdio.h>
#include <qmon.h>

// convenient mechanism to access QNICE's Memory Mapped IO registers
#define MMIO( __x ) *((unsigned int volatile *) __x )

volatile unsigned long isr_sum = 0;
volatile unsigned long isr_count = 0;

#define NUM_RESULTS 7
volatile unsigned long isr_results[NUM_RESULTS];
volatile unsigned int isr_enabled = 0;

static __interrupt void isr(void)
{
if (isr_enabled)
{
isr_count += 1;

// Do some calculations that use the EAE.
isr_sum += qmon_rand();

if ((isr_count & 0xFFF) == 0xFFF)
{
int index = isr_count >> 12;
if (index < NUM_RESULTS)
{
isr_results[index] = isr_sum;
}
}
}
} // isr

int main()
{
// Enable timer interrupt @ 50000 Hz
MMIO(IO_TIMER_0_INT) = (unsigned int) isr;
MMIO(IO_TIMER_0_PRE) = 1;
MMIO(IO_TIMER_0_CNT) = 1;

// Initialize random number
qmon_srand(1);

unsigned long loop_count = 0;

unsigned int cycles = MMIO(IO_CYC_MID);

isr_enabled = 1;

unsigned int error_count1 = 0;
unsigned int error_count2 = 0;

while (isr_count < 500000)
{
++loop_count;

// Generate two different numbers
unsigned int o11 = loop_count + 1;
unsigned int o21 = loop_count + 2;

// Calculate the product using two different methods
unsigned long r1 = qmon_mulu(o11, o21);
unsigned long e1 = ((unsigned long) o11) * ((unsigned long) o21); // Calls ___mulint32

// Compare the result
if (r1 != e1)
{
++error_count1;
}

unsigned int o12 = loop_count & 0xFF;
unsigned int o22 = (loop_count+1) & 0xFF;

if (o22)
{
unsigned int r2 = (o12*o22) / o22; // Two inline assembly operations using EAE
unsigned int e2 = o12;

if (r2 != e2)
{
++error_count2;
}
}

if (MMIO(IO_UART_SRA) & 1)
{
unsigned int tmp = MMIO(IO_UART_RHRA);
break;
}
if (MMIO(IO_KBD_STATE) & KBD_NEW_ANY)
{
unsigned int tmp = MMIO(IO_KBD_DATA);
break;
}
}

isr_enabled = 0;

cycles = MMIO(IO_CYC_MID) - cycles;

printf("Finished!\n");
printf("cycles = %u\n", cycles);
printf("loop_count = %lu\n",loop_count);
printf("isr_count = %lu\n",isr_count);
printf("error_count1 = %u\n", error_count1);
printf("error_count2 = %u\n", error_count2);
printf("isr_results = ");
for (int i=0; i<NUM_RESULTS; ++i)
{
printf("%lu, ", isr_results[i]);
}
printf("\n");

// Disable timer interrupt
MMIO(IO_TIMER_0_PRE) = 0;
MMIO(IO_TIMER_0_CNT) = 0;

return 0;
}

0 comments on commit ac7cd4d

Please sign in to comment.