Probably (!) fixed problem with spurious interrupts.

After turning on the analog section of the mfrc522, a lot of spurious
interrupts could be observed. Debugging revealed that the mfrc522 did not
give consistent information about an interrupt source.

A closer look into the chip documentation (chapter 9.3.1.4) revealed that
the interrupt pin is open drain by default, but can be set to CMOS.

Switched to CMOS, deactivated internal and external pull down resistors.
No more spurious interrupts.
This commit is contained in:
2024-05-31 15:20:11 +02:00
parent 2b98beab3a
commit 561b6d7ff7
2 changed files with 47 additions and 7 deletions

32
main.c
View File

@@ -15,8 +15,16 @@ static void mfrc522_integration_irq_handler(uint gpio, uint32_t event_mask)
(void) mfrc522_irq_handler(&ctx);
}
static void mfrc522_integration_irq_init(void)
static void mfrc522_integration_irq_init(mfrc522_handle_t* const ctx)
{
bool pu = gpio_is_pulled_up(MFRC522_CFG_IRQ_GPIO);
bool pd = gpio_is_pulled_down(MFRC522_CFG_IRQ_GPIO);
ctx->debug_print("GPIO PU: %d PD: %d\n", (int) pu, (int) pd);
gpio_set_pulls(MFRC522_CFG_IRQ_GPIO, false, false);
pu = gpio_is_pulled_up(MFRC522_CFG_IRQ_GPIO);
pd = gpio_is_pulled_down(MFRC522_CFG_IRQ_GPIO);
ctx->debug_print("GPIO PU: %d PD: %d\n", (int) pu, (int) pd);
gpio_set_irq_enabled_with_callback(MFRC522_CFG_IRQ_GPIO, GPIO_IRQ_EDGE_RISE, true,
mfrc522_integration_irq_handler);
}
@@ -47,19 +55,31 @@ void mfrc522_integration_init(void)
mfrc522_set_interface(&ctx, MFRC522_INTERFACE_SPI);
uint8_t init_retval = mfrc522_init(&ctx);
if (init_retval == 0) {
mfrc522_integration_irq_init();
} else {
printf("ERR: %s failed: %d\n", __FUNCTION__, init_retval);
if (init_retval != 0) {
mfrc522_interface_debug_print("ERR: %s failed: %d\n", __FUNCTION__, init_retval);
}
uint8_t irq_pin_type_ret = mfrc522_set_interrupt_pin_type(&ctx, MFRC522_INTERRUPT_PIN_TYPE_STANDARD_CMOS);
if (irq_pin_type_ret != 0) {
mfrc522_interface_debug_print("ERR: Could not set interrupt pin type.");
}
else
{
mfrc522_integration_irq_init(&ctx);
}
// TODO Clear all interrupt bits here?
uint8_t analog_enable_retval = mfrc522_set_receiver_analog(&ctx, MFRC522_BOOL_TRUE);
if (analog_enable_retval != 0) {
mfrc522_interface_debug_print("ERR: Enabling analog receiver failed: %d\n", analog_enable_retval);
}
}
int main(void)
{
timer_hw->dbgpause = 0;
stdio_init_all();
sleep_ms(2500);
printf("Hello World!\n");

View File

@@ -37,6 +37,7 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/sync.h"
#ifndef NO_DEBUG
#include <stdarg.h>
@@ -52,12 +53,22 @@
#define MFRC522_CFG_SPI_SS_GPIO 13
#define MFRC522_CFG_SPI_SPEED_MHZ (1000 * 1000)
static inline void print_hex(uint8_t *bytes, size_t len)
{
for (size_t idx = 0; idx < len; ++idx) {
mfrc522_interface_debug_print("%x", bytes[idx]);
}
mfrc522_interface_debug_print("\n");
}
static uint32_t irq_status = 0;
/**
* @brief Helper function to pull the CS line low
*
* Taken from pico-examples, bme280_spi.c
*/
static inline void cs_select() {
// irq_status = save_and_disable_interrupts();
asm volatile("nop \n nop \n nop");
gpio_put(MFRC522_CFG_SPI_SS_GPIO, 0); // Active low
asm volatile("nop \n nop \n nop");
@@ -72,6 +83,7 @@ static inline void cs_deselect() {
asm volatile("nop \n nop \n nop");
gpio_put(MFRC522_CFG_SPI_SS_GPIO, 1);
asm volatile("nop \n nop \n nop");
// restore_interrupts(irq_status);
}
/**
@@ -241,6 +253,10 @@ uint8_t mfrc522_interface_spi_read(uint8_t reg, uint8_t *buf, uint16_t len)
// ...and ignore the first byte we received.
memcpy(buf, local_buf + 1, len);
// XXX Debug - remove me
mfrc522_interface_debug_print("[SPI-RX]: ");
print_hex(buf, len);
return (uint8_t) (n_bytes_read == local_buf_len) ? 0 : 1;
}
@@ -265,7 +281,11 @@ uint8_t mfrc522_interface_spi_write(uint8_t reg, uint8_t *buf, uint16_t len)
uint8_t local_buf[local_buf_len];
local_buf[0] = reg;
memcpy(&local_buf[1], buf, len);
// XXX Debug - remove me
mfrc522_interface_debug_print("[SPI-TX]: ");
print_hex(buf, len);
cs_select();
uint16_t n_bytes_written = spi_write_blocking(MFRC522_CFG_SPI_INSTANCE, local_buf, local_buf_len);
cs_deselect();