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 <[email protected]>
Enviado: sexta-feira, 6 de outubro de 2023 10:36
Para: [email protected] <[email protected]>
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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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.
>>>
>>>
>
>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/ioexpander/pcf8575.h>
#include <nuttx/ioexpander/ioexpander.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define PCF8575_I2C_BUS 1
#define PCF8575_I2C_ADDR 0x20
#define PCF8575_I2C_MAXFREQUENCY 400000
#define OK 0
struct pcf8575_config_s config =
{
.address = PCF8575_I2C_ADDR,
.frequency = PCF8575_I2C_MAXFREQUENCY
};
static void pcf8575_pinscfg(struct ioexpander_dev_s *dev)
{
}
int main(void) //stm32_pcf8575_initialize(void)
{
struct i2c_master_s *i2c = NULL;
struct ioexpander_dev_s *ioe = NULL;
int ret = OK;
ret = i2c_register(i2c, PCF8575_I2C_BUS); // stm32_i2c_register()?
if(ret != OK)
{
perror("Could not register i2c");
return -1;
}
ioe = pcf8575_initialize(i2c, &config);
if (!ioe)
{
perror("Could not init PCF8575");
return -1;
}
pcf8575_pinscfg(ioe);
//return I2C_TRANSFER(ioe, , 1);
return 1;
}