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.
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.
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!
smart-tags.cywrk_.Archive02.zip 863.7 K
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?
smart-tags.cywrk_.Archive03.zip 864.3 K
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.
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?
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..
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 :(
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 :(
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.
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.
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?
@Andy I'm not a cypress employee ;P
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.
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
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,