Skip to content

Commit 59d4df5

Browse files
authored
Merge pull request #9164 from tannewt/max3421e
Add Max3421E support for usb host
2 parents 842a2e5 + aca3191 commit 59d4df5

File tree

34 files changed

+1014
-32
lines changed

34 files changed

+1014
-32
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,7 @@ TAGS
9191

9292
# Uncrustify formatting
9393
*.uncrustify
94+
95+
# clangd cache
96+
##############
97+
.cache

docs/shared_bindings_matrix.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
"select": "MICROPY_PY_SELECT_SELECT",
8484
"sys": "CIRCUITPY_SYS",
8585
"terminalio": "CIRCUITPY_DISPLAYIO",
86-
"usb": "CIRCUITPY_USB_HOST",
86+
"usb": "CIRCUITPY_PYUSB",
8787
}
8888

8989
MODULES_NOT_IN_BINDINGS = [ "binascii", "errno", "json", "re", "ulab" ]

lib/tinyusb

Submodule tinyusb updated 72 files
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 Scott Shawcroft for Adafruit Industries
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-module/max3421e/Max3421E.h"
28+
29+
#include "common-hal/max3421e/Max3421E.h"
30+
31+
#include "lib/tinyusb/src/host/usbh.h"
32+
#include "supervisor/usb.h"
33+
34+
#include "eic_handler.h"
35+
#include "py/runtime.h"
36+
#include "samd/external_interrupts.h"
37+
38+
#include "shared-bindings/microcontroller/Pin.h"
39+
40+
void samd_max3421e_interrupt_handler(uint8_t channel) {
41+
max3421e_interrupt_handler((max3421e_max3421e_obj_t *)get_eic_channel_data(channel));
42+
}
43+
44+
// Setup irq on self->irq to call tuh_int_handler(rhport, true) on falling edge
45+
void common_hal_max3421e_max3421e_init_irq(max3421e_max3421e_obj_t *self) {
46+
const mcu_pin_obj_t *pin = self->irq.pin;
47+
if (!pin->has_extint) {
48+
raise_ValueError_invalid_pin();
49+
}
50+
if (eic_get_enable()) {
51+
if (!eic_channel_free(pin->extint_channel)) {
52+
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
53+
}
54+
} else {
55+
turn_on_external_interrupt_controller();
56+
}
57+
58+
set_eic_channel_data(pin->extint_channel, self);
59+
set_eic_handler(pin->extint_channel, EIC_HANDLER_MAX3421E);
60+
turn_on_eic_channel(pin->extint_channel, EIC_CONFIG_SENSE0_LOW_Val);
61+
}
62+
63+
void common_hal_max3421e_max3421e_deinit_irq(max3421e_max3421e_obj_t *self) {
64+
const mcu_pin_obj_t *pin = self->irq.pin;
65+
set_eic_handler(pin->extint_channel, EIC_HANDLER_NO_INTERRUPT);
66+
turn_off_eic_channel(pin->extint_channel);
67+
reset_pin_number(pin->extint_channel);
68+
}
69+
70+
// Enable or disable the irq interrupt.
71+
void common_hal_max3421e_max3421e_irq_enabled(max3421e_max3421e_obj_t *self, bool enabled) {
72+
const mcu_pin_obj_t *pin = self->irq.pin;
73+
uint32_t mask = 1 << pin->extint_channel;
74+
// Don't use the turn_(on|off) API because it may deinit the eic completely.
75+
if (!enabled) {
76+
EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos;
77+
} else {
78+
EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos;
79+
}
80+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2024 Scott Shawcroft for Adafruit Industries
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+
#pragma once
28+
29+
#include <stdint.h>
30+
31+
void samd_max3421e_interrupt_handler(uint8_t channel);

ports/atmel-samd/eic_handler.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include "common-hal/max3421e/Max3421E.h"
2728
#include "common-hal/pulseio/PulseIn.h"
2829
#include "common-hal/ps2io/Ps2.h"
2930
#include "common-hal/rotaryio/IncrementalEncoder.h"
@@ -73,6 +74,12 @@ void shared_eic_handler(uint8_t channel) {
7374
break;
7475
#endif
7576

77+
#if CIRCUITPY_MAX3421E
78+
case EIC_HANDLER_MAX3421E:
79+
samd_max3421e_interrupt_handler(channel);
80+
break;
81+
#endif
82+
7683
default:
7784
break;
7885
}

ports/atmel-samd/eic_handler.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,15 @@
2323
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2424
* THE SOFTWARE.
2525
*/
26-
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_EIC_HANDLER_H
27-
#define MICROPY_INCLUDED_ATMEL_SAMD_EIC_HANDLER_H
26+
#pragma once
2827

2928
#define EIC_HANDLER_NO_INTERRUPT 0x0
3029
#define EIC_HANDLER_PULSEIN 0x1
3130
#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2
3231
#define EIC_HANDLER_PS2 0x3
3332
#define EIC_HANDLER_COUNTER 0x04
3433
#define EIC_HANDLER_ALARM 0x05
34+
#define EIC_HANDLER_MAX3421E 0x06
3535

3636
void set_eic_handler(uint8_t channel, uint8_t eic_handler);
3737
void shared_eic_handler(uint8_t channel);
38-
39-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_EIC_HANDLER_H

ports/atmel-samd/mpconfigport.mk

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ ifeq ($(CIRCUITPY_FULL_BUILD),0)
9999
CIRCUITPY_LTO_PARTITION ?= one
100100
endif
101101

102+
# 20A skus have 1MB flash and can fit more.
103+
ifeq ($(patsubst %20A,,$(CHIP_VARIANT)),)
104+
HAS_1MB_FLASH = 1
105+
else
106+
HAS_1MB_FLASH = 0
107+
endif
108+
102109
# The ?='s allow overriding in mpconfigboard.mk.
103110

104111

@@ -107,6 +114,7 @@ CIRCUITPY_ALARM ?= 1
107114
CIRCUITPY_BITMAPFILTER ?= 0
108115
CIRCUITPY_FLOPPYIO ?= $(CIRCUITPY_FULL_BUILD)
109116
CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD)
117+
CIRCUITPY_MAX3421E ?= $(HAS_1MB_FLASH)
110118
CIRCUITPY_PS2IO ?= 1
111119
CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FRAMEBUFFERIO)
112120
CIRCUITPY_SAMD ?= 1

ports/espressif/boards/adafruit_feather_esp32s3_nopsram/mpconfigboard.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
USB_VID = 0x239A
22
USB_PID = 0x8114
3-
USB_PRODUCT = "Adafruit Feather ESP32S3 No PSRAM"
3+
USB_PRODUCT = "Feather ESP32S3 No PSRAM"
44
USB_MANUFACTURER = "Adafruit"
55

66
IDF_TARGET = esp32s3

ports/espressif/common-hal/busio/SPI.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <string.h>
2828

29+
#include "freertos/projdefs.h"
2930
#include "py/runtime.h"
3031
#include "shared-bindings/busio/SPI.h"
3132
#include "shared-bindings/microcontroller/Pin.h"
@@ -37,6 +38,7 @@
3738

3839
static bool spi_never_reset[SOC_SPI_PERIPH_NUM];
3940
static spi_device_handle_t spi_handle[SOC_SPI_PERIPH_NUM];
41+
static StaticSemaphore_t spi_mutex[SOC_SPI_PERIPH_NUM];
4042

4143
static bool spi_bus_is_free(spi_host_device_t host_id) {
4244
return spi_bus_get_attr(host_id) == NULL;
@@ -121,6 +123,8 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
121123
claim_pin(miso);
122124
}
123125
claim_pin(clock);
126+
127+
self->mutex = xSemaphoreCreateMutexStatic(&spi_mutex[self->host_id]);
124128
}
125129

126130
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
@@ -143,14 +147,22 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
143147
return;
144148
}
145149

150+
// Wait for any other users of this to finish.
151+
while (!common_hal_busio_spi_try_lock(self)) {
152+
}
153+
154+
// Mark us as deinit early in case we are used in an interrupt.
155+
common_hal_reset_pin(self->clock);
156+
self->clock = NULL;
157+
146158
spi_never_reset[self->host_id] = false;
147159
spi_bus_remove_device(spi_handle[self->host_id]);
148160
spi_bus_free(self->host_id);
149161

162+
vSemaphoreDelete(self->mutex);
163+
150164
common_hal_reset_pin(self->MOSI);
151165
common_hal_reset_pin(self->MISO);
152-
common_hal_reset_pin(self->clock);
153-
self->clock = NULL;
154166
}
155167

156168
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
@@ -167,20 +179,18 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
167179
}
168180

169181
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
170-
bool grabbed_lock = false;
171-
if (!self->has_lock) {
172-
grabbed_lock = true;
173-
self->has_lock = true;
182+
if (common_hal_busio_spi_deinited(self)) {
183+
return false;
174184
}
175-
return grabbed_lock;
185+
return xSemaphoreTake(self->mutex, 1) == pdTRUE;
176186
}
177187

178188
bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
179-
return self->has_lock;
189+
return xSemaphoreGetMutexHolder(self->mutex) == xTaskGetCurrentTaskHandle();
180190
}
181191

182192
void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
183-
self->has_lock = false;
193+
xSemaphoreGive(self->mutex);
184194
}
185195

186196
bool common_hal_busio_spi_write(busio_spi_obj_t *self,
@@ -229,7 +239,10 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self,
229239

230240
transactions[0].flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
231241
transactions[0].length = bits_to_send;
232-
spi_device_transmit(spi_handle[self->host_id], &transactions[0]);
242+
esp_err_t result = spi_device_transmit(spi_handle[self->host_id], &transactions[0]);
243+
if (result != ESP_OK) {
244+
return false;
245+
}
233246

234247
if (data_in != NULL) {
235248
memcpy(data_in, &transactions[0].rx_data, len);

0 commit comments

Comments
 (0)