How can i start to write an interrupt for device drivers?

dear all,
Please help me where i can start to write an interrupt for device drivers(resource manager)?

thanks,
tuyndie

In the helpviewer search for “interrupt” keyword. Then select the section that says “Writing an interrupt handler”

Dear mario,
I have ever read “Writing an Interrupt Handler”
and i started write an CAN interrupt
my code is here:
//vector interrupt number
#define HCAN_IRQ 0x2024

SIGEV_INTR_INIT(&dev->intr_event);
dev->irq = HCAN_IRQ;

//interrupt attatch
dev->iid = InterruptAttach(dev->irq, (void*) _hcan2_irq_ser, dev, 0, 0);

sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGTERM);
sa.sa_handler = exit_signal;
sa.sa_flags = 0;
sigaction(SIGTERM, &sa, NULL);

procmgr_daemon(0, PROCMGR_DAEMON_NOCLOSE);

/Start the recource manager loop/
while(1)
{
if((dev->ctp = resmgr_block(dev->ctp)) == NULL)
{
fprintf(stderr, “block error\n”);
return EXIT_FAILURE;
}
resmgr_handler(dev->ctp);
}

InterruptDetach(dev->iid);

and event function is here:

const struct sigevent *
_hcan2_irq_ser(void *arg, int iid)
{
hcan2_dev_t *dev=(hcan2_dev_t *)arg;
struct sigevent *event = NULL;
_Uint16t irr;
_Uint16t txack;
int icntr;
uint16_t whatReg = 0;

event = &dev->intr_event;    
InterruptMask(dev->irq,dev->iid);	

/* handler */
switch (dev->mode){
case CMODE_TRANSMIT:
	if ( (num_transmit == 0) || (num_transmit > HCAN_MAILBOXES_USED) || ((2*sizeof(data)) > <!-- s8) --><img src="{SMILIES_PATH}/icon_cool.gif" alt="8)" title="Cool" /><!-- s8) --> )
    break;  
      
	// transmit test frame
	dev->hcanp->mailbox[num_transmit].ctr0 = id_transmit << 4 ;		// Set Mailbox standard id	
	dev->hcanp->mailbox[num_transmit].ctr1 = 0;			// Set Mailbox Extended ID to 0
	dev->hcanp->mailbox[num_transmit].ctr2 =  (8)|(1<<8);	// Datalength and MBC = Data Frame TX and Remote Frame TX/RX
	dev->hcanp->mailbox[num_transmit].time_stamp = 0xffff;
	dev->hcanp->mailbox[num_transmit].lafm_ttt0 = 0x00;
	dev->hcanp->mailbox[num_transmit].lafm_ttt1 = 0x00;
	// Initialize mailbox
	dev->hcanp->mailbox[num_transmit].msg_data0 = data[0];
	dev->hcanp->mailbox[num_transmit].msg_data1 = data[1];
	dev->hcanp->mailbox[num_transmit].msg_data2 = data[2];
	dev->hcanp->mailbox[num_transmit].msg_data3 = data[3];
	dev->hcanp->mailbox[num_transmit].msg_data4 = data[4];
	dev->hcanp->mailbox[num_transmit].msg_data5 = data[5];
	dev->hcanp->mailbox[num_transmit].msg_data6 = data[6];
	dev->hcanp->mailbox[num_transmit].msg_data7 = data[7];	

	for( icntr = 0; icntr < 60000; icntr++ );		// need a delay of at least 23 clock cycles

	// set the transmit pending register to transmist from given mailbox 
	bitval = (1 << num_transmit);		
	dev->hcanp->txpr0 =((dev->hcanp->txpr0) | bitval);	
	atomic_set(&dev->status, HCAN_STATUS_DONE); 
	InterruptUnmask(dev->irq,dev->iid);
	return (event);
	break;
case CMODE_RECEIVE:
	if( dev->hcanp->rxpr0 != 0x0000 )
	{
		// Store where the pending flag is set
		whatReg = dev->hcanp->rxpr0;
		for( icntr = 0; icntr < 16; icntr++ )
		{
			// Find the proper flag set... and determine the Mailbox that the message is stored in
			whatReg = dev->hcanp->rxpr0 >> icntr;
						
			if( whatReg == 0x0001 )
			{
				bFlag = 1;
				break;
			}
		}
	}
	atomic_set(&dev->status, HCAN_STATUS_DONE); 
	InterruptUnmask(dev->irq,dev->iid);
	return (event);
	break;
default:	
	atomic_set(&dev->status, HCAN_STATUS_DONE);
	InterruptUnmask(dev->irq,dev->iid);
	return (event);
}
InterruptUnmask(dev->irq,dev->iid);
return (event);

}

