Skip to content

Commit edf069d

Browse files
committed
Add BUSIO.I2C and MAX32690 I2C structure
- Data structure and constructor for I2C (tested) - Lock and probing functions complete and tested TODO: Implement I2C Write, Read, Wr/Rd Signed-off-by: Brandon-Hurst <[email protected]>
1 parent 68d8daa commit edf069d

File tree

6 files changed

+193
-14
lines changed

6 files changed

+193
-14
lines changed

ports/analog/Makefile

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ INC += \
8686
-I$(PERIPH_SRC)/ICC \
8787
-I$(PERIPH_SRC)/TMR \
8888
-I$(PERIPH_SRC)/RTC \
89-
-I$(PERIPH_SRC)/UART
89+
-I$(PERIPH_SRC)/UART \
90+
-I$(PERIPH_SRC)/I2C
9091

9192
INC += -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC
9293

@@ -119,14 +120,18 @@ SRC_MAX32 += \
119120
$(PERIPH_SRC)/TMR/tmr_$(DIE_TYPE).c \
120121
$(PERIPH_SRC)/UART/uart_common.c \
121122
$(PERIPH_SRC)/UART/uart_$(DIE_TYPE).c \
122-
$(PERIPH_SRC)/UART/uart_revb.c
123+
$(PERIPH_SRC)/UART/uart_revb.c \
124+
$(PERIPH_SRC)/I2C/i2c_$(DIE_TYPE).c \
125+
$(PERIPH_SRC)/I2C/i2c_reva.c
123126

124127
SRC_C += $(SRC_MAX32) \
125128
boards/$(BOARD)/board.c \
126129
boards/$(BOARD)/pins.c \
127130
peripherals/$(MCU_VARIANT_LOWER)/pins.c \
128131
peripherals/$(MCU_VARIANT_LOWER)/gpios.c \
129-
peripherals/$(MCU_VARIANT_LOWER)/max32_uart.c
132+
peripherals/$(MCU_VARIANT_LOWER)/max32_uart.c \
133+
peripherals/$(MCU_VARIANT_LOWER)/max32_i2c.c
134+
130135

131136
# *******************************************************************************
132137
### Compiler & Linker Flags ###
@@ -267,6 +272,11 @@ flash-msdk:
267272
-f interface/cmsis-dap.cfg -f target/$(MCU_VARIANT_LOWER).cfg \
268273
-c "program $(BUILD)/firmware.elf verify; init; reset; exit"
269274

275+
flash-openocd-jlink:
276+
$(OPENOCD) -s $(OPENOCD_SCRIPTS) \
277+
-f interface/jlink.cfg -f target/$(MCU_VARIANT_LOWER).cfg \
278+
-c "program $(BUILD)/firmware.elf verify; init; reset; exit"
279+
270280
# flash target using JLink
271281
JLINK_DEVICE = $(MCU_VARIANT_LOWER)
272282

ports/analog/common-hal/busio/I2C.c

Lines changed: 122 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,103 @@
3030
#include "shared-bindings/microcontroller/__init__.h"
3131
#include "shared-bindings/microcontroller/Pin.h"
3232

33-
static bool in_used = false;
33+
#include "max32_port.h"
34+
35+
#define I2C_PRIORITY 1
36+
37+
typedef enum {
38+
I2C_FREE = 0,
39+
I2C_BUSY,
40+
I2C_NEVER_RESET,
41+
} i2c_status_t;
42+
43+
// Set each bit to indicate an active UART
44+
// will be checked by ISR Handler for which ones to call
45+
static uint8_t i2c_active = 0;
46+
static i2c_status_t i2c_status[NUM_I2C];
47+
static volatile int i2c_err;
48+
49+
// I2C Interrupt Handler
50+
void i2c_isr(void) {
51+
for (int i = 0; i < NUM_I2C; i++) {
52+
if (i2c_active & (1 << i)) {
53+
// NOTE: I2C_GET_TMR actually returns the I2C registers
54+
MXC_I2C_AsyncHandler(MXC_I2C_GET_I2C(i));
55+
}
56+
}
57+
}
58+
59+
// Callback gets called when AsyncRequest is COMPLETE
60+
// (e.g. txLen == txCnt)
61+
// static volatile void i2cCallback(mxc_i2c_req_t *req, int error) {
62+
// i2c_status[MXC_I2C_GET_IDX(req->i2c)] = I2C_FREE;
63+
// i2c_err = error;
64+
// }
3465

3566
// Construct I2C protocol, this function init i2c peripheral
3667
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
3768
const mcu_pin_obj_t *scl,
3869
const mcu_pin_obj_t *sda,
3970
uint32_t frequency, uint32_t timeout) {
4071

41-
72+
int temp, err = 0;
73+
74+
// Check for NULL Pointers && valid I2C settings
75+
assert(self);
76+
77+
// Assign I2C ID based on pins
78+
temp = pinsToI2c(sda, scl);
79+
if (temp == -1) {
80+
// Error will be indicated by pinsToUart(tx, rx) function
81+
return;
82+
} else {
83+
self->i2c_id = temp;
84+
self->i2c_regs = MXC_I2C_GET_I2C(temp);
85+
}
86+
87+
assert((self->i2c_id >= 0) && (self->i2c_id < NUM_I2C));
88+
89+
// Init I2C as main / controller node (0x00 is ignored)
90+
if ((scl != NULL) && (sda != NULL)) {
91+
err = MXC_I2C_Init(self->i2c_regs, 1, 0x00);
92+
if (err) {
93+
mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to init I2C.\n"));
94+
}
95+
err = MXC_I2C_SetFrequency(self->i2c_regs, frequency);
96+
if (err < 0) {
97+
mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to set I2C frequency\n"));
98+
}
99+
} else if (scl != NULL) {
100+
mp_raise_NotImplementedError(MP_ERROR_TEXT("I2C needs SDA & SCL"));
101+
} else if (sda != NULL) {
102+
mp_raise_NotImplementedError(MP_ERROR_TEXT("I2C needs SDA & SCL"));
103+
} else {
104+
// Should not get here, as shared-bindings API should not call this way
105+
}
106+
107+
// Attach I2C pins
108+
self->sda = sda;
109+
self->scl = scl;
110+
common_hal_mcu_pin_claim(self->sda);
111+
common_hal_mcu_pin_claim(self->scl);
112+
113+
// Indicate to this module that the I2C is active
114+
i2c_active |= (1 << self->i2c_id);
115+
116+
// Set the timeout to a default value
117+
if (((timeout < 0.0) || (timeout > 100.0))) {
118+
self->timeout = 1.0;
119+
} else {
120+
self->timeout = timeout;
121+
}
122+
123+
/* Setup I2C interrupt */
124+
NVIC_ClearPendingIRQ(MXC_I2C_GET_IRQ(self->i2c_id));
125+
NVIC_DisableIRQ(MXC_I2C_GET_IRQ(self->i2c_id));
126+
NVIC_SetPriority(MXC_I2C_GET_IRQ(self->i2c_id), I2C_PRIORITY);
127+
NVIC_SetVector(MXC_I2C_GET_IRQ(self->i2c_id), (uint32_t)i2c_isr);
128+
129+
return;
42130
}
43131

44132
// Never reset I2C obj when reload
@@ -54,7 +142,13 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
54142

55143
// Deinit i2c obj, reset I2C pin
56144
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
57-
// FIXME: Implement
145+
MXC_I2C_Shutdown(self->i2c_regs);
146+
147+
common_hal_reset_pin(self->sda);
148+
common_hal_reset_pin(self->scl);
149+
150+
self->sda = NULL;
151+
self->scl = NULL;
58152
}
59153

60154
void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) {
@@ -63,17 +157,36 @@ void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) {
63157

64158
// Probe device in I2C bus
65159
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
66-
// FIXME: Implement
67-
68-
return true;
160+
int nack = 0;
161+
162+
mxc_i2c_req_t addr_req = {
163+
.addr = addr,
164+
.i2c = self->i2c_regs,
165+
.tx_len = 0,
166+
.tx_buf = NULL,
167+
.rx_len = 0,
168+
.rx_buf = NULL,
169+
.callback = NULL
170+
};
171+
172+
// Probe the address
173+
nack = MXC_I2C_MasterTransaction(&addr_req);
174+
if (nack) {
175+
return false;
176+
} else {
177+
return true;
178+
}
69179
}
70180

71181
// Lock I2C bus
72182
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
73183

74-
// FIXME: Implement
75-
76-
return false;
184+
if (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) {
185+
return false;
186+
} else {
187+
self->has_lock = true;
188+
return true;
189+
}
77190
}
78191

79192
// Check I2C lock status

ports/analog/common-hal/busio/I2C.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
// Define a struct for what BUSIO.I2C should carry
1818
typedef struct {
1919
mp_obj_base_t base;
20+
21+
int i2c_id;
2022
mxc_i2c_regs_t *i2c_regs;
21-
bool has_lock;
2223
const mcu_pin_obj_t *scl;
2324
const mcu_pin_obj_t *sda;
25+
const int frequency;
26+
27+
uint32_t timeout;
28+
bool has_lock;
2429
} busio_i2c_obj_t;

ports/analog/max32_port.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
// UART Ports & pins
2626
#include "peripherals/max32690/max32_uart.h"
27-
#define NUM_UARTS 4
27+
#include "peripherals/max32690/max32_i2c.h"
2828

2929
/** START: GPIO4 Handling specific to MAX32690 */
3030
#define GPIO4_PIN_MASK 0x00000003
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include "peripherals/pins.h"
8+
9+
#include "common-hal/busio/I2C.h"
10+
#include "max32_i2c.h"
11+
#include "max32690.h"
12+
13+
#include "py/runtime.h"
14+
#include "py/mperrno.h"
15+
16+
const mxc_gpio_cfg_t i2c_maps[NUM_I2C] = {
17+
// I2C0A
18+
{ MXC_GPIO0, (MXC_GPIO_PIN_30 | MXC_GPIO_PIN_31), MXC_GPIO_FUNC_ALT1,
19+
MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 },
20+
// I2C1A
21+
{ MXC_GPIO2, (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18), MXC_GPIO_FUNC_ALT1,
22+
MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 },
23+
};
24+
25+
int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl) {
26+
for (int i = 0; i < NUM_I2C; i++) {
27+
if ((i2c_maps[i].port == (MXC_GPIO_GET_GPIO(sda->port)))
28+
&& (i2c_maps[i].mask == ((sda->mask) | (scl->mask)))) {
29+
return i;
30+
}
31+
}
32+
mp_raise_RuntimeError_varg(MP_ERROR_TEXT("ERR: Unable to find an I2C matching pins...\nSCL: port %d mask %d\nSDA: port %d mask %d\n"),
33+
sda->port, sda->mask, scl->port, scl->mask);
34+
return -1;
35+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc.
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#pragma once
8+
9+
#include "i2c_regs.h"
10+
#include "mxc_sys.h"
11+
#include "i2c.h"
12+
#include "peripherals/pins.h"
13+
14+
#define NUM_I2C 2
15+
16+
int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl);

0 commit comments

Comments
 (0)