Skip to content

Commit 835ba0e

Browse files
authored
add i2c_master (#280)
1 parent 7354f2b commit 835ba0e

File tree

3 files changed

+153
-16
lines changed

3 files changed

+153
-16
lines changed

cparser.nim

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,22 +1135,63 @@ proc parseStructBody(p: var Parser, stmtList: PNode,
11351135
# handle anonymous unions / structs
11361136
if p.tok.xkind == pxSemiColon:
11371137
if pfAnonymousAsFields in p.options.flags:
1138-
let tdef = sstmts[^1][0]
1139-
let odef = tdef[2]
1140-
for i in 0..<sstmts.len-1:
1141-
stmtList.add(sstmts[i])
1142-
let rlist = odef[2]
1143-
for field in rlist:
1144-
if gotUnion and field[0][0].kind == nkPostfix and
1145-
not startsWith($(field[0][0][1]),"ano_"):
1146-
let name = "anon" & $cntAnonUnions & "_" & $field[0][0][1]
1147-
field[0][0][1] = newIdentNodeP(name, p)
1148-
elif gotUnion and
1149-
not startsWith($(field[0][1]),"ano_"):
1150-
let name = "anon" & $cntAnonUnions & "_" & $field[0][1]
1151-
field[0][1] = newIdentNodeP(name, p)
1152-
result.add(field)
1153-
getTok(p, nil)
1138+
# Be defensive: inner struct/union may yield no typesection
1139+
# (e.g. due to preprocessing oddities). If so, fall back to
1140+
# emitting a regular anonymous field instead of flattening.
1141+
if sstmts.len > 0 and sstmts[^1].len > 0:
1142+
let tdef = sstmts[^1][0]
1143+
if tdef.len > 2:
1144+
let odef = tdef[2]
1145+
for i in 0..<sstmts.len-1:
1146+
stmtList.add(sstmts[i])
1147+
if odef.len > 2:
1148+
let rlist = odef[2]
1149+
for field in rlist:
1150+
# Only handle actual field definitions; pass others through
1151+
if field.kind == nkIdentDefs and field.len > 0 and gotUnion:
1152+
let nameNode = field[0]
1153+
if nameNode.kind == nkPostfix:
1154+
# postfix form like: name*
1155+
if not startsWith($(nameNode[1]), "ano_"):
1156+
let name = "anon" & $cntAnonUnions & "_" & $nameNode[1]
1157+
nameNode[1] = newIdentNodeP(name, p)
1158+
elif nameNode.kind == nkIdent:
1159+
if not startsWith($(nameNode), "ano_"):
1160+
let name = "anon" & $cntAnonUnions & "_" & $nameNode
1161+
# Replace the ident in place
1162+
field[0] = newIdentNodeP(name, p)
1163+
result.add(field)
1164+
getTok(p, nil)
1165+
else:
1166+
# Structure node unexpected; degrade gracefully
1167+
let def = newNodeP(nkIdentDefs, p)
1168+
var t = pointer(p, baseTyp)
1169+
let i = fieldIdent("ano_" & p.hashPosition, p)
1170+
t = parseTypeSuffix(p, t)
1171+
addSon(def, i, t, emptyNode)
1172+
addSon(result, def)
1173+
getTok(p, nil)
1174+
stmtList.add(sstmts)
1175+
else:
1176+
# Missing expected child nodes; fallback to anonymous field
1177+
let def = newNodeP(nkIdentDefs, p)
1178+
var t = pointer(p, baseTyp)
1179+
let i = fieldIdent("ano_" & p.hashPosition, p)
1180+
t = parseTypeSuffix(p, t)
1181+
addSon(def, i, t, emptyNode)
1182+
addSon(result, def)
1183+
getTok(p, nil)
1184+
stmtList.add(sstmts)
1185+
else:
1186+
# No statements collected for inner type; fallback
1187+
let def = newNodeP(nkIdentDefs, p)
1188+
var t = pointer(p, baseTyp)
1189+
let i = fieldIdent("ano_" & p.hashPosition, p)
1190+
t = parseTypeSuffix(p, t)
1191+
addSon(def, i, t, emptyNode)
1192+
addSon(result, def)
1193+
getTok(p, nil)
1194+
stmtList.add(sstmts)
11541195
else:
11551196
let def = newNodeP(nkIdentDefs, p)
11561197
var t = pointer(p, baseTyp)

testsuite/results/i2c_master.nim

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
##
2+
## SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
3+
##
4+
## SPDX-License-Identifier: Apache-2.0
5+
##
6+
7+
import
8+
esp_err, driver/i2c_types, hal/gpio_types
9+
10+
##
11+
## @brief I2C master bus specific configurations
12+
##
13+
14+
type
15+
INNER_C_STRUCT_i2c_master_3* {.bycopy.} = object
16+
enable_internal_pullup* {.bitsize: 1.}: uint32_t
17+
## !< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible
18+
allow_pd* {.bitsize: 1.}: uint32_t
19+
## !< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode.
20+
## By this approach, the system can power off I2C's power domain.
21+
## This can save power, but at the expense of more RAM being consumed
22+
23+
i2c_master_bus_config_t* {.bycopy.} = object
24+
i2c_port*: i2c_port_num_t
25+
## !< I2C port number, `-1` for auto selecting, (not include LP I2C instance)
26+
sda_io_num*: gpio_num_t
27+
## !< GPIO number of I2C SDA signal, pulled-up internally
28+
scl_io_num*: gpio_num_t
29+
## !< GPIO number of I2C SCL signal, pulled-up internally
30+
anon2_clk_source*: i2c_clock_source_t
31+
## !< Clock source of I2C master bus
32+
when SOC_LP_I2C_SUPPORTED:
33+
var lp_source_clk*: lp_i2c_clock_source_t
34+
## !< LP_UART source clock selection
35+
glitch_ignore_cnt*: uint8_t
36+
## !< 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)
37+
intr_priority*: cint
38+
## !< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3).
39+
trans_queue_depth*: csize_t
40+
## !< 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)
41+
flags*: INNER_C_STRUCT_i2c_master_3
42+
## !< I2C master config flags
43+
44+
45+
const
46+
I2C_DEVICE_ADDRESS_NOT_USED* = (0xffff) ## !< Skip carry address bit in driver transmit and receive

testsuite/tests/i2c_master.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#anonymousAsFields
8+
9+
10+
#pragma once
11+
12+
#include <stdint.h>
13+
#include "esp_err.h"
14+
#include "driver/i2c_types.h"
15+
#include "hal/gpio_types.h"
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
/**
22+
* @brief I2C master bus specific configurations
23+
*/
24+
typedef struct {
25+
i2c_port_num_t i2c_port; /*!< I2C port number, `-1` for auto selecting, (not include LP I2C instance) */
26+
gpio_num_t sda_io_num; /*!< GPIO number of I2C SDA signal, pulled-up internally */
27+
gpio_num_t scl_io_num; /*!< GPIO number of I2C SCL signal, pulled-up internally */
28+
union {
29+
i2c_clock_source_t clk_source; /*!< Clock source of I2C master bus */
30+
#if SOC_LP_I2C_SUPPORTED
31+
lp_i2c_clock_source_t lp_source_clk; /*!< LP_UART source clock selection */
32+
#endif
33+
};
34+
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)*/
35+
int intr_priority; /*!< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). */
36+
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)*/
37+
struct {
38+
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 */
39+
uint32_t allow_pd: 1; /*!< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode.
40+
By this approach, the system can power off I2C's power domain.
41+
This can save power, but at the expense of more RAM being consumed */
42+
} flags; /*!< I2C master config flags */
43+
} i2c_master_bus_config_t;
44+
45+
#define I2C_DEVICE_ADDRESS_NOT_USED (0xffff) /*!< Skip carry address bit in driver transmit and receive */
46+
47+
48+
#ifdef __cplusplus
49+
}
50+
#endif

0 commit comments

Comments
 (0)