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 <acas...@gmail.com> Enviado: sexta-feira, 6 de outubro de 2023 10:36 Para: dev@nuttx.apache.org <dev@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 <david.s.ales...@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 <acas...@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 <david.s.ales...@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 <spudan...@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. >>> >>> > >
#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; }