Question

I've written code than handles interrupts and I added a function that will do something "useful" (calculating the next prime) and that should handle interrupts. The interrupts are working but not printing the calculated primes from within the while loop, while it is printing the time if I don't try to print the prime.

I think that putchar can't be used since a) It's for characters and I want to print an int and b) putchar uses interrupts so I must do it some other way.

When I tried with printf("%d",next) it didn't work either, why? How should I do to print the next prime from the main loop?

The program is

#include <stddef.h>
#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_alarm.h"
#include "alt_types.h"
#include "alt_irq.h"

extern int initfix_int(void);
extern void puttime(int* timeloc);
extern void puthex(int time);
extern void tick(int* timeloc);
extern void delay(int millisec);
extern int hexasc(int invalue);

#define TRUE 1
#define KEYS4 ( (unsigned int *) 0x840 )
#define TIMER1 ( (unsigned int *) 0x920 )
#define PERIOD (49999)
#define NULL_POINTER ( (void *) 0)
#define NULL ( (void *) 0)
#define PRIME_FALSE 0 /* Constant to help readability. */
#define PRIME_TRUE 1 /* Constant to help readability. */

volatile int timeloc = 0x5957;
volatile int RUN = 1;
volatile int * const de2_pio_keys4_base = (volatile int *) 0x840;
volatile int * const de2_pio_keys4_intmask = (volatile int *) 0x848;
volatile int * const de2_pio_keys4_edgecap = (volatile int *) 0x84c;
volatile int * de2_pio_hex_low28 = (volatile int *) 0x9f0;

const int de2_pio_keys4_intindex = 2;
const int de2_pio_keys4_irqbit = 1 << 2;

/* The alt_alarm must persist for the duration of the alarm. */
static alt_alarm alarm;

/*
 * The callback function.
 */
alt_u32 my_alarm_callback(void* context) {
    /* This function is called once per second */

    if (RUN == 1) {
        tick(&timeloc);
        puttime(&timeloc);
        puthex(timeloc);
    }
    return alt_ticks_per_second();
}

void n2_fatal_error() {
    /* Define the pattern to be sent to the seven-segment display. */
#define N2_FATAL_ERROR_HEX_PATTERN ( 0xcbd7ff )
    /* Define error message text to be printed. */
    static const char n2_fatal_error_text[] = "FATAL ERROR";
    /* Define pointer for pointing into the error message text. */
    register const char * cp = n2_fatal_error_text;

    /* Send pattern to seven-segment display. */
    *de2_pio_hex_low28 = N2_FATAL_ERROR_HEX_PATTERN;
    /* Print the error message. */
    while (*cp) {
        //out_char_uart_0( *cp );
        cp = cp + 1;
    }

    /* Stop and wait forever. */
    while (1)
        ;
}

/*
 * Interrupt handler for de2_pio_keys4.
 * The parameters are ignored here, but are
 * required for correct compilation.
 * The type alt_u32 is an Altera-defined
 * unsigned integer type.
 */
void irq_handler_keys(void * context, alt_u32 irqnum) {
    alt_u32 save_value;
    save_value = alt_irq_interruptible(de2_pio_keys4_intindex);
    /* Read edge capture register of the de2_pio_keys4 device. */
    int edges = *de2_pio_keys4_edgecap;
    *de2_pio_keys4_edgecap = 0;

    /* If action on KEY0 */
    if (edges & 1) {
        /* If KEY0 is pressed now */
        if ((*de2_pio_keys4_base & 1) == 0) {

            if (RUN == 0) {
                RUN = 1;
            } else {
                RUN = 0;
            }

        }
        /* If KEY0 is released now */
        else if ((*de2_pio_keys4_base & 1) != 0) {

        }
        alt_irq_non_interruptible(save_value);
    } else if (edges & 2) {
        /* If KEY1 is pressed now */
        if ((*de2_pio_keys4_base & 2) == 0) {

            tick(&timeloc);
            puttime(&timeloc);
            puthex(timeloc);

        }
        /* If KEY1 is released now */
        else if ((*de2_pio_keys4_base & 2) != 0) {

        }
        alt_irq_non_interruptible(save_value);
    }

    else if (edges & 4) {
        /* If KEY2 is pressed now */
        if ((*de2_pio_keys4_base & 4) == 0) {

            timeloc = 0x0;
            puttime(&timeloc);
            puthex(timeloc);

        }
        /* If KEY2 is released now */
        else if ((*de2_pio_keys4_base & 4) != 0) {

        }
        alt_irq_non_interruptible(save_value);
    }

    else if (edges & 8) {
        /* If KEY3 is pressed now */
        if ((*de2_pio_keys4_base & 8) == 0) {

            timeloc = 0x5957;
            puttime(&timeloc);
            puthex(timeloc);

        }
        /* If KEY3 is released now */
        else if ((*de2_pio_keys4_base & 8) != 0) {

        }
        alt_irq_non_interruptible(save_value);
    }

}

