Interfacing

1-wire and Dallas DS18b20

34 19974
The 1-wire driver is from sunxi, we did not modify it. udelay we will check the upstream sunxi.

Post Last Edited by tony_zhang at 2014-8-20 23:18

the problem seems to be in the file cpu-freq.c: the loops_per_jiffy gets updated per cpu, but as it seems that for the busy-loop in udelay the "global" loops_per_jiffy is used (probably wrong in the first place, but unrelated to sunxi). Therefore the global loops_per_jiffy needs to be updated alongside the per-cpu values (see drivers/cpufreq/omap-cpufreq.c which I used as an example).

here is my patch that solves the issue for onewire (confirmed to udelay as expected). I have done a bit of cleanup, but still this is just a very rough early patch:
  1. --- a/arch/arm/mach-sun7i/cpu-freq/cpu-freq.c        2014-07-30 22:05:19.534123526 +0200
  2. +++ b/arch/arm/mach-sun7i/cpu-freq/cpu-freq.c        2014-08-20 23:04:58.500013548 +0200
  3. @@ -22,6 +22,7 @@
  4. #include <linux/init.h>
  5. #include <linux/interrupt.h>
  6. #include <linux/cpufreq.h>
  7. +#include <linux/delay.h>
  8. #include <linux/cpu.h>
  9. #include <linux/clk.h>
  10. #include <linux/err.h>
  11. @@ -500,7 +501,7 @@ static int sunxi_cpufreq_settarget(struc
  12. {
  13.      struct cpufreq_freqs    freqs;
  14.      struct sunxi_cpu_freq_t cpu_new;
  15. -    int                     i;
  16. +    int                     i, ret = 0;

  17.      #ifdef CONFIG_CPU_FREQ_DVFS
  18.      unsigned int    new_vdd;
  19. @@ -524,8 +525,6 @@ static int sunxi_cpufreq_settarget(struc
  20.              freqs.cpu = i;
  21.              cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  22.          }
  23. -#else
  24. -        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  25. #endif
  26.          }

  27. @@ -540,12 +539,11 @@ static int sunxi_cpufreq_settarget(struc

  28.              /* notify everyone that clock transition finish */
  29.                  if (policy) {
  30. -                freqs.cpu = policy->cpu;
  31. -                    freqs.old = freqs.new;
  32. -                    freqs.new = cpu_cur.pll / 1000;
  33. -                        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  34. -                }
  35. -            return -EINVAL;
  36. +                freqs.old = freqs.new;
  37. +                freqs.new = cpu_cur.pll / 1000;
  38. +            }
  39. +            ret = -EINVAL;
  40. +            goto done;
  41.          }
  42.      }
  43.      #endif
  44. @@ -566,21 +564,11 @@ static int sunxi_cpufreq_settarget(struc

  45.          /* notify everyone that clock transition finish */
  46.              if (policy) {
  47. -            freqs.cpu = policy->cpu;
  48. -                freqs.old = freqs.new;
  49. -                freqs.new = cpu_cur.pll / 1000;
  50. -#ifdef CONFIG_SMP
  51. -            /* notifiers */
  52. -            for_each_cpu(i, policy->cpus) {
  53. -                freqs.cpu = i;
  54. -                cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  55. -            }
  56. -#else
  57. -            cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  58. -#endif
  59. -            }
  60. -
  61. -        return -EINVAL;
  62. +            freqs.old = freqs.new;
  63. +            freqs.new = cpu_cur.pll / 1000;
  64. +        }
  65. +        ret = -EINVAL;
  66. +        goto done;
  67.      }

  68.      #ifdef CONFIG_CPU_FREQ_DVFS
  69. @@ -597,7 +585,6 @@ static int sunxi_cpufreq_settarget(struc
  70.          /* update our current settings */
  71.          cpu_cur = cpu_new;

  72. -        /* notify everyone we've done this */
  73.          if (policy) {
  74. #ifdef CONFIG_SMP
  75.          /*
  76. @@ -608,16 +595,23 @@ static int sunxi_cpufreq_settarget(struc
  77.          for_each_cpu(i, policy->cpus) {
  78.              per_cpu(cpu_data, i).loops_per_jiffy =
  79.                   cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, freqs.old, freqs.new);
  80. -            freqs.cpu = i;
  81. -            cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  82.          }
  83. -#else
  84. -        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  85. +        /* adjust global jiffies */
  86. +        loops_per_jiffy = cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
  87. #endif
  88.          }

  89. +done:
  90. +        /* notify everyone we've done this */
  91. +        if (policy) {
  92. +        for_each_cpu(i, policy->cpus) {
  93. +            freqs.cpu = i;
  94. +            cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  95. +        }
  96. +        }
  97. +
  98.          CPUFREQ_DBG("%s: finished\n", __func__);
  99. -        return 0;
  100. +        return ret;
  101. }
Copy the Code

Reply 12# ucmaniac

Did it cause any affect on other function? Because cpu frequency is related to many drivers and threads.

Reply 13# tony_zhang
no problem or indication of strange behaviour detected so far. I2C works as intended (tested with hwclock reading the realtime clock), Onewire as well.

Post Last Edited by actkk2000 at 2014-8-24 19:16

I decided to try 1-wire with temperature sensor, since I ordered a free sample of DS18b20 last year (when I was tinkering with Raspberry Pi) from here, but I never used it:
https://shop.maximintegrated.com/storefront/samplecart.do?event=ShowSampleCart&menuitem=SampleCart&mode=getfreesamples

I can confirm it is working fine on Raspbian 3.1, here a first try on Banana Pi showing temperature on a i2C Led character display:



I followed these instructions:
https://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing
https://learn.adafruit.com/matrix-7-segment-led-backpack-with-the-raspberry-pi/
https://learn.adafruit.com/large-pi-based-thermometer-and-clock

The only change I made in script.bin is:

[w1_para]
gpio = 18

Gpio 18 is connected to White wire, and gpio 23 is connected to alternate 5v and ground to switch between clock and temperature on the display (Green wire on the breadboard).

rmays  
Post Last Edited by rmays at 2014-9-2 12:28

If you don't want to recompile anything you can install the CPU frequency tools and set it to not drop below 500mhz that way - in this example i am using 600mhz to be safe :-)

sudo apt-get install cpufrequtils
sudo cpufreq-set -d 600000
I haven't tested if this still applies after a reboot

https://wiki.archlinux.org/index.php/CPU_frequency_scaling

mikem  
if anyone is still struggling with getting it to run please refer to this tutorial: http://www.linuxx.eu/2014/09/ban ... sensor-ds18b20.html

Post Last Edited by actkk2000 at 2014-9-17 20:50

Reply 17# mikem

Thanks, it's quite easy to make DS18B20 to work. On the other hand, DHT11 is far more difficult...
or at least to make it work as I needed...
http://forum.lemaker.org/redirect.php?goto=findpost&ptid=353&pid=22812&fromuid=1602

Post Last Edited by MrGlasspoole at 2014-10-13 10:11

I hope its ok to hijack this thread

Here is a better circuit if you ad more sensors to the 1-wire bus or have long cables.
DS18B20.GIF
The 1000Z@100MHz is a ferrite bead. In my case it's a SMD-Ferrite and they are small:
https://www.reichelt.de/Filter/B ... artnr&OFFSET=16
On a stripboard i solder two wires in the holes, then place the ferrite between and solder on top.
Sure you can solder it also on the bottom...
DS18B20.jpg
What you see is the floor screed of my bathroom before i made a grove to place the DS18B20 in it.
On top of that is a infrared floor header and then the laminate flooring...

Great, thanks for sharing this improvement!

You have to log in before you can reply Login | Sign Up

Points Rules