首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Nios 2的硬件中断

Nios 2的硬件中断
EN

Code Review用户
提问于 2013-09-11 06:51:12
回答 1查看 685关注 0票数 1

这个程序表现得和预期的一样,但我认为可以做一些更好的事情,因为我是一个新手C程序员。我怀疑中断处理程序可以使用其他方式来调用硬件,而不是直接内存。你能看一下并告诉我什么可以改进吗?

代码语言:javascript
复制
#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"

/* Include header file for alt_irq_register() */
#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 NULL_POINTER ( (void *) 0)

int timeloc = 0x5957; /* startvalue given in hexadecimal/BCD-code */
int RUN = 1;

#define TIMER1 ( (unsigned int *) 0x920 )
#define PERIOD (49999)

/* Define addresses etc for de2_pio_keys4 */
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;
const int de2_pio_keys4_intindex = 2;
const int de2_pio_keys4_irqbit = 1 << 2;

/* Define address for de2_pio_hex_low28 */
volatile int * de2_pio_hex_low28 = (volatile int *) 0x9f0;

/*
 * The n2_fatal_error function is called for unexpected
 * conditions which most likely indicate a programming error
 * somewhere in this file. The function prints "FATAL ERROR"
 * using out_char_uart_0, lights an "Err" pattern on the
 * seven-segment display, and then enters an infinite loop.
 */
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.
 *
 * To help debugging interruptible interrupt-handlers,
 * this handler delays a long while when a key is pressed.
 * However, there is no delay when the key is released.
 *
 * We keep a software copy of the LED value, since
 * the parallel output ports are not program-readable.
 *
 * Example: we send out the value 1 on de2_pio_keys4,
 * by executing *DE2_PIO_KEYS4_BASE = 1;
 * Then we try to read the port by executing
 * int test_val = *DE2_PIO_KEYS4_BASE; // WRONG
 * The value of test_val is now undefined.
 * The port returns some bits which are not related
 * to the value we have written.
 *
 * The software copy of the LED value
 * for this interrupt handler
 * is the global variable myleds, defined above.
 */
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();
}

int main() {

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

    keysinit_int();
    int counter = 0;
    while (1) {
        delay(1);
        ++counter;
        if (counter % 1000 == 0) {
            IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_REDLED18_BASE, timeloc);
            if (RUN == 1) {
                tick(&timeloc);
                puttime(&timeloc);
                puthex(timeloc);
            }
        }
    }

    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);
}
EN

回答 1

Code Review用户

发布于 2013-09-11 13:51:46

中断处理程序看起来有点冗长。有太多的评论,其中大部分是“噪音”(它们的贡献很小,在其他地方也是正确的),还有很多空白处(键控检测)。这是一个简化的版本,如果ISR:

代码语言:javascript
复制
void irq_handler_keys(void *context, alt_u32 irqnum) 
{
    const alt_u32 save_value = alt_irq_interruptible(irqnum);
    const unsigned edges = *de2_pio_keys4_edgecap;
    const unsigned keys = ~*de2_pio_keys4_base; // inverted

    *de2_pio_keys4_edgecap = 0;

    if (edges & PIO_KEYS4_TICK & keys) {
        tick(&timeloc);
        puttime(&timeloc);
        puthex(timeloc);
    } else if (edges & PIO_KEYS4_RUN & keys) {
        RUN ^= 1;
    } else if (edges & PIO_KEYS4_ZERO & keys) {
        timeloc = ZERO_TIME;
        puttime(&timeloc);
        puthex(timeloc);
    } else if (edges & PIO_KEYS4_RESET & keys) {
        timeloc = INITIAL_TIME;
        puttime(&timeloc);
        puthex(timeloc);
    }
    alt_irq_non_interruptible(save_value);
}

这些变化是明确的,但我会仔细研究一下。

  • 首先,对alt_irq_interruptible的调用需要通过一个对alt_irq_non_interruptible的调用来平衡,而不是四个。对我来说,传递irqnum似乎比传递您假定的中断号更符合逻辑。
  • 寄存器看起来更像unsigned值而不是int值(例如不能添加它们),键寄存器只需要在函数开始时读取。
  • 我重新排序测试,以检查最有可能的第一次。如果滴答声每秒发生一次,这并没有太大的区别(尽管如果它是时钟滴答,为什么要通过键按?--也许我读了太多关于函数调用名称的内容),但这是一个ISR,所以效率是很重要的。
  • 我已经删除了冗余条件,以使主体变得更简单(编译器也会这样做,因此在运行时它并不重要)。这也改变了函数的功能(即。它向下下降如果-否则的序列,直到它找到一个下降的边缘,而不是仅仅是任何边缘),这可能不是你想要的。
  • 我用常量代替了1,2,4,8等等。

注意,RUNtimeloc应该是volatile

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/31080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档