How to code Interrupt Service Routine (ISR) for Timer Interrupts

Started by abrarmi, May 20, 2014, 01:18:59 PM

Previous topic - Next topic

abrarmi

Hi,

I am working on a project where I need to use the timer-1 interrupt of Olinuxino A13. I have successfully initialized the timer also enabled the timer-1 interrupt.

Can someone help me with writing the Interrupt Service Routine (ISR) for the timer-1 interrupt.

This is my C code so far,


/////////////////////////////////////////////////////////////
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <pthread.h>
#include <unistd.h>
#include <sched.h>

#define GPIO_BASE    0x01C20800
#define PWM_BASE     0x01C20C00
#define INT_BASE   0x01C20400

unsigned int *portGConfig;
unsigned int *portGData;

unsigned int *portBConfig;   
unsigned int *PWMControl;   
unsigned int *PWMPeriod;

unsigned int *TimerIRQEn;
unsigned int *TimerStatus;
unsigned int *Timer1Control;
unsigned int *Timer1Interval;
unsigned int *Timer1Current;   

unsigned int *IntVector;
unsigned int *IntBaseAddr;
unsigned int *IntProtect;
unsigned int *IntControl;
unsigned int *IntIRQP0;
unsigned int *IntIRQP1;
unsigned int *IntIRQP2;
unsigned int *IntFIQP0;
unsigned int *IntFIQP1;
unsigned int *IntFIQP2;
unsigned int *IntSel0;
unsigned int *IntSel1;
unsigned int *IntSel2;
unsigned int *IntEn0;
unsigned int *IntEn1;
unsigned int *IntEn2;
unsigned int *IntMask0;
unsigned int *IntMask1;
unsigned int *IntMask2;
unsigned int *IntResp0;
unsigned int *IntResp1;
unsigned int *IntResp2;
unsigned int *IntForce0;
unsigned int *IntForce1;
unsigned int *IntForce2;
unsigned int *IntScrPr0;
unsigned int *IntScrPr1;
unsigned int *IntScrPr2;
unsigned int *IntScrPr3;
unsigned int *IntScrPr4;
unsigned int *IntScrPr5;

static unsigned int GPIO_MMAP = 0;
static unsigned int PWM_MMAP = 0;
static unsigned int TIMER_MMAP = 0;
static unsigned int INT_MMAP = 0;

