Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 08 Aug 2018 09:45:40 -0600
From:      Ian Lepore <ian@freebsd.org>
To:        "Dr. Rolf Jansen" <rj@obsigna.com>, freebsd-arm@FreeBSD.org
Subject:   Re: BeagleBone Black with a I2C Digital Analog Converter
Message-ID:  <1533743140.9860.99.camel@freebsd.org>
In-Reply-To: <3C191052-1E2C-4D85-8CF1-AAC64F0500B7@obsigna.com>
References:  <3C191052-1E2C-4D85-8CF1-AAC64F0500B7@obsigna.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 2018-08-08 at 10:59 -0300, Dr. Rolf Jansen wrote:
> Hello,
> 
> I got a BeagleBone Black running the latest FreeBSD 12.0-CURRENT (snapshot o July, 2nd).
> 
> I am in the process of getting a tiny I2C Digital Analog Converter board to work with it. It got a MCP4725 DAC chip and it is designed to work with the Arduino system. https://learn.sparkfun.com/tutorials/mcp4725-digital-to-analog-converter-hookup-guide 
> 
> However, it should be possible to get it to work with FreeBSD on the BeagleBone as well, since the operation principle looks very simple, e.g. write to the base address 0x60 the update command byte 0x40 followed by two bytes in network byte order which constitutes for the desired voltage output as a 12bit value.
> 
> I managed to create a DTB overlay:
> 
> /dts-v1/;
> /plugin/;
> 
> / {
>         compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
> 
>         part-number = "MCP4725-I2C1";
>         version = "0001";
>         exclusive-use = "P9.17","P9.18","i2c1";
> 
>         fragment@0 {
>                 target = <&am33xx_pinmux>;
>                 __overlay__ {
>                         pinmux_i2c1_pins {
>                                 pinctrl-single,pins = <0x158 0x32 0x15c 0x32>;
>                                 phandle = <0xff>;
> #                               pinctrl-single,pins = <
> #                                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_d1.i2c1_sda */
> #                                       AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2)       /* spi0_cs0.i2c1_scl */
> #                               >;
>                         };
>                 };
>         };
> 
>         fragment@1 {
>                 target = <&i2c1>;
>                 __overlay__ {
>                         status = "okay";
>                         pinctrl-names = "default";
>                         pinctrl-0 = <0xff>;
> 
>                         MCP4725 {
>                                 comaptible = "Microchip,MCP4725";
>                                 reg = <0x60>;
>                         };
>                 };
>         };
> };
> 
> 
> This actually activates the I2C1 device, and creates a node for the MCP4725 I2C chip. Since I see the additional iic device in /dev:
> 
> ls -l /dev/iic*
> ls -l /dev/iic*
> crw-------  1 root  wheel  0x43 Aug  8 10:36 /dev/iic0
> crw-------  1 root  wheel  0x45 Aug  8 10:36 /dev/iic1
> crw-------  1 root  wheel  0x46 Aug  8 10:36 /dev/iic2
> 
> Without the overlay, only 2 device show up. Furthermore, the nodes for nodes activated I2C1, its sub node for the DAC chip and the additional pinmux node show up in the ofwdump:
> 
> ...
>       Node 0x2f00: scm@210000
>         Node 0x2fa0: pinmux@800
>           Node 0x3064: pinmux_i2c1_pins
> ...
>     Node 0x5290: i2c@4802a000
>       Node 0x5360: MCP4725
> ...
> 
> My doubts are now, whether I got the specs of the pinmux right. I read several documents in the and according to this https://github.com/jadonk/bonescript/blob/master/src/bone.js, the addresses of P9.17 and P9.18 should be 0x15c and 0x158 respectively. I deduced the order and options from other pinmuxes of a decompiled device tree.
> 
> Please can somebody, check this, and perhaps give some hints in case I got something wrong? I don't have an oscilloscope, a multimeter only, can I check somehow if I specified the correct pins?
> 
> What needs to be done next? I guess, I need to write a simple device driver, don't I? Or can I use somehow the iicbb(4) – I2C generic bit-banging driver, since actually that DAC chip needs bit banging only -- repeatedly write 3 byte in row. I yes, how can I use it for my purpose?
> 
> Best regards
> 
> Rolf

At this point, i2c(8) is your friend, it lets you do i2c bus
transactions from the commandline without a device-specific driver for
each i2c device. A good starting point is a bus scan:

  i2c -f /dev/iic1 -s

If the bus is working you should see something like:

  Scanning I2C devices on /dev/iic1: 60

You can also use i2c(8) to transfer data to and from the device, but
that's something I've never done myself, so I can't give a working
example here.

Writing a custom driver for an i2c device is usually pretty simple. For
chips with just a few registers, it's common to provide a userland
interface with sysctl, allowing each register to be read or written by
reading or setting a sysctl var. Some examples exist in the
sys/dev/iicbus directory.

-- Ian



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1533743140.9860.99.camel>