Phase 3: MFRC522 RFID subsystem on Core 0 with UID hex conversion, enable FreeRTOS SMP

This commit is contained in:
2026-09-09 16:55:04 +02:00
parent 02410d33d8
commit ec1e7a0d5a
6 changed files with 197 additions and 9 deletions

View File

@@ -2,5 +2,6 @@ idf_component_register(SRCS
"main.c"
"spi_bus_manager.c"
"storage_manager.c"
"rfid_manager.c"
INCLUDE_DIRS "."
)

View File

@@ -4,6 +4,7 @@
#include "esp_log.h"
#include "spi_bus_manager.h"
#include "storage_manager.h"
#include "rfid_manager.h"
static const char *TAG = "MAIN";
@@ -14,7 +15,10 @@ void app_main(void)
ESP_ERROR_CHECK(spi_bus_manager_init());
ESP_ERROR_CHECK(storage_manager_init());
ESP_LOGI(TAG, "Boot sequence complete. Ready for Phase 3+.");
ESP_ERROR_CHECK(rfid_manager_init());
ESP_ERROR_CHECK(rfid_manager_start());
ESP_LOGI(TAG, "Boot sequence complete. Ready for Phase 4+.");
while (1) {
vTaskDelay(pdMS_TO_TICKS(1000));

133
main/rfid_manager.c Normal file
View File

@@ -0,0 +1,133 @@
/*
* MTG RFID Companion - MFRC522 RFID manager (Core 0)
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_event.h"
#include "rc522.h"
#include "rc522_picc.h"
#include "driver/rc522_spi.h"
#include "hw_pins.h"
#include "spi_bus_manager.h"
#include "rfid_manager.h"
static const char *TAG = "rfid";
#define RC522_TASK_NAME "rc522_polling_task"
#define RC522_POLL_INTERVAL_MS (100)
#define RC522_TASK_STACK_SIZE (6 * 1024)
#define RC522_TASK_PRIORITY (4)
static rc522_driver_handle_t s_driver;
static rc522_handle_t s_scanner;
static char s_last_uid[RFID_UID_STR_MAX_LEN] = {0};
static bool s_pending_card = false;
static void uid_to_hex_string(const rc522_picc_uid_t *uid, char *out)
{
int i;
for (i = 0; i < uid->length && i < RC522_PICC_UID_SIZE_MAX; i++) {
snprintf(out + (i * 2), 3, "%02X", uid->value[i]);
}
}
static void on_picc_state_changed(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
rc522_picc_state_changed_event_t *event = (rc522_picc_state_changed_event_t *)data;
rc522_picc_t *picc = event->picc;
(void)arg;
(void)base;
(void)event_id;
if (picc->state == RC522_PICC_STATE_ACTIVE) {
uid_to_hex_string(&picc->uid, s_last_uid);
s_pending_card = true;
ESP_LOGI(TAG, "Card scanned: UID=%s (%d bytes, %s)",
s_last_uid, picc->uid.length, rc522_picc_type_name(picc->type));
} else if ((picc->state == RC522_PICC_STATE_IDLE || picc->state == RC522_PICC_STATE_HALT)
&& event->old_state >= RC522_PICC_STATE_ACTIVE) {
ESP_LOGI(TAG, "Card removed");
}
}
esp_err_t rfid_manager_init(void)
{
rc522_spi_config_t driver_config = {
.host_id = HW_SPI_HOST,
/* Bus already owned by spi_bus_manager: attaching as an extra device. */
.bus_config = NULL,
.dev_config = {
.spics_io_num = HW_RC522_CS_GPIO,
},
.dma_chan = SPI_DMA_CH_AUTO,
.rst_io_num = HW_RC522_RST_GPIO,
};
esp_err_t ret = rc522_spi_create(&driver_config, &s_driver);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "rc522_spi_create failed: %s", esp_err_to_name(ret));
return ret;
}
ESP_ERROR_CHECK(rc522_driver_install(s_driver));
rc522_config_t scanner_config = {
.driver = s_driver,
.poll_interval_ms = RC522_POLL_INTERVAL_MS,
.task_stack_size = RC522_TASK_STACK_SIZE,
.task_priority = RC522_TASK_PRIORITY,
};
ret = rc522_create(&scanner_config, &s_scanner);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "rc522_create failed: %s", esp_err_to_name(ret));
return ret;
}
ESP_ERROR_CHECK(
rc522_register_events(s_scanner, RC522_EVENT_PICC_STATE_CHANGED, on_picc_state_changed, NULL));
return ESP_OK;
}
esp_err_t rfid_manager_start(void)
{
esp_err_t ret = rc522_start(s_scanner);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "rc522_start failed: %s", esp_err_to_name(ret));
return ret;
}
/* Pin the library's polling task to Core 0 so that RFID I/O never
* competes with the UI renderer on Core 1. */
TaskHandle_t task = xTaskGetHandle(RC522_TASK_NAME);
if (task != NULL) {
vTaskCoreAffinitySet(task, (UBaseType_t)(1U << 0));
ESP_LOGI(TAG, "RC522 polling task pinned to Core 0");
} else {
ESP_LOGW(TAG, "rc522_polling_task handle not found, affinity not set");
}
ESP_LOGI(TAG, "RFID scanner ready (SPI2_HOST, CS=%d, RST=%d)",
HW_RC522_CS_GPIO, HW_RC522_RST_GPIO);
return ESP_OK;
}
const char *rfid_manager_last_uid(void)
{
return s_last_uid;
}
bool rfid_manager_has_pending_card(void)
{
return s_pending_card;
}
void rfid_manager_consume_card(void)
{
s_pending_card = false;
}

49
main/rfid_manager.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* MTG RFID Companion - MFRC522 RFID manager (Core 0)
*
* Phase 3: Initializes the MFRC522 as a device on the shared SPI2_HOST bus,
* registers an ESP event loop listener for card state changes, converts UIDs
* to uppercase hex strings, and pins the polling task to Core 0.
*/
#pragma once
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RFID_UID_STR_MAX_LEN (24) /* 10 bytes x 2 hex chars */
/**
* @brief Initialize the MFRC522 driver and register event listeners.
* @return ESP_OK on success.
*/
esp_err_t rfid_manager_init(void);
/**
* @brief Start polling for cards and pin the polling task to Core 0.
* @return ESP_OK on success.
*/
esp_err_t rfid_manager_start(void);
/**
* @brief Return the most recently scanned UID (uppercase hex, no separators).
* 8 chars for 4-byte UIDs, 14 chars for 7-byte UIDs.
*/
const char *rfid_manager_last_uid(void);
/**
* @brief True once a new card has been scanned since the last poll().
*/
bool rfid_manager_has_pending_card(void);
/**
* @brief Clear the pending-card flag (call after consuming the UID).
*/
void rfid_manager_consume_card(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1055,7 +1055,6 @@ CONFIG_ESP_PHY_ENABLE_VERSION_PRINT=y
# Power Management
#
# CONFIG_PM_SLEEP_FUNC_IN_IRAM is not set
# CONFIG_PM_ENABLE is not set
# CONFIG_PM_SLP_IRAM_OPT is not set
# end of Power Management
@@ -1314,7 +1313,7 @@ CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0
#
# Kernel
#
# CONFIG_FREERTOS_SMP is not set
CONFIG_FREERTOS_SMP=y
# CONFIG_FREERTOS_UNICORE is not set
CONFIG_FREERTOS_HZ=100
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set
@@ -1323,6 +1322,7 @@ CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
# CONFIG_FREERTOS_USE_IDLE_HOOK is not set
# CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK is not set
# CONFIG_FREERTOS_USE_TICK_HOOK is not set
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set
@@ -1331,7 +1331,7 @@ CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc"
# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set
# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set
CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y
CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0xFFFFFFFF
CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048
CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10
@@ -1351,7 +1351,6 @@ CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y
# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set
# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set
CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y
CONFIG_FREERTOS_ISR_STACKSIZE=1536
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
# CONFIG_FREERTOS_FPU_IN_ISR is not set
@@ -1369,7 +1368,7 @@ CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y
# end of Extra
CONFIG_FREERTOS_PORT=y
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_NO_AFFINITY=0xFFFFFFFF
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_FREERTOS_DEBUG_OCDAWARE=y
CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y
@@ -1567,7 +1566,7 @@ CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072
CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set
CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF
CONFIG_LWIP_TCPIP_TASK_AFFINITY=0xFFFFFFFF
CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3
CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5
@@ -2275,7 +2274,7 @@ CONFIG_TCPIP_TASK_STACK_SIZE=3072
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set
# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
CONFIG_TCPIP_TASK_AFFINITY=0xFFFFFFFF
# CONFIG_PPP_SUPPORT is not set
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set

View File

@@ -4,3 +4,5 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
CONFIG_VFS_SUPPORT_DIR=y
CONFIG_FREERTOS_SMP=y