int main(void)
{

////////////////////////////_MEMORY_MAPPING_////////////////////////////

   int fd;
   unsigned int addr_start, addr_offset, pwm_offset, int_offset;
   unsigned int PageSize, PageMask;
   void *pc;

   fd = open("/dev/mem", O_RDWR);
      if(fd < 0) { perror("Unable to open /dev/mem"); }

   PageSize = sysconf(_SC_PAGESIZE);
   PageMask = (~(PageSize-1));
     
   addr_start  = GPIO_BASE &  PageMask;
   addr_offset = GPIO_BASE & ~PageMask;
   pwm_offset = PWM_BASE & ~PageMask;
   int_offset = INT_BASE & ~PageMask;
     
   pc = (void *)mmap(0, PageSize*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, addr_start);
      if(pc == MAP_FAILED) { perror("Unable to mmap file"); }
         
   GPIO_MMAP = (unsigned int)pc;
   GPIO_MMAP += addr_offset;   

   PWM_MMAP = (unsigned int)pc;
   PWM_MMAP += pwm_offset;
   
   TIMER_MMAP = PWM_MMAP;

   INT_MMAP = (unsigned int)pc;
   INT_MMAP += int_offset;
 
   close(fd);
      if(fd == -1) { perror("Unable to close file"); }

////////////////////////////_GPIO_CONFIG_////////////////////////////

   portGConfig =     (unsigned int *)(GPIO_MMAP + 0xDC);
   portGData =     (unsigned int *)(GPIO_MMAP + 0xE8);

   *portGConfig = 0x1110;      //configure port G pin 9 to output

   if (*portGData == 0x6)   *portGData = 0x200;   else   *portGData = 0x000;

////////////////////////////_PWM_CONFIG_////////////////////////////

   portBConfig =     (unsigned int *)(GPIO_MMAP + 0x24);   
   PWMControl =     (unsigned int *)(PWM_MMAP + 0x200);   
   PWMPeriod =     (unsigned int *)(PWM_MMAP + 0x204);

   *portBConfig = 0x200;      //Configure Port B pin 2 to PWM

   *PWMControl = 0x00;      //printf("PWM cleared\n");
   *PWMControl |= 0x00000020;    //printf("PWM High Level\n");
   *PWMControl |= 0x00000002;    //printf("PWM 24MHz/240 = 100kHz\n");
   *PWMControl |= 0x00000040;    //printf("PWM Gating = pass\n");
   *PWMControl |= 0x00000010;    //printf("PWM Enabled\n");

   *PWMPeriod = 0x01F30064;   //printf("PWM period 0x01F30064\n");

////////////////////////////_TIMER_1_CONFIG_////////////////////////////

   TimerIRQEn =     (unsigned int *)(TIMER_MMAP + 0x00);
   TimerStatus =     (unsigned int *)(TIMER_MMAP + 0x04);
   Timer1Control =  (unsigned int *)(TIMER_MMAP + 0x20);
   Timer1Interval = (unsigned int *)(TIMER_MMAP + 0x24);
   Timer1Current =  (unsigned int *)(TIMER_MMAP + 0x28);

   *TimerIRQEn |= 0x02;      //printf("*TimerIRQEn = 0x%x\n", *TimerIRQEn);
   *Timer1Control = 0x04;      //printf("*Timer1Control = 0x%x\n", *Timer1Control);
   *TimerStatus = 0x02;      //printf("*TimerStatus = 0x%x\n", *TimerStatus);
   *Timer1Interval = 0x16E3600;   //printf("*Timer1Interval = 0x%x\n", *Timer1Interval);
   *Timer1Current = 0x16E3600;   //printf("*Timer1Current = 0x%x\n", *Timer1Current);

   *Timer1Control = 0x05;      //printf("*Timer1Control = 0x%x\n", *Timer1Control);

////////////////////////////_INTERRUPT_REGISTERS_////////////////////////////

   IntVector =    (unsigned int *)(INT_MMAP + 0x00);   printf("*IntVector = 0x%x\n", *IntVector);
   IntBaseAddr =    (unsigned int *)(INT_MMAP + 0x04);   printf("*IntBaseAddr = 0x%x\n", *IntBaseAddr);
   IntProtect =    (unsigned int *)(INT_MMAP + 0x08);   printf("*IntProtect = 0x%x\n", *IntProtect);
   IntControl =    (unsigned int *)(INT_MMAP + 0x0C);   printf("*IntControl = 0x%x\n", *IntControl);
   IntIRQP0 =    (unsigned int *)(INT_MMAP + 0x10);   printf("*IntIRQP0 = 0x%x\n", *IntIRQP0);
   IntIRQP1 =    (unsigned int *)(INT_MMAP + 0x14);   printf("*IntIRQP1 = 0x%x\n", *IntIRQP1);
   IntIRQP2 =    (unsigned int *)(INT_MMAP + 0x18);   printf("*IntIRQP2 = 0x%x\n", *IntIRQP2);
   IntFIQP0 =    (unsigned int *)(INT_MMAP + 0x20);   printf("*IntFIQP0 = 0x%x\n", *IntFIQP0);
   IntFIQP1 =    (unsigned int *)(INT_MMAP + 0x24);   printf("*IntFIQP1 = 0x%x\n", *IntFIQP1);
   IntFIQP2 =    (unsigned int *)(INT_MMAP + 0x28);   printf("*IntFIQP2 = 0x%x\n", *IntFIQP2);
   IntSel0 =    (unsigned int *)(INT_MMAP + 0x30);   printf("*IntSel0 = 0x%x\n", *IntSel0);
   IntSel1 =    (unsigned int *)(INT_MMAP + 0x34);   printf("*IntSel1 = 0x%x\n", *IntSel1);
   IntSel2 =    (unsigned int *)(INT_MMAP + 0x38);   printf("*IntSel2 = 0x%x\n", *IntSel2);
   IntEn0 =    (unsigned int *)(INT_MMAP + 0x40);   printf("*IntEn0 = 0x%x\n", *IntEn0);
   IntEn1 =    (unsigned int *)(INT_MMAP + 0x44);   printf("*IntEn1 = 0x%x\n", *IntEn1);
   IntEn2 =    (unsigned int *)(INT_MMAP + 0x48);   printf("*IntEn2 = 0x%x\n", *IntEn2);
   IntMask0 =    (unsigned int *)(INT_MMAP + 0x50);   printf("*IntMask0 = 0x%x\n", *IntMask0);
   IntMask1 =    (unsigned int *)(INT_MMAP + 0x54);   printf("*IntMask1 = 0x%x\n", *IntMask1);
   IntMask2 =    (unsigned int *)(INT_MMAP + 0x58);   printf("*IntMask2 = 0x%x\n", *IntMask2);
   IntResp0 =    (unsigned int *)(INT_MMAP + 0x60);   printf("*IntResp0 = 0x%x\n", *IntResp0);
   IntResp1 =    (unsigned int *)(INT_MMAP + 0x64);   printf("*IntResp1 = 0x%x\n", *IntResp1);
   IntResp2 =    (unsigned int *)(INT_MMAP + 0x68);   printf("*IntResp2 = 0x%x\n", *IntResp2);
   IntForce0 =    (unsigned int *)(INT_MMAP + 0x70);   printf("*IntForce0 = 0x%x\n", *IntForce0);
   IntForce1 =    (unsigned int *)(INT_MMAP + 0x74);   printf("*IntForce1 = 0x%x\n", *IntForce1);
   IntForce2 =    (unsigned int *)(INT_MMAP + 0x78);   printf("*IntForce2 = 0x%x\n", *IntForce2);
   IntScrPr0 =    (unsigned int *)(INT_MMAP + 0x80);   printf("*IntScrPr0 = 0x%x\n", *IntScrPr0);
   IntScrPr1 =    (unsigned int *)(INT_MMAP + 0x84);   printf("*IntScrPr1 = 0x%x\n", *IntScrPr1);
   IntScrPr2 =    (unsigned int *)(INT_MMAP + 0x88);   printf("*IntScrPr2 = 0x%x\n", *IntScrPr2);
   IntScrPr3 =    (unsigned int *)(INT_MMAP + 0x8C);   printf("*IntScrPr3 = 0x%x\n", *IntScrPr3);
   IntScrPr4 =    (unsigned int *)(INT_MMAP + 0x90);   printf("*IntScrPr4 = 0x%x\n", *IntScrPr4);
   IntScrPr5 =    (unsigned int *)(INT_MMAP + 0x94);   printf("*IntScrPr5 = 0x%x\n", *IntScrPr5);

}

/////////////////////////////////////////////////////////////


In my code the timer-1 successfully works. Now I need to write a code to run when the timer-1 interrupt occurs.

I am new in interrupt code writing. I have once written an ISR for 8051. I am not sure how to write the code for Olinuxino A13 using the GCC compiler.

In other words, how do I link the timer-1 vector address, which is 0x005C, with the code I want to run.

say for example I want to Turn On and Off the on board LED (GPIO-2 Pin-9) when the timer-1 interrupt occurs.


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

if (*portGData == 0x6)   *portGData = 0x200;    else      *portGData = 0x000;

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\


Please help. Thanks.

MBR

In Linux, AFAIK, there is no way to serve interrupts from the userspace, you have to write a kernel module.

PS: If you just want to blink the LED, there is a much easier way using sunxi_led driver (see https://www.olimex.com/forum/index.php?topic=3156.msg13226#msg13226).