Reputation: 13621
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:
[{
"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?
Upvotes: 1
Views: 667
Reputation: 13621
@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}}
};
Upvotes: 0
Reputation: 4034
For the first error, it means the "designator order for field .sda_pullup_en
in your config
does not match declaration order in i2c_config_t
.
A struct is a series of data with various data type in sequence, in your i2c_config_t
, the sequence(the order of different data) is
typedef struct{
i2c_mode_t mode;
gpio_num_t sda_io_num;
gpio_pullup_t sda_pullup_en;
...
}i2c_config_t;
While when you using it in your config
, you change the order of the members within the struct which caused the first error because the data would not aligned with its definition:
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO, // this is out of order from i2c_config_t
...
};
For your second error, the error message "a designator for an anonymous union member can only appear between braces that match that anonymous union" is clear, but your usage is wrong, the master
is a struct within a struct, so with the braces notation, it should be:
i2c_config_t conf = {
.master {.clk_speed = I2C_MASTER_FREQ_HZ}
};
In summary, this is the snippet with both errors corrected and should works.
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,
.master {.clk_speed = I2C_MASTER_FREQ_HZ}
};
Upvotes: 2