Jump to content
LIndigo

System hangs with SWIRQ

Recommended Posts

Hi,

 

I want to use the PCDuino as a tachometer (RPM counter) and it all works nicely except for an annoying glitch every now and then:

the pcduino completely freezes at random moments while using SWIRQ. I have simplified the code of the interrupt handler to the maximum, but nevertheless, the system will freeze after some time. The only way to start the pcDuino is pushing the reset button on the board. (or unplug power...)

 

My test environment is the following: I attached an AC motor via a rectifier (keeping only the positive signal pulses) to the PCDuino. The motor runs at a speed of 250-500 RPM, meaning between 200 and 450 irq pulses / sec.

 

I included below a minimal code sample (a single main.cpp file) that demonstrates the issue: it seems to work but eventually will freeze the machine. The code for IRQ handling comes from the arduinolibs. Note: I had to wait for >64000 pulses before the machine froze.)

 

any help is appreciated - This is the one feature I still miss to complete this project.

 

regards.

 

here the code sample:

#include <QCoreApplication>
#include <inttypes.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>

static const char *swirq_dev = "/dev/swirq";

#define SWIRQ_START     (0x201)
#define SWIRQ_STOP      (0x202)
#define SWIRQ_SETPID    (0x203)
#define SWIRQ_ENABLE    (0x204)
#define SWIRQ_DISABLE   (0x205)

typedef struct tagSwirq_Config {
    uint8_t channel;
    int mode;
    int pid;
} SWIrq_Config,*pSWIrq_Config;


void pabort(const char *s)
{
    perror(s);
    abort();
}

void attachInterrupt(void (*userFunc)(int))
{
   uint8_t interruptNum = 0;
   int ret = -1, fd = -1;
   int hwmode = 0, pid = 0;  // hwmode 0 means RISING
   SWIrq_Config irqconfig;

   if(userFunc) {
      signal(SIGUSR1, (void (*) (int))userFunc);

      pid = getpid();
      irqconfig.channel = interruptNum;
      irqconfig.mode = hwmode;
      irqconfig.pid = pid;

      fd = open(swirq_dev, O_RDONLY);
      if ( fd < 0 )
         pabort("open swirq device fail");

      ret = ioctl(fd, SWIRQ_STOP, &interruptNum);
      if (ret < 0)
         pabort("can't set SWIRQ_STOP");
      ret = ioctl(fd, SWIRQ_SETPID, &irqconfig);
      if (ret < 0)
         pabort("can't set SWIRQ_SETPID");
      ret = ioctl(fd, SWIRQ_START, &interruptNum);
      if (ret < 0)
         pabort("can't set SWIRQ_START");
      ret = ioctl(fd, SWIRQ_ENABLE, &interruptNum);
      if (ret < 0)
         pabort("can't set interrupt0 SWIRQ_ENABLE");


      printf("ch:%d, mode:%d, pid:%d \r\n", irqconfig.channel, irqconfig.mode, irqconfig.pid);
      if (fd)
         close(fd);
   }
}

void detachInterrupt()
{
    uint8_t interruptNum = 0;

    int fd = open(swirq_dev, O_RDONLY);
    if ( fd < 0 )
       pabort("open swirq device fail");

    int ret = ioctl(fd, SWIRQ_STOP, &interruptNum);
    if (ret < 0)
       pabort("can't set SWIRQ_STOP");
    ret = ioctl(fd, SWIRQ_DISABLE, &interruptNum);
    if (ret < 0)
       pabort("can't set interrupt0 SWIRQ_DISABLE");

    if (fd)
       close(fd);
}

int counter = 0;

void irq_handler(int) {
    counter++;
}

int main(int argc, char *argv[])
{
//    QCoreApplication a(argc, argv);

    attachInterrupt(irq_handler);
    time_t start = time(NULL);
    while ((time(NULL) - start) < 30*60) {
        printf("Counted: %d\n", counter);
        sleep(1);
    }
    detachInterrupt();
    //    return a.exec();
}

 

Share this post


Link to post
Share on other sites

Note: I did find reports on PCDuino freezing at very high IRQ frequencies but I am working with frequencies less than 500 hz.

Failing to count correctly (e.g. skipping some pulses) would also be a much less problematic behaviour than a full system freeze.

Share this post


Link to post
Share on other sites

I am working with ubuntu 14, I use the QT IDE, but the example does not contain anything QT specific.

It's very unpredictable when it happens - I ran some trials where it freezes within 2 minutes, sometimes it runs nice for about 15 mins and then freezes.

I tried something extra yesterday - which was to introduce pauzes in the counting: I counted in block of 1000 and pauzed for 2 sec after each block.

In 1 trial it counted to ~200 000 before freezing.

 

Since it is this random, both with higher and lower frequencies (200-500 pulses / sec) I would guess the issue is related to the moment at which an IRQ occurs (with respect to other software/drivers, ....) and the more often this SWIRQ happens, the higher the chance that this bad timing occurs.

Share this post


Link to post
Share on other sites

To answer your last question: I did not run any other process - but I did not stop any processes or drivers either.

 

If I examine the syslog, it always ends with a huge list of entries reporting the SWIRQ, nothing else. e.g.

 

May 5 19:03:55 linaro-alip kernel: [ 1671.269175] sw_keypad_irq status = 0x00000000

May 5 19:03:55 linaro-alip kernel: [ 1671.270175] sw_keypad_irq status = 0x00000000

...

The last line of these messages is typically incomplete and continue with the first event report after the reset of the system (in bold)

May 5 19:03:55 linaro-alip kernel: [ 1671.270875] sw_keypad_irqMay 5 19:03:55 linaro-alip rsyslogd: [origin software="rsyslogd" swVersion="7.4.4 .......

Share this post


Link to post
Share on other sites

A few more questions....

 

What is the input voltage from your motor and rectifier combination? Does it exceed 3v3?

 

Have you tried this with one of the ubuntu releases? 

Share this post


Link to post
Share on other sites

Hi, the voltage should remain below 3.3 but I do not have the hardware to check if a short peak could go higher. I am looking for an oscilloscoop to measure this out to get absolute certainty.

 

As mentioned I am using Ubuntu 14.

Share this post


Link to post
Share on other sites

Hi, the voltage should remain below 3.3 but I do not have the hardware to check if a short peak could go higher. I am looking for an oscilloscoop to measure this out to get absolute certainty.

 

As mentioned I am using Ubuntu 14.

 

I am moving this to the Ubuntu discussion area.

Share this post


Link to post
Share on other sites

Hi Cwilt:

 

I too seem to be having this same issue (ie: pcDuino hangs on interrupts).  I have a square wave generator running at 50 hz (50 pulses per sec), and the system runs great for about 5 minutes and then poops out.

 

I found a couple of things and if you read this, can you tell me if/did you move this discussion somewhere else.  I would like to post my findings on this effort.

 

Thanks,

HH

Share this post


Link to post
Share on other sites

Hi harthenry,

 

This is now on the Ubuntu area. The status for me is the following: I switched to a 32 bit arduino (due)  for IRQ handling, but note that not all models support it well. For control functions I am still using the PCDuino - this split of responsibilities was in fact a very handy design change for me. An alternative could be to perform polling in function of what frequencies you need to be able to detect.

 

regards,

 

LIndigo

Share this post


Link to post
Share on other sites

Lindigo:

 

You mentioned this is now on the Ubuntu area.... Do you happen to have an URL?

 

One thing I noticed with my test was with respect to heat.  When my CPU warmed up, It would run for less than 5 minutes.  I placed the pcDuino into an environmental test chamber, and took the temperature down to about 5 Degrees C (40 F).  The unit ran an hour before I shut the system down.  (perhaps coincidence????)

 

I would like to look at the "Ubuntu" area if you have an URL for that info.

 

FYI: the purpose of the interrupt is the Timer Interrupt is not as accurate as the hardware interrupts, and I need a good 50 HZ ISR.

 

Thanks,

HH

Share this post


Link to post
Share on other sites

I would prefer < 1ms.  Perhaps 500 micro(s).  My testing is the software interrupt is only good +/- 2 mSec. (contingent on what is happening in the ISR).  The issue I have found is the software ISR is accumulative.  If you start with the interrupt running every 20 mSec (and it slips), the timer restarts its "timer" after the Interrupt ISR is complete.  Therefore, you never catch back up to where you should be, you will always be off.

 

thanks for the URL

Share this post


Link to post
Share on other sites

I would prefer < 1ms.  Perhaps 500 micro(s).  My testing is the software interrupt is only good +/- 2 mSec. (contingent on what is happening in the ISR).  The issue I have found is the software ISR is accumulative.  If you start with the interrupt running every 20 mSec (and it slips), the timer restarts its "timer" after the Interrupt ISR is complete.  Therefore, you never catch back up to where you should be, you will always be off.

 

thanks for the URL

 

Which pins are you using?

Share this post


Link to post
Share on other sites

Hi CW:

 

My current frequency is 5 hz (5 pulses per second).  The pcDuino will run for about 2 minutes and then poop out.  (this is a variable time, sometimes less, sometimes more).  Please dis-regard my previous note about running for a couple hours at 5 deg C in environment test chamber.  I was looking at the "source" blinking lights (3.3 v), and not the pcDuino.  I need new glasses.

 

Tried both on pcDuino Ver 3 and the Nano.  Both come back with similar results.  My next step is to try the C++ version of this -- however, I think the issue might be hardware related and not software.

Here is the code -- I use an external Output (to pcDuino input) to perform a graceful shut down the system -- however, I never use it because the pcDuino poops out < 2min.

Edit - I am not using the PartPulse, only the Oscillator input at this time.

 

Thanks,

HH

#include <core.h>
#include <time.h> 

#define INT_MODE	  FALLING
int iPulse = 0;
int iShutDownPin = 4;
time_t rawtime;
struct tm * timeinfo;

void PartPulse()
{
  printf("PartPulse\r\n");
}

void Oscillator()
{
  iPulse ++;
  if (iPulse == 20)
  {
    iPulse = 0;
    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
    printf ( "Oscillator: %s", asctime (timeinfo) );
  }
}

void setup()
{
  pinMode(iShutDownPin, INPUT);
  attachInterrupt(0, PartPulse, INT_MODE);  // pin 2
  attachInterrupt(1, Oscillator, INT_MODE); // pin 3
}

void loop()
{
  if (digitalRead(iShutDownPin) == LOW)
  {
    detachInterrupt(0);
    detachInterrupt(1);
    exit(0);
  }
}

Share this post


Link to post
Share on other sites

Followup on this Post -- I wanted to launch my pcDuino straight to Command Prompt mode and bypass the Desktop, just in case the Desktop graphics are getting in the way, however, when I go to  -- sudo board-config.sh -- and place the bootup sequence to Command Line mode, the Command Line mode will not stick.  Continues to boot into desktop mode.

 

Is there some other way to boot only in command line mode?

Share this post


Link to post
Share on other sites

Thanks for the info, however, I tried but I do not have a lxdm.conf file.  This is what I am running:  Also, F8 is not available on startup with "this version" of the Nano

No LSB modules are available.
Distributor ID: Linaro
Description: Linaro 12.11
Release: 12.11
Codename: precise
 

Share this post


Link to post
Share on other sites

sorry -- no go -- same thing -- it lasted a little longer, however, nothing.  Perhaps a different version of the firmware for the Nano will help?

 

Edit: I am download https://s3.amazonaws.com/pcduino/Images/v3/ubuntu14/pcduino3b_nano_dd_1404.zip

 

I am trying to find a way to boot the pcDuino without the Desktop, and I am not finding it.  If you look above in this thread, I have followed a couple ideas, but no go here.  Also, I do not have the F8 key, so I am launching the config from terminal and the "boot from Command Prompt" does not stick.

 

Do you know how to boot the pcDuino straight into Command Prompt?

Share this post


Link to post
Share on other sites

Nope, that does not work -- will not stick.  Will always boot to Desktop no matter what you do.  Download is complete for Ubuntu 14.  I am in the process of installing that and will provide you with a full report once done.

Share this post


Link to post
Share on other sites

Update:  The follwoing is/was the version of firmware that came with the Nano when purchased, in addition, this is the version I have been using for all of our local and field testing:  https://s3.amazonaws.com/pcduino/Images/pcduino3nano/ubuntu/pcduino3nano_ubuntu_20140807.7z

The External Interrupts do not work with this version (however, the Timer Interrupts work just fine).

 

I have updated my Nano to this version:

https://s3.amazonaws.com/pcduino/Images/v3/ubuntu14/pcduino3b_nano_dd_1404.zip

In this version of the code, the External interrupts have been running for the past 20 minutes without issue. So far so good.  However, I do not know the difference between these 2 firmware(s).  I already have the 1st version of the firmware out in the field, and changing firmware(s) will require QA and QC processes.  If someone has a white paper on the difference between these 2 firmware(s), that would be helpful.

 

I will provide stress test details on the status of my External Interrupt test in about 10 hours.

 

Thanks,

HH

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×