Forum

Please consider registering
guest

Log In Register

Register | Lost password?
Advanced Search

— Forum Scope —

  

— Match —

   

— Forum Options —

   

Minimum search word length is 4 characters - maximum search word length is 84 characters

Topic RSS
System freeze when use interrupt, while connecting USB
2017 年 10 月 08 日
16:57:04
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline

I wrote my interrupt library using Timer1 library as reference. Everything works fine except that if I connect USB, system "may" freeze and not even able to reprogram it.

Interrupt frequency I used is 100us (50us pwm and interrupt every 2 pulse), and interrupt programs consume about 40us computing time. It may freeze if I connect USB during program running (It will works for a while, may be an hour or a minute, before freeze). But it totally fine if I don't connect USB to a computer.

2017 年 10 月 13 日
17:04:30
Android_Lin
Moderator
Forum Posts: 204
Member Since:
2014 年 04 月 01 日
Offline

Hi, zerozaber,

I simulate your situation with the below code on my 86Duino One:
====================
#include "TimerOne.h"
volatile int num = 0;
void setup() {
Timer1.initialize(100); // 100us interrupt frequence
Timer1.attachInterrupt(timerIsr);
}

void loop() {
Serial.println("testing"); // send "testing" string to Serial Monitor
printf("num = %d", num); // show the value of num on my LED screen with 86Duino VGA card.
delay(10);
}

void timerIsr() {
num++;
delayMicroseconds(40); // delay 40 microseconds to simulate your situation.
}
====================
I can see the increasing num on the screen, then connect USB during program, also can see "testing" string on 86Duino Serial Monitor.
It seem works fine, and reprogram is ok, even for an hour or a minute.
I am not sure how do you know the "freeze" program if connect USB during program. If possible, briefly explain what's work in your ISR. :)

Android_Lin

2017 年 10 月 14 日
00:22:30
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline

Android_Lin said

Hi, zerozaber,

I simulate your situation with the below code on my 86Duino One:
====================
#include "TimerOne.h"
volatile int num = 0;
void setup() {
Timer1.initialize(100); // 100us interrupt frequence
Timer1.attachInterrupt(timerIsr);
}

void loop() {
Serial.println("testing"); // send "testing" string to Serial Monitor
printf("num = %d", num); // show the value of num on my LED screen with 86Duino VGA card.
delay(10);
}

void timerIsr() {
num++;
delayMicroseconds(40); // delay 40 microseconds to simulate your situation.
}
====================
I can see the increasing num on the screen, then connect USB during program, also can see "testing" string on 86Duino Serial Monitor.
It seem works fine, and reprogram is ok, even for an hour or a minute.
I am not sure how do you know the "freeze" program if connect USB during program. If possible, briefly explain what's work in your ISR. :)

Android_Lin

By freezing, the system stop and I cannot even reprogram 86duino (IDE tell me that it can't connect to 86duino) until I shut it down.

I mean that if I boot 86duino by connecting USB to PC, there is a chance that the system may freeze after running for a while. Some programs manage to run a day without freezing, some programs freeze after 20 sec or so.
Some programs that it seems to run fine, when I add more variable without using that variable, it become freezing.

I have never tried booting with other supply, let the program run, and then connect USB after.

I write my own interrupt using Timer1 as reference, but what different in my situation are...
1. I use SC_END instead of PULSE_END. I need 100us interrupt while doing 50us pwm length (interrupt every 2 pulse)
2. Interrupt function takes very long time, approx 70 us.
3. Interrupt function access MCM many times, it is designed to read 6 encoder and writing 6 pwm.

Below this is how I implement interrupt
1. HardwareInitialize(); << config crossbar, config MCM MODEREG1, mcpwm_Enable(); Everything is done inside io_DisableINT();
2. PwmInitialize(); <<initialize with 50us pwm sampling time, call io_DisableINT(); mcpwm_SetWidth, ReloadPWM, SetOutMask, SetOutPolarity, SetDeadband, ReloadOut_unsafe, SetWaveform, SetSamplCycle, SetWidth, ReloadPWM then io_RestoreINT();
3. Set pwm sample cycle (call mcpwm_SetSamplCycle)
4. attachPwmInterrupt(function) << see below

This is my attachPwmInterrupt

void attachPwmInterrupt(void (*isr)()){
disable_MCINT(0, 0);
clear_INTSTATUS(0, 0);
io_DisableINT();
isrPWM0 = NULL;
io_RestoreINT();
if(irq_InstallISR(GetMCIRQ(), pwm_isr_handler0, isrname_PWM_0) == false){
printf("irq_install fail
");
return;
}
enable_MCINT(0, 0, SC_END_INT);
io_DisableINT();
isrPWM0 = isr;//register real function to ISR function
io_RestoreINT();
}

And this is my pwm_isr_handler0

static int pwm_isr_handler0(int irq, void* data){
if((mc_inp(0, 0x04) & (SC_END_INT << 0)) == 0) return 0;
mc_outp(0, 0x04, (mc_inp(0, 0x04) & ~(0xffL<<0)));//disable INT of this handler
if(isrPWM0 != NULL) isrPWM0();
mc_outp(0, 0x04, (mc_inp(0, 0x04) & ~(0xffL<<0)) | (SC_END_INT << 0));//enable INT of this handler
return 1;
}

2017 年 10 月 17 日
20:03:00
Android_Lin
Moderator
Forum Posts: 204
Member Since:
2014 年 04 月 01 日
Offline

By freezing, the system stop and I cannot even reprogram 86duino (IDE tell me that it can't connect to 86duino) until I shut it down.
I mean that if I boot 86duino by connecting USB to PC, there is a chance that the system may freeze after running for a while. Some programs manage to run a day without freezing, some programs freeze after 20 sec or so.
Some programs that it seems to run fine, when I add more variable without using that variable, it become freezing.
I have never tried booting with other supply, let the program run, and then connect USB after.

Sorry, that is my misunderstanding, now I use your method to run my testing code and change interrupt function running time to 70us. The testing code also seems work fine.

Below this is how I implement interrupt
1. HardwareInitialize(); << config crossbar, config MCM MODEREG1, mcpwm_Enable(); Everything is done inside io_DisableINT();
2. PwmInitialize(); <<initialize with 50us pwm sampling time, call io_DisableINT(); mcpwm_SetWidth, ReloadPWM, SetOutMask, SetOutPolarity, SetDeadband, ReloadOut_unsafe, SetWaveform, SetSamplCycle, SetWidth, ReloadPWM then io_RestoreINT();
3. Set pwm sample cycle (call mcpwm_SetSamplCycle)
4. attachPwmInterrupt(function) << see below

Recommend to call the mcpwm_Enable() after all steps. If you want to call mcpwm_Enable() in Step1, remember to call mcpwm_ReadReloadPWM() to update the value of the PWM register after Step 1.

And this is my pwm_isr_handler0

The address 0x04 of PWM is interrupt status register, and it need to be cleared by writing 1 in ISR. Recommend to do as below:
mc_outp(0, 0x04, (mc_inp(0, 0x04) & ~(0xffL<<0)) | (SC_END_INT << 0));

When running isrPWM0() in ISR, the process is not be interrupted by next interrupt signal until ISR is complete, so we don't disable/enable PWM INT at start/end of isrPWM0(). If really to enable/disable PWM INT, the INT Enable Register address is 0x00 not 0x04, we can modify as below (but still remember to clear PWM Status Register):

mc_outp(0, 0x00, (mc_inp(0, 0x00) & ~(0xffL<<0)));//disable INT of this handler
mc_outp(0, 0x00, (mc_inp(0, 0x00) & ~(0xffL<<0)) | (SC_END_INT << 0));//enable INT of this handler

Note: In isrPWM0(), not to call printf(), Serial.print, or floating point operation.

2017 年 10 月 18 日
02:03:21
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline

I did calculating a lot of floating point operation in isrPWM0(), I really need to calculate floating point (and it seems to works fine, I think this is not a problem, it only freeze when connect USB to a PC)

I am not sure if clearing interrupt status register will help but I will try. However, it seems I already forgot where can I get information about register 0x00 and 0x04? It is not in MCM datasheet.

2017 年 10 月 18 日
15:22:34
Android_Lin
Moderator
Forum Posts: 204
Member Since:
2014 年 04 月 01 日
Offline

I did calculating a lot of floating point operation in isrPWM0(), I really need to calculate floating point (and it seems to works fine, I think this is not a problem, it only freeze when connect USB to a PC)

Under directory hardware\86duino\x86\cores\arduino, open the wiring.cpp, and add a parameter "IRQ_USE_FPU" to irq_Setting() :

old : irq_Setting(GetMCIRQ(), IRQ_LEVEL_TRIGGER + IRQ_DISABLE_INTR)
new : irq_Setting(GetMCIRQ(), IRQ_LEVEL_TRIGGER + IRQ_DISABLE_INTR + IRQ_USE_FPU)

If we don't add "IRQ_USE_FPU", the calculating result may be incorrect. The incorrect result may get a unstable program.
After adding "IRQ_USE_FPU", we can do floating point operation in isrPWM0(), but note that it will spend more time than integer operations.
Try to do this and see whether it improves this problem.

2017 年 10 月 18 日
17:34:05
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline

I think the problem is about clearing INT bit. Now I am testing and I will report after left it for a day.

I don't think the problem lies with having floating point calculation, but I do notice that if I try to read float or double variable which are used in INTERRUPT in main program, the result may be incorrect.

I would like to add IRQ_USE_FPU to it, but I need a way to do it in my program. I don't want to mess with internal library (I don't want to add it everytime when I download new IDE). Is there anyway?

Also, there are 2 more questions
1. You said the program will not interrupted by next signal if ISR still not completed. If interrupted is set at 100us, but first calling takes 120us, will the second interrupt be called immediately or skipped?
2.Connecting USB to PC means that there is one more interrupt inside 86Duino. Now 86Duino has two interrupts (USB and mine). I would like to know how much time the USB function consumes? And if the USB interrupts happened when my interrupt is computing, what will happened? Do I need to call io_DisableINT(); before my ISR? Should I avoid connecting USB?

2017 年 10 月 19 日
11:00:58
Android_Lin
Moderator
Forum Posts: 204
Member Since:
2014 年 04 月 01 日
Offline

I would like to add IRQ_USE_FPU to it, but I need a way to do it in my program. I don't want to mess with internal library (I don't want to add it everytime when I download new IDE). Is there anyway?

Open 86Duino IDE, select "Tools" > "Board" > "Boards Managers...", select "86Duino" in "Type" option, and install 86Duino version 3.0.1.
The version 3.0.1 provides "isrFpuEnable()" and "isrFpuDisable()" to do this, they are global function, try to use them in your program.

Also, there are 2 more questions
1. You said the program will not interrupted by next signal if ISR still not completed. If interrupted is set at 100us, but first calling takes 120us, will the second interrupt be called immediately or skipped?

The second interrupt be called immediately. (Because MCM interrupt is set as "LEVEL TRIGGER", it's interrupt signal is not skipped)

2.Connecting USB to PC means that there is one more interrupt inside 86Duino. Now 86Duino has two interrupts (USB and mine). I would like to know how much time the USB function consumes? And if the USB interrupts happened when my interrupt is computing, what will happened? Do I need to call io_DisableINT(); before my ISR? Should I avoid connecting USB?

For 86Duino, there is a priority mechanism for interrupt signals : the USB interrupt priority always is higher than MCM interrupt,
but MCM interrupt is set "IRQ_DISABLE_INTR" in irq_Setting(), means that it will not be robbed by other interrupts(include USB interrupt) before your ISR is completed, same that you call io_DisableINT().
Once your ISR is completed and exit, although the second MCM interrupt happened at same time, but USB will get higher priority to do it's things if they happen at same time. It will come back to your ISR until the USB interrupt event is completed.

2017 年 10 月 19 日
23:07:58
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline

This is not related to freezing problem.
I am interested in using linux RT image. I read TimerOne library and found that you created a new thread to read signal (which use SIF pin). Since this image is patched by Xenomai, do you plan to implement real interrupt? (With high priority)
If you are going to monitor a pin, why not observe a timer instead?

2017 年 10 月 25 日
15:41:06
Android_Lin
Moderator
Forum Posts: 204
Member Since:
2014 年 04 月 01 日
Offline
10

About the freeze, we may meet an unknown problem, it is difficult to be solved only according to the above information, a simple method helps you to debug : remove the one part of code (ex: floating operation) and run again, if result is not OK, remove another part of code (ex: encoder operation), ... remove one by one until it is not freeze, you will know where is problem.

In addition, the TimerOne library in linux RT image, it creates a new thread by calling attachInterrupt(), but the variable "pin number" passed into attachInterrupt() is 12, it is a virtual pin which tells attachInterrupt() to set thread's time and not use any SIF pin.

2017 年 10 月 26 日
17:48:55
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline
11

Freezing problems seems to be solved, but I have a new problem.

When using interrupt, FPU can be used only either in irq or in loop();
My program uses FPU a lot in irq (and I already set irq_Setting(GetMCIRQ(), IRQ_LEVEL_TRIGGER + IRQ_DISABLE_INTR + IRQ_USE_FPU)). And then I tried print value of floating point in loop() by copy in io_DisableINT(), then io_RestoreINT(); and print copied value. After run for a while, my original variable turns to NaN.
And then I tried Serial.println(copiedValue) while io_DisableINT(); and it works fine.
It seems that if I use FPU in irq, I have to disable interrupt everytime I use FPU in main loop().

Below this is a programs that my variable turns NaN
volatile double value[3]; //<<used in IRQ
volatile double valueToPrint[3]; <<//used to copy

void loop(){
io_DisableINT();
valueToPrint[0] = value[0];
valueToPrint[1] = value[1];
valueToPrint[2] = value[2];
io_RestoreINT();
Serial.println(valueToPrint[0]);
Serial.println(valueToPrint[1]);
Serial.println(valueToPrint[2]);
}
After run for a while, all of floating point variables becomes NaN

But if I call Serial.println before io_RestoreINT(), everything works fine.

2017 年 11 月 16 日
15:34:36
zerozaber
Moderator
Forum Posts: 50
Member Since:
2015 年 02 月 11 日
Offline
12

The freezing still occur after I change how I clear INT bit.

The situation which "may" occur are...
1. USB is connect (even Serial.begin is not called)
2. UART is used.

It seems that my codes may freeze if the system has more than one interrupt. I need to do everything else not using any interrupt except MCM.
Until I know how to fix this problems, I need to use UART directly (not by Serial1 Serial2). Could you teach me how I can get BaseAddress of UART register? I will use function io_outpb and other to do UART in my interrupt loops manually.

Forum Timezone: Asia/Taipei

Most Users Ever Online: 50

Currently Online:
3 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

Dinosaur: 27

leutenecker: 13

mrZagg: 10

lukeross: 8

UIdahoCIT: 8

hippy: 8

smeezekitty: 8

tomka: 8

Ekkehard: 8

Kato Gangstad: 7

Member Stats:

Guest Posters: 0

Members: 1462

Moderators: 14

Admins: 5

Forum Stats:

Groups: 2

Forums: 10

Topics: 226

Posts: 1068

Newest Members: ray9979, jay411335, Fut, futkc, veista, c12468907, a0958606079, rouan, vicky, emily860118

Moderators: Glaux: 70, uaa: 11, guigra: 16, asian55: 22, Android_Lin: 204, bcarroll: 12, cucubutter: 84, recycled-air: 12, stevemork: 16, zerozaber: 50, pongraczi: 20, George Andrews III: 56, poto: 11, garpastym: 20

Administrators: eveshih: 1, anthony: 31, viky6: 0, roboard: 135, hcl: 0