Skip to content

Commit d0401f0

Browse files
committed
Add initial I2C support, not quite working fully though
1 parent 9b8d648 commit d0401f0

File tree

13 files changed

+1085
-3
lines changed

13 files changed

+1085
-3
lines changed

ports/esp32s2/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ INC += -Iesp-idf/components/freertos/xtensa/include
7878
INC += -Iesp-idf/components/esp32s2/include
7979
INC += -Iesp-idf/components/xtensa/esp32s2/include
8080
INC += -Iesp-idf/components/esp_common/include
81+
INC += -Iesp-idf/components/esp_ringbuf/include
8182
INC += -Iesp-idf/components/esp_rom/include
8283
INC += -Iesp-idf/components/xtensa/include
8384
INC += -Iesp-idf/components/esp_timer/include

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

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Scott Shawcroft
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared-bindings/busio/I2C.h"
28+
#include "py/mperrno.h"
29+
#include "py/runtime.h"
30+
31+
#include "driver/i2c.h"
32+
33+
#include "esp_log.h"
34+
35+
#include "shared-bindings/microcontroller/__init__.h"
36+
#include "supervisor/shared/translate.h"
37+
38+
// Number of times to try to send packet if failed.
39+
#define ATTEMPTS 2
40+
41+
static const char* TAG = "CircuitPython I2C";
42+
43+
typedef enum {
44+
STATUS_FREE = 0,
45+
STATUS_IN_USE,
46+
STATUS_NEVER_RESET
47+
} i2c_status_t;
48+
49+
static i2c_status_t i2c_status[I2C_NUM_MAX];
50+
51+
void never_reset_i2c(i2c_port_t num) {
52+
i2c_status[num] = STATUS_NEVER_RESET;
53+
}
54+
55+
void i2c_reset(void) {
56+
for (i2c_port_t num = 0; num < I2C_NUM_MAX; num++) {
57+
if (i2c_status[num] == STATUS_IN_USE) {
58+
i2c_driver_delete(num);
59+
i2c_status[num] = STATUS_FREE;
60+
}
61+
}
62+
}
63+
64+
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
65+
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) {
66+
67+
// Make sure scl and sda aren't input only
68+
69+
#if CIRCUITPY_REQUIRE_I2C_PULLUPS
70+
// // Test that the pins are in a high state. (Hopefully indicating they are pulled up.)
71+
// gpio_set_pin_function(sda->number, GPIO_PIN_FUNCTION_OFF);
72+
// gpio_set_pin_function(scl->number, GPIO_PIN_FUNCTION_OFF);
73+
// gpio_set_pin_direction(sda->number, GPIO_DIRECTION_IN);
74+
// gpio_set_pin_direction(scl->number, GPIO_DIRECTION_IN);
75+
76+
// gpio_set_pin_pull_mode(sda->number, GPIO_PULL_DOWN);
77+
// gpio_set_pin_pull_mode(scl->number, GPIO_PULL_DOWN);
78+
79+
// common_hal_mcu_delay_us(10);
80+
81+
// gpio_set_pin_pull_mode(sda->number, GPIO_PULL_OFF);
82+
// gpio_set_pin_pull_mode(scl->number, GPIO_PULL_OFF);
83+
84+
// // We must pull up within 3us to achieve 400khz.
85+
// common_hal_mcu_delay_us(3);
86+
87+
// if (!gpio_get_pin_level(sda->number) || !gpio_get_pin_level(scl->number)) {
88+
// reset_pin_number(sda->number);
89+
// reset_pin_number(scl->number);
90+
// mp_raise_RuntimeError(translate("SDA or SCL needs a pull up"));
91+
// }
92+
#endif
93+
ESP_EARLY_LOGW(TAG, "create I2C");
94+
95+
96+
self->semaphore_handle = xSemaphoreCreateBinaryStatic(&self->semaphore);
97+
xSemaphoreGive(self->semaphore_handle);
98+
ESP_EARLY_LOGW(TAG, "new I2C lock %x", self->semaphore_handle);
99+
self->sda_pin = sda;
100+
self->scl_pin = scl;
101+
ESP_EARLY_LOGW(TAG, "scl %d sda %d", self->sda_pin->number, self->scl_pin->number);
102+
self->i2c_num = I2C_NUM_MAX;
103+
for (i2c_port_t num = 0; num < I2C_NUM_MAX; num++) {
104+
if (i2c_status[num] == STATUS_FREE) {
105+
self->i2c_num = num;
106+
}
107+
}
108+
if (self->i2c_num == I2C_NUM_MAX) {
109+
mp_raise_ValueError(translate("All I2C peripherals are in use"));
110+
}
111+
i2c_status[self->i2c_num] = STATUS_IN_USE;
112+
i2c_config_t i2c_conf = {
113+
.mode = I2C_MODE_MASTER,
114+
.sda_io_num = self->sda_pin->number,
115+
.scl_io_num = self->scl_pin->number,
116+
.sda_pullup_en = GPIO_PULLUP_DISABLE, /*!< Internal GPIO pull mode for I2C sda signal*/
117+
.scl_pullup_en = GPIO_PULLUP_DISABLE, /*!< Internal GPIO pull mode for I2C scl signal*/
118+
119+
.master = {
120+
.clk_speed = frequency,
121+
}
122+
};
123+
// ESP_EARLY_LOGW(TAG, "param config %p %p %d %d", &i2c_conf, &(i2c_conf.mode), i2c_conf.mode, I2C_MODE_MAX);
124+
ESP_EARLY_LOGW(TAG, "param config %p %d %d", &i2c_conf, i2c_conf.mode, I2C_MODE_MAX);
125+
esp_err_t result = i2c_param_config(self->i2c_num, &i2c_conf);
126+
if (result != ESP_OK) {
127+
ESP_EARLY_LOGW(TAG, "error %d %p %d %d", result, &i2c_conf, (&i2c_conf)->mode, I2C_MODE_MAX);
128+
vTaskDelay(0);
129+
mp_raise_ValueError(translate("Invalid pins"));
130+
}
131+
ESP_EARLY_LOGW(TAG, "param config I2C done");
132+
result = i2c_driver_install(self->i2c_num,
133+
I2C_MODE_MASTER,
134+
0,
135+
0,
136+
0);
137+
if (result != ESP_OK) {
138+
mp_raise_OSError(MP_EIO);
139+
}
140+
141+
claim_pin(sda);
142+
claim_pin(scl);
143+
ESP_EARLY_LOGW(TAG, "create I2C done");
144+
}
145+
146+
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
147+
return self->sda_pin == NULL;
148+
}
149+
150+
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
151+
if (common_hal_busio_i2c_deinited(self)) {
152+
return;
153+
}
154+
155+
i2c_driver_delete(self->i2c_num);
156+
i2c_status[self->i2c_num] = STATUS_FREE;
157+
158+
reset_pin(self->sda_pin);
159+
reset_pin(self->scl_pin);
160+
self->sda_pin = NULL;
161+
self->scl_pin = NULL;
162+
}
163+
164+
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
165+
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
166+
i2c_master_start(cmd);
167+
i2c_master_write_byte(cmd, addr << 1, true);
168+
i2c_master_stop(cmd);
169+
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100);
170+
i2c_cmd_link_delete(cmd);
171+
return result == ESP_OK;
172+
}
173+
174+
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
175+
ESP_EARLY_LOGW(TAG, "locking I2C %x", self->semaphore_handle);
176+
self->has_lock = xSemaphoreTake(self->semaphore_handle, 0) == pdTRUE;
177+
if (self->has_lock) {
178+
ESP_EARLY_LOGW(TAG, "lock grabbed");
179+
} else {
180+
ESP_EARLY_LOGW(TAG, "unable to grab lock");
181+
}
182+
return self->has_lock;
183+
}
184+
185+
bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
186+
return self->has_lock;
187+
}
188+
189+
void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
190+
ESP_EARLY_LOGW(TAG, "unlocking I2C");
191+
xSemaphoreGive(self->semaphore_handle);
192+
self->has_lock = false;
193+
}
194+
195+
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
196+
const uint8_t *data, size_t len, bool transmit_stop_bit) {
197+
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
198+
i2c_master_start(cmd);
199+
i2c_master_write_byte(cmd, addr << 1, true);
200+
i2c_master_write(cmd, (uint8_t*) data, len, true);
201+
if (transmit_stop_bit) {
202+
i2c_master_stop(cmd);
203+
}
204+
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100 /* wait in ticks */);
205+
i2c_cmd_link_delete(cmd);
206+
207+
if (result == ESP_OK) {
208+
return 0;
209+
} else if (result == ESP_FAIL) {
210+
return MP_ENODEV;
211+
}
212+
return MP_EIO;
213+
}
214+
215+
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
216+
uint8_t *data, size_t len) {
217+
218+
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
219+
i2c_master_start(cmd);
220+
i2c_master_write_byte(cmd, addr << 1 | 1, true); // | 1 to indicate read
221+
i2c_master_read(cmd, data, len, true);
222+
i2c_master_stop(cmd);
223+
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100 /* wait in ticks */);
224+
i2c_cmd_link_delete(cmd);
225+
226+
if (result == ESP_OK) {
227+
return 0;
228+
} else if (result == ESP_FAIL) {
229+
return MP_ENODEV;
230+
}
231+
return MP_EIO;
232+
}
233+
234+
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
235+
never_reset_i2c(self->i2c_num);
236+
237+
never_reset_pin(self->scl_pin);
238+
never_reset_pin(self->sda_pin);
239+
}

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Scott Shawcroft
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_I2C_H
28+
#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_I2C_H
29+
30+
#include "common-hal/microcontroller/Pin.h"
31+
32+
#include "esp-idf/components/soc/include/hal/i2c_types.h"
33+
#include "FreeRTOS.h"
34+
#include "freertos/semphr.h"
35+
#include "py/obj.h"
36+
37+
typedef struct {
38+
mp_obj_base_t base;
39+
const mcu_pin_obj_t* scl_pin;
40+
const mcu_pin_obj_t* sda_pin;
41+
i2c_port_t i2c_num;
42+
StaticSemaphore_t semaphore;
43+
SemaphoreHandle_t semaphore_handle;
44+
bool has_lock;
45+
} busio_i2c_obj_t;
46+
47+
void i2c_reset(void);
48+
49+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_I2C_H
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_ONEWIRE_H
28+
#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_ONEWIRE_H
29+
30+
// Use bitbangio.
31+
#include "shared-module/busio/OneWire.h"
32+
33+
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_ONEWIRE_H

0 commit comments

Comments
 (0)