#: 20906 S12/OS9/68000 (OSK)
14-Apr-95 13:30:26
Sb: #20897-Install Intrpt Handler
Fm: Jost Eberbach 73502,2041
To: Taji S. Abraham 76760,2232
Hi Taji!
I have a lot of experience with the MVME162 board. Installing an interrupt
handler without using a device driver is not a problem.
The following programs is an example of how to install a timer interrupt
service routine with C. Some assembler code is required, but I think newer
versions of the Ultra C compiler provide functions that you can use instead of
the Assembler code. The lastest compiler versions even allow using floating
point instructions inside an interrupt service routine. This was always a
problem with the old versions, as the 68040 has some unimplemented floating
point instructions, which were be handled by the trap handler (CSL). The old
trap handler was not 100% reentrant. The new compiler has a new trap handler.
It can also generate code for 68040 by emulating the unimplemented instructions
in software.
If you need more help, send me an email. Maybe I can do some consulting for
you. I have developed code for several Greenspring IP-modules. I also wrote a
utility to use the onboard flash-memory, it allows you to store your
application as well as OS9 in the Flash and boot from flash-memory.
Here is the example code:
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* VMEchip2 definitions */
/* This chip is integral to the MVME162 board */
#define VMEchipBase 0xFFF40000
#ifndef _UCC
#define volatile /* the old compiler doesn't understand 'volatile' */
#endif
#ifdef DEBUG
#define volatile
#endif
typedef volatile struct vmechip {
u_int SLAVE1; /* Slave 1 address registers */
u_int SLAVE2; /* Slave 2 address registers */
u_int SLAVE1TR; /* Slave 1 address translation registers */
u_int SLAVE2TR; /* Slave 2 address translation registers */
u_int SLAVEWPSM;/* Slave write post, snoop, address modifier */
u_int MASTER1; /* Master 1 address registerS */
u_int MASTER2; /* Master 2 address registers */
u_int MASTER3; /* Master 3 address registers */
u_int MASTER4; /* Master 4 address registers */
u_int MASTERTR; /* Master address translation registers */
u_int MASTERAM; /* Master address modifier registers */
u_int GCSRETC; /* GCSR and other control bits */
u_int dum0 [7]; /* not defined yet */
u_int MCNTL; /* Prescale register */
u_int T1CMP; /* Timer 1 compare register */
u_int T1CNT; /* Timer 1 counter */
u_int T2CMP; /* Timer 2 compare register */
u_int T2CNT; /* Timer 2 counter */
u_int CNTL; /* Control registers */
u_int PRESCALER;
u_int IRQ; /* Interrupt source register */
u_int EIRQ; /* Enable Interrupt register */
u_int SETIRQ; /* Software Interrupt register*/
u_int CIRQ; /* Clear Interrupt register */
u_int ILVL1; /* Interrupt level register 1*/
u_int ILVL2; /* Interrupt level register 2*/
u_int ILVL3; /* Interrupt level register 3*/
u_int ILVL4; /* Interrupt level register 4*/
u_int VBASE; /* Vector base and I/O Control register*/
} *VMEchip;
#define VMEChip ((VMEchip)VMEchipBase) /* properly casted
constant */
/* For now, I've only provided the register definitions I've needed. */
/* Feel free to add those required, but please keep them in order of */
/* occurrance in the VMEchip. */
/* Remember : only 32bit write operations are supported by the VMEchip2 */
/* Fixed interrupt vector offsets */
#define VMEVT1 0x68 /* Timer 1 */
#define VMEVT2 0x69 /* Timer 2 */
#define SFTW0 0x78 /* Software interrupt 0 */
/*make this program system state */
_asm("_sysattr: equ 0xA001");
volatile unsigned int s_cnt, start_cnt = 0;
VMEchip vmechip = VMEChip;
#define PRIORITY 1
int _f_irq();
int irqsvc_t1();
void cleanup()
{
register procid *prc = sysglob(procid*, D_Proc);
prc->_path[0]=0;
prc->_path[1]=0;
prc->_path[2]=0;
}
char *term = "/term"; /* default terminal */
int kbhit(){
int keyboard, hit;
keyboard = open(term, 0x3);
if (_gs_rdy(keyboard)==-1) hit = 0;
else hit = 1;
close(keyboard);
return(hit);
}
main()
{
int i=0;
char *hwptr = (char *)vmechip;
char prior = PRIORITY;
register int error;
register procid *prc = sysglob(procid*, D_Proc);
/* fix up standard i/o for a system state process */
stdin -> _fd = prc->_path[0];
stdout -> _fd = prc->_path[1];
stderr -> _fd = prc->_path[2];
_from_new(stdin); _from_new(stdout); _from_new(stderr);
if (error = _f_irq((char)VMEVT1, prior, irqsvc_t1, get_global_base(),
hwptr))
exit(_errmsg(error, "Can't install timer1 interrupt service
routine.\n"));
else{
printf ("Timer1 Interrupt service routine installed!\n");
}
/* Setup VMEchip2 to produce timer interrupts */
/* |= or &= operators cannot be used on the VMEchip */
/* because the compiler might produce byte-wide write operations */
vmechip->MCNTL = (vmechip->MCNTL & 0xffffff00L) | 0x000000E7L; /* set
prescaler for 25 MHz */
vmechip->T1CMP= 1000L; /* 1 millisecond */
vmechip->T1CNT= 0L; /* clear counter */
vmechip->CNTL = vmechip->CNTL | 0x00000007L; /* enable timer1, reset on
compare */
vmechip->ILVL1 = (vmechip->ILVL1 & 0xfffffff0L) | 0x00000006L; /* set irq
level */
vmechip->ILVL3 = (vmechip->ILVL3 & 0xfffffff0L) | 0x00000006L; /* set irq
level */
vmechip->VBASE = (vmechip->VBASE & 0x007fffffL) | 0x67800000L; /* set irq
base vector, enable interrupts*/
vmechip->EIRQ = vmechip->EIRQ | 0x01000100L; /* enable timer 1 and
software0 interrupts */
/* do anything here, e.g. : */
while (!kbhit()) {
printf("ticks : %6d\n", ticks);
}
vmechip->EIRQ &= 0xfeffffef; /* disable timer 1 and software0 interrupts
*/
ipic->IP_D_INT0 = 0x00; /* disable IPIC Interrupt */
ipquad->CG[0].CHCR = 0x40; /* Interrupt disabled */
_f_irq((char)VMEVT1, prior, NULL, get_global_base(), hwptr); /*remove
ISR*/
system ("tmode pause -w=1");
cleanup();
exit(0);
}
irq_timer1(char *system_globals, register char *hwptr)
{
if (!(vmechip->IRQ & 0x01000000L)){ /* is timer1 the interrupter ?*/
return(-1); /* if not :return error */
}
vmechip->CIRQ = 0x01000000L; /* clear interrupt */
ticks++;
/* do your interrupt service here */
return(0);
}
_asm("params equ 8");
_asm("irqsv set 0");
_asm("static set 4");
_asm("port set 8");
_asm("_f_irq: link a5,#0");
_asm(" movem.l d1/a0/a2-a3,-(sp)");
_asm(" move.l irqsv+params(a5),a0");
_asm(" move.l static+params(a5),a2");
_asm(" move.l port+params(a5),a3");
_asm(" os9 F$IRQ");
_asm(" bsr.s HandleErr");
_asm(" movem.l (sp)+,d1/a0/a2-a3");
_asm(" unlk a5");
_asm(" rts");
_asm("HandleErr bcs.s HandleErr10");
_asm(" moveq.l #0,d0");
_asm(" rts");
_asm("HandleErr10 ext.l d1");
_asm(" move.l d1,d0");
_asm(" rts");
_asm("irqsvc_t1: move.l a6,-(a7)");
_asm(" move.l a6,d0");
_asm(" movea.l a2,a6");
_asm(" move.l a3,d1");
_asm(" fsave -(a7)");
_asm(" fmove.l fpsr,-(a7)");
_asm(" bsr irq_timer1");
_asm(" fmove.l (a7)+,fpsr");
_asm(" frestore (a7)+");
_asm(" move.l d0,d1");
_asm(" beq.s irq_done");
_asm(" ori.b #01,ccr");
_asm("irq_done movea.l (a7)+,a6");
_asm(" rts");
_asm("get_global_base:");
_asm(" move.l a6,d0");
_asm(" rts");
#ifdef OSK
_asm("mask_irq:");
_asm(" clr.l -(sp)");
_asm(" move.w sr2(sp)");
_asm(" move.w d0,sr");
_asm(" move.l (sp)+,d0");
_asm(" rts");
#endif
|