hardware-interrupt in a resource manager

Hello,

I’m writting a resource manager for a framegrabber card. If I write a test-program, which initializes the card and saves an image, it works. But if I insert the initialisation into the resource managers code, I get two errors :

The resmgr_block(ctp))-call causes an EINTR-error, which means : The call was interrupted by a signal.

The framegrabber-card throws an BT848_INT_OCERR-interrupt, which is Set when the DMA controller detects a reserved/unused opcode in the instruction sequence,or reserved/unused sync status in a SYNC instruction. In general, this includes any detected RISC instruction error.

This is the code of my resource managers main-function :

[code]main(int argc, char **argv) {
if (init_video_card()) {
// init resource manager
:
:
:

  while(1) {
    if((ctp = resmgr_block(ctp)) == NULL) {
       printf("block error: %s\n", strerror( errno ));fflush(stdout);
       return EXIT_FAILURE;
    }
    resmgr_handler(ctp);
  }
  shutdown_video_card();

} else {
printf(“error with card\n”);
}
}
[/code]

I hope someone can help me,

Tobias

This mean programs has received a signal, is there something in your program that setup signal event or signal handler?

tobiZI,

Did you write the application from scratch or are you using bttvx stuff.

I have a BT848 too and I would like to know what is already working.

I don’t know the current status of bttvx and I am looking for someone to tell me.

Further, there is another BT8x8 C++ implementation, but this one only captures a few images. Both apps/drivers don’t give me any output ;-(

Cheers,
Freddy

fmartens : I’m using the btlib-functions. I can initialize the card (sensoray modell 611), edit and save the captured pics, but not in a resource manager.

I setup sig event in the bt_bringup-function, when I initialize the card.

[code]/**

  • initializes the framegrabber card
    */
    int init_video_card() {
    dma_buffs.dmabuffer=dmabuffer;
    dma_buffs.dmabuffsize=DMABUFFSIZE;
    dma_buffs.callback=use_now;
    if (!btInit()) exit(-1);
    mydev=&bt_devices[DEVICE_NR];
    // startup device if necessary: allocate IRQ etc.[/code]
    [color=red]if (bt_bringup(mydev)){[code] btClose();
    fprintf(stderr, “Error while bt_bringup\n”);
    return 0;
    }
    bt_set_video_format(mydev, BT848_IFORM_PAL_BDGHI);
    // bt_set_video_format(mydev, BT848_IFORM_NTSC);
    // color <-> sw
    bt_switch_control_comp(mydev); // remove it if there’s no color
    if (bt_initialize_operation(mydev, &dma_buffs, PX_FLAG_COLOR)){
    bt_shutdown(mydev);
    btClose();
    fprintf(stderr, “Error while bt_initialize_operation\n”);
    return 0;
    }
    width = mydev->xsize;
    height = mydev->ysize;
    bpp = PX_PIXEL_SIZE(mydev);
    return 1;
    }

/**

  • close the framegrabber card
    */
    int shutdown_video_card() {
    bt_shutdown(mydev);
    btClose();
    return 1;
    }

main(int argc, char *argv)
{
if (init_video_card()) {
/
initialize dispatch interface /
if((dpp = dispatch_create()) == NULL) {
fprintf(stderr, “%s: Unable to allocate dispatch handle.\n”,argv[0]);
return EXIT_FAILURE;
}
/
initialize resource manager attributes /
memset(&resmgr_attr, 0, sizeof resmgr_attr);
resmgr_attr.nparts_max = 1;
resmgr_attr.msg_max_size = 2048;
/
initialize functions for handling messages /
iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
_RESMGR_IO_NFUNCS, &io_funcs);
io_funcs.read = io_read;
/
initialize attribute structure used by the device /
iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);
attr.nbytes = MAXWIDTH
MAXHEIGHTMAXBPP;
/
attach our device name /
if((id = resmgr_attach(dpp, &resmgr_attr, FRAMEGRABBER_DEVICE_NAME, _FTYPE_ANY, 0, &connect_funcs, &io_funcs, &attr)) == -1) {
fprintf(stderr, “%s: Unable to attach name.\n”, argv[0]);
return EXIT_FAILURE;
}
/
allocate a context structure /
ctp = resmgr_context_alloc(dpp);
// setup CTRL-C handler, it will set quit to true
signal(SIGINT, quit_now);
/
start the resource manager message loop */
while(!quit) {
if((ctp = resmgr_block(ctp)) == NULL) {
printf( “block error: %s\n”, strerror( errno ) );fflush(stdout);
return EXIT_FAILURE;
}
resmgr_handler(ctp);
}
shutdown_video_card();
} else {
printf(“error with card\n”);
}
}
[/code]

[code]/*

  • When a grabber is first used, it must be powered on. Dma is still
  • kept disabled, but memory mapping is enabled
    */

int bt_bringup(struct BtDevice * dev){
unsigned short cmd16;
unsigned char cmd8;
int retval, pci;
/* QNX /
struct sigevent event;
/
QNX /
if (dev->isup) return 0;
bt_set_mux(dev, dev->mux); /
couldn’t be performed at bringup /
if (dev->flags & PX_FLAG_PERSIST) return 0; /
no bringup /
/
set mux to default /
dev->mux = (dev->flags & PX_FLAG_BTONLY) ? 3 : 0;
/
enable memory */
pci = pci_attach(0);
if (pci==-1){
fprintf(stderr, “Cannot access PCI server\n”);
return -1;
}
retval=pci_present(NULL, NULL, NULL);
if (retval==-1){
fprintf(stderr, “PCI BIOS isn’t present\n”);
pci_detach(pci);
return -1;
}
if (retval!=PCI_SUCCESS) {
fprintf(stderr, “PCI failed\n”);
pci_detach(pci);
return -1;
}
pci_read_config16(dev->bus, dev->dev_func.uint, PCI_COMMAND, 1, &cmd16);
cmd16|=PCI_COMMAND_MEMORY;
pci_write_config16(dev->bus, dev->dev_func.uint, PCI_COMMAND, 1, &cmd16);
pci_read_config8(dev->bus, dev->dev_func.uint, PCI_COMMAND, 1, &cmd8);
cmd8 |= PCI_COMMAND_MASTER;
pci_write_config8(dev->bus, dev->dev_func.uint, PCI_COMMAND, 1, &cmd8);
pci_detach(pci);
dev->irq_count = 0;
if (ThreadCtl(_NTO_TCTL_IO, 0)==-1){
fprintf(stderr, “Are you root?\n”);
return -1;
}
dev->sival.sival_ptr=dev;[/code]
[color=red]SIGEV_THREAD_INIT((&event), btInterrupt, (&(dev->sival)), NULL);

[code]dev->irq_id=InterruptAttachEvent(dev->irq, &event, _NTO_INTR_FLAGS_TRK_MSK);
if ((dev->irq_id)==-1) {
fprintf(stderr, “Cannot attach IRQ%d\n”, dev->irq);
return -1;
}
dev->irq_active = dev->irq;
printf(“IRQ%d attached with id=%d\n”, dev->irq, dev->irq_id);
REG_WRITE32(dev,0,BT848_SRESET);
if (!(dev->flags & PX_FLAG_BTONLY)) {
/* PXC200-specific initialization /
bt_init_i2c(dev, 0 /
no test /);
bt_init_gpio(dev, 0);
/
Put the reference voltage to the default /
dev->refv = PX_DEFAULT_REF;
bt_set_refv(dev);
}
dev->flags &= PX_HWTYPE_FLAGS; /
Preserve those */
dev->isup = 1;
bt_set_mux(dev, dev->mux);
return 0;
}

void btInterrupt(union sigval sival){
BufferInfo * b; int i;
unsigned long status;
unsigned long tmp;
struct BtDevice * dev;

dev=(struct BtDevice *)*((struct BtDevice **)(sival.sival_ptr));
status=REG_READ32(dev, BT848_INT_STAT);
if (!(status & PX_DEFAULT_IRQ_MASK)) return; /* not mine */
dev->irq_count++;
if (status & (BT848_INT_PABORT|BT848_INT_OCERR|BT848_INT_RIPERR)) {
   if (status & (BT848_INT_OCERR)) fprintf(stderr, "btInterrupt : BT848_INT_OCERR\n"); //occurs
   InterruptUnmask(dev->irq, dev->irq_id);
   return;
}
if (status & BT848_INT_VSYNC){
   if (!(status & BT848_INT_RISCI)){
     InterruptUnmask(dev->irq, dev->irq_id);
     return;
   }
}
if (!(status & BT848_INT_RISCI)) {
  InterruptUnmask(dev->irq, dev->irq_id);
  return;
}
SyncMutexLock(&(dev->mutex));
if (dev->currentbuffer) {    
  dev->image_count++;
  dev->currentbuffer->frame = dev->image_count;
  for (b = dev->buffers, i=0; i < dev->bufferlen; b++, i++) {
    if (!((b->flags) & BFLAG_OWNED)) break;
  }
  if (i == dev->bufferlen) b = dev->currentbuffer;
  dev->currentbuffer->flags &= ~(BFLAG_OWNED | BFLAG_DMA);
  if (i < dev->bufferlen) dev->recentbuffer = dev->currentbuffer;
  b->flags |= (BFLAG_OWNED | BFLAG_DMA);
  *(dev->currentbuffer->dmanextptr) = mphys(b->dmaE  +8  );
  dev->currentbuffer = b;
  if (i < dev->bufferlen){
     dev->recentbuffer->flags |= (BFLAG_OWNED | BFLAG_USER);
     if (dev->recentbuffer->callback) dev->recentbuffer->callback(dev->recentbuffer);
  }    
}
SyncMutexUnlock(&(dev->mutex));
InterruptUnmask(dev->irq, dev->irq_id);

}[/code]

Do I have to write a special ISR, if I write a resource manager ? Or do I need multiple threads ? I hope You can help me.

Thanks, Tobias

Could you post the btlib since the linkt to the library is dead.

When I have some time, I’ll try to help.

Gimme some time.

Freddy

On another note, it’s not recommended to use SIGEV_THREAD - this creates a new thread each time an interrupt comes in, and creating a thread is not a particularly lightweight operation.

It would be MUCH better to create a thread up front, and wait for pulses…

Here’s the btlib.

And how can I do this ? I’m new to thread-programming and QNX.

Use pthread_create to create the thread. Have the thread install the interrupt handler or event. Setup the event to be of type _INTR then the thread, once everything is setup does:

while ( 1 ) {
InterruptWait();
// Do interrupt related stuff
InterruptUnmask();
}

tobiZl, is this the original btlib.c code or is this the version you changed?

Do you have the unmodified version of btlib laying around somewhere ? I tried another link to btlib on openqnx, but that one is dead. I want to try btlib on my rig too.

Lookup “Writing interrupt handler” in the QNX docs, it helps you understand interrupt handling on QNX.

Freddy

I think it’s original, but I don’t really know. I got this version from a friend, because the btlib-link was dead, when I tried to download it. I didn’t modify it. If you want, I can post the code to initialize the card and to edit and save one or more pics.

Yes,

I would like to see the initialize code. I will cleanup the btlib a little.

Freddy

Hmmm, you are using a framegrabber, I am using a pinnacle PCTV Rave.

Maybe I should go for bttvx. Phearbear, please assist ;-) cause All I see is black using bttvx, can’t change frequency.

Freddy