I have created a small test program (attached) that runs on the CY8CKit-050.
Basically I have a UDB PWM that triggers an interrupt on the terminal count and both of the compare events (which are set up to be about 1/3 and 2/3 through the period). The PWM ISR sets a pin high and also starts an ADC conversion (which itself has an ISR that drops the pin and also outputs the ADC value).
The idea is that I want to time turning on a LED with the PWM signal and then get an ADC reading while LED is lit (and also later when the LED is not lit for comparison purposes).
The issue I have is that the pin signal is raised about 3uSec (as seen on my scope) BEFORE the PWM output pin goes high. I would have expected the PWM signal to go high, THEN the ISR to trigger and THEN the code to set the pin high be executed which would ensure that the ADC sampling is started after the LED is lit.
As it stands, the processor seems to be calling the ISR and executing code before the UDB is actually raising it's output.
Is this correct order of events? Is there a way to achieve having the ISR called AFTER the PWM event?
Edit: By way of a cross-check I changed the PWM form UDB to Fixed and the issue remains.
Probably you finally found some Thiotimoline and added it to your board? ;-))
You access the LCD within your interrupt handler, which in turn will use some delays in the ms range.
I took the freedom to re-arrange the code for several reasons. Cypress goes away from making modifications within the generated files. There are the StartEx() APIs for. Newly introduced are the Macro Callbacks (see Creator Help) which allow to execute code within the original interrupt handlers without any modifications.
Coming to the point: I changed your project to run on a -059 Prototyping Kit and the output looks quite normal.
See attached logic analyzer output.
See modified project, see I could delete (you willo re-generate) all generated modules.
Thanks Bob - very helpful as always.
I must admit I'm having a bit of a hard time understanding how best to use ISRs in this environment. For example, I see you use the ADC_xxx_IRQ_StartEx function but I cannot see that listed in the API for ADC DelSig V3.2 that I'm using. I can see the xxx_IRQ_Enable and the xxx_Start (but no StartEx either). I can see them in the generated .h file (xxx_IRQ.h) but I'm not clear on when to consider the generated functions as 'private' when they are not specified in the documentation.
Is there some general principle I need to apply here or just learn each peripheral as I go.
(By the way, this is a bit of a humbling experience for me. I often given help on the Microchip forums but I see that I'm making some of the similar mistakes here that I correct others for - calling functions from within ISRs for example. A salutary lesson for me!)
As far as I can tell I have duplicated your changes and the result is still the same.
I have attached the updated archive plus two images form my scope:
- NewFile0.jpg shows the PWM trace at the top and the 'Pin 4' at the bottom
- NewFile1.jpg zooms in on the trigger (the PWM trace) and shows the 'Pin 4' trace rising about 3uSec before the leading edge of the PWM.
(While typing this I noticed that the archived code actually still contains the line to start the PWM ISR twice with the second one being the 'StartEx' version. Correcting this does not change the situation.)
Susan, so when the only differences between our two projects are the measurement ways (osc with trigger vs logic analyzer without trigger) and the results are different, I would conclude that the way we measure may cause these ambiguities.
Concerning interrupt handlers:
Of course you may call functions from within a handler. When they aren't self-written you should at least know whether they use any delay-loops and avoid them if so. The ARM interrupt system is rather flexible and is able to swallow multiple ints even at comparable high frequencies (1k ints/s and more, tested).
Because there are some circumstances where the generated files get overwritten ie. a component update, I always avoided to make changes to generated files. the StartEx() API is just like a combination of setting an own handler address and enabling the interrupt. The use of CY_ISR_PROTO and CY_ISR is only used for maintaining compatibility between PSoC3 and PSoC4/5 compilers.
The new (Creator 3.3) implementation of using callback macros allows for some more flexibility because there can be a callback without actually being in an interrupt handler.
I think I have found the time warp on my board.
The PWM component raises the TC pin (and presumably the corresponding interrupt) 4 uSec (using my clock settings) or 1 "clock" pulse before the PWM signal is changed. I'm guess in that it is being raised when the clocked counter gets to 0 and lowered when the counter is reset (back to 255 in this case) and the PWM signal goes high.
As the interrupt is connected to either the TC or 'interrupt' lines, it will therefore fire off the ISR 4 uSec before the start of the next cycle.
The (partial) solution therefore is to trigger my interrupt off the inverted TC signal (using the 'rising edge' as the 'interrupt type') and the pin is now driven high (by the ISR) a little less than 1uSec after the start of the PWM cycle.
I say 'partial' solution as I really want to get the interrupt at the start of the PWM cycle and also after the first comparator value counts down, but there are ways around that.
Thanks for the assistance