Got an unscheduled requirement....
When I designed another of my little embedded-controller boards last year, I was assured that there was only one pulse-train input to be monitored, and that checking the frequency, pulse width, and duty cycle of another signal would be the responsibility of another board in the system.
You know what comes next, right?
Yup. Many moons later, my board not including an FPGA for handling high-speed measurements, and it turns out that the other board isn't quite up to the task.
So... gotta do some cutting & patching to reroute an unused input to a pair of the LPC2387's pulse-capture inputs. The only ones available are on Timer 0, which means I can't just take control of the raw hardware: it's used by the system timer.
First off, let's try the naïve approach! AGROS has a pulse-capture handler. Configure one input for interval, and the other for pulse width, and code up simple event handlers to be called on each pulse.
Turns out there are Issues with pulse widths less than about 15 μs, but (assuming reasonably constant pulse trains) there's an easy workaround. That being fixed, all's well until the pulse rate gets a bit north of 30 KHz, and then everything falls apart.
Well... the event-capture system was designed for convenience, and for pulse rates of a few hundred Hz or so: think RC servo inputs, tachometers, and the like. On each timer event, we have the interrupt, basic processing, then event dispatching (allocate memory, fill in event structure, search system table for any handlers claiming events of this type, call the handler(s), free memory, exit through the scheduler). That we can't do this much more than 60,000 times per second on a 72 MHz processor, while still doing useful work and occasionally running the low-priority task that feeds the watchdog timer? Not surprising.
But, 30 KHz is rather less than the frequency range of interest, so now I need to come up with a fix that bypasses the lovely shiny event-handling system, and just handles the interrupts locally. Eminently do-able, I think, but not exactly clean.
Update: simply patching a cut-down and customized capture handler into the two table slots in question gets the maximum frequency up to 50 KHz, which is plenty... though for some reason the width capture isn't happening; I may have a wrong case somewhere.
But wait! Since all Timer 0 interrupt activity goes through a single vector, and the wrapper selected is "reschedule always"... every smegging interrupt-generating event is causing the task scheduler to run, which is supposed to happen at 1 KHz, or "whenever something interesting happens."
So, aside from fixing whatever's not handling the pulse width correctly, I need to change the system-timer driver so that only the Match 0.0 event forces rescheduling, and others are conditional.
(When I get around to porting AGROS to the Cortex M family, I'll move the system-timer functionality to the dedicated ticky-timer that's included for the purpose. ARM7 doesn't have that, so I've been using one of the general-purpose timer channels.)
Recent Comments