Slow response on changes to hardware pwm0 [SOLVED]

Post Reply
paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Slow response on changes to hardware pwm0 [SOLVED]

Unread post by paulcrawford » Sat Jan 21, 2017 12:02 pm

I have been using one of the two hardware pwm gpio pins, pwm0, for several months to control the voltage available to a load resistor. Previously the response of the pwm output to changes in duty was very fast, a few seconds at most. Just lately though I have been experiencing very slow responses which can take anywhere from 30 seconds to several minutes. Needless to say this is not the kind of performance one would expect.

Today I completed the troubleshooting as far as I can take it and really need some deeper experience on this issue.

The gpio pwm0 output pin is connected to the base of a power transistor that acts as a switch to control the available voltage to the resistor. The switching frequency is 60Hz, i.e. very slow, which helps to minimize the heat buildup in the transistor. The voltage is nominal 12V through a 2.2ohm resistor resulting in about a 5A maximum current at a duty of 1023. I have a "C" program running on the C2 which reads the required duty value for the pwm from a database and then writes that value to "/sys/devices/platform/pwm-ctrl/duty0". I have verified that when the database is manually edited, the value of "/sys/devices/platform/pwm-ctrl/duty0" changes virtually immediately as expected, but the current developed in the resistor, which is monitored every few seconds, does not change immediately in response to the change in the duty value.

I have disconnected the pwm0 gpio from the power transistor base and monitored it with a logic analyzer and found that if the "C" program is not running, then the pwm output is perfect at 60Hz and whichever duty is manually written to "/sys/devices/platform/pwm-ctrl/duty0" is what shows up in the pulse pattern and response is virtually instantaneous as expected. If I do the same thing with the "C" program running, then I get the delayed response on the pwm output.

My conclusion is therefore that there is nothing wrong with the hardware pwm gpio (I even tried it with two different C2s), but there is some interaction that the"C" program is creating that is causing the delay in change from one duty value to another.

My assumption is that once pwm0 is enabled and has a frequency set, the only requirement to get a different output for duty is to change the value in "/sys/devices/platform/pwm-ctrl/duty0". My testing confirms that, but is there anything else that my "C" program could be doing that could possibly change the speed of response of the pwm0 output?
Last edited by paulcrawford on Wed Jan 25, 2017 1:40 am, edited 2 times in total.

User avatar
odroid
Site Admin
Posts: 33297
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 376 times
Been thanked: 449 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by odroid » Sat Jan 21, 2017 12:32 pm

Can you show us your "C" code which accesses the /sys/devices/platform/pwm-ctrl/duty0 to reproduce the issue?

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Sat Jan 21, 2017 12:50 pm

Here is the code:

Code: Select all

void gpiowrite(int gexp, int state, int kind)
{
char exbuf[64];
char valbuf[5];
int ret;
int fdg;
   switch(kind)
   {
      case(GPIO):
      {
         sprintf(exbuf, "/sys/class/gpio/gpio%d/value",  gexp);
         break;
      }
      case(PWM):
      {
         sprintf(exbuf, "/sys/devices/platform/pwm-ctrl/duty0");
         break;
      }
      case(WDT):
      {
         sprintf(exbuf, "/home/daco/src/wdt");
         break;
      }
  }
   fdg = open(exbuf, O_WRONLY);
   snprintf(valbuf,sizeof(valbuf),"%d",state);
   ret = write(fdg, valbuf, sizeof(valbuf)-1);
   if(!ret || ret == -1)
   {
      fprintf(stderr,"could not write to gpio at %s \n", exbuf);
   }
   close(fdg);
}
I have checked the value of duty0 after setting it manually:

Code: Select all

daco@n:~$ echo 800 >/sys/devices/platform/pwm-ctrl/duty0
daco@n:~$ cat /sys/devices/platform/pwm-ctrl/duty0
800
I get the same value when I check it manually after setting it programmatically using the code above.

Perhaps that is the issue though, that while duty0 reports a certain value with cat, the real value is something else. I have seen that before.

I did check the "C" program error log and there were no entries indicating that it was not possible to write to the gpio.

User avatar
mad_ady
Posts: 7347
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, N1, H2, N2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 350 times
Been thanked: 252 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by mad_ady » Sat Jan 21, 2017 4:12 pm

Do you call gpiowrite in some sort of loop? If yes, how often do you call it? If you keep setting the pwm in a tight loop you might get anomalies. I suggest your program remembers the last duty set and only set it if the new value differs from the old

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Sun Jan 22, 2017 12:32 am

Yes, gpiowrite is called in a loop but only about once every 3 seconds so not exactly what you might call a "tight" loop ;) . Since the program knows the past value already I have changed the code to allow gpiowrite for pwm0 only if duty0 has changed. Probably not really necessary, but it is better code so thank you for the advice.

I think I may be getting closer to the problem though as I was testing the above change. I noticed that not only had duty0 not changed when I forced it to test the modified code but it had not changed from initialization in the program. When I checked the value of duty0 I got 250 as expected since that was the value in the database:

Code: Select all

daco@n:~$ cat /sys/devices/platform/pwm-ctrl/duty0
250
But the actual value of duty0 was clearly 0 as there was no current produced.

When I manually set duty0 with:

Code: Select all

daco@n:~$ echo 250 > /sys/devices/platform/pwm-ctrl/duty0
the current immediately jumped to 1.14A exactly as expected.

So now it is clear that the problem is in what actually gets written into /sys/devices/platform/pwm-ctrl/duty0. When one manually changes duty0 with "echo 250 >" I think an integer value of "250" goes into the file and that makes pwm0 work correctly. My present code, however, writes a buffer filled with the characters "2", "5" and "0". Doing the "cat" on duty0 outputs the characters to screen but internally I suspect duty0 does not know what to do with the characters and does not convert them to an int value to make pwm0 change. How it eventually gets the correct value after a random delay, I do not know, but it does seem to.

If the code in pwm0 is not going to change, then I will have to change my code to write an int value into duty0.

User avatar
mad_ady
Posts: 7347
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, N1, H2, N2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 350 times
Been thanked: 252 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by mad_ady » Sun Jan 22, 2017 3:44 am

My C is beyond rusty, but what is exbuf and why isn't it set to anything?
To rule out your code logic you could try calling system("echo 250 > /sys/bla/bla/duty");

LiquidAcid
Posts: 1093
Joined: Fri Oct 11, 2013 11:07 pm
languages_spoken: english
ODROIDs: X2
Has thanked: 0
Been thanked: 1 time
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by LiquidAcid » Sun Jan 22, 2017 4:11 am

mad_ady wrote:My C is beyond rusty, but what is exbuf and why isn't it set to anything?
exbuf is set in the switch statement (which could use a default case btw).

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Sun Jan 22, 2017 5:40 am

mad_ady wrote:My C is beyond rusty, but what is exbuf and why isn't it set to anything?
To rule out your code logic you could try calling system("echo 250 > /sys/bla/bla/duty");
I did try that and it does work. The problem is that the "250" part of the string must be changeable and since system() only takes a const char * command I cannot see how to make it change. Does anyone know an easy way to do that?
LiquidAcid wrote:
mad_ady wrote:My C is beyond rusty, but what is exbuf and why isn't it set to anything?
exbuf is set in the switch statement (which could use a default case btw).
I agree but this is self-contained code not depending on any user input so there cannot really be another case to consider if I write the code properly ;) .

I have made some additional progress on this issue. If the echo command is used, it does not matter whether the value is 250 or "250" which suggests that the file duty0 can take either text or a numeral. The response is virtually instantaneous with either and cat returns 250 in both cases.

My code puts the text "250" into the file duty0 and I added some code to read back what went in and it returns "250". So it would seem that the code does the same thing that echo "250" does except there is still a random delay in the pwm0 response to the change in duty0.

What I do not know, of course, is what goes on inside the pwm0 code and what triggers it to even look at the value of duty0. Perhaps @odroid can assist here? Does the "echo xxx >" creating a new file trigger the change. If so my code only changes the value in the file and does not create a new file. Maybe that it what I need to try next...

I did try to remove the duty0 file as root:

Code: Select all

root@n:/home/daco# rm /sys/devices/platform/pwm-ctrl/duty0
rm: cannot remove '/sys/devices/platform/pwm-ctrl/duty0': Operation not permitted
so I will not be able to remove programmatically either.

User avatar
odroid
Site Admin
Posts: 33297
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 376 times
Been thanked: 449 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by odroid » Sun Jan 22, 2017 1:08 pm

Don't try to remove the sysfs. It will not work.

Write a PWM duty0 value and read back it in your C code to find a root cause.

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Sun Jan 22, 2017 1:37 pm

odroid wrote:Don't try to remove the sysfs. It will not work.

Write a PWM duty0 value and read back it in your C code to find a root cause.
Yes, I understand now that sysfs is a virtual file system so nothing can be removed. I have also read that there should be only one value per file, which is what duty0 has, and that a new value written should be simple ASCII text, which is what I have written in with my C code. When I manually determine the value of duty0 with "cat" from the command line, I get exactly the same value that my C code put into duty0. And I have read back the new value from duty0, after writing the new value to duty0, and they are one and the same.

Therefore, I think I have implemented changing the value in duty0 correctly. What does not happen is that the pwm0 signal pulse width changes in response to the new duty0 value as it should. The change should be virtually instantaneous, but instead there appears to be a random delay of as much as minutes. If I change the value of duty0 from the command line with echo xxx > duty0, the change in the pulse width is virtually instantaneous, so I know that pwm0 does work but I need it to work programmatically not manually.

As noted above I have tried echo xxx > and echo "xxx" > and manually they both work the same, so my suspicion that the problem was putting an ASCII text, rather than an integer value, into duty0 was incorrect. Which simply means that there should be no reason that my C code should not work as it is doing exactly what sysfs expects.

Therefore, there must be some other reason for this random response delay that I am experiencing. Can you please look at how pwm0 is implemented to determine the reason for this abnormal behaviour?

Thank you for your help and patience on this issue.

User avatar
mad_ady
Posts: 7347
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, N1, H2, N2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 350 times
Been thanked: 252 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by mad_ady » Sun Jan 22, 2017 2:37 pm

Are you closing or flushing the duty0 file after writing to it? Also you have to open it for writing with truncate option set (should be default)

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Mon Jan 23, 2017 1:47 am

mad_ady wrote:Are you closing or flushing the duty0 file after writing to it? Also you have to open it for writing with truncate option set (should be default)
Thanks for the suggestions. Yes the file is closed with close(fdg) at the end of the function. I also changed the open call to:

Code: Select all

   fdg = open(exbuf, O_WRONLY || O_TRUNC);
but there is no difference in the behaviour of pwm0. The latest test, switching from 450 to 250, I waited for 25 minutes and there was no change in the pulse width, so I did:

Code: Select all

daco@n:~$ echo "250" > /sys/devices/platform/pwm-ctrl/duty0
from the command line and the change was immediate.

I also read back the value in duty0 in hex from within the C code and got 32 35 30, which of course is exactly 250.

It is clear to me that the contents of duty0 is correct but by some means pwm0 does not know about it so does not change the pulse width in response to programmatic changes to duty0, although it works fine with echo xxx > duty0.

Over to you @odroid...

afremont
Posts: 128
Joined: Sun Mar 08, 2015 12:58 am
languages_spoken: english
Has thanked: 0
Been thanked: 0
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by afremont » Mon Jan 23, 2017 9:38 am

Maybe check the return value from open? Maybe you're getting an error. Sure acts like a buffer flush issue though.

Edit:. I see you're checking the return from write. That seems like it should catch a problem with the call to open.

Just for grins, you could try it with fopen and friends. Maybe using a FILE * will make a difference.

Sent from my Moto G (4) using Tapatalk

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Mon Jan 23, 2017 1:32 pm

afremont wrote:
Just for grins, you could try it with fopen and friends. Maybe using a FILE * will make a difference.
I have implemented "fopen" and "fwrite" to get the new value into duty0. Checking the result with "cat" gives the correct value in duty0 after changing the value in the database to trigger the code. The pulse width of pwm0 still does not change though just as before with "open" and "write". It was certainly worth a try, but unfortunately it is not the solution.

Thank you for taking the time to review this issue. Collectively we will get to the bottom of this and solve the problem...

brad
Posts: 1051
Joined: Tue Mar 29, 2016 1:22 pm
languages_spoken: english
ODROIDs: C2 N1 N2 H2 (64 bit ftw)
Location: Australia
Has thanked: 26 times
Been thanked: 56 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by brad » Mon Jan 23, 2017 2:28 pm

I had success operating with GPIO sysfs using the following to update values (This sets pin direction for GPIO but you might like to try for your purposes)..

Code: Select all

 // Open a fd to gpio pin direction
        int fd_gpio_direction;  File descriptor for GPIO direction

        if ((fd_gpio_direction = open ("/sys/class/gpio/gpio249/direction", O_WRONLY)) < 0) {
                printf ("Unable to open : /sys/class/gpio/gpio249/direction %s\n", strerror(errno));
        }

        // Set  pin as out
        if(dprintf(fd_gpio_direction, "%s" , "out") < 0) {
                printf ("Unable to write : /sys/class/gpio/gpio249/direction %s\n", strerror(errno));
        }
printf's are for messages to screen
dprintf is for writing to file descriptors (ie sysfs)

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by paulcrawford » Mon Jan 23, 2017 9:21 pm

brad wrote:I had success operating with GPIO sysfs using the following to update values (This sets pin direction for GPIO but you might like to try for your purposes)..
Thanks for the suggestion. I have implemented it but the behaviour is identical to all of the other approaches: the value of duty0 is changed as verified by "cat duty0" but the pulse width of pwm0 does not change.

I also have to set direction on my GPIOs and use a similar approach to yours but not using "dprintf", but rather "write" (actually in the same function "gpiowrite") and it works fine just as yours does. But I am coming to inescapable conclusion that pwm0's duty0 virtual file in sysfs is a different beast altogether, which is why I would appreciate HK's review of the internals of the hardware pwm and how it can be manipulated by other than a manual cli line.

afremont
Posts: 128
Joined: Sun Mar 08, 2015 12:58 am
languages_spoken: english
Has thanked: 0
Been thanked: 0
Contact:

Re: Slow response on changes to hardware pwm0

Unread post by afremont » Wed Jan 25, 2017 12:07 am

You might want to look at the source code for echo and see if there is some secret ioctl function you need.

Sent from my Moto G (4) using Tapatalk

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by paulcrawford » Wed Jan 25, 2017 1:38 am

I have finally solved this issue. Kudos to @mad_ady for suggesting the possibility of a tight loop causing the problem.

After looking more deeply into the code, I did find that the gpiowrite function that set the value of duty0 was called twice, not in a loop, but in rapid succession, which probably appeared to be like a loop to duty0. To correct that, I have set up to read duty0 before setting it and check the value about to be set. Only if they are different does anything get written. That change has completely solved the problem.

Thanks to all that reviewed this issue and made valuable suggestions for changes. The depth of expertise in this forum is incredible.

User avatar
mad_ady
Posts: 7347
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, N1, H2, N2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 350 times
Been thanked: 252 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by mad_ady » Wed Jan 25, 2017 3:46 am

Glad to hear it's sorted out. You may want to mark the thread as solved

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by paulcrawford » Wed Jan 25, 2017 3:51 am

mad_ady wrote:You may want to mark the thread as solved
I thought I did...(I changed the title to ...[SOLVED], is there something else I need to do?)

Thanks again for your insightful comments.

Paul

User avatar
mad_ady
Posts: 7347
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, N1, H2, N2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 350 times
Been thanked: 252 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by mad_ady » Wed Jan 25, 2017 3:52 am

Sorry, tapatalk didn't reflect your changes. That should do it

elmerfudd
Posts: 21
Joined: Sun May 15, 2016 10:00 pm
languages_spoken: english
Has thanked: 0
Been thanked: 0
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by elmerfudd » Wed Jan 25, 2017 7:02 am

Your original code did not have a newline following the "%d":

Code: Select all

   snprintf(valbuf,sizeof(valbuf),"%d",state);
   ret = write(fdg, valbuf, sizeof(valbuf)-1);
That might have been part of the problem.
This might be a better way to write it:

Code: Select all

   int len = snprintf(valbuf,sizeof(valbuf),"%d\n",state);
   ret = write(fdg, valbuf, len);

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by paulcrawford » Fri Jan 27, 2017 12:11 pm

elmerfudd wrote: This might be a better way to write it:

Code: Select all

   int len = snprintf(valbuf,sizeof(valbuf),"%d\n",state);
   ret = write(fdg, valbuf, len);
Thanks for the suggestion. I did implement the above code but the results are the same, i.e. this variation and the original code both work fine.

Can you please explain the purpose and advantage of including the "\n" in the creation of the string to be written to duty0?

crashoverride
Posts: 4716
Joined: Tue Dec 30, 2014 8:42 pm
languages_spoken: english
ODROIDs: C1
Has thanked: 0
Been thanked: 191 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by crashoverride » Fri Jan 27, 2017 10:59 pm

paulcrawford wrote:Can you please explain the purpose and advantage of including the "\n" in the creation of the string to be written to duty0?
It means "new line". Its probably best explained with an example:

If you are trying to write the value "123":

With "\n"

Code: Select all

123
123
123
123
Without "\n"

Code: Select all

123123123123
The "\n" lets the sysfs entry know where the value ends. WIthout it, it will wait until the buffer is full (taking a longer time).

Another example:

Code: Select all

printf("1");
printf("2");
printf("3\n");
Is equivalent to:

Code: Select all

printf("123\n");

brad
Posts: 1051
Joined: Tue Mar 29, 2016 1:22 pm
languages_spoken: english
ODROIDs: C2 N1 N2 H2 (64 bit ftw)
Location: Australia
Has thanked: 26 times
Been thanked: 56 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by brad » Sun Jan 29, 2017 9:49 am

paulcrawford wrote: to be written to duty0?
I too am interested in how the buffers work when writing to sysfs.

From the documentation (https://github.com/hardkernel/linux/blo ... /sysfs.txt) and specifically these few sections regarding attributes...
Attributes should be ASCII text files, preferably with only one value
per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type.

Mixing types, expressing multiple lines of data, and doing fancy
formatting of data is heavily frowned upon. Doing these things may get
you publicly humiliated and your code rewritten without notice.
And then this seciton...
- On write(2), sysfs expects the entire buffer to be passed during the
first write. Sysfs then passes the entire buffer to the store()
method.

When writing sysfs files, userspace processes should first read the
entire file, modify the values it wishes to change, then write the
entire buffer back.

Attribute method implementations should operate on an identical
buffer when reading and writing values.
Based from what I can understand it seems we should be not using a newline to flush a buffer of these small sizes but rather writing once the full attribute value to the file and disabling buffers on the stream.

It seems setvbuf can be used to disable the buffer on the stream https://linux.die.net/man/3/setvbuf

paulcrawford
Posts: 166
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: c2 and n2
Has thanked: 23 times
Been thanked: 4 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by paulcrawford » Mon Jan 30, 2017 4:30 am

brad wrote:

From the documentation (https://github.com/hardkernel/linux/blo ... /sysfs.txt) and specifically these few sections regarding attributes...
Attributes should be ASCII text files, preferably with only one value
per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type.

Mixing types, expressing multiple lines of data, and doing fancy
formatting of data is heavily frowned upon. Doing these things may get
you publicly humiliated and your code rewritten without notice.
And then this seciton...
- On write(2), sysfs expects the entire buffer to be passed during the
first write. Sysfs then passes the entire buffer to the store()
method.

When writing sysfs files, userspace processes should first read the
entire file, modify the values it wishes to change, then write the
entire buffer back.

Attribute method implementations should operate on an identical
buffer when reading and writing values.
Based from what I can understand it seems we should be not using a newline to flush a buffer of these small sizes but rather writing once the full attribute value to the file and disabling buffers on the stream.

It seems setvbuf can be used to disable the buffer on the stream https://linux.die.net/man/3/setvbuf
I read the original document that HK has put into its github page and although I am not that knowledgeable on buffers and streams, I ended up implementing essentially what is specified. I needed to ensure that the change was only made once, so I read the file first and if its contents differed from what was about to be set, then that new value was written to the file. I have now changed the code ever so slightly by using the same buffer to hold the new value. Before I used the same size buffer but a different buffer to hold the read value.

This is my code now for changing duty0:

Code: Select all

void gpiowrite(int gexp, int state, int kind)
{
char exbuf[64];
char valbuf[5];
int ret;
int bytesread = 0;
int writedata = 1;
int fdg;
int fdr;
   switch(kind)
   {
      case(GPIO):
      {
         sprintf(exbuf, "/sys/class/gpio/gpio%d/value",  gexp);
         break;
      }
      case(PWM):
      {
         sprintf(exbuf, "/sys/devices/platform/pwm-ctrl/duty0");
         break;
      }
      case(WDT):
      {
         sprintf(exbuf, "/home/daco/src/wdt");
         break;
      }
      default:

   if(kind==PWM)
   {
      fdr = open(exbuf, O_RDONLY);
      bytesread = read(fdr,&valbuf,sizeof(valbuf)-1);
      if(!bytesread)
      {
         fprintf(stderr,"could not read from gpio at %s \n", exbuf);
      }
      if(atoi(valbuf) == state)
      {
         writedata = 0;
      }
      close(fdr);
   }
   if(writedata)
   {
      fdg = open(exbuf, O_WRONLY || O_TRUNC);
      snprintf(valbuf,sizeof(valbuf),"%d",state);
      ret = write(fdg, valbuf, sizeof(valbuf)-1);
      if(!ret || ret == -1)
      {
         fprintf(stderr,"could not write to gpio at %s \n", exbuf);
      }
      close(fdg);
   }
}
Looking at setvbuf, it seems that it is applicable when using FILE * stream. Since I am using only a file descriptor, fdg and fdr, I don't think disabling the buffer is necessary. Do you agree?

If we can all agree on this whole issue of getting changed values into sysfs, I would be happy to create a small section for the HK's wiki to augment the manual procedure (echo xxx > duty0) that is there already for the PWM.

brad
Posts: 1051
Joined: Tue Mar 29, 2016 1:22 pm
languages_spoken: english
ODROIDs: C2 N1 N2 H2 (64 bit ftw)
Location: Australia
Has thanked: 26 times
Been thanked: 56 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by brad » Mon Jan 30, 2017 4:37 pm

paulcrawford wrote:Looking at setvbuf, it seems that it is applicable when using FILE * stream. Since I am using only a file descriptor, fdg and fdr, I don't think disabling the buffer is necessary. Do you agree?
Yes I think I agree as it seems read() and write() always use unbuffered transfers.
paulcrawford wrote:I would be happy to create a small section for the HK's wiki to augment the manual procedure (echo xxx > duty0) that is there already for the PWM.
Thank you Paul, very nice work :)

User avatar
odroid
Site Admin
Posts: 33297
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 376 times
Been thanked: 449 times
Contact:

Re: Slow response on changes to hardware pwm0 [SOLVED]

Unread post by odroid » Tue Jan 31, 2017 7:42 pm

@paulcrawford
Thank you for sharing your final working code. It looks very solid solution to access the sysfs based IO devices.
I've added a link of this thread on the WiKi page.
http://odroid.com/dokuwiki/doku.php?id= ... _pwm#freq0

Post Reply

Return to “Issues”

Who is online

Users browsing this forum: No registered users and 1 guest