From 9cd031dfe52aca698247ab94ec137cd73557720b Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 27 Aug 2025 21:06:20 -0600 Subject: [PATCH] add i2c_master --- cparser.nim | 73 +++++++++++++++++++++++++------- testsuite/results/i2c_master.nim | 46 ++++++++++++++++++++ testsuite/tests/i2c_master.h | 50 ++++++++++++++++++++++ 3 files changed, 153 insertions(+), 16 deletions(-) create mode 100644 testsuite/results/i2c_master.nim create mode 100644 testsuite/tests/i2c_master.h diff --git a/cparser.nim b/cparser.nim index 876d1e0..4baf22d 100644 --- a/cparser.nim +++ b/cparser.nim @@ -1135,22 +1135,63 @@ proc parseStructBody(p: var Parser, stmtList: PNode, # handle anonymous unions / structs if p.tok.xkind == pxSemiColon: if pfAnonymousAsFields in p.options.flags: - let tdef = sstmts[^1][0] - let odef = tdef[2] - for i in 0.. 0 and sstmts[^1].len > 0: + let tdef = sstmts[^1][0] + if tdef.len > 2: + let odef = tdef[2] + for i in 0.. 2: + let rlist = odef[2] + for field in rlist: + # Only handle actual field definitions; pass others through + if field.kind == nkIdentDefs and field.len > 0 and gotUnion: + let nameNode = field[0] + if nameNode.kind == nkPostfix: + # postfix form like: name* + if not startsWith($(nameNode[1]), "ano_"): + let name = "anon" & $cntAnonUnions & "_" & $nameNode[1] + nameNode[1] = newIdentNodeP(name, p) + elif nameNode.kind == nkIdent: + if not startsWith($(nameNode), "ano_"): + let name = "anon" & $cntAnonUnions & "_" & $nameNode + # Replace the ident in place + field[0] = newIdentNodeP(name, p) + result.add(field) + getTok(p, nil) + else: + # Structure node unexpected; degrade gracefully + let def = newNodeP(nkIdentDefs, p) + var t = pointer(p, baseTyp) + let i = fieldIdent("ano_" & p.hashPosition, p) + t = parseTypeSuffix(p, t) + addSon(def, i, t, emptyNode) + addSon(result, def) + getTok(p, nil) + stmtList.add(sstmts) + else: + # Missing expected child nodes; fallback to anonymous field + let def = newNodeP(nkIdentDefs, p) + var t = pointer(p, baseTyp) + let i = fieldIdent("ano_" & p.hashPosition, p) + t = parseTypeSuffix(p, t) + addSon(def, i, t, emptyNode) + addSon(result, def) + getTok(p, nil) + stmtList.add(sstmts) + else: + # No statements collected for inner type; fallback + let def = newNodeP(nkIdentDefs, p) + var t = pointer(p, baseTyp) + let i = fieldIdent("ano_" & p.hashPosition, p) + t = parseTypeSuffix(p, t) + addSon(def, i, t, emptyNode) + addSon(result, def) + getTok(p, nil) + stmtList.add(sstmts) else: let def = newNodeP(nkIdentDefs, p) var t = pointer(p, baseTyp) diff --git a/testsuite/results/i2c_master.nim b/testsuite/results/i2c_master.nim new file mode 100644 index 0000000..fdd2b38 --- /dev/null +++ b/testsuite/results/i2c_master.nim @@ -0,0 +1,46 @@ +## +## SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +## +## SPDX-License-Identifier: Apache-2.0 +## + +import + esp_err, driver/i2c_types, hal/gpio_types + +## +## @brief I2C master bus specific configurations +## + +type + INNER_C_STRUCT_i2c_master_3* {.bycopy.} = object + enable_internal_pullup* {.bitsize: 1.}: uint32_t + ## !< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible + allow_pd* {.bitsize: 1.}: uint32_t + ## !< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode. + ## By this approach, the system can power off I2C's power domain. + ## This can save power, but at the expense of more RAM being consumed + + i2c_master_bus_config_t* {.bycopy.} = object + i2c_port*: i2c_port_num_t + ## !< I2C port number, `-1` for auto selecting, (not include LP I2C instance) + sda_io_num*: gpio_num_t + ## !< GPIO number of I2C SDA signal, pulled-up internally + scl_io_num*: gpio_num_t + ## !< GPIO number of I2C SCL signal, pulled-up internally + anon2_clk_source*: i2c_clock_source_t + ## !< Clock source of I2C master bus + when SOC_LP_I2C_SUPPORTED: + var lp_source_clk*: lp_i2c_clock_source_t + ## !< LP_UART source clock selection + glitch_ignore_cnt*: uint8_t + ## !< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle) + intr_priority*: cint + ## !< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). + trans_queue_depth*: csize_t + ## !< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction) + flags*: INNER_C_STRUCT_i2c_master_3 + ## !< I2C master config flags + + +const + I2C_DEVICE_ADDRESS_NOT_USED* = (0xffff) ## !< Skip carry address bit in driver transmit and receive diff --git a/testsuite/tests/i2c_master.h b/testsuite/tests/i2c_master.h new file mode 100644 index 0000000..52a1413 --- /dev/null +++ b/testsuite/tests/i2c_master.h @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#anonymousAsFields + + +#pragma once + +#include +#include "esp_err.h" +#include "driver/i2c_types.h" +#include "hal/gpio_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief I2C master bus specific configurations + */ +typedef struct { + i2c_port_num_t i2c_port; /*!< I2C port number, `-1` for auto selecting, (not include LP I2C instance) */ + gpio_num_t sda_io_num; /*!< GPIO number of I2C SDA signal, pulled-up internally */ + gpio_num_t scl_io_num; /*!< GPIO number of I2C SCL signal, pulled-up internally */ + union { + i2c_clock_source_t clk_source; /*!< Clock source of I2C master bus */ +#if SOC_LP_I2C_SUPPORTED + lp_i2c_clock_source_t lp_source_clk; /*!< LP_UART source clock selection */ +#endif + }; + uint8_t glitch_ignore_cnt; /*!< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle)*/ + int intr_priority; /*!< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). */ + size_t trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction)*/ + struct { + uint32_t enable_internal_pullup: 1; /*!< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible */ + uint32_t allow_pd: 1; /*!< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode. + By this approach, the system can power off I2C's power domain. + This can save power, but at the expense of more RAM being consumed */ + } flags; /*!< I2C master config flags */ +} i2c_master_bus_config_t; + +#define I2C_DEVICE_ADDRESS_NOT_USED (0xffff) /*!< Skip carry address bit in driver transmit and receive */ + + +#ifdef __cplusplus +} +#endif