Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can interrupts be handled in standard C?

Tags:

c

interrupt

Is there a method of servicing hardware interrupts in standard C (ANSI/ISO)? All the implementations Ive seen so far either use compiler specific language extensions or pre-processor directives.

I just came across the standard C library 'signals' feature, but wikipedia is very light on its use and I dont think it serves the purpose.

like image 265
Toby Avatar asked Dec 25 '22 14:12

Toby


1 Answers

POSIX signals can allow a user program written in C to catch and handle some types of interrupts and/or exceptions. It's the most standard approach I know about.

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
int a,b,*p;
jmp_buf jump_destination;

void exception_handler (int sg)
{
  printf ("Error dereferencing pointer\n");
  p=&b; /* pointer quick fix. */
  longjmp(jump_destination,1); /* long GOTO... */
}

void main (void)
{
  int i;

  signal (SIGSEGV, exception_handler);
  b=0; p=NULL;    

  setjmp(jump_destination); /* ...to this position */
  printf ("Trying to dereference pointer p with value %08.8X... ",p);
  printf ("After dereferencing pointer, its value is: %d\n", *p);
}

For hardware interrupts, C has no explicit semantics, mainly because it is not needed. For example, a Linux device driver can install its own interrupt handler for a hardware device. All you need is to call request_irq() function with the address of the function that will be in charge of handling the interrupt.

For example, this will install an interrupt handler for the RTC chip (assumming it's present and activated in your hardware)

...
...
res=request_irq (8,                     /* que IRQ queremos */
                 interrupt_handler,         /* address of handler */
                 IRQF_DISABLED,         /* this is not a shared IRQ */
                 “mydriver",            /* to be shown at /proc/interrupts */
                 NULL);
if (res!=0)
{
  printk ("Can't request IRQ 8\n");
}
...
...

Your handler is just a regular C function:

static irqreturn_t gestor_interrupcion (int irq, void *dev_id, struct pt_regs *regs)
{
  /* do stuff with your device, like read time or whatever */
   ...
   ...
   ...

  return IRQ_HANDLED; /* notify the kernel we have handled this interrupt */
}

This is possible (to use a regular C function to handle a hardware interrupt) because the handler itself is called from another kernel function, that has taken care of preserving the current context so the interrupted process won't notice anything. If you are dealing with interrupts in a "naked" computer and you want to keep your C code from deviating from the standard, then you will need to use some assembler to call your function.

like image 183
mcleod_ideafix Avatar answered Jan 03 '23 12:01

mcleod_ideafix