/*
 * Initialize de2_pio_keys4 for interrupts.
 */
void keysinit_int(void) {
    /* Declare a temporary for checking return values
     * from system-calls and library functions. */
    register int ret_val_check;

    /* Allow interrupts */
    *de2_pio_keys4_intmask = 15;

    /* Set up Altera's interrupt wrapper for
     * interrupts from the de2_pio_keys4 device.
     * The function alt_irq_register will enable
     * interrupts from de2_pio_keys4.
     * Return value is zero for success,
     * nonzero for failure. */
    ret_val_check = alt_irq_register(de2_pio_keys4_intindex, NULL_POINTER,
            irq_handler_keys);
    /* If there was an error, terminate the program. */
    if (ret_val_check != 0)
        n2_fatal_error();
}

/*
 * NextPrime
 *
 * Return the first prime number larger than the integer
 * given as a parameter. The integer must be positive.
 */
int nextPrime(int inval) {
    int perhapsprime; /* Holds a tentative prime while we check it.
     */
    int testfactor; /* Holds various factors for which we test
     perhapsprime. */
    int found; /* Flag, false until we find a prime. */
    if (inval < 3) /* Initial sanity check of parameter. */
    {
        if (inval <= 0)
            return (1); /* Return 1 for zero or negative input. */
        if (inval == 1)
            return (2); /* Easy special case. */
        if (inval == 2)
            return (3); /* Easy special case. */
    } else {
        /* Testing an even number for primeness is pointless, since
         * all even numbers are divisible by 2. Therefore, we make sure
         * that perhapsprime is larger than the parameter, and odd. */
        perhapsprime = (inval + 1) | 1;
    }
    /* While prime not found, loop. */
    for (found = PRIME_FALSE; found != PRIME_TRUE; perhapsprime += 2) {
        /* Check factors from 3 up to perhapsprime/2. */
        for (testfactor = 3; testfactor <= (perhapsprime >> 1); testfactor +=
                1) {
            found = PRIME_TRUE; /* Assume we will find a prime. */
            if ((perhapsprime % testfactor) == 0) { /* If testfactor divides perhapsprime... */
                found = PRIME_FALSE; /* ...then, perhapsprime was non-prime. */
                goto check_next_prime;
                /* Break the inner loop,
                 go test a new perhapsprime. */

            }
        }
        check_next_prime: ; /* This label is used to break the inner loop. */
        if (found == PRIME_TRUE) /* If the loop ended normally,
         we found a prime. */
        {
            return (perhapsprime); /* Return the prime we found. */
        }
    }
    return (perhapsprime); /* When the loop ends,
     perhapsprime is a real prime. */
}

int main() {
    int next = 3;

    /* Remove unwanted interrupts.
     * A nonzero return value indicates failure. */
    if (initfix_int() != 0)
        n2_fatal_error();

    keysinit_int();
    if (alt_alarm_start(&alarm, alt_ticks_per_second(), my_alarm_callback, NULL)
            < 0) {
        printf("No system clock available\n");
    }

      while( 1 )                /* Loop forever. */
      {
        next = nextPrime(next);
        //printf("%d",next);
        //printf("P %d ", next);
      }

    return 0;
}

int hex7seg(int digit) {
    int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
            0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
    register int tmp = digit & 0xf;
    return (trantab[tmp]);
}

void puthex(int inval) {
    unsigned int hexresult;
    hexresult = hex7seg(inval);
    hexresult = hexresult | (hex7seg(inval >> 4) << 7);
    hexresult = hexresult | (hex7seg(inval >> 8) << 14);
    hexresult = hexresult | (hex7seg(inval >> 12) << 21);
    IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE, hexresult);
}
Was it helpful?

Solution

Basically your code is working fine on me. The only problem is with printing, for some reason you should print a newline before such as:

printf("start program\n");
  while( 1 )                /* Loop forever. */
  {
    next = nextPrime(next);
    printf("%d",next);

  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top