and waiting interupt here:

while(!(dev->status & HCAN_STATUS_DONE))
{
InterruptWait(0, NULL);
fprintf(stderr,“Received interrupt \n”);
}

I have built successfully but when i debug it run into InterruptWait(0,NULL);
anh stop here …it can not return any event to exit InterruptWait(0, NULL);i don’t know why?Please help me

thanks ,
tuyndie

#define HCAN_IRQ 0x2024

Is this code running on x86. If so then IRQ number is the HARDWARE IRQ line not the IRQ vector.

Dear mario,
this code is not running on x86.
it is running on SH7770
so IRQ number is true.
Please help me
thanks,
tuyndie

Your code doesn’t show where you map to the devices memory. And also how do you get in the while loop that waits for the interrupt?

Dear mario,
where i map to the devices memory:
hcan2_dev_t dev;
uintptr_t hcan2_regs = (uintptr_t)MAP_FAILED;

// Map the HCAN registers
if ((hcan2_regs = mmap_device_io(HCAN2_REG_SIZE, HCAN2_BASE)) == (uintptr_t)MAP_FAILED)
{
perror(“HCAN error: MAP FAILED\n”);
exit(-1);
}
dev->hcanp =((hcan2_t
) hcan2_regs );

//mail box structure using only registers, no bit fields
typedef struct {
//unsure about implementation, only Big Endian illustrated in documentation
uint16_t ctr0; //H’100 + N32
uint16_t ctr1; //H’102 + N
32
uint16_t ctr2; //H’104 + N*32
uint16_t time_stamp;
uint8_t msg_data1;
uint8_t msg_data0;
uint8_t msg_data3;
uint8_t msg_data2;
uint8_t msg_data5;
uint8_t msg_data4;
uint8_t msg_data7;
uint8_t msg_data6;
uint16_t lafm_ttt0; //Local Acceptance Filter Mask 0 or Tx-Triggered
uint16_t lafm_ttt1; //Local Acceptance Filter Mask 1 or Tx-Triggered
//filler
uint16_t __filler10[6];
} reg_mailbox_t;

typedef struct {
uint16_t mcr;
uint16_t gsr;
uint16_t bcr1;
uint16_t bcr0;
uint16_t irr; //Interrupt Request Register
uint16_t imr; //Interrupt Mask Register
uint8_t rec;
uint8_t tec;
//filler
uint16_t __filler0[9];
uint16_t txpr1;
uint16_t txpr0;
//filler
uint16_t __filler1[2];
uint16_t txcr1;
uint16_t txcr0;
//filler
uint16_t __filler2[2];
uint16_t txack1;
uint16_t txack0;
//filler
uint16_t __filler3[2];
uint16_t aback1;
uint16_t aback0;
//filler
uint16_t __filler4[2];
uint16_t rxpr1;
uint16_t rxpr0;
//filler
uint16_t __filler5[2];
uint16_t rfpr1;
uint16_t rfpr0;
//filler
uint16_t __filler6[2];
//Mailbox Interrupt Registers (MBIMBR1, MBIMR2)
//Prevents the setting of IRR related to the Mailbox activities only
uint16_t mbimr1;
uint16_t mbimr0;
//filler
uint16_t __filler7[2];
uint16_t umsr1;
uint16_t umsr0;
//filler
uint16_t __filler9[82];
reg_mailbox_t mailbox[32];
} hcan2_t;

typedef struct {
iofunc_attr_t hdr;
dispatch_t *dpp;
dispatch_context_t *ctp;
int id;
hcan2_t hcanp;
volatile unsigned mode;
volatile unsigned status;
int irq; /
interrupt number /
int iid; /
interrupt ID */
struct sigevent intr_event;
}hcan2_dev_t;


#define HCAN2_BASE 0xFF908000
#define HCAN2_REG_SIZE 0x4

I used function devctl in Application to call int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg, RESMGR_OCB_T *ocb) of driver

please help me,
thanks ,
tuyndie

Shouldn’t the size specify in map_device_io be the size of the structure hcan2_t and not 4?

dear mario,
it means :
// Map the HCAN registers
if ((hcan2_regs = mmap_device_io([color=red]sizeof(hcan2_t), HCAN2_BASE)) == (uintptr_t)MAP_FAILED)
{
perror(“HCAN error: MAP FAILED\n”);
exit(-1);
}
dev->hcanp =((hcan2_t* ) hcan2_regs );

HCAN2_REG_SIZE is not 4? replace by sizeof(hcan2_t)?

regards,
tuyndie

No it’s not 4, you must specify the size of the io space that you want to access. Looking at your code it’s obvious the device has more then 4 bytes of space since you use the hscan2_t to map the io space.

Dear mario,
i understand

and i have to replace

#define HCAN2_REG_SIZE 0x4F3
//0x4F3 is maximum of The number of bytes of device I/O memory

and map again

// Map the HCAN registers
if ((hcan2_regs = mmap_device_io(HCAN2_REG_SIZE, HCAN2_BASE)) == (uintptr_t)MAP_FAILED)
{
perror(“HCAN error: MAP FAILED\n”);
exit(-1);
}
dev->hcanp =((hcan2_t* ) hcan2_regs );

is it okie?

thanks,
tuyndie

Yes. Not sure it that is the source of the problem though but that will surely help ;-)

Dear mario,

i repair mycode is here:

//file hcan2.h
#ifndef __HCAN2_H
#define __HCAN2_H

#include <sys/iofunc.h>
#include <sys/dispatch.h>

#define HCAN2_BASE 0xFF908000
#define HCAN2_REG_SIZE 0x4F3

#define SH7770_PMMR_ADDR 0xFF800010
#define SH7770_PMMR_SIZE 0x4

#define SH7770_PMSR3_ADDR 0xFF80001C
#define SH7770_PMSR3_SIZE 0x4

#define HCAN2_MEM_SIZE 16

//mail box structure using only registers, no bit fields
typedef struct {
//unsure about implementation, only Big Endian illustrated in documentation
uint16_t ctr0; //H’100 + N32
uint16_t ctr1; //H’102 + N
32
uint16_t ctr2; //H’104 + N*32
uint16_t time_stamp;
uint8_t msg_data1;
uint8_t msg_data0;
uint8_t msg_data3;
uint8_t msg_data2;
uint8_t msg_data5;
uint8_t msg_data4;
uint8_t msg_data7;
uint8_t msg_data6;
uint16_t lafm_ttt0; //Local Acceptance Filter Mask 0 or Tx-Triggered
uint16_t lafm_ttt1; //Local Acceptance Filter Mask 1 or Tx-Triggered
//filler
uint16_t __filler10[6];
} reg_mailbox_t;

typedef struct {
uint16_t mcr;
uint16_t gsr;
uint16_t bcr1;
uint16_t bcr0;
uint16_t irr; //Interrupt Request Register
uint16_t imr; //Interrupt Mask Register
uint8_t rec;
uint8_t tec;
//filler
uint16_t __filler0[9];
uint16_t txpr1;
uint16_t txpr0;
//filler
uint16_t __filler1[2];
uint16_t txcr1;
uint16_t txcr0;
//filler
uint16_t __filler2[2];
uint16_t txack1;
uint16_t txack0;
//filler
uint16_t __filler3[2];
uint16_t aback1;
uint16_t aback0;
//filler
uint16_t __filler4[2];
uint16_t rxpr1;
uint16_t rxpr0;
//filler
uint16_t __filler5[2];
uint16_t rfpr1;
uint16_t rfpr0;
//filler
uint16_t __filler6[2];
//Mailbox Interrupt Registers (MBIMBR1, MBIMR2)
//Prevents the setting of IRR related to the Mailbox activities only
uint16_t mbimr1;
uint16_t mbimr0;
//filler
uint16_t __filler7[2];
uint16_t umsr1;
uint16_t umsr0;
//filler
uint16_t __filler9[82];
reg_mailbox_t mailbox[32];
} hcan2_t;

typedef struct {
iofunc_attr_t hdr;
dispatch_t *dpp;
dispatch_context_t *ctp;
int id;
uint8_t data[8];
int id_rec;
int num_rec;
int id_tran;
int num_tran;
int bflag;
uint16_t bitval;
int icntr;
hcan2_t hcanp;
uintptr_t regbase;
unsigned physbase;
volatile unsigned mode;
volatile unsigned status;
int irq; /
interrupt number /
int iid; /
interrupt ID */
struct sigevent intr_event;
}hcan2_dev_t;

/***********************/

// Note use baudrate.xls to calculate values…
#define BCR1_790 0x3100 // TSEG 1 = Bits 15-12; TSEG2 = Bits 11 - 8;
#define BCR0_790 0x0005 // BRP = Bits 3 - 0;

#define BCR1_496 0x7200
#define BCR0_496 0x0006

#define BCR1_97 0x8300
#define BCR0_97 0x0004

#define BCR1_24 0x3100
#define BCR0_24 0x00c0

#define BCR1_12 0x8300
#define BCR0_12 0x00c0

#define BCR1_194 0x3100
#define BCR0_194 0x0030

#define HCAN_MAILBOXES_USED 16 // Number of Mailboxes used - only using 0-15 for right now

#define HCAN_IRQ 0x2024
#define CMODE_TRANSMIT 1
#define CMODE_RECEIVE 2
#define HCAN_STATUS_DONE 3

#endif

//and file hcan2.c
#include <stdlib.h>
#include <stdio.h>

#include <stdint.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <hw/inout.h>
#include <sys/resmgr.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <errno.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <devctl.h>

#include <atomic.h>
#include <sys/procmgr.h>

#include “hcan2.h”
#include “io.h”
#include “devmsg.h”
#include “hcan2_hw.h”
#include “funcs.h”

// our connect functions
resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;

// our dispatch, resource manager and iofunc variables
resmgr_attr_t rattr;

hcan2_dev_t *dev;
uintptr_t hcan2_regs = (uintptr_t)MAP_FAILED;

// getopt vars
char* progname = NULL;
int verbose = 0; // -v for verbose operation
//int adc_channel = 0; // -c the ADC channel number

char io_buf[IOBUF_SIZE] = “HCAN2 resmgr\n”;

static volatile unsigned done = 0;

static void
exit_signal(int signo)
{
atomic_set(&done, 1);
return;
}

//
// options
//
// This routine handles the command line options.
//
static void options(int argc, char* argv[])
{

}

//
// single_instance
//
// Ensure that the driver is not already running
// request a minor number of 0
// if we get it, we’re the first instantiation.
//
static void single_instance(char* resmgr_name)
{
name_attach_t* attach;

// Create a local name
if ((attach = name_attach(NULL, resmgr_name, 0)) == NULL)
{
	fprintf(stderr, "\nError: Is '%s' already started?  ", resmgr_name);
	perror("name_attach Failed");
	exit(-1);
}

if (-1 == ChannelDestroy(attach->chid))
{
	perror("ChannelDestroy failed:");
}

}

int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg, RESMGR_OCB_T *ocb);

int main(int argc, char *argv[]) {
int pathID;
char *name;
struct sigaction sa;

if (-1 == ThreadCtl(_NTO_TCTL_IO, 0)) 
{
    if (verbose)
    {
	    printf("%s: main: ThreadCtl failed\n", argv[0]);
    }
    return 0;
}
dev=(hcan2_dev_t *) malloc(sizeof(hcan2_dev_t ));
dev->regbase = (uintptr_t)MAP_FAILED;
SIGEV_INTR_INIT(&dev->intr_event);	    	
// parse the command-line options
options(argc, argv);

// make sure the driver isn't already running
if ((name = malloc(sizeof(DEV_NAME) + 1)) == NULL)
{
	fprintf(stderr, "%s: malloc failed\n", progname);
	exit(-1);
}

// sprintf(name, “%s%d”, RESMGR_NAME, adc_channel);
sprintf(name, “%s”, RESMGR_NAME);
single_instance(name);

//	allocate and initialize a dispatch structure for use by our main loop
dev->dpp = dispatch_create();
if (dev->dpp == NULL)
{
	fprintf(stderr, "%s:  couldn't dispatch_create: %s\n",
			progname, strerror (errno));
	exit(-1);
}

//
// Set up the resource manager attributes structure, we'll
// use this as a way of passing information to resmgr_attach().
// For now, we just use defaults.
//
memset(&rattr, 0, sizeof (rattr));
rattr.nparts_max = MAX_IOV_SIZE;	// max ctp->iov[] size
rattr.msg_max_size = MAX_MSG_SIZE;	// max size of a message

//
// Intialize the connect functions and I/O functions tables to
// their defaults and then override the defaults with the
// functions that we are providing.
//
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
				 _RESMGR_IO_NFUNCS, &io_funcs);

// use our own: open, read, write, and devctl
connect_funcs.open = io_open;
io_funcs.read = io_read;
io_funcs.write = io_write;
io_funcs.devctl = io_devctl;

//	set the mode to 0666 (R/W)
//	Note leading 0 for octal -------v
iofunc_attr_init(&dev->hdr, S_IFCHR | 0666, NULL, NULL);

//
//	Call resmgr_attach to register our prefix with the
//	process manager, and also to let it know about our connect
//	and I/O functions.
//
//	On error, returns -1 and errno is set.
//
sprintf(name, "%s", DEV_NAME);
dev->id= resmgr_attach(dev->dpp, &rattr, name, _FTYPE_ANY, 0,
					 &connect_funcs, &io_funcs, &dev->hdr);
if (dev->id == -1)
{
	fprintf(stderr, "%s:  couldn't attach pathname: %s\n",
		    progname, strerror(errno));
	exit(1);
}
free(name);

/*allocate a context structure*/ 
dev->ctp = resmgr_context_alloc(dev->dpp); 	

//
//	initialize the HW, map the registers and create driver structures
//
if (!hcan2_hw_init())
{
    // HW init failed
	fprintf(stderr, "%s:  hcan_hw_init failed\n", progname);
    return 0;
}
    
//Start up a thread that is dedicated to interrupt processing

// pthread_create(NULL, NULL, int_thread, NULL);
//interrupt attatch
dev->iid = InterruptAttach(dev->irq,(void*)_hcan2_irq_ser,dev,0,0);

sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGTERM);
sa.sa_handler = exit_signal;
sa.sa_flags = 0;
sigaction(SIGTERM, &sa, NULL);

procmgr_daemon(0, PROCMGR_DAEMON_NOCLOSE);



/*Start the recource manager loop*/ 
while (!done) {
    if (dev->ctp == resmgr_block(dev->ctp))
        resmgr_handler(dev->ctp);
    else if (errno != EFAULT)
        atomic_set(&done, 1);
}

InterruptDetach(dev->iid);
free(dev);

return 0;

}


//file interrupt intr.c
#include “hcan2.h”

#include <assert.h>
#include <atomic.h>
#include <string.h>
#include <time.h>

const struct sigevent *
_hcan2_irq_ser(void *arg, int iid)
{
hcan2_dev_t *dev=(hcan2_dev_t *)arg;
struct sigevent *event = NULL;
int icntr;
uint16_t whatReg = 0;

event = &dev->intr_event;    
InterruptMask(dev->irq,dev->iid);	

/* handler */
switch (dev->mode){
case CMODE_TRANSMIT:		
	// set the transmit pending register to transmist from given mailbox 
	dev->bitval= (1 << (dev->num_tran));		
	dev->hcanp->txpr0 =((dev->hcanp->txpr0) | (dev->bitval));	
	atomic_set(&dev->status, HCAN_STATUS_DONE); 
	InterruptUnmask(dev->irq,dev->iid);
	return (event);
	break;
case CMODE_RECEIVE:
	if( dev->hcanp->rxpr0 != 0x0000 )
	{
		// Store where the pending flag is set
		whatReg = dev->hcanp->rxpr0;
		for( icntr = 0; icntr < 16; icntr++ )
		{
			// Find the proper flag set... and determine the Mailbox that the message is stored in
			whatReg = dev->hcanp->rxpr0 >> icntr;
						
			if( whatReg == 0x0001 )
			{
				dev->bflag = 1;
				dev->icntr=icntr;
				break;
			}
		}
	}
	atomic_set(&dev->status, HCAN_STATUS_DONE); 
	InterruptUnmask(dev->irq,dev->iid);
	return (event);
	break;
default:	
	atomic_set(&dev->status, HCAN_STATUS_DONE);
	InterruptUnmask(dev->irq,dev->iid);
	return (event);
}
InterruptUnmask(dev->irq,dev->iid);
return (event);

}

//and io_devctl.c

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <assert.h>
#include <devctl.h>

#include “io.h”
#include “devmsg.h”
#include “funcs.h”
#include “hcan2.h”

extern hcan2_dev_t *dev;
int ret_val = 0;
int *global_integer;

int flag_rx=0;
int flag_tx=0;
int flag_data=0;
int baudrate=1;
uint8_t mode=1;

int io_devctl(resmgr_context_t *ctp, io_devctl_t *msg, RESMGR_OCB_T *ocb) {
int nbytes, status, previous;
int i;

union {
    data_t  data;
    int     data32;
    int 	data33;
    // ... other devctl types you can receive
} *rx_data;
 global_integer =(int* )malloc( sizeof(int) );
/*
 Let common code handle DCMD_ALL_* cases.
 You can do this before or after you intercept devctl's depending
 on your intentions.  Here we aren't using any pre-defined values
 so let the system ones be handled first.
*/
if ((status = iofunc_devctl_default(ctp, msg, ocb)) != _RESMGR_DEFAULT) {
    return(status);
}
status = nbytes = 0;

/*
 Note this assumes that you can fit the entire data portion of
 the devctl into one message.  In reality you should probably
 perform a MsgReadv() once you know the type of message you
 have received to suck all of the data in rather than assuming
 it all fits in the message.  We have set in our main routine
 that we'll accept a total message size of up to 2k so we
 don't worry about it in this example where we deal with ints.
*/
rx_data = _DEVCTL_DATA(msg->i);

/*
 Three examples of devctl operations.
 SET: Setting a value (int) in the server
 GET: Getting a value (int) from the server
 SETGET: Setting a new value and returning with the previous value
*/
switch (msg->i.dcmd) {
case MY_DEVCTL_SETVAL:     	
	global_integer = rx_data->data32;
    nbytes = 0;
    if(flag_rx==0)
    {        	 	
    	set_mode();
    	set_baud_rate();    	
    	dev->mode=CMODE_RECEIVE;
    	dev->num_rec=global_integer;      	
    	dev->bflag=0;
    	flag_rx++;	        
    }
    else
    {          	
   		dev->id_rec=global_integer;   
   		dev->hcanp->imr = 0x0000;		// interrupts will generate IRQ
		fprintf(stderr,"imr= 0x%04x \n",dev->hcanp->imr);     
        [color=red]while(!(dev->status & HCAN_STATUS_DONE)) 
        {	        	
        	InterruptWait(0, NULL);	
        	printdata();
			printf("Received interrupt\n");
        }
     	flag_rx=0; 	        
    }        
    break;

case MY_DEVCTL_GETVAL:  
	global_integer = rx_data->data32;
    nbytes = 0;               
    break;        
case MY_DEVCTL_SETGET: 
	previous = global_integer; 
    global_integer = rx_data->data.tx;        
    nbytes = 0;
    if(flag_tx==0)
    {        		        	    	
    	dev->num_tran=global_integer;     	
        flag_tx++;	        
    }
    else
    {    
   		dev->id_tran=global_integer;       		        
        flag_tx=0;  	        	          	
    }        
    rx_data->data.rx = previous;        //Overwrites tx data
    nbytes = sizeof(rx_data->data.rx);
    break;
case MY_DEVCTL_SETGETVAL: 
	
	previous = global_integer; 
	switch (flag_data)
	{
		case 0:
 			set_mode();
			set_baud_rate();    
			dev->mode=CMODE_TRANSMIT;
			global_integer = rx_data->data.x;		        
	        dev->data[0]=global_integer ;    
			flag_data++;
			break;
		case 1:
			global_integer = rx_data->data.x;
	        dev->data[1]=global_integer ;    
			flag_data++;
			break;
		case 2:
			global_integer = rx_data->data.x;
	        dev->data[2]=global_integer ;    
			flag_data++;
			break;
		case 3:
			global_integer = rx_data->data.x;
	        dev->data[3]=global_integer ;    
			flag_data++;
			break;
		case 4:
			global_integer = rx_data->data.x;
	        dev->data[4]=global_integer ;    
			flag_data++;
			break;
		case 5:
			global_integer = rx_data->data.x;
	        dev->data[5]=global_integer ;    
	        fprintf(stderr,"data[5]= 0x%04x \n",dev->data[5]);	
			flag_data++;
			break;
		case 6:
			global_integer = rx_data->data.x;
	        dev->data[6]=global_integer ;  
	        fprintf(stderr,"data[6]= 0x%04x \n",dev->data[6]);	  
			flag_data++;
			break;
		case 7:
			global_integer = rx_data->data.x;
	        dev->data[7]=global_integer ;    
			fprintf(stderr,"data[7]= 0x%04x \n",dev->data[7]);			
			flag_data=0; 	
			transmit();
			fprintf(stderr,"imr= 0x%04x \n",dev->hcanp->imr);			
		   [color=red] while(!(dev->status & HCAN_STATUS_DONE)) 
			{ 					
				InterruptWait(0, NULL);	
				fprintf(stderr,"Received interrupt \n");
			} 				  
			break; 
		default:
			break;		
	}        	        	    	
    rx_data->data.rx = previous;        //Overwrites tx data
    nbytes = sizeof(rx_data->data.rx);
    break;
case MY_DEVCTL_SETGETMODE:
	previous = global_integer;
	global_integer = rx_data->data.mode;
	mode=global_integer;    	  	    	    
 	rx_data->data.rx = previous;        //Overwrites tx data
    nbytes = sizeof(rx_data->data.rx);	
	break;
case MY_DEVCTL_SETGETRATE:
	previous = global_integer;
	global_integer = rx_data->data.baudrate;
	baudrate=global_integer; 
	rx_data->data.rx = previous;        //Overwrites tx data
    nbytes = sizeof(rx_data->data.rx);    		
	break;
default:
    return(ENOSYS); 
}

/* Clear the return message ... note we saved our data _after_ this */
memset(&msg->o, 0, sizeof(msg->o));

/*
 If you wanted to pass something different to the return
 field of the devctl() you could do it through this member.
*/
msg->o.ret_val = status;

/* Indicate the number of bytes and return the message */
msg->o.nbytes = nbytes;
return(_RESMGR_PTR(ctp, &msg->o, sizeof(msg->o) + nbytes));

}

//and map IO device here
dev->physbase=HCAN2_BASE;
dev->irq = HCAN_IRQ;
// Map the HCAN registers
if ((dev->regbase = mmap_device_io(HCAN2_REG_SIZE,dev->physbase)) == (uintptr_t)MAP_FAILED)
{
perror(“HCAN error: MAP FAILED\n”);
exit(-1);
}
dev->hcanp =((hcan2_t* ) dev->regbase );

but when i transmit from application .it run here
while(!(dev->status & HCAN_STATUS_DONE))
{
InterruptWait(0, NULL);
fprintf(stderr,“Received interrupt \n”);
}
and stop .
i don’t know why it can not run file intc.c:
const struct sigevent *
_hcan2_irq_ser(void *arg, int iid)

to return any event.

can you help me?
thanks,
tuyndie

Sorry code is too long for me to help you in the context of this forum.

dear mario,
when i run :
the hardware announce:
“Out of interrupt events!”

how can i do?
thanks,
tuyndie

I think it mean the interrupt handler is generating more event then what main program is dealing with (more interrupt then InterruptWait)

By the way why are you masking / unmasking the interrupt in the handler?

Dear mario,
in my code:

dev->irq = HCAN_IRQ;

#define HCAN_IRQ 0x2024

please help me to calculate number interrupt= 0x2024
i really don’t know how to calculate this number?(0x2024)
thanks ,
tuyndie

Dear mario,

in my code:

dev->irq = HCAN_IRQ;

#define HCAN_IRQ 0x2024

and dev->irq gets passed to
dev->iid = InterruptAttach(dev->irq, (void*) _hcan2_irq_ser, &dev,sizeof(dev), 0);

please help me how to calculate this number interrupt of device which This value gets passed to InterruptAttach*() functions.

thanks very much,
tuyndie

Sorry never worked with SH processors

Thanks mario :slight_smile: