Menu

serial example constantly running USBHwISR

Help
2007-01-10
2013-04-17
  • Galen Seitz

    Galen Seitz - 2007-01-10

    When I run the serial example, the code appears to be constantly entering and exiting the usb interrupt routine.  It does this roughly every 22 us.  Based on some experiments I've done, it looks like the EP_SLOW interrupt never gets cleared, despite the write to USBDevIntClr.  Is this normal?  If so, do you have any ideas about the code can be altered to prevent this.

    thanks,
    galen

     
    • Bertrik Sikken

      Bertrik Sikken - 2007-01-10

      There was someone on the LPC2000 who reported something similar to this, so this indeed looks like a real bug.

      It is to be expected that the serial port example gets a lot of interrupts, but I expect only something like max. 1 interrupt per millisecond, not every 22 us.

      The whole USB interrupt system is a bit stacked:
      1) USB interrupt in VIC
      2) USB device EP_SLOW/EP_FAST/DEV_STAT interrupt
      3) USB device endpoint interrupts
      I would not be surprised if there is something wrong there (please help out if you have experience), although I did try to follow the recommendations from the LPC2148 user manual.

       
    • Galen Seitz

      Galen Seitz - 2007-01-10

      I just spotted that message.  Here's the beginning of the thread for anyone else that is following along.

      http://tech.groups.yahoo.com/group/lpc2000/message/21597

      I think this is likely an issue with the Philips documentation(big surprise!).  Your code looks good to me.

      I added some trace code to try to determine what is going on.  The code saves DevIntSt and EpIntSt at both entry and exit to the ISR, as well as the device status if it is a status interrupt.  It also saves the endpoint status for first 16 endpoints.  Here is the output I get.  The timestamp 4672 is where the host opened the usb serial port.  I did this by starting kermit on my Linux host.
      I've trimmed the beginning data to keep this message short.  You can see that once the NAK occurs, we are unsuccessful in clearing the associated interrupt.  Thus we constantly execute the ISR.  I'm afraid we're going to need some help from Philips/NXP on this.
      Let me know if you have other ideas.

      galen

      T1TC.T1PC:        entry | exit           entry | exit
      19d0.19bf: DevIntSt 02c4|02c0, EpIntSt 00000000|00000000, dstat 00
      00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
      4672.419f: DevIntSt 02c5|02d4, EpIntSt 00000001|00000022, dstat 00
      25,00,00,00,00,10,00,00,00,00,00,00,00,00,00,00,
      4672.4754: DevIntSt 02d4|02d4, EpIntSt 00000022|00000020, dstat 00
      00,02,00,00,00,10,00,00,00,00,00,00,00,00,00,00,
      4672.4bd1: DevIntSt 02d4|02d4, EpIntSt 00000020|00000020, dstat 00
      00,00,00,00,00,10,00,00,00,00,00,00,00,00,00,00,
      4672.4f2a: DevIntSt 02d4|02d4, EpIntSt 00000020|00000020, dstat 00
      00,00,00,00,00,10,00,00,00,00,00,00,00,00,00,00,
      4672.5283: DevIntSt 02d4|02d4, EpIntSt 00000020|00000020, dstat 00
      00,00,00,00,00,10,00,00,00,00,00,00,00,00,00,00,
      4672.55dc: DevIntSt 02d4|02d4, EpIntSt 00000020|00000020, dstat 00
      00,00,00,00,00,10,00,00,00,00,00,00,00,00,00,00,
      ...

       
    • Galen Seitz

      Galen Seitz - 2007-01-11

      I've come up with a workaround for the time being.  I disabled NAK interrupts and added two functions.  I call VCOM_wake every 20 ms.  This flushes any pending output data.

      galen

      /*
      * Force handler to run if there is pending Bulk In data.
      */
      void
      VCOM_wake(void)
      {
        if (fifo_len(&txfifo))
          USBHwForceEPInt(BULK_IN_EP);
      }

      void USBHwForceEpInt(U8 bEP)
      {
          int idx;
         
          idx = EP2IDX(bEP);

          ASSERT(idx<32);

          USBEpIntSet = 1 << idx;
      }

       
    • Galen Seitz

      Galen Seitz - 2007-01-20

      I've discussed this with Philips.  We shouldn't be using NAK interrupts because when the host receives a NAK, it may immediately request data again.  This is dependent upon whether there are other devices needing the bus.  Without any other devices present, the host is constantly requesting data from the lpc.  Thus the constant processing of NAK interrupts.

      I know how to fix this, but it requires using a timer.  Would you accept a patch that uses a timer?  None of the examples currently use any timers, so I thought I should ask first.

      thanks,
      galen

       
      • Bertrik Sikken

        Bertrik Sikken - 2007-01-22

        I'm not very happy with a patch that adds a timer to the core USB code, but I find it OK if it is specific to the serial port code.

        I'd like to know exactly what is going on, I have some doubts on the current order of clearing interrupts specifically (and need to experiment with that a bit). As far as I understand, simply not clearing the OUT buffer (and thus sending a NAK) is the only way of doing flow control, but this probably keeps the interrupt asserted. I wonder how other serial port implementations tackled this problem.

         
      • Bertrik Sikken

        Bertrik Sikken - 2007-01-28

        I experimented a bit with this today. Conclusions so far:
        * the problem does not seem related to the interrupt clearing order as I thought previously
        * the host just seems to send a lot of IN packets

        I think your concept of checking the fifo at regular intervals can also be implemented using the frame interrupt (which occurs every milisecond), e.g. in the following ways:
        1) Let the bulk-in interrupt disable itself when it detects that no more data can be sent to the host (fifo is empty). The frame interrupt enables the bulk-in interrupt again.
        2) Same as 1) but disable/enable the interrupt-on-NAK feature (not the interrupt itself).
        3) Variation of your idea: interrupt-on-NAK is disabled and the frame interrupt triggers an artificial interrupt if data is available to be sent to the host.

        I tried 1) and 2). 1) does not seem to work for unknown reasons: I can disable the interrupt, but after enabling it again in the frame handler, I never get another interrupt. 2) currently works fine here.
        I think option 3) is also a good candidate but I haven't tried it yet. A nice thing about it, is that it does not rely on the interrupt-on-NAK feature at all.

         
    • Bertrik Sikken

      Bertrik Sikken - 2007-02-05

      I implemented fix number 2 (disabling interrupt-on-NAK when sending last packet and re-enabling it again on the frame interrupt). The fix is in revision 142 of the SVN archive.

      The mass storage application example also seems to suffer from the same problem (it also uses the interrupt-on-NAK feature).

      Bug report for this problem is here:
      http://sourceforge.net/tracker/index.php?func=detail&aid=1635251&group_id=160384&atid=815632

       
    • Codegrinder

      Codegrinder - 2007-02-16

      I still have trouble with fix#2.
      I need to shut USB interrupts off periodically, for a critical event that requires polling.
      As you already know, the NAK int enable was working, but the 20usec interrupt was not tolerable. I suspect that the current version method of detecting if there is no data left to be sent doesn't work reliably, at least in my application. It seems that testing the fifo for empty and then diasabling NAK, does not actually insure that the data has actually left the device. I believe an int must occur to actually carry the data away. Sometimes all the data goes, and others data is lost. My temporary work around is this:
      void UsbWaitTx(void)
      {
          enableIRQ();
          while( (USBDevIntSt & TxENDPKT) ==0);
          USBDevIntClr |= TxENDPKT;
          disableIRQ();
      }
      I call it after I send data to the USB, and want to make sure data gets out before I shut off IRQ.
      To receive data I turn the nak int off, manually, to avoid the slow transfer speed w/20usec interrupts, and turn it back on when finished receiving. I lose full duplex, but seem to get total flow control at the best speeds.

      I am no USB expert at all, this was just by some trial and error. I use a scope to monitor IRQ activity. The crux of the problem seems to be determing if there is actually any data left to send in the device, not just in the fifo. Please advise if my method is totally off the wall or there is another preffered method. It does seem to work though.

      Another possible idea:
      Wait for the fifo empty and dont disable the NAK until the first NAK, then re-enable on frame like before.
      Wouldn't that first NAK truly indicate that the device is empty?

       

Log in to post a comment.