Re: [Q] Frequency & duty cycle measurement?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi William,

On 2025. 01. 27. 16:00, William Breathitt Gray wrote:
In the userspace application, you would setup a Counter "watch" to
collect each desired timer value on the respective Counter events; I
assume RA and RB are Count 0 and Count 1 respectively, but if they
represent something else please let me know:

     static struct counter_watch watches[2] = {
             {
                     /* Component data: Count 0 count */
                     .component.type = COUNTER_COMPONENT_COUNT,
                     .component.scope = COUNTER_SCOPE_COUNT,
                     .component.parent = 0,
                     /* Event type: Capture */
                     .event = COUNTER_EVENT_CAPTURE,
                     /* Device event channel 0 */
                     .channel = 0,
             },
             {
                     /* Component data: Count 1 count */
                     .component.type = COUNTER_COMPONENT_COUNT,
                     .component.scope = COUNTER_SCOPE_COUNT,
                     .component.parent = 1,
                     /* Event type: Capture */
                     .event = COUNTER_EVENT_CAPTURE,
                     /* Device event channel 0 */
                     .channel = 0,
             },
     };
     ...
     int main(void)
     {
             int fd;
             int i;
	    unsigned long long delta_ts, delta_ra, delta_rb;
	    double ra_frequency, rb_frequency, rb_ra;
             struct counter_event first_capture[2], second_capture[2];
/* Open Counter chrdev */
             fd = open("/dev/counter0", O_RDWR);
for (i = 0; i < 2; i++) {
	            /* Register all Counter watches */
                     ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i);
             }
	    /* Start collecting Counter events */
             ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL);
for (;;) {
	        /* Read first Counter event capture */
             	read(fd, first_capture, sizeof(first_capture));
	        /* Read second Counter event capture */
             	read(fd, second_capture, sizeof(second_capture));
/* Within each capture, timestamp is the same so only
		 * first element of each capture needs to be compared */
		delta_ts = second_capture[0].timestamp - first_capture[0].timestamp;
		/* Compute deltas of timer register pair RA and RB.
		delta_ra = second_capture[0].value - first_capture[0].value;
		delta_rb = second_capture[1].value - first_capture[1].value;
ra_frequency = (double)delta_ra / delta_ts;
		rb_frequency = (double)delta_rb / delta_ts;
		rb_ra = (double)delta_rb / delta_ra;
printf("RA frequency: %ld\n"
		       "RB frequency: %ld\n"
		       "RB per RA: %ld\n"
             	       ra_frequency, rb_frequency, rb_ra);
             }
return 0;
     }

If RA and RB are provided as a memory buffer on your device, you can
instead expose them via DEFINE_COUNTER_ARRAY_CAPTURE() such as the
ti-ecap-capture driver does, then perform your userspace computations
by utilizing those respective "capture" array attribute values (via
chrdev like the example above or alternatively via sysfs).

Thanks for your extensive explanation! With DEFINE_COUNTER_ARRAY_CAPTURE() I was able to expose RA and RB as `/sys/bus/counter/devices/counter0/count0/capture{0,1}`, and could verify that by replacing `devmem` calls with read()-reopen(), our PoC code still works. Now I want to use the chardev interface, but I couldn't find how to set up the watches appropriately. So far I have:

	{
		.component.type = COUNTER_COMPONENT_EXTENSION,
		// also tried COUNTER_COMPONENT_COUNT
		.component.scope = COUNTER_SCOPE_COUNT,
		.component.parent = 0,
		.component.id = X, // also tried this instead:
		// .channel = X,
		.event = COUNTER_EVENT_CAPTURE,
	},

However, with this, the first read() never comes back.

Bence





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux