External interrupt handling

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

I have a custom board with an accelerometer that generates interrupts when movement is detected.

   

The part INT pin  is configured for open drain and active low.

   

I have an ISR component and the input pin configured in the project. 

   

The pin is connected to the correct port in the Pins window, according ty my schematics.

   

I do call ISR_StartEx and pass it my ISR handler.

   

The ISR gets called multiple times on startup ( even without any movement ) but after several seconds it stops and never gets called again

   

Verified with the part support that it is correctly configured to generate interrupts So it must be something on the PRoC side in the setup of the ISR component or the pin.

   

Attached is the screenshot of the pin configuration.

   

Your help is much appreciated.

   

Thank you

0 Likes
1 Solution
Anonymous
Not applicable

The variable assignment in Acc_ISR is a leftover from my experiments, the value is not used.

   

The number of times the interrupt fires is random. 11 is just one of the values. I saw 10, 20 etc. So it is some sort of a timing issue between the BLE and my part. At this point I decided to move on and use a watchdog timer instead. Since the part  raises the interrupt every 650 ms anyway,  a WDT is a suitable workaround. I may lose a reading or two from the part, but that's not crucial to my application

   

Thank you I really appreciate your help

   

Andy

View solution in original post

0 Likes
17 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Andy, can you please post your complete project or a shortened version that shows the error so that we all can have a look at all of your settings. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Depending on how you configure your interrupt pin: If you set it to Level- interrupt, that would explain why it fires for a time, but then stops after a while? Otherwise, if you correctly configured the pin to interrupt on a falling-edge and the accelerometer does a pulse by pulling the output Low for a clock pulse, then I would expect it to work fine.

   

Another thing to check is that you are clearing the interrupt for the pin when handling the ISR (I don't remember if the ISR routine does it automatically or not); If it isn't cleared, then that would cause back-to-back interrupts as you are seeing.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Attached is the project that sets up and handles the interrupt for the accelerometer . I've been playing with pin configuration and in the current one I do get the orientation interrupt correctly i.e only when the device orientation changes. However the  data ready (i.e movement detected) interrupt fires constantly 

   

This could be the part issue , but I want to make sure that the  pin is configured  correctly. I do call clear interrupt routine in the ISR ( function Acc_ISR() in mma865x.c)

   

Thank you for all your help!

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Update on the interrupt issue

   

Interrupts in the project in the previous post work as designed. The orientation interrupt fires only when device's orientation changes. The "data ready" interrupt fires constantly because the part samples constantly and just signals that it has data. So that's all as designed.

   

However there is still a problem. When I added a  BLE handler routine and call CyBle_GappStartAdvertisement() on CYBLE_EVT_STACK_ON, the accelerometer interrupt gets messed up

   

With CyBle_GappStartAdvertisement function commented out this is what I see ( and this is what I expect ) 

   

-Stop at a breakpoint  in the ISR (Acc_ISR() in mma865x.c)

   

-Stop at a  breakpoint where the data is being read. (ReadMovementData() in mma865x.c) When the device moves the data changes. This happens at 1 second interval as the part reads the data and raises the interrupt

   

-Stop at a breakpoint where the orientation change is handled. (line 265 in mma865x,c)  Happens only when device orientation changes

   

When CyBle_GappStartAdvertisement() is called on CYBLE_EVT_STACK_ON:

   

Execution never stops at more than one breakpoint 

   

The data never changes even though the part is moved

   

I tried to play with the order of initialization i.e initialize the part after the CYBLE_EVT_STACK_ON event - that did not help

   

Any suggestions what the problem is and how to fix it?

   

Thank you

   

Andy

0 Likes
Anonymous
Not applicable

Fyi: When you set a breakpoint, the peripherals (Accel, I2C, BLE) don't stop running while the CPU is halted, and thus the interrupts can be messed up by breaking while debugging if you are not aware of what peripherals are running/doing.

   

Looking at the code, it seems as if the Accelerometer interrupts are handled be the generated code to buffer data, which you then poll and read in main-loop. I would suggest messing with the interrupt priorities and see if setting the accelerometer to higher priority (lower number than the BLESS interrupt) to see if it is just unable to fire the interrupt. If you can verify that it is working without breakpoints, that would be the best as the breakpoints will cause all of the interrupt flags to be set while the CPU is halted in realtime.

   

One workaround is to set the CyEnterCriticalSection() and CyExitCriticalSection() before and after the location you want to break on; It won't prevent peripheral operation iirc, but it will at least prevent flags changing/interrupting while the CPU is halted between those routines, allowing you to get by with debug points easier.

0 Likes
Anonymous
Not applicable

Changing interrupt priority did not help, Verified that the data does not get updated. I have a service that I can connect to and dump real time  accelerometer data. When I do that the data is the same even though I'm moving the part. If I poll instead of using interrupts, the data gets updated just fine.So I'm stuck 😞

   

PS. Is my pin configuration OK?

   

PS2 

   

Given the fact that the data ready interrupt fires every second anyway, maybe I should just read the data on a 1 second timer.. just thinking out loud..

0 Likes
Anonymous
Not applicable

Fyi: There is a method to updating the advertisement data. See this thread for details/link to example project(s): http://www.cypress.com/forum/psoc-4-ble/updating-advertising-packet-real-time-data

   

Keep in mind that variables accessed from interrupt routines need to be declared as volatile, otherwise they will cause issues.

   

When you say service you connect to, do you mean a BLE service?

   

PS: Your pin configuration looks fine assuming the hardware matches 😉

   

PS2: If you know the data rate/sampling you want, then doing it with polling will probably work just as well as trying to debug/implement interrupts. Interrupts are inherently "multithreaded" in nature, and thus can cause alot of issues 😞

0 Likes
Anonymous
Not applicable

Thank you I'm aware of that, portions of my code are based on the Dynamic Broadcaster project.

   

The service is a BLE service ,yes. 

   

Good point about the volatile variable.Unfortunately that did not help 😞

0 Likes
Anonymous
Not applicable

For the interrupt mechanism, are you setting the StartEx(Acc_ISR) to register a callback for handling the accelerometer interrupts? I don't see it in the code, but I figured the generated code for the component was handling it. If not, that could be why?

   

If you can, try to get it working with just the accelerometer interrupting and putting data into a buffer/variables; That way, once you are sure the interrupts for the accelerometer are working properly, you can start transferring the data to the BLE database to send to the remote device.

0 Likes
Anonymous
Not applicable

Yes, it's at the very end of MMA865_Init() function

   

The sample I gave you does not include all the code  because some of it is proprietary , so I cannot just post on the open forum. In the complete project the data collected by the sensor is copied into the advertising packet. When I examine the packet in CySmart ( and other tools I'm using ) the accelerometer data does not change when the device moves. If I use the polling mechanism it does.

   

If you're a Cypress employee, I'd be glad to send you the whole project - just let me know how I can do it privately.

   

Thank you

   

Andy

0 Likes
Anonymous
Not applicable

Another independent verification that the interrupt stops firing.

   

Added a global volatile uint64 asr_count variable that is incremented every time the ISR is called. Let the device run for 10 minutes and then put a breakpoint in the main loop to examine the value of the asr_count.. Since the interrupt fires every second I was expecting to see the asr_count to be around 600 but it is stuck at 10.  So the interrupt fires for the first 10 seconds and then stops. Ideas? 

0 Likes
Anonymous
Not applicable

@Andy I'm not a cypress employee 😜

   

But, I don't need to see the code. I can work with general-design to help you at least be able to find it on your own 🙂

   

For updating the data that cysmart sees, keep in mind that you have to write to the GATT-DB on the BLESS system using the API call to set new data for the BLE connection to request from the cysmart dongle. Since it works for "polling", I'll assume you have that figured out 🙂

   

Under the mma865x.c, function Acc_ISR(), I'm confused by the ret value that you set/modify, but then fail to use in any way? The compiler might be optimizing away the ret = Acc_Isw_ClearInterrupt(); line. Maybe just replace it with Acc_Isw_ClearInterrupt(); instead?

   

At this point though, I don't see any red flags that stand out for what is going wrong. Maybe try adding a breakpoint for when the interrupt hits a count of 11 or 10 to see what happens on the "last interrupt"?

   

If the code is working at the beginning, then it must be failing later due to: A counter, a timer, or some sort of timing issue.

0 Likes
Anonymous
Not applicable

The variable assignment in Acc_ISR is a leftover from my experiments, the value is not used.

   

The number of times the interrupt fires is random. 11 is just one of the values. I saw 10, 20 etc. So it is some sort of a timing issue between the BLE and my part. At this point I decided to move on and use a watchdog timer instead. Since the part  raises the interrupt every 650 ms anyway,  a WDT is a suitable workaround. I may lose a reading or two from the part, but that's not crucial to my application

   

Thank you I really appreciate your help

   

Andy

0 Likes
Anonymous
Not applicable

Hmm, yeah that sounds like a timing issue 😞

   

(The worst kind of bug lol)

   

Well, WDT is indeed a good workaround for that. Too bad we can't figure out the issue. Generally, when I run into timing issues, I re-examine the ISR routines to see if they are too bloated, double check timing routines/procedures, and then if all of that fails, I implement a debug routine to see if I can get it to fire consistently by triggering bits/bytes. But, it's whatever now.

   

Glad you have a solution to it! Good luck,

   

Pratt

0 Likes
Anonymous
Not applicable

Thank you!

   

On to the next problem 🙂

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Andy, there are no problems, only solutions you haven't found yet ;-))

   

 

   

Bob

0 Likes
Anonymous
Not applicable

That's what I meant 🙂
Thank you Bob and Pratt

   

You guys have been a great help

   

I'm sure you'll hear from me again 🙂

   

Andy

0 Likes