You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@nuttx.apache.org by Gustavo Soares <gu...@hotmail.com> on 2023/10/05 01:02:40 UTC

PCF8575 driver for NuttX

Hello everyone!

I'm trying to access the PCF8575 device from my application on NuttX to make it light up LEDs. I'm not really sure how to implement it, but this is what I've got:

  1.  I copied/pasted both pcf8575_write and pcf8575_direction methods from the driver (at nuttx/drivers/ioexpander/pcf8575.c<https://github.com/apache/nuttx/blob/master/drivers/ioexpander/pcf8575.c>);
  2.  I wrote a main function using those two methods;
  3.  the pcf8575_config_s struct I imported from nuttx/include/nuttx/ioexpander/pcf8575.h<https://github.com/apache/nuttx/blob/master/include/nuttx/ioexpander/pcf8575.h> and the pcf8575_dev_s struct I imported from nuttx/drivers/ioexpander/pcf8575.h<https://github.com/apache/nuttx/blob/master/drivers/ioexpander/pcf8575.h>;

The main function is not finished, I cannot run it to test if it works and also I'm not sure if it is correct. When I use the make command to compile, this error shows up:
[cid:d37d51d4-eb76-47f8-a4cb-896f272e4008]
pcf8575.h is the file I import to get the definition of pcf8575_dev_s struct and it is even possible to reach the file by CRTL clicking the struct and the import line.

I've attached my test file so you all can take a better look.
Does anyone know how to work with this driver to check if the logic is correct? Why wouldn't the compiler access nuttx/drivers/ioexpander/pcf8575.h?

If any additional info is needed, I'll be very happy to send it.
Thank you!

Re: PCF8575 driver for NuttX

Posted by Gregory Nutt <sp...@gmail.com>.
> Actually, the problem is very simple.  This file does not exist.
>
> #include <nuttx/drivers/ioexpander/pcf8575.h>
>
> You probably wanted
>
> #include <nuttx/ioexpander/pcf8575.h>
>
The more I look at what you are trying to do, the more confused I get.

There is a file at drivers/ioexpander/pcf8575.h, but you are not 
permitted to include that.  That contains internal driver definitions 
that are not available to applications.  For testing purposes (ONLY!!) 
you could copy those definitions into your app.  (Your app could never 
be included upstream anyway because it violates far too many basic POSIX 
interfacing principles.  But for testing, you can do anything you want.).

The directory nuttx/drivers would be nonsense in that case because there 
is no nuttx/ directory in the repository.  You made that up and there is 
no include path to access it.

The include file path corresponding to:

    #include <nuttx/drivers/ioexpander/pcf8575.h>

is include/nuttx/drivers/ioexpander/pcf8575.h which does not exist.

This include file path

    #include <nuttx/drivers/ioexpander/pcf8575.h>

corresponds to:

include/nuttx/drivers/ioexpander/pcf8575.h which exists and is legal to 
include.  But it is a different file.



Re: PCF8575 driver for NuttX

Posted by "Alan C. Assis" <ac...@gmail.com>.
Hi Gustavo,

On 10/6/23, Gustavo Soares <gu...@hotmail.com> wrote:
> Hi, Alan and David!
>
> I'm using nrf52_sx1509.c (at boards/arm/nrf62/thingy52/src) as model for my
> driver. I've attached what I have wrote so far and I'd like to know if you
> could tell me if I'm at the right direction:
> [cid:efd68788-44d6-4e3f-a528-ab0fb1e35f03] (print from nrf52_sx1509.c,
> nrf52_sx1509_pinscfg() method)
>
> My guess for what I should implement is to set the direction and option for
> every pin in PCF8575 and after that write bytes to those I set as outputs,
> is it correct?
> what exactly does IOEXP_SETOPTION() do?
>

Yes, I think you are moving on!

The best way to search for NuttX documentation is looking the source
code (all NuttX source code has a lot of documentation embedded on it)

I use this command to find my direction:

$ git grep IOEXP_SETOPTION

So, it will return:

include/nuttx/ioexpander/ioexpander.h: * Name: IOEXP_SETOPTION
include/nuttx/ioexpander/ioexpander.h:#define
IOEXP_SETOPTION(dev,pin,opt,val)
((dev)->ops->ioe_option(dev,pin,opt,val))

Please open this file and there you will find the comments explaining
what these macros do.

Best Regards,

Alan

RE: PCF8575 driver for NuttX

Posted by Gustavo Soares <gu...@hotmail.com>.
Hi, Alan and David!

I'm using nrf52_sx1509.c (at boards/arm/nrf62/thingy52/src) as model for my driver. I've attached what I have wrote so far and I'd like to know if you could tell me if I'm at the right direction:
[cid:efd68788-44d6-4e3f-a528-ab0fb1e35f03] (print from nrf52_sx1509.c, nrf52_sx1509_pinscfg() method)

My guess for what I should implement is to set the direction and option for every pin in PCF8575 and after that write bytes to those I set as outputs, is it correct?
what exactly does IOEXP_SETOPTION() do?

Thank you for the support!
________________________________
De: Alan C. Assis <ac...@gmail.com>
Enviado: sexta-feira, 6 de outubro de 2023 10:36
Para: dev@nuttx.apache.org <de...@nuttx.apache.org>
Assunto: Re: PCF8575 driver for NuttX

Hi David,

In a quick search I noticed that i2c_vbus_initialize() never was part
of NuttX, maybe it is something you created to abstract from different
MCUs initialization.

I think we can use some similar (a generic function) to create a
boards/common/ directory to keep all I2C, SPI, devices initialization
that could be common for all boards, even for boards from different
chip families or architecture.

So, i2cbus_initialize() could be just an "alias" to
stm32_i2cbus_initialize, esp32s2_i2cbus_uninitialize,
cxd56_i2cbus_initialize(), etc, depending of what is the MCU arch of
the board.

It could simplify the sensor or other devices support as in this PCF8575 case.

BR,

Alan

On 10/5/23, David S. Alessio <da...@gmail.com> wrote:
> Hi, Alan,
>
> I don’t see my I2C virtual bus driver code in the current repo.  I’m not
> sure what happened, but I’d like to [re-] submit it.  Can you point me to
> how that’s done today?  (I’m sure email won’t work).
>
> The problem I see with the existing IOEXPANDER code is that I don’t believe
> it’s thread safe (multiple threads each hammering its own sensor on
> different sub buses).
>
> Cheers,
> -david
>
>
>> On Oct 5, 2023, at 6:18 AM, Alan C. Assis <ac...@gmail.com> wrote:
>>
>> Hi David,
>>
>> I think you figure out Gustavo's mistake.
>>
>> Gustavo, all you need to do is use the existing driver. In your code
>> you was trying to implement a low level driver to communicate with
>> your PCF8575. You don't need to do it.
>>
>> Unfortunately there is not much boards examples using IOEXPANDER (shame on
>> us).
>>
>> But I think Mateusz (raiden00) created one here:
>> boards/arm/nrf52/thingy52/src/nrf52_sx1509.c
>>
>> Just look this example and you will figure out everything.
>>
>> Basically:
>>
>> struct pcf8575_config_s g_pcf8575_cfg
>> {
>>  .address   = 0x71;      /* the I2C address returned by i2ctool */
>>  .frequency = 100000;
>> };
>>
>> ...
>>
>> int stm32_pcf8575_initialize(void)
>> {
>>  struct i2c_master_s     *i2c = NULL;
>>  struct ioexpander_dev_s *ioe = NULL;
>>  int                      ret = OK;
>>
>>  i2c = stm32_i2c_register(I2C_BUS); /* I2C_BUS is your I2Cx bus
>> number (0, 1, etc) */
>>
>>  ioe = pcf8575_initialize(i2c, &g_pcf8575_cfg);
>>  ...
>>
>> }
>>
>> BR,
>>
>> Alan
>>
>> On 10/5/23, David S. Alessio <da...@gmail.com> wrote:
>>> Hi, Gustavo,
>>>
>>> You might consider using the I2C IO expander driver I wrote some time ago
>>> to
>>> manage a multi-tiered tree of I2C bus expanders.
>>>
>>> The advantages are:
>>>  * I2C sub buses are transparently available to application space
>>> through
>>> /dev/i2c*
>>>  * transparently manages hierarch of I2C bus expanders
>>>  * downstream I2C device drivers go through the I2C character driver
>>> (pro
>>> and con)
>>>
>>> The disadvantages are:
>>>  * I2C drivers need to use the I2C character driver
>>>  * many I2C HW drivers don’t properly handle multiple command packets in
>>> I2C_TRANSFER()
>>>
>>> Example:  let’s say we have an 4-port I2C switch PCA9545A attached to
>>> /dev/i2c1 using an STM32F407 MCU.  The board initialization would be:
>>>
>>>
>>>  i2c = stm32_i2c_register(1);
>>>
>>>  /*
>>>   *    support for I2C bus epander
>>>   *    /dev/i2c1.0 -- /dev/i2c1.3
>>>   */
>>>  ret = i2c_vbus_initialize("/dev/i2c1", 0x70, I2C_VBUS_PCA9545, 0x0f, 0,
>>> NULL);
>>>  if (ret != OK)
>>>    {
>>>      syslog(LOG_ERR, "ERROR: Failed to initialize i2c_vbus %#x: %d\n",
>>> 0x70, ret);
>>>    }
>>>
>>> Now the sub bus I2C segments are transparently available as /dev/i2c1.0
>>> through /dev/i2c1.3.
>>>
>>> You can add a second PCA9545A, let’s say connected to port 2
>>> (/dev/i2c1.2)
>>> of the first PCA9545A.  It would be registered as:
>>>
>>>      ret = i2c_vbus_initialize("/dev/i2c1.2", 0x71, I2C_VBUS_PCA9545, 0x0f,
>>> 0,
>>> NULL);
>>>
>>> and its ports would be addressable as /dev/i2c1.2.0 through
>>> /dev/i2c1.2.3.
>>>
>>> Let me know if this is something of interest to you, I’ll help you get
>>> it
>>> working...
>>>
>>> Cheers,
>>> -david
>>>
>>>
>>>
>>>> On Oct 4, 2023, at 7:36 PM, Gregory Nutt <sp...@gmail.com> wrote:
>>>>
>>>>
>>>> On 10/4/2023 8:02 PM, Gustavo Soares wrote:
>>>>> Hi Greg!
>>>>>
>>>>> Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is
>>>>> solved, but then the code loses the reference to that specific struct
>>>>> causing another error.
>>>>>
>>>>> And how exactly "the file does not exist"? I can open it and it is at
>>>>> the
>>>>> nuttx repo, I shared it's link.
>>>> Because the compiler keeps a list of paths that it will include files
>>>> from.  It will NOT include files from drivers/ioexpander because that
>>>> is
>>>> not in that include path list.  So "the file does not exists" in any
>>>> directory in the list of include paths. You could hack up  the build
>>>> system  (but no PRs for that please)or you could just copy the header
>>>> file
>>>> (a lot easier). But you cannot include it from drivers/ioexpander.
>>>> Since
>>>> this is necessarily throw-away code, the easier solution is
>>>> recommended.
>>>
>>>
>
>

Re: PCF8575 driver for NuttX

Posted by "Alan C. Assis" <ac...@gmail.com>.
Hi David,

On 10/6/23, David S. Alessio <da...@gmail.com> wrote:
>>>
>>>> In a quick search I noticed that i2c_vbus_initialize() never was part
>>>> of NuttX,
>>>
>>> OK, that’s not good.  What’s the best way to submit it now?
>>>
>>
>> No idea, I think this function is something you created for your project.
>>
>> How is i2c_vbus_initialize() defined in your source code?
>
>
> I’ve attached a tarball of the src here.  How should I submit it to NuttX (I
> haven’t followed the project closely after Greg xfer’d it).
>

I think your tarball didn't show up (Apache mailing remove all files
except .txt, .png, .jpg, etc).

Everything now shoud come from github's PR, more info:

https://nuttx.apache.org/docs/12.2.1/contributing/workflow.html

BR,

Alan

Re: PCF8575 driver for NuttX

Posted by "David S. Alessio" <da...@gmail.com>.
>> 
>>> In a quick search I noticed that i2c_vbus_initialize() never was part
>>> of NuttX,
>> 
>> OK, that’s not good.  What’s the best way to submit it now?
>> 
> 
> No idea, I think this function is something you created for your project.
> 
> How is i2c_vbus_initialize() defined in your source code?


I’ve attached a tarball of the src here.  How should I submit it to NuttX (I haven’t followed the project closely after Greg xfer’d it).



Re: PCF8575 driver for NuttX

Posted by "Alan C. Assis" <ac...@gmail.com>.
Hi David,

On 10/6/23, David S. Alessio <da...@gmail.com> wrote:
>
>> In a quick search I noticed that i2c_vbus_initialize() never was part
>> of NuttX,
>
> OK, that’s not good.  What’s the best way to submit it now?
>

No idea, I think this function is something you created for your project.

How is i2c_vbus_initialize() defined in your source code?

BR,

Alan

Re: PCF8575 driver for NuttX

Posted by "David S. Alessio" <da...@gmail.com>.
> In a quick search I noticed that i2c_vbus_initialize() never was part
> of NuttX,

OK, that’s not good.  What’s the best way to submit it now?


Re: PCF8575 driver for NuttX

Posted by "Alan C. Assis" <ac...@gmail.com>.
Hi David,

In a quick search I noticed that i2c_vbus_initialize() never was part
of NuttX, maybe it is something you created to abstract from different
MCUs initialization.

I think we can use some similar (a generic function) to create a
boards/common/ directory to keep all I2C, SPI, devices initialization
that could be common for all boards, even for boards from different
chip families or architecture.

So, i2cbus_initialize() could be just an "alias" to
stm32_i2cbus_initialize, esp32s2_i2cbus_uninitialize,
cxd56_i2cbus_initialize(), etc, depending of what is the MCU arch of
the board.

It could simplify the sensor or other devices support as in this PCF8575 case.

BR,

Alan

On 10/5/23, David S. Alessio <da...@gmail.com> wrote:
> Hi, Alan,
>
> I don’t see my I2C virtual bus driver code in the current repo.  I’m not
> sure what happened, but I’d like to [re-] submit it.  Can you point me to
> how that’s done today?  (I’m sure email won’t work).
>
> The problem I see with the existing IOEXPANDER code is that I don’t believe
> it’s thread safe (multiple threads each hammering its own sensor on
> different sub buses).
>
> Cheers,
> -david
>
>
>> On Oct 5, 2023, at 6:18 AM, Alan C. Assis <ac...@gmail.com> wrote:
>>
>> Hi David,
>>
>> I think you figure out Gustavo's mistake.
>>
>> Gustavo, all you need to do is use the existing driver. In your code
>> you was trying to implement a low level driver to communicate with
>> your PCF8575. You don't need to do it.
>>
>> Unfortunately there is not much boards examples using IOEXPANDER (shame on
>> us).
>>
>> But I think Mateusz (raiden00) created one here:
>> boards/arm/nrf52/thingy52/src/nrf52_sx1509.c
>>
>> Just look this example and you will figure out everything.
>>
>> Basically:
>>
>> struct pcf8575_config_s g_pcf8575_cfg
>> {
>>  .address   = 0x71;      /* the I2C address returned by i2ctool */
>>  .frequency = 100000;
>> };
>>
>> ...
>>
>> int stm32_pcf8575_initialize(void)
>> {
>>  struct i2c_master_s     *i2c = NULL;
>>  struct ioexpander_dev_s *ioe = NULL;
>>  int                      ret = OK;
>>
>>  i2c = stm32_i2c_register(I2C_BUS); /* I2C_BUS is your I2Cx bus
>> number (0, 1, etc) */
>>
>>  ioe = pcf8575_initialize(i2c, &g_pcf8575_cfg);
>>  ...
>>
>> }
>>
>> BR,
>>
>> Alan
>>
>> On 10/5/23, David S. Alessio <da...@gmail.com> wrote:
>>> Hi, Gustavo,
>>>
>>> You might consider using the I2C IO expander driver I wrote some time ago
>>> to
>>> manage a multi-tiered tree of I2C bus expanders.
>>>
>>> The advantages are:
>>>  * I2C sub buses are transparently available to application space
>>> through
>>> /dev/i2c*
>>>  * transparently manages hierarch of I2C bus expanders
>>>  * downstream I2C device drivers go through the I2C character driver
>>> (pro
>>> and con)
>>>
>>> The disadvantages are:
>>>  * I2C drivers need to use the I2C character driver
>>>  * many I2C HW drivers don’t properly handle multiple command packets in
>>> I2C_TRANSFER()
>>>
>>> Example:  let’s say we have an 4-port I2C switch PCA9545A attached to
>>> /dev/i2c1 using an STM32F407 MCU.  The board initialization would be:
>>>
>>>
>>>  i2c = stm32_i2c_register(1);
>>>
>>>  /*
>>>   *    support for I2C bus epander
>>>   *    /dev/i2c1.0 -- /dev/i2c1.3
>>>   */
>>>  ret = i2c_vbus_initialize("/dev/i2c1", 0x70, I2C_VBUS_PCA9545, 0x0f, 0,
>>> NULL);
>>>  if (ret != OK)
>>>    {
>>>      syslog(LOG_ERR, "ERROR: Failed to initialize i2c_vbus %#x: %d\n",
>>> 0x70, ret);
>>>    }
>>>
>>> Now the sub bus I2C segments are transparently available as /dev/i2c1.0
>>> through /dev/i2c1.3.
>>>
>>> You can add a second PCA9545A, let’s say connected to port 2
>>> (/dev/i2c1.2)
>>> of the first PCA9545A.  It would be registered as:
>>>
>>> 	ret = i2c_vbus_initialize("/dev/i2c1.2", 0x71, I2C_VBUS_PCA9545, 0x0f,
>>> 0,
>>> NULL);
>>>
>>> and its ports would be addressable as /dev/i2c1.2.0 through
>>> /dev/i2c1.2.3.
>>>
>>> Let me know if this is something of interest to you, I’ll help you get
>>> it
>>> working...
>>>
>>> Cheers,
>>> -david
>>>
>>>
>>>
>>>> On Oct 4, 2023, at 7:36 PM, Gregory Nutt <sp...@gmail.com> wrote:
>>>>
>>>>
>>>> On 10/4/2023 8:02 PM, Gustavo Soares wrote:
>>>>> Hi Greg!
>>>>>
>>>>> Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is
>>>>> solved, but then the code loses the reference to that specific struct
>>>>> causing another error.
>>>>>
>>>>> And how exactly "the file does not exist"? I can open it and it is at
>>>>> the
>>>>> nuttx repo, I shared it's link.
>>>> Because the compiler keeps a list of paths that it will include files
>>>> from.  It will NOT include files from drivers/ioexpander because that
>>>> is
>>>> not in that include path list.  So "the file does not exists" in any
>>>> directory in the list of include paths. You could hack up  the build
>>>> system  (but no PRs for that please)or you could just copy the header
>>>> file
>>>> (a lot easier). But you cannot include it from drivers/ioexpander.
>>>> Since
>>>> this is necessarily throw-away code, the easier solution is
>>>> recommended.
>>>
>>>
>
>

Re: PCF8575 driver for NuttX

Posted by "David S. Alessio" <da...@gmail.com>.
Hi, Alan,

I don’t see my I2C virtual bus driver code in the current repo.  I’m not sure what happened, but I’d like to [re-] submit it.  Can you point me to how that’s done today?  (I’m sure email won’t work).

The problem I see with the existing IOEXPANDER code is that I don’t believe it’s thread safe (multiple threads each hammering its own sensor on different sub buses).

Cheers,
-david


> On Oct 5, 2023, at 6:18 AM, Alan C. Assis <ac...@gmail.com> wrote:
> 
> Hi David,
> 
> I think you figure out Gustavo's mistake.
> 
> Gustavo, all you need to do is use the existing driver. In your code
> you was trying to implement a low level driver to communicate with
> your PCF8575. You don't need to do it.
> 
> Unfortunately there is not much boards examples using IOEXPANDER (shame on us).
> 
> But I think Mateusz (raiden00) created one here:
> boards/arm/nrf52/thingy52/src/nrf52_sx1509.c
> 
> Just look this example and you will figure out everything.
> 
> Basically:
> 
> struct pcf8575_config_s g_pcf8575_cfg
> {
>  .address   = 0x71;      /* the I2C address returned by i2ctool */
>  .frequency = 100000;
> };
> 
> ...
> 
> int stm32_pcf8575_initialize(void)
> {
>  struct i2c_master_s     *i2c = NULL;
>  struct ioexpander_dev_s *ioe = NULL;
>  int                      ret = OK;
> 
>  i2c = stm32_i2c_register(I2C_BUS); /* I2C_BUS is your I2Cx bus
> number (0, 1, etc) */
> 
>  ioe = pcf8575_initialize(i2c, &g_pcf8575_cfg);
>  ...
> 
> }
> 
> BR,
> 
> Alan
> 
> On 10/5/23, David S. Alessio <da...@gmail.com> wrote:
>> Hi, Gustavo,
>> 
>> You might consider using the I2C IO expander driver I wrote some time ago to
>> manage a multi-tiered tree of I2C bus expanders.
>> 
>> The advantages are:
>>  * I2C sub buses are transparently available to application space through
>> /dev/i2c*
>>  * transparently manages hierarch of I2C bus expanders
>>  * downstream I2C device drivers go through the I2C character driver (pro
>> and con)
>> 
>> The disadvantages are:
>>  * I2C drivers need to use the I2C character driver
>>  * many I2C HW drivers don’t properly handle multiple command packets in
>> I2C_TRANSFER()
>> 
>> Example:  let’s say we have an 4-port I2C switch PCA9545A attached to
>> /dev/i2c1 using an STM32F407 MCU.  The board initialization would be:
>> 
>> 
>>  i2c = stm32_i2c_register(1);
>> 
>>  /*
>>   *    support for I2C bus epander
>>   *    /dev/i2c1.0 -- /dev/i2c1.3
>>   */
>>  ret = i2c_vbus_initialize("/dev/i2c1", 0x70, I2C_VBUS_PCA9545, 0x0f, 0,
>> NULL);
>>  if (ret != OK)
>>    {
>>      syslog(LOG_ERR, "ERROR: Failed to initialize i2c_vbus %#x: %d\n",
>> 0x70, ret);
>>    }
>> 
>> Now the sub bus I2C segments are transparently available as /dev/i2c1.0
>> through /dev/i2c1.3.
>> 
>> You can add a second PCA9545A, let’s say connected to port 2 (/dev/i2c1.2)
>> of the first PCA9545A.  It would be registered as:
>> 
>> 	ret = i2c_vbus_initialize("/dev/i2c1.2", 0x71, I2C_VBUS_PCA9545, 0x0f, 0,
>> NULL);
>> 
>> and its ports would be addressable as /dev/i2c1.2.0 through /dev/i2c1.2.3.
>> 
>> Let me know if this is something of interest to you, I’ll help you get it
>> working...
>> 
>> Cheers,
>> -david
>> 
>> 
>> 
>>> On Oct 4, 2023, at 7:36 PM, Gregory Nutt <sp...@gmail.com> wrote:
>>> 
>>> 
>>> On 10/4/2023 8:02 PM, Gustavo Soares wrote:
>>>> Hi Greg!
>>>> 
>>>> Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is
>>>> solved, but then the code loses the reference to that specific struct
>>>> causing another error.
>>>> 
>>>> And how exactly "the file does not exist"? I can open it and it is at the
>>>> nuttx repo, I shared it's link.
>>> Because the compiler keeps a list of paths that it will include files
>>> from.  It will NOT include files from drivers/ioexpander because that is
>>> not in that include path list.  So "the file does not exists" in any
>>> directory in the list of include paths. You could hack up  the build
>>> system  (but no PRs for that please)or you could just copy the header file
>>> (a lot easier). But you cannot include it from drivers/ioexpander. Since
>>> this is necessarily throw-away code, the easier solution is recommended.
>> 
>> 


Re: PCF8575 driver for NuttX

Posted by "Alan C. Assis" <ac...@gmail.com>.
Hi David,

I think you figure out Gustavo's mistake.

Gustavo, all you need to do is use the existing driver. In your code
you was trying to implement a low level driver to communicate with
your PCF8575. You don't need to do it.

Unfortunately there is not much boards examples using IOEXPANDER (shame on us).

But I think Mateusz (raiden00) created one here:
boards/arm/nrf52/thingy52/src/nrf52_sx1509.c

Just look this example and you will figure out everything.

Basically:

struct pcf8575_config_s g_pcf8575_cfg
{
  .address   = 0x71;      /* the I2C address returned by i2ctool */
  .frequency = 100000;
};

...

int stm32_pcf8575_initialize(void)
{
  struct i2c_master_s     *i2c = NULL;
  struct ioexpander_dev_s *ioe = NULL;
  int                      ret = OK;

  i2c = stm32_i2c_register(I2C_BUS); /* I2C_BUS is your I2Cx bus
number (0, 1, etc) */

  ioe = pcf8575_initialize(i2c, &g_pcf8575_cfg);
  ...

}

BR,

Alan

On 10/5/23, David S. Alessio <da...@gmail.com> wrote:
> Hi, Gustavo,
>
> You might consider using the I2C IO expander driver I wrote some time ago to
> manage a multi-tiered tree of I2C bus expanders.
>
> The advantages are:
>   * I2C sub buses are transparently available to application space through
> /dev/i2c*
>   * transparently manages hierarch of I2C bus expanders
>   * downstream I2C device drivers go through the I2C character driver (pro
> and con)
>
> The disadvantages are:
>   * I2C drivers need to use the I2C character driver
>   * many I2C HW drivers don’t properly handle multiple command packets in
> I2C_TRANSFER()
>
> Example:  let’s say we have an 4-port I2C switch PCA9545A attached to
> /dev/i2c1 using an STM32F407 MCU.  The board initialization would be:
>
>
>   i2c = stm32_i2c_register(1);
>
>   /*
>    *    support for I2C bus epander
>    *    /dev/i2c1.0 -- /dev/i2c1.3
>    */
>   ret = i2c_vbus_initialize("/dev/i2c1", 0x70, I2C_VBUS_PCA9545, 0x0f, 0,
> NULL);
>   if (ret != OK)
>     {
>       syslog(LOG_ERR, "ERROR: Failed to initialize i2c_vbus %#x: %d\n",
> 0x70, ret);
>     }
>
> Now the sub bus I2C segments are transparently available as /dev/i2c1.0
> through /dev/i2c1.3.
>
> You can add a second PCA9545A, let’s say connected to port 2 (/dev/i2c1.2)
> of the first PCA9545A.  It would be registered as:
>
> 	ret = i2c_vbus_initialize("/dev/i2c1.2", 0x71, I2C_VBUS_PCA9545, 0x0f, 0,
> NULL);
>
> and its ports would be addressable as /dev/i2c1.2.0 through /dev/i2c1.2.3.
>
> Let me know if this is something of interest to you, I’ll help you get it
> working...
>
> Cheers,
> -david
>
>
>
>> On Oct 4, 2023, at 7:36 PM, Gregory Nutt <sp...@gmail.com> wrote:
>>
>>
>> On 10/4/2023 8:02 PM, Gustavo Soares wrote:
>>> Hi Greg!
>>>
>>> Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is
>>> solved, but then the code loses the reference to that specific struct
>>> causing another error.
>>>
>>> And how exactly "the file does not exist"? I can open it and it is at the
>>> nuttx repo, I shared it's link.
>> Because the compiler keeps a list of paths that it will include files
>> from.  It will NOT include files from drivers/ioexpander because that is
>> not in that include path list.  So "the file does not exists" in any
>> directory in the list of include paths. You could hack up  the build
>> system  (but no PRs for that please)or you could just copy the header file
>> (a lot easier). But you cannot include it from drivers/ioexpander. Since
>> this is necessarily throw-away code, the easier solution is recommended.
>
>

Re: PCF8575 driver for NuttX

Posted by "David S. Alessio" <da...@gmail.com>.
Hi, Gustavo,

You might consider using the I2C IO expander driver I wrote some time ago to manage a multi-tiered tree of I2C bus expanders.

The advantages are:
  * I2C sub buses are transparently available to application space through /dev/i2c*
  * transparently manages hierarch of I2C bus expanders
  * downstream I2C device drivers go through the I2C character driver (pro and con)

The disadvantages are: 
  * I2C drivers need to use the I2C character driver
  * many I2C HW drivers don’t properly handle multiple command packets in I2C_TRANSFER()

Example:  let’s say we have an 4-port I2C switch PCA9545A attached to /dev/i2c1 using an STM32F407 MCU.  The board initialization would be:


  i2c = stm32_i2c_register(1);

  /*
   *    support for I2C bus epander
   *    /dev/i2c1.0 -- /dev/i2c1.3
   */
  ret = i2c_vbus_initialize("/dev/i2c1", 0x70, I2C_VBUS_PCA9545, 0x0f, 0, NULL);
  if (ret != OK)
    {
      syslog(LOG_ERR, "ERROR: Failed to initialize i2c_vbus %#x: %d\n", 0x70, ret);
    }

Now the sub bus I2C segments are transparently available as /dev/i2c1.0 through /dev/i2c1.3.

You can add a second PCA9545A, let’s say connected to port 2 (/dev/i2c1.2) of the first PCA9545A.  It would be registered as:

	ret = i2c_vbus_initialize("/dev/i2c1.2", 0x71, I2C_VBUS_PCA9545, 0x0f, 0, NULL);

and its ports would be addressable as /dev/i2c1.2.0 through /dev/i2c1.2.3.

Let me know if this is something of interest to you, I’ll help you get it working...

Cheers,
-david



> On Oct 4, 2023, at 7:36 PM, Gregory Nutt <sp...@gmail.com> wrote:
> 
> 
> On 10/4/2023 8:02 PM, Gustavo Soares wrote:
>> Hi Greg!
>> 
>> Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is solved, but then the code loses the reference to that specific struct causing another error.
>> 
>> And how exactly "the file does not exist"? I can open it and it is at the nuttx repo, I shared it's link.
> Because the compiler keeps a list of paths that it will include files from.  It will NOT include files from drivers/ioexpander because that is not in that include path list.  So "the file does not exists" in any directory in the list of include paths. You could hack up  the build system  (but no PRs for that please)or you could just copy the header file (a lot easier). But you cannot include it from drivers/ioexpander. Since this is necessarily throw-away code, the easier solution is recommended.


Re: PCF8575 driver for NuttX

Posted by Gregory Nutt <sp...@gmail.com>.
On 10/4/2023 8:02 PM, Gustavo Soares wrote:
> Hi Greg!
>
> Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is solved, but then the code loses the reference to that specific struct causing another error.
>
> And how exactly "the file does not exist"? I can open it and it is at the nuttx repo, I shared it's link.
Because the compiler keeps a list of paths that it will include files 
from.  It will NOT include files from drivers/ioexpander because that is 
not in that include path list.  So "the file does not exists" in any 
directory in the list of include paths. You could hack up  the build 
system  (but no PRs for that please)or you could just copy the header 
file (a lot easier). But you cannot include it from drivers/ioexpander. 
Since this is necessarily throw-away code, the easier solution is 
recommended.

Re: PCF8575 driver for NuttX

Posted by Gustavo Soares <gu...@hotmail.com>.
Hi Greg!

Yes, if I use #include <nuttx/ioexpander/pcf8575.h> this problem is solved, but then the code loses the reference to that specific struct causing another error.

And how exactly "the file does not exist"? I can open it and it is at the nuttx repo, I shared it's link.

________________________________
From: Gregory Nutt <sp...@gmail.com>
Sent: Wednesday, October 4, 2023 10:52:32 PM
To: dev@nuttx.apache.org <de...@nuttx.apache.org>
Subject: Re: PCF8575 driver for NuttX



>>> Why wouldn't the compiler access nuttx/drivers/ioexpander/pcf8575.h?
>>>
>> Access to internal driver files by applications is specifically
>> forbidden.  This is part of the enforcement of the modular design to
>> assure that people do not do that kind of thing:  Applications must
>> not have access to the internal implementation of drivers.
>>
>>
> Never mind,  I misread the ultra tiny fonts in the image.
> include/nuttx/ holds the public interface to the driver (vs. the
> internal private definitions for the driver in drivers/). Anything
> under include/ should be include-able by your application.


Actually, the problem is very simple.  This file does not exist.


#include <nuttx/drivers/ioexpander/pcf8575.h>


You probably wanted


#include <nuttx/ioexpander/pcf8575.h>



Re: PCF8575 driver for NuttX

Posted by Gregory Nutt <sp...@gmail.com>.

>>> Why wouldn't the compiler access nuttx/drivers/ioexpander/pcf8575.h?
>>>
>> Access to internal driver files by applications is specifically 
>> forbidden.  This is part of the enforcement of the modular design to 
>> assure that people do not do that kind of thing:  Applications must 
>> not have access to the internal implementation of drivers.
>>
>>
> Never mind,  I misread the ultra tiny fonts in the image. 
> include/nuttx/ holds the public interface to the driver (vs. the 
> internal private definitions for the driver in drivers/). Anything 
> under include/ should be include-able by your application.


Actually, the problem is very simple.  This file does not exist.


#include <nuttx/drivers/ioexpander/pcf8575.h>


You probably wanted


#include <nuttx/ioexpander/pcf8575.h>


Re: PCF8575 driver for NuttX

Posted by Gregory Nutt <sp...@gmail.com>.

>> Why wouldn't the compiler access nuttx/drivers/ioexpander/pcf8575.h?
>>
> Access to internal driver files by applications is specifically 
> forbidden.  This is part of the enforcement of the modular design to 
> assure that people do not do that kind of thing: Applications must not 
> have access to the internal implementation of drivers.
>
>
Never mind,  I misread the ultra tiny fonts in the image. include/nuttx/ 
holds the public interface to the driver (vs. the internal private 
definitions for the driver in drivers/).  Anything under include/ should 
be include-able by your application.

Re: PCF8575 driver for NuttX

Posted by Gregory Nutt <sp...@gmail.com>.
On 10/4/2023 7:02 PM, Gustavo Soares wrote:
> Why wouldn't the compiler access nuttx/drivers/ioexpander/pcf8575.h?
>
Access to internal driver files by applications is specifically 
forbidden.  This is part of the enforcement of the modular design to 
assure that people do not do that kind of thing:  Applications must not 
have access to the internal implementation of drivers.


Re: PCF8575 driver for NuttX

Posted by Michal Lenc <mi...@seznam.cz>.
Hi,


Perhaps I am too late to the discussion and some of those stuffs were 
already said but I use PCF8575 on a custom board so I think a can help a bit
with that.

> I'm trying to access the PCF8575 device from my application on NuttX to 
make it light up LEDs. I'm not really sure how to implement it, but this is 
what I've got:

The easiest way if you want to use PCF8575 for LEDs is to register those as 
GPIOs using CONFIG_GPIO_LOWER_HALF. First you have to initialize I2C and 
register the expander (you can do it in BSP layer).




struct pcf8575_config_s g_pcf8575_cfg =

{ 

  .address     = PCF8575_I2C_ADDRESS, 

  .frequency  = PCF8575_I2C_FREQ, 

}; 




struct i2c_master_s *i2c;
struct ioexpander_dev_s *ioe;


i2c = sam_i2cbus_initialize(TWIHS0_BUS);

ioe = pcf8575_initialize(i2c, &g_pcf8575_cfg);




Then you can register the pins.




IOEXP_SETDIRECTION(ioe, 0, IOEXPANDER_DIRECTION_OUT);

gpio_lower_half_byname(ioe, 0, GPIO_OUTPUT_PIN, "led_red");

IOEXP_WRITEPIN(ioe, 0, 1);  





etc.




The pin is registered as dev/led_red and you can access it from your 
application using classic GPIO interface (take a look at examples/gpio). 
Writing multiple pins is a bit trickier, you can use IOEXP_MULTIWRITEPIN but
this requires ioexpander_dev_s structure to be available in application 
layer (which is possible, but you would have to do the whole

initialization in application layer and as someone already mentioned, this 
might not be thread safe).




But accessing pins one by one should be straightforward with CONFIG_GPIO_
LOWER_HALF option. Hope this helps.




Best regards,

Michal Lenc