Search code examples
c++arduinoesp32i2chardware

Could not initialize my i2c_config_t structure


According to the i2C.h as follows:


/**
 * @brief I2C initialization parameters
 */
typedef struct{
    i2c_mode_t mode;       /*!< I2C mode */
    gpio_num_t sda_io_num;        /*!< GPIO number for I2C sda signal */
    gpio_pullup_t sda_pullup_en;  /*!< Internal GPIO pull mode for I2C sda signal*/
    gpio_num_t scl_io_num;        /*!< GPIO number for I2C scl signal */
    gpio_pullup_t scl_pullup_en;  /*!< Internal GPIO pull mode for I2C scl signal*/

    union {
        struct {
            uint32_t clk_speed;     /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
        } master;
        struct {
            uint8_t addr_10bit_en;  /*!< I2C 10bit address mode enable for slave mode */
            uint16_t slave_addr;    /*!< I2C address for slave mode */
        } slave;

    };
}i2c_config_t;

I wrote the following assignment:

    const i2c_port_t i2c_master_port = (i2c_port_t)I2C_MASTER_NUM;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE,
        .scl_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE,
        .master = {.clk_speed = I2C_MASTER_FREQ_HZ},
    };

Which reports 2 errors (sorry its in French so I added my own translation into English):

At line .sda_pullup_en (translated as: "Out-of-order initializers are not standard in C++"):


[{

    "code": "2904",
    "severity": 8,
    "message": "les initialiseurs hors service ne sont pas standard en C++",
    "source": "C/C++",
    "startLineNumber": 103,
    "startColumn": 9,
    "endLineNumber": 103,
    "endColumn": 9
}

At line .master (translated as: "a designator for an anonymous union member can only appear between braces that match that anonymous union"):

    "owner": "C/C++",
    "code": "2358",
    "severity": 8,
    "message": "un désignateur pour un membre d'union anonyme peut uniquement apparaître entre des accolades qui correspondent à cette union anonyme",
    "source": "C/C++",
    "startLineNumber": 105,
    "startColumn": 9,
    "endLineNumber": 105,
    "endColumn": 9
}]

[UPDATE] My initial code writings was as follows:

 i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE,
        .scl_pullup_en = (gpio_pullup_t)GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ
    };

And were producing those two errors:

At .sda_pullup_en = line (109) (translated as: "out of order initializers are not standard in C++"):

[{
    "owner": "C/C++",
    "code": "2904",
    "severity": 8,
    "message": "les initialiseurs hors service ne sont pas standard en C++",
    "source": "C/C++",
    "startLineNumber": 109,
    "startColumn": 3,
    "endLineNumber": 109,
    "endColumn": 3
}]

At .master.clk_speed = line (111), translated as:

  • a designator for an anonymous union member can only appear between braces that match that anonymous union
  • expected primary-expression before '.' token
  • class "i2c_config_t" has no "clk_speed" field
[{

    "owner": "C/C++",
    "code": "2358",
    "severity": 8,
    "message": "un désignateur pour un membre d'union anonyme peut uniquement apparaître entre des accolades qui correspondent à cette union anonyme",
    "source": "C/C++",
    "startLineNumber": 111,
    "startColumn": 3,
    "endLineNumber": 111,
    "endColumn": 3
},{

    "owner": "cpp",
    "severity": 8,
    "message": "expected primary-expression before '.' token",
    "startLineNumber": 111,
    "startColumn": 3,
    "endLineNumber": 111,
    "endColumn": 3
},{

    "owner": "C/C++",
    "code": "136",
    "severity": 8,
    "message": "classe \"i2c_config_t\" n'a pas de champ \"clk_speed\"",
    "source": "C/C++",
    "startLineNumber": 111,
    "startColumn": 10,
    "endLineNumber": 111,
    "endColumn": 10
}]

How to fix my code?


Solution

  • @hcheung gave the right answer about the order of the members.

    But regarding the anonymous union, his solution does not work.

    I finally came up with the solution:

    i2c_config_t conf = {
            .mode = I2C_MODE_MASTER,
            .sda_io_num = I2C_MASTER_SDA_IO,
            .sda_pullup_en = GPIO_PULLUP_ENABLE,
            .scl_io_num = I2C_MASTER_SCL_IO,
            .scl_pullup_en = GPIO_PULLUP_ENABLE,
            { {I2C_MASTER_FREQ_HZ}}
        };
    

    Anonymous union are not standard but compiler extension and should actually be named. But here, the struct belongs to a third-party lib I cannot update.

    So the solution is that I need to put an open curry braces to catch the first member of the union and then provide the value I am interested in. Very important to note that it sounds we can only reach the first union member as we can't name it.

    Additional note: You can also be explicit about the clock speed as follows:

    i2c_config_t conf = {
            .mode = I2C_MODE_MASTER,
            .sda_io_num = I2C_MASTER_SDA_IO,
            .sda_pullup_en = GPIO_PULLUP_ENABLE,
            .scl_io_num = I2C_MASTER_SCL_IO,
            .scl_pullup_en = GPIO_PULLUP_ENABLE,
            {{.clk_speed = I2C_MASTER_FREQ_HZ}}
        };