Author Topic: using the GPT inputs  (Read 26684 times)

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
using the GPT inputs
« on: October 27, 2008, 12:47:06 PM »
Hi Mark,
  I want to use the GPT module for input capture, what is the best way to do this within utasker?

Thanks
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #1 on: October 27, 2008, 01:14:12 PM »
Hi Neil

At the time of writing there is not support for the general purpose timer module in the M5223X in the uTasker project (apart from the register and bit definitions in M5223x.h).

This module is however fairly similar to the GPT module in the MC9S12NE64. Using that module I have programmed PWM outputs but not actually used the input capture function.

I am working on the M522XX project today (verifying support for a new SPI FLASH chip from SST) so will quickly add a GPT interface and see whether I can do an input capture. I will send you any resulting code, assuming that it proves successful.

Can you give a quick description of the exact use that you require?

Regards

Mark



Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #2 on: October 27, 2008, 05:46:50 PM »
Hi Mark,
  I basically want to read time intervals between pulses (to work out frequency). I know I can use a timer between basic interupts, but would like to use the deticated module.

Thanks
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #3 on: October 27, 2008, 09:02:29 PM »
Hi Neil

Thanks. I will look at this use in more details:

I think that the advantage of the capture inputs in this case is that the edge will directly latch the timer value so that there is no 'jitter' due to interrupt response delays; in the case of interrupts the timer will be free running and its capture value determined also by the IRQ interrupt response time to read the timer value.
A limit to the frequency being measured would be the interrupt processing between two edges - the first interrupt will read the latched value and restart the measurement. If the second edge arrives before the measurement can be restarted it will be missed and hence the measurement will be wrong.
An idea to measure very fast 'pulses' would be to connect the pulse input to two capture inputs, where one latches a rising edge and the other a falling edge. This will allow accurate pulse widths to be recorded without any difficulties with interrupt reaction time limits. Assuming a square wave input is 50/50 mark-space then this would also allow measurement of high frequencies with high accuracy.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #4 on: October 29, 2008, 11:06:06 AM »
Hi Mark,
 Thanks for the reply. I agree this is the best way to read high frequencies, and I can use 2 of the GPT for this, and also have another input with a lower frequency in which the last channel would be used for this.

Can you please let me know when this will be available?

Many thanks
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #5 on: October 29, 2008, 12:17:12 PM »
Hi Neil

I have started working on this and a first version should be ready quite soon (I had some difficulties with a new SPI FLASH chip [older version needed some different commands which I hadn't noticed] which lost me some time...).

I have defined an interface where the user can pass a pointer to an array, with its length, and the capture function will first fill the array with the defined number of time samples before calling the application - this will allow the application to average out over several periods if it wants but can still be used with just one sample if this is adequate.

Since the timers are 16 bit I will also support (optional) overflow counting to extend samples to 32bit, allowing measuring much larger time intervals.

The first version will do only the capture function and afterwards can be extended with waveform generation and pulse accumulation options.

Regards

Mark

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #6 on: October 30, 2008, 12:55:49 AM »
Hi Neil

I have just tested a first version of GPT capture support. I will send you the new files so that you can integrate the new parts and try them out in your project. Here is a short guide to using the first implementation:

Step 1: Activate the GPT support in the project (driver) - in app_hw_m5223x.h
#define SUPPORT_GENERAL_PURPOSE_TIMER
and optionally
#define GPT_EXTENDED_COUNTER                                         // extend the general purpose timer capture value to 32bits using overflow interrupt

Since the GPT is only 16 bits in width it will overflow after max. 280ms at 60MHz - using maximum prescaler value. In order to increase this maximum capture time the overflow interrupt is automatically used to add a software counter (incremented on each timer overflow) which extends the effective width to 32 bits and so the maximum period to much larger values (up to about 5 hours if my calculations are correct - again with highest prescaler setting or 128).

Step 2: configure and start the capture process


static void fnConfigure_GPT(void)
{
    GPTIMER_SETUP gptimer_setup;                                         // interrupt configuration parameters
    gptimer_setup.int_type = GPT_TIMER_INTERRUPT;
    gptimer_setup.int_handler = gptimer_int;
    gptimer_setup.channel = 0;                                           // general purpose timer channel 1
    gptimer_setup.int_priority = GPTIMER0_INTERRUPT_PRIORITY;            // define interrupt priority
    gptimer_setup.mode = (GPT_CAPTURE_FALLING_EDGE | ENABLE_INPUT_PULLUP | GPT_INTERNAL_CLOCK | GPT_PRESCALE_16); // set up capture mode and define the timer clock
                                                                         // (in this example system clock / 2 / 16 = 1.875MHz with 60MHz: GTP timer overflows at 34.95ms but longer periods can be recorded using the extended option GPT_EXTENDED_COUNTER)
    gptimer_setup.usCaptureCount = GPT_CAPTURES;                         // request this many capture values to be recorded before calling our interrupt
    gptimer_setup.capture_list = ulCaptureList;                          // the capture list for saving to
    fnConfigureInterrupt((void *)&gptimer_setup);                        // enter interrupt for DMA timer test
}


The number of samples is defined in gptimer_setup.usCaptureCount and a pointer to a sample list is entered gptimer_setup.capture_list
Eg. for 5 samples the following can be used:

#define GPT_CAPTURES     5
static unsigned long ulCaptureList[GPT_CAPTURES];                    // make space for capture values


Note that you need to set up the timers base frequency which is the system clock/2 divided by a prescaler of 1..128 in powers of 2 (1,2,4 etc.)). The prescaler value most suited depends on the resolution required and the largest period to be measured. When GPT_EXTENDED_COUNTER is enabled the driver will be handling an overflow interrupt at a rate of once every 2.18ms (prescaler 1) up to 279ms with maximum prescaler (assuming 60MHz system clock).

The example shows capturing on falling edges but rising edges can be defined, or both edges. A list of mode settings can be found in M5223x.h.
Also a single sample can be programmed using the value 1.

Step 3:
Define the handler on completion (this is an interrupt call-back which only occurs after all defined samples have been recorded). The timer module is completely powered down if no more captures are open and can then be reconfigured for further work if required.

This is my test routine which simply wakes the local task to start analysis of the collected data:

static void gptimer_int(void)
{
    fnInterruptMessage(OWN_TASK, CAPTURE_COMPLETE_EVENT);
}



The data can be printed out as follows:
            case CAPTURE_COMPLETE_EVENT:
                {
                    int i = 0;
                    fnDebugMsg("Capture complete\r\n");
                    fnDebugMsg("================\r\n");
                    while (i < GPT_CAPTURES) {                           // list the capture samples
                        fnDebugHex(ulCaptureList, (WITH_LEADIN | sizeof(ulCaptureList)));
                        i++;
                        fnDebugMsg("\r\n");
                    }
                }
                break;


Here's an example of a few quite fast edges:

#Capture complete
================
0x07022abf
0x07022af7
0x0707a2d9
0x0707a2e1
0x0707a2f7


Although I haven't tested the following yet, it should be possible to have multiple capture channels operating at the same time. Note, when setting up a further channel the mode flag GPT_NO_CLOCK_CONFIGURATION can be passed to avoid basic timer configurations, like prescaler, being modified.

It should also be possible to restart captures, whether terminated or not.

I modified the uTasker simulator to allow basic testing of the operation. By clicking on the port configured as capture input, the interrupts and handling routines can be verified. Of course the resolution in the simulator doesn't match the hardware so probably you will want move directly to the target to try out your real signals...

The present implementation state assumed only capture input use. The module can be extended to perform also output control and pulse accumulator operation. However the other uses can restrict the capture mode operation: for example the timer reset can be controlled by other count matches when generating waveforms and the main timer counter can also be clocked from pulse accumulator inputs. Such uses will make it rather difficult to mix together with the input capture operation and thus require a basic understanding of the limitations for real use. For the moment the capture-only support is otherwise unrestricted so see how it goes!

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #7 on: December 12, 2008, 06:15:21 PM »
Hi Mark,
  I got the input capture to work, thanks.

I used the above settings, apart from the ENABLE_PULL_UP, as I am driving the pin through a mosfet, with a pulldown on the drain going to the GPT0 pin.

1. In the gptimer_int(void) routine I placed the code for displaying the results, instead of having the line 'fnInterruptMessage(OWN_TASK, CAPTURE_COMPLETE_EVENT)', and works. Can you see a problem on doing this instead of calling a task?

2. I have tied the pulse to the 1Hz output of the RTC, and have checked this on the scope. The results are:
0x000e4ef4
0x000e4ef7
0x000e4efd
0x000e4f02
0x000e4f07

As in the example, it is a 1.875MHz clock, and captures on the folling edge, this seems to be 0.5 seconds instead of 1.
I have enabled GPT_EXTENDED_COUNTER.

Could this be capturing on both edges?

Regards
Neil
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #8 on: December 12, 2008, 09:58:12 PM »
Hi Neil

There is no real problem in displaying the results directly in interrupt callback (just remember that it is in an interrupt routine and will this be blocking other interrupts for the duration - the more it does, the longer it blocks).

As for the capture time stamps, I don't understand these. If you use a 1Hz test signal (and it is capturing falling edges) with the clock running at 1.875MHz there should be 1s between each sample.

The first sample occurs at 0x000e4ef4 so the next should occur around 0x002a3b2c (using extended counter). But the samples in your list are very fast (2,6,5,5 clocks between them or around 2us).

Can you explain this?

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #9 on: December 12, 2008, 10:10:59 PM »
Hi Mark,
  I see, I will call a task so the interupt isnt blocking, I never thought about that, cheers.

I dont understand it either, I measured it on the scope and looks fine at 1Hz. The values seem to represent 0.5 seconds why is this?
And your right, it seems to increase by 2us (approx) between readings, I cant think why it should happen as its a steady 1 Hz signal.

Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #10 on: December 12, 2008, 11:17:32 PM »
Hi Neil

>>The values seem to represent 0.5 seconds

I still don't see where you get this from. Which values are you referring to?

A factor 2 error could be due to a calculation error with the clock or due to triggering on both edges. Once I understand where you get the value from I may be able to explain where this could be.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #11 on: December 12, 2008, 11:59:36 PM »
Hi Mark,
  As the clock is 1.875Mhz, each pulse is 1/1875000=0.53333ns. As time between pulses is 0x000e4efd (937725), time is 937725*0.53333ns=0.5seconds.

I may be picking this up wrong..

Neil

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #12 on: December 13, 2008, 01:00:05 AM »
Hi Mark,
 I have being doing some more tests. I dont think I am understanding how this works. Here is how I see it:
The timer is set at 1.875Mhz, and as soon a capture is made (low capture), the counter is starts, at the next High-Low of the pulse, the timer is captured, and stored in capture location 1 (within ulCaptureList array).Now the timer is cleared, and on the next High-Low, the timer is captured, and stored in capture location 2(within ulCaptureList array), and so on. As in the below results, I set array for 20 captures, so I assumed this meant that there would take 20 seconds to fill the ulCaptureList  array, 1 reading per second, which is not how its working.

Can you explain how the input capture works?

Regards
Neil

0x000e4ec7
0x000e4ed3
0x000e4ed9
0x000e4edd
0x000e4ee2
0x000e4ee6
0x000e4eeb
0x000e4eef
0x000e4ef4
0x000e4ef7
0x000e4efa
0x002aea91
0x002aea94
0x002aea9d
0x002aeaa1
0x002aeaa7
0x002aeaac
0x002aeab0
0x002aeab5
0x002aeab9

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: using the GPT inputs
« Reply #13 on: December 13, 2008, 04:39:04 PM »
Hi Neil

My first impression is that you are getting 11 values on the first edge and then 9 values on the second edge (filling the capture buffer).
Is it possible that the signal is not clean (ringing causing multiple edges to be seen?).

Taking the two values 0x000e4ec7 and 0x002aea91 gives a difference of 0x1c9bca, or 1874890 clocks. At 1.875MHz this is 0.99994s - which is within 60us of the actual 1Hz signal being measured and thus quite accurate.

The question is whether the problem with the multiple captures at each (real) edge is due to a hardware problem of whether there is a software error involved.

To your questions - the timer is not reset when there is a capture but continues running. I would also expect that your test to take 20s (20 real capture values) before completing.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: using the GPT inputs
« Reply #14 on: December 13, 2008, 05:11:43 PM »
Hi Mark,
  I have tied the 1Hz from the rtc to an interupt on the processor (as well as the GPT input, and placed a scope on the input), so I know its getting 1 second pulses, as it displays a short message evry second.

I enable the interupt on the 1Hz, after the rtc is set to produce the 1 hz pulse. Then within the 1 second interup I enable the GPT after 4 seconds, so I can see exactly when its called. Straight after its called, and as soon as the next 1 second message is displayed (approx), the message appears showing the GPT timer values for all 20 readings.

Neil
« Last Edit: December 13, 2008, 05:17:44 PM by neil »