I'm working on a system where the i.MX8MP acts as an SPI master and an ESP32 mcu operates as an SPI slave. The ESP32 sends a notification to the i.MX8MP by pulling up a dedicated GPIO pin (configured to trigger on a rising edge) when a key is pressed on the ESP32 side. The interrupt is configured like this:
static int esp32_keys_probe(struct spi_device *spi)
{
struct esp32_keys_data *data;
int ret;
data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->spi = spi;
spi->mode = SPI_MODE_1;
spi->bits_per_word = 8;
spi->max_speed_hz = 100000;
ret = spi_setup(spi);
spi_set_drvdata(spi, data);
data->irq = of_irq_get(spi->dev.of_node, 0);
ret = devm_request_threaded_irq(&spi->dev,
data->irq,
NULL,
esp32_keys_irq_thread,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
dev_name(&spi->dev),
data);
dev_info(&spi->dev, "esp32-spi driver probed successfully, irq=%d\n", data->irq);
return 0;
}
static irqreturn_t esp32_keys_irq_thread(int irq, void *dev_id)
{
struct esp32_keys_data *data = dev_id;
u8 rx_buf[2] = {0};
struct spi_transfer xfer = {
.rx_buf = rx_buf,
.len = 2,
.cs_change = 0,
.bits_per_word = 8,
};
struct spi_message msg;
int ret;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(data->spi, &msg);
if (ret) {
dev_err(&data->spi->dev, "SPI read failed: %d\n", ret);
return IRQ_HANDLED;
}
dev_info(&data->spi->dev, "Got key event from ESP32: key=%u, pressed=%u\n", rx_buf[0], rx_buf[1]);
return IRQ_HANDLED;
};
The issue I'm encountering is that for a single key press, the interrupt handler on the i.MX8MP is triggered twice sometimes, and usually after key released. Here’s what I’ve observed:
First Trigger: The SPI transaction returns valid data.
Second Trigger: The SPI transaction returns a 2-byte signal filled with zeros.
[ 4706.468780] esp32-keys spi2.0: Got key event from ESP32: key=1, pressed=1
[ 4706.583153] esp32-keys spi2.0: Got key event from ESP32: key=1, pressed=0
[ 4706.590741] esp32-keys spi2.0: Got key event from ESP32: key=0, pressed=0
[ 4710.472679] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4710.591171] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
[ 4711.259909] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4711.397588] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
[ 4711.970879] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4712.070331] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
[ 4712.655575] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4712.756878] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
[ 4713.252659] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4713.383631] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
[ 4713.870644] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4714.033996] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
[ 4714.041587] esp32-keys spi2.0: Got key event from ESP32: key=0, pressed=0
[ 4714.492322] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=1
[ 4714.669565] esp32-keys spi2.0: Got key event from ESP32: key=2, pressed=0
I doesn't look like a key bounce/noise issue to me, since I only observed with a scope that the interrupt pin pulled up once, and the second trigger occurred around 8ms after the first one.
The 4 signals above are 1. GPIO/INT 2. SS 3. CLK 4. MISO.
Questions:
What are some potential causes for the double triggering of the GPIO interrupt in this scenario?
I'm new to Embedded Linux and not sure whether the "Interrupt Control Register (ECSPIx_INTREG) found in the manual" is related to the issue. If so, how to further debug taking advantage of the register
Hello @willvio
I hope you are doing very well.
You can check if you have another gpio that can activate the IRQ, because you can see on reference manual of i.MX8MP the GPIOs IRQs are combined between 0-15 and 16-31 bit:
Best regards,
Salas.