From d0ecd9f83719ba8e328fa4138efa41932dc33cc6 Mon Sep 17 00:00:00 2001
From: kopecdav <david.kopecky@satoshilabs.com>
Date: Thu, 6 Feb 2025 20:13:01 +0100
Subject: [PATCH] refactor(core): resolve requested changes

---
 core/embed/io/nfc/inc/io/nfc.h                |  59 ++-
 core/embed/io/nfc/rfal/LOCAL_CHANGES.md       |   8 +
 core/embed/io/nfc/st25r3916b/card_emulation.c |   2 +-
 core/embed/io/nfc/st25r3916b/card_emulation.h |  10 +-
 core/embed/io/nfc/st25r3916b/ndef.c           |  41 +-
 core/embed/io/nfc/st25r3916b/ndef.h           |  12 +-
 core/embed/io/nfc/st25r3916b/nfc.c            | 429 ++++++++----------
 core/embed/io/nfc/st25r3916b/nfc_internal.h   |   6 +-
 core/embed/io/nfc/st25r3916b/rfal_platform.h  |  24 +-
 .../models/T3W1/boards/trezor_t3w1_revA.h     |  34 +-
 .../models/T3W1/boards/trezor_t3w1_revB.h     |  34 +-
 core/embed/projects/prodtest/README.md        |  45 ++
 .../projects/prodtest/cmd/prodtest_nfc.c      |  93 ++--
 13 files changed, 400 insertions(+), 397 deletions(-)
 create mode 100644 core/embed/io/nfc/rfal/LOCAL_CHANGES.md

diff --git a/core/embed/io/nfc/inc/io/nfc.h b/core/embed/io/nfc/inc/io/nfc.h
index d516a12fff..72bed61937 100644
--- a/core/embed/io/nfc/inc/io/nfc.h
+++ b/core/embed/io/nfc/inc/io/nfc.h
@@ -17,12 +17,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef TREZORHAL_NFC_H
-#define TREZORHAL_NFC_H
 
-#include <trezor_bsp.h>
-#include <trezor_rtl.h>
-#include "ndef.h"
+#pragma once
+
+#include "trezor_types.h"
 
 #define NFC_MAX_UID_LEN 10
 
@@ -46,7 +44,7 @@ typedef enum {
 } nfc_dev_type_t;
 
 typedef enum {
-  NFC_STATE_IDLE,
+  NFC_NO_EVENT,
   NFC_STATE_ACTIVATED,
 } nfc_event_t;
 
@@ -60,45 +58,40 @@ typedef enum {
 
 typedef struct {
   uint8_t type;
-  char uid[NFC_MAX_UID_LEN];
+  char uid[NFC_MAX_UID_LEN + 1]; // Plus one for string termination
   uint8_t uid_len;
 } nfc_dev_info_t;
 
-// Initialize NFC driver including supportive RFAL middlewere
-nfc_status_t nfc_init();
+// Initialize NFC driver including supportive RFAL middleware
+nfc_status_t nfc_init(void);
 
-// Deinitialize NFC drive
-nfc_status_t nfc_deinit();
+// Deinitialize NFC driver
+nfc_status_t nfc_deinit(void);
 
 // Register NFC technology (or several) to be explored by NFC state machine
 // use this function before activating the state machine with nfc_activate_stm()
-nfc_status_t nfc_register_tech(nfc_tech_t tech);
+nfc_status_t nfc_register_tech(const nfc_tech_t tech);
 
-// Register event callbacks to be called with state machine, this function is
-// used when user need to further interact (read/write) with the connected NFC
-// device
-nfc_status_t nfc_register_event_callback(nfc_event_t event_type,
-                                         void (*cb_fn)(void));
-
-// Activate the NFC RFAL state machine which will explore the registered
-// technologies State machine handles the low level NFC protocols of registered
-// technologies and provide the user with the activated device information. With
-// activated, user have to constantly run NFC workerwith nfc_feed_worker() to
-// activly loop the state machine.
-nfc_status_t nfc_activate_stm();
+// Activates the NFC RFAL state machine to explore the previously registered technologies.
+// The RFAL handles low-level NFC protocols and provides information about the activated device.
+// This function only starts the exploration; you must regularly call nfc_get_event() to continue
+// processing NFC operations.
+nfc_status_t nfc_activate_stm(void);
 
 // Deactivate the NFC RFAL state machine (put in IDLE state).
-nfc_status_t nfc_deactivate_stm();
+nfc_status_t nfc_deactivate_stm(void);
 
-// Calls NFC RFAL worker which service the NFC statemachine exploring the
-// registered technologies. this function has to be actively called in loop
-// (main NFC poll function).
-nfc_status_t nfc_feed_worker();
+// Calls NFC RFAL worker to service the NFC state machine and expolore
+// registered technologies. This function has to be actively called in loop
+// (main NFC poll function), returns nfc event.
+nfc_event_t nfc_get_event(void);
+
+// Deactivate the currently activated NFC device and put RFAL state machine back to
+// discovary state.
+nfc_status_t nfc_dev_deactivate(void);
 
 // Read the general device information of the activated NFC device.
 nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info);
 
-// Write the NDFE message with the trezor.io URI to the activated NFC device.
-nfc_status_t nfc_def_write_ndef_uri();
-
-#endif  // TREZORHAL_NFC_H
+// Write the NDEF message with the trezor.io URI to the activated NFC device.
+nfc_status_t nfc_dev_write_ndef_uri(void);
diff --git a/core/embed/io/nfc/rfal/LOCAL_CHANGES.md b/core/embed/io/nfc/rfal/LOCAL_CHANGES.md
new file mode 100644
index 0000000000..394d73e6a0
--- /dev/null
+++ b/core/embed/io/nfc/rfal/LOCAL_CHANGES.md
@@ -0,0 +1,8 @@
+
+RFAL middleware was imported into trezor-firmware to support a low level NFC operations of st25r3916b from
+https://www.st.com/en/embedded-software/stsw-st25r-lib.html#overview (version 1.7.0)
+
+# Local changes
+
+1. rfalIsoDepInfo structure defined in include/rfal_isoDep.h and rfalNfcDepInfo include/rfal_nfcDep.h contains variable DSI which colide with the DSI macro in
+STM32 HAL drivers. To resolve this,  variale in RFAL library was refactored to DSI_ID.
\ No newline at end of file
diff --git a/core/embed/io/nfc/st25r3916b/card_emulation.c b/core/embed/io/nfc/st25r3916b/card_emulation.c
index 983ee1737b..cb92e73010 100644
--- a/core/embed/io/nfc/st25r3916b/card_emulation.c
+++ b/core/embed/io/nfc/st25r3916b/card_emulation.c
@@ -529,7 +529,7 @@ static uint16_t card_emulation_t3t_update(uint8_t *cmdData, uint8_t *rspData) {
  * @return None
  *****************************************************************************
  */
-void card_emulation_init(uint8_t *nfcfNfcid) {
+void card_emulation_init(const uint8_t *nfcfNfcid) {
   if (nfcfNfcid != NULL) {
     memcpy(gNfcfNfcid, nfcfNfcid, RFAL_NFCF_NFCID2_LEN);
   }
diff --git a/core/embed/io/nfc/st25r3916b/card_emulation.h b/core/embed/io/nfc/st25r3916b/card_emulation.h
index d747d0b37a..f175e3ab4c 100644
--- a/core/embed/io/nfc/st25r3916b/card_emulation.h
+++ b/core/embed/io/nfc/st25r3916b/card_emulation.h
@@ -16,16 +16,14 @@
  */
 
 /* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef DEMO_CE_H
-#define DEMO_CE_H
+#pragma once
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /* Includes ------------------------------------------------------------------*/
-#include <stdbool.h>
-#include <stdint.h>
+#include <trezor_bsp.h>
 
 /** @addtogroup X-CUBE-NFC6_Applications
  *  @brief Sample applications for X-NUCLEO-NFC06A1 STM32 expansion boards.
@@ -74,7 +72,7 @@ extern "C" {
 /** @defgroup CE_CardEmul_Exported_functions
  *  @{
  */
-void card_emulation_init(uint8_t *nfcfNfcid);
+void card_emulation_init(const uint8_t *nfcfNfcid);
 uint16_t card_emulation_t3t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
                             uint16_t txBufLen);
 uint16_t card_emulation_t4t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
@@ -100,6 +98,4 @@ uint16_t card_emulation_t4t(uint8_t *rxData, uint16_t rxDataLen, uint8_t *txBuf,
 }
 #endif
 
-#endif /* DEMO_CE_H */
-
 /******************* (C) COPYRIGHT 2018 STMicroelectronics *****END OF FILE****/
diff --git a/core/embed/io/nfc/st25r3916b/ndef.c b/core/embed/io/nfc/st25r3916b/ndef.c
index d656fcc282..0a30342f55 100644
--- a/core/embed/io/nfc/st25r3916b/ndef.c
+++ b/core/embed/io/nfc/st25r3916b/ndef.c
@@ -1,12 +1,28 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 
-
+#include <trezor_rtl.h>
 #include "ndef.h"
-#include <stdint.h>
-#include <string.h>
 
 // ndef_status_t create_ndef_record_uri(uint8_t *bytearray, )
 
-ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len,
+ndef_status_t ndef_parse_message(const uint8_t *buffer, uint16_t buffer_len,
                                  ndef_message_t *message) {
   memset(message, 0, sizeof(ndef_message_t));
 
@@ -34,7 +50,7 @@ ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len,
   remaining_len = message->message_total_len;
 
   while (1) {
-    parse_ndef_record(buffer, remaining_len,
+    ndef_parse_record(buffer, remaining_len,
                       &(message->records[message->records_cnt]));
     buffer += message->records[message->records_cnt].record_total_len;
     remaining_len -= message->records[message->records_cnt].record_total_len;
@@ -57,7 +73,7 @@ ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len,
   return NDEF_OK;
 }
 
-ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len,
+ndef_status_t ndef_parse_record(const uint8_t *buffer, uint16_t len,
                                 ndef_record_t *rec) {
   uint8_t bp = 0;
 
@@ -119,7 +135,7 @@ ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len,
   return NDEF_OK;
 }
 
-uint16_t create_ndef_uri(const char *uri, uint8_t *buffer) {
+uint16_t ndef_create_uri(const char *uri, uint8_t *buffer) {
   *buffer = 0x3;  // TLV header
   buffer++;
 
@@ -129,15 +145,6 @@ uint16_t create_ndef_uri(const char *uri, uint8_t *buffer) {
   *buffer = uri_len + 5;  // uri + record header;
   buffer++;
 
-  // ndef_record_header_t hdr = {
-  //   .tnf = 0x01,
-  //   .il = 0,
-  //   .sr = 1,
-  //   .cf = 0,
-  //   .me = 1,
-  //   .mb = 1,
-  // };
-
   *buffer = 0xD1;  // NDEF record Header
   buffer++;
 
@@ -158,8 +165,6 @@ uint16_t create_ndef_uri(const char *uri, uint8_t *buffer) {
     buffer++;
   }
 
-  // memcpy(buffer, uri, uri_len);
-
   *buffer = 0xFE;  // TLV termination
 
   return uri_len + 7;  // return buffer len
diff --git a/core/embed/io/nfc/st25r3916b/ndef.h b/core/embed/io/nfc/st25r3916b/ndef.h
index f68f6eeff7..cef1899580 100644
--- a/core/embed/io/nfc/st25r3916b/ndef.h
+++ b/core/embed/io/nfc/st25r3916b/ndef.h
@@ -1,7 +1,6 @@
-#include <stdint.h>
+#pragma once
 
-#ifndef NDEF_H
-#define NDEF_H
+#include <trezor_types.h>
 
 #define NDEF_MAX_RECORDS 3
 #define NDEF_MAX_RECORD_PAYLOAD_BYTES 50
@@ -37,10 +36,9 @@ typedef struct {
   ndef_record_t records[NDEF_MAX_RECORDS];
 } ndef_message_t;
 
-ndef_status_t parse_ndef_message(uint8_t *buffer, uint16_t buffer_len,
+ndef_status_t ndef_parse_message(const uint8_t *buffer, uint16_t buffer_len,
                                  ndef_message_t *message);
-ndef_status_t parse_ndef_record(uint8_t *buffer, uint16_t len,
+ndef_status_t ndef_parse_record(const uint8_t *buffer, uint16_t len,
                                 ndef_record_t *rec);
-uint16_t create_ndef_uri(const char *uri, uint8_t *buffer);
+uint16_t ndef_create_uri(const char *uri, uint8_t *buffer);
 
-#endif
diff --git a/core/embed/io/nfc/st25r3916b/nfc.c b/core/embed/io/nfc/st25r3916b/nfc.c
index 4ecdffa954..7bd708bebb 100644
--- a/core/embed/io/nfc/st25r3916b/nfc.c
+++ b/core/embed/io/nfc/st25r3916b/nfc.c
@@ -1,23 +1,52 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 
-#include <sys/irq.h>
-#include <sys/systick.h>
 #include <trezor_bsp.h>
 #include <trezor_rtl.h>
 
-#include "../inc/io/nfc.h"
+#include <sys/irq.h>
+#include <sys/systick.h>
+#include <rtl/strutils.h>
+
+#include "io/nfc.h"
+#include "rfal_isoDep.h"
+#include "rfal_nfc.h"
+#include "rfal_nfca.h"
+#include "rfal_rf.h"
+#include "rfal_t2t.h"
+#include "rfal_utils.h"
 #include "card_emulation.h"
 #include "ndef.h"
 #include "nfc_internal.h"
 #include "rfal_platform.h"
 
-#include "../rfal/include/rfal_isoDep.h"
-#include "../rfal/include/rfal_nfc.h"
-#include "../rfal/include/rfal_nfca.h"
-#include "../rfal/include/rfal_rf.h"
-#include "../rfal/include/rfal_t2t.h"
-#include "../rfal/include/rfal_utils.h"
-
-#include "stm32u5xx_hal.h"
+#define LM_SEL_RES \
+  0x20U /*!<NFC-A SEL_RES configured for Type 4A Tag Platform    */
+#define LM_NFCID2_BYTE1 \
+  0x02U /*!<NFC-F SENSF_RES configured for Type 3 Tag Platform   */
+#define LM_SC_BYTE1 \
+  0x12U /*!<NFC-F System Code byte 1                             */
+#define LM_SC_BYTE2 \
+  0xFCU /*!<NFC-F System Code byte 2                             */
+#define LM_PAD0 \
+  0x00U /*!<NFC-F PAD0                                           */
 
 typedef struct {
   bool initialized;
@@ -26,10 +55,6 @@ typedef struct {
   // NFC IRQ pin callback
   void (*nfc_irq_callback)(void);
 
-  // Event callbacks
-  void (*nfc_state_idle_cb)(void);
-  void (*nfc_state_activated_cb)(void);
-
   EXTI_HandleTypeDef hEXTI;
 
   rfalNfcDiscoverParam disc_params;
@@ -54,24 +79,10 @@ typedef struct {
   };
 } nfc_device_header_t2t_t;
 
-// static void parse_tag_header(uint8_t *data, uint16_t dataLen);
-static char *hex2Str(unsigned char *data, size_t dataLen);
-
-#define LM_SEL_RES \
-  0x20U /*!<NFC-A SEL_RES configured for Type 4A Tag Platform    */
-#define LM_NFCID2_BYTE1 \
-  0x02U /*!<NFC-F SENSF_RES configured for Type 3 Tag Platform   */
-#define LM_SC_BYTE1 \
-  0x12U /*!<NFC-F System Code byte 1                             */
-#define LM_SC_BYTE2 \
-  0xFCU /*!<NFC-F System Code byte 2                             */
-#define LM_PAD0 \
-  0x00U /*!<NFC-F PAD0                                           */
-
 /* P2P communication data */
-static uint8_t NFCID3[] = {0x01, 0xFE, 0x03, 0x04, 0x05,
+const  uint8_t NFCID3[] = {0x01, 0xFE, 0x03, 0x04, 0x05,
                            0x06, 0x07, 0x08, 0x09, 0x0A};
-static uint8_t GB[] = {0x46, 0x66, 0x6d, 0x01, 0x01, 0x11, 0x02,
+const uint8_t GB[] = {0x46, 0x66, 0x6d, 0x01, 0x01, 0x11, 0x02,
                        0x02, 0x07, 0x80, 0x03, 0x02, 0x00, 0x03,
                        0x04, 0x01, 0x32, 0x07, 0x01, 0x03};
 
@@ -80,18 +91,18 @@ static uint8_t GB[] = {0x46, 0x66, 0x6d, 0x01, 0x01, 0x11, 0x02,
  * 3 bytes. 4-byte UIDs with first byte 0x*F are Fixed number, not unique, use
  * for this demo 7-byte UIDs need a manufacturer ID and need to assure
  * uniqueness of the rest.*/
-static uint8_t ceNFCA_NFCID[] = {
+const uint8_t ceNFCA_NFCID[] = {
     0x1, 0x2, 0x3, 0x4}; /* =_STM, 5F 53 54 4D NFCID1 / UID (4 bytes) */
-static uint8_t ceNFCA_SENS_RES[] = {0x02,
+const uint8_t ceNFCA_SENS_RES[] = {0x02,
                                     0x00};  /* SENS_RES / ATQA for 4-byte UID */
-static uint8_t ceNFCA_SEL_RES = LM_SEL_RES; /* SEL_RES / SAK */
+const uint8_t ceNFCA_SEL_RES = LM_SEL_RES; /* SEL_RES / SAK */
 
-static uint8_t ceNFCF_nfcid2[] = {
+const uint8_t ceNFCF_nfcid2[] = {
     LM_NFCID2_BYTE1, 0xFE, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
 
 /* NFC-F CE config */
-static uint8_t ceNFCF_SC[] = {LM_SC_BYTE1, LM_SC_BYTE2};
-static uint8_t ceNFCF_SENSF_RES[] = {
+const uint8_t ceNFCF_SC[] = {LM_SC_BYTE1, LM_SC_BYTE2};
+uint8_t ceNFCF_SENSF_RES[] = {
     0x01, /* SENSF_RES                                */
     0x02,    0xFE,    0x11, 0x22, 0x33,
     0x44,    0x55,    0x66, /* NFCID2 */
@@ -103,12 +114,8 @@ static uint8_t ceNFCF_SENSF_RES[] = {
 static ReturnCode nfc_transcieve_blocking(uint8_t *txBuf, uint16_t txBufSize,
                                           uint8_t **rxBuf, uint16_t **rcvLen,
                                           uint32_t fwt);
-static void nfc_card_emulator_loop(rfalNfcDevice *nfcDev);
 
-#define MAX_HEX_STR 4
-#define MAX_HEX_STR_LENGTH 512
-char hexStr[MAX_HEX_STR][MAX_HEX_STR_LENGTH];
-uint8_t hexStrIdx = 0;
+static void nfc_card_emulator_loop(rfalNfcDevice *nfcDev);
 
 nfc_status_t nfc_init() {
   st25r3916b_driver_t *drv = &g_st25r3916b_driver;
@@ -119,35 +126,37 @@ nfc_status_t nfc_init() {
 
   // Enable clock of relevant peripherals
   // SPI + GPIO ports
-  SPI_INSTANCE_3_CLK_EN();
-  SPI_INSTANCE_3_MISO_CLK_EN();
-  SPI_INSTANCE_3_MOSI_CLK_EN();
-  SPI_INSTANCE_3_SCK_CLK_EN();
-  SPI_INSTANCE_3_NSS_CLK_EN();
+  NFC_SPI_FORCE_RESET();
+  NFC_SPI_RELEASE_RESET();
+  NFC_SPI_CLK_EN();
+  NFC_SPI_MISO_CLK_EN();
+  NFC_SPI_MOSI_CLK_EN();
+  NFC_SPI_SCK_CLK_EN();
+  NFC_SPI_NSS_CLK_EN();
 
   // SPI peripheral pin config
   GPIO_InitTypeDef GPIO_InitStruct = {0};
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
   GPIO_InitStruct.Pull = GPIO_NOPULL;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
-  GPIO_InitStruct.Alternate = SPI_INSTANCE_3_PIN_AF;
+  GPIO_InitStruct.Alternate = NFC_SPI_PIN_AF;
 
-  GPIO_InitStruct.Pin = SPI_INSTANCE_3_MISO_PIN;
-  HAL_GPIO_Init(SPI_INSTANCE_3_MISO_PORT, &GPIO_InitStruct);
+  GPIO_InitStruct.Pin = NFC_SPI_MISO_PIN;
+  HAL_GPIO_Init(NFC_SPI_MISO_PORT, &GPIO_InitStruct);
 
-  GPIO_InitStruct.Pin = SPI_INSTANCE_3_MOSI_PIN;
-  HAL_GPIO_Init(SPI_INSTANCE_3_MOSI_PORT, &GPIO_InitStruct);
+  GPIO_InitStruct.Pin = NFC_SPI_MOSI_PIN;
+  HAL_GPIO_Init(NFC_SPI_MOSI_PORT, &GPIO_InitStruct);
 
-  GPIO_InitStruct.Pin = SPI_INSTANCE_3_SCK_PIN;
-  HAL_GPIO_Init(SPI_INSTANCE_3_SCK_PORT, &GPIO_InitStruct);
+  GPIO_InitStruct.Pin = NFC_SPI_SCK_PIN;
+  HAL_GPIO_Init(NFC_SPI_SCK_PORT, &GPIO_InitStruct);
 
-  // NSS pin controled by software, set as classical GPIO
+  // NSS pin controlled by software, set as classical GPIO
   GPIO_InitTypeDef GPIO_InitStruct_nss = {0};
   GPIO_InitStruct_nss.Mode = GPIO_MODE_OUTPUT_PP;
   GPIO_InitStruct_nss.Pull = GPIO_NOPULL;
   GPIO_InitStruct_nss.Speed = GPIO_SPEED_FREQ_LOW;
-  GPIO_InitStruct_nss.Pin = SPI_INSTANCE_3_NSS_PIN;
-  HAL_GPIO_Init(SPI_INSTANCE_3_NSS_PORT, &GPIO_InitStruct_nss);
+  GPIO_InitStruct_nss.Pin = NFC_SPI_NSS_PIN;
+  HAL_GPIO_Init(NFC_SPI_NSS_PORT, &GPIO_InitStruct_nss);
 
   // NFC IRQ pin
   GPIO_InitTypeDef GPIO_InitStructure_int = {0};
@@ -159,7 +168,7 @@ nfc_status_t nfc_init() {
 
   memset(&(drv->hspi), 0, sizeof(drv->hspi));
 
-  drv->hspi.Instance = SPI_INSTANCE_3;
+  drv->hspi.Instance = NFC_SPI_INSTANCE;
   drv->hspi.Init.Mode = SPI_MODE_MASTER;
   drv->hspi.Init.BaudRatePrescaler =
       SPI_BAUDRATEPRESCALER_32;  // TODO: Calculate frequency precisly.
@@ -204,7 +213,7 @@ nfc_status_t nfc_init() {
   return NFC_OK;
 }
 
-nfc_status_t nfc_deinit() {
+nfc_status_t nfc_deinit(void) {
   st25r3916b_driver_t *drv = &g_st25r3916b_driver;
 
   if (!drv->initialized) {
@@ -228,40 +237,25 @@ nfc_status_t nfc_deinit() {
 
   HAL_SPI_DeInit(&(drv->hspi));
 
-  HAL_GPIO_DeInit(SPI_INSTANCE_3_MISO_PORT, SPI_INSTANCE_3_MISO_PIN);
-  HAL_GPIO_DeInit(SPI_INSTANCE_3_MOSI_PORT, SPI_INSTANCE_3_MOSI_PIN);
-  HAL_GPIO_DeInit(SPI_INSTANCE_3_SCK_PORT, SPI_INSTANCE_3_SCK_PIN);
-  HAL_GPIO_DeInit(SPI_INSTANCE_3_NSS_PORT, SPI_INSTANCE_3_NSS_PIN);
+  HAL_GPIO_DeInit(NFC_SPI_MISO_PORT, NFC_SPI_MISO_PIN);
+  HAL_GPIO_DeInit(NFC_SPI_MOSI_PORT, NFC_SPI_MOSI_PIN);
+  HAL_GPIO_DeInit(NFC_SPI_SCK_PORT, NFC_SPI_SCK_PIN);
+  HAL_GPIO_DeInit(NFC_SPI_NSS_PORT, NFC_SPI_NSS_PIN);
   HAL_GPIO_DeInit(NFC_INT_PORT, NFC_INT_PIN);
 
   drv->initialized = false;
 
   return NFC_OK;
+
 }
 
-void rfal_callback(rfalNfcState st) {
+
+nfc_status_t nfc_register_tech(const nfc_tech_t tech) {
   st25r3916b_driver_t *drv = &g_st25r3916b_driver;
 
-  switch (st) {
-    case RFAL_NFC_STATE_IDLE:
-      if (drv->nfc_state_idle_cb != NULL) {
-        drv->nfc_state_idle_cb();
-      }
-      break;
-
-    case RFAL_NFC_STATE_ACTIVATED:
-      if (drv->nfc_state_activated_cb != NULL) {
-        drv->nfc_state_activated_cb();
-      }
-      break;
-    default:
-      // State not reported
-      break;
+  if (drv->initialized == false) {
+    return NFC_NOT_INITIALIZED;
   }
-}
-
-nfc_status_t nfc_register_tech(nfc_tech_t tech) {
-  st25r3916b_driver_t *drv = &g_st25r3916b_driver;
 
   drv->disc_params.devLimit = 1;
   memcpy(&drv->disc_params.nfcid3, NFCID3, sizeof(NFCID3));
@@ -269,11 +263,6 @@ nfc_status_t nfc_register_tech(nfc_tech_t tech) {
   drv->disc_params.GBLen = sizeof(GB);
   drv->disc_params.p2pNfcaPrio = true;
   drv->disc_params.totalDuration = 1000U;
-  drv->disc_params.notifyCb = rfal_callback;
-
-  if (drv->initialized == false) {
-    return NFC_NOT_INITIALIZED;
-  }
 
   if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) {
     return NFC_ERROR;
@@ -324,34 +313,13 @@ nfc_status_t nfc_register_tech(nfc_tech_t tech) {
   return NFC_OK;
 }
 
-nfc_status_t nfc_register_event_callback(nfc_event_t event_type,
-                                         void (*cb_fn)(void)) {
+nfc_status_t nfc_activate_stm(void) {
   st25r3916b_driver_t *drv = &g_st25r3916b_driver;
 
-  switch (event_type) {
-    case NFC_STATE_IDLE:
-      drv->nfc_state_idle_cb = cb_fn;
-      break;
-    case NFC_STATE_ACTIVATED:
-      drv->nfc_state_activated_cb = cb_fn;
-      break;
-    default:
-      return NFC_ERROR;
+  if(!drv->initialized) {
+    return NFC_NOT_INITIALIZED;
   }
 
-  return NFC_OK;
-}
-
-nfc_status_t nfc_unregister_event_callback() {
-  st25r3916b_driver_t *drv = &g_st25r3916b_driver;
-  drv->disc_params.notifyCb = NULL;
-
-  return NFC_OK;
-}
-
-nfc_status_t nfc_activate_stm() {
-  st25r3916b_driver_t *drv = &g_st25r3916b_driver;
-
   ReturnCode err;
   err = rfalNfcDiscover(&(drv->disc_params));
   if (err != RFAL_ERR_NONE) {
@@ -361,7 +329,14 @@ nfc_status_t nfc_activate_stm() {
   return NFC_OK;
 }
 
-nfc_status_t nfc_deactivate_stm() {
+nfc_status_t nfc_deactivate_stm(void) {
+
+  st25r3916b_driver_t *drv = &g_st25r3916b_driver;
+
+  if(!drv->initialized) {
+    return NFC_OK;
+  }
+
   // In case the NFC state machine is active, deactivate to idle before
   // registering a new card emulation technology.
   if (rfalNfcGetState() != RFAL_NFC_STATE_IDLE) {
@@ -374,61 +349,60 @@ nfc_status_t nfc_deactivate_stm() {
   return NFC_OK;
 }
 
-nfc_status_t nfc_feed_worker() {
+nfc_event_t nfc_get_event(void) {
+
+  st25r3916b_driver_t *drv = &g_st25r3916b_driver;
+
+  if(!drv->initialized) {
+    return NFC_NOT_INITIALIZED;
+  }
+
   static rfalNfcDevice *nfcDevice;
 
   rfalNfcWorker(); /* Run RFAL worker periodically */
 
-  if (rfalNfcIsDevActivated(rfalNfcGetState())) {
+  if(rfalNfcIsDevActivated(rfalNfcGetState())) {
+
     rfalNfcGetActiveDevice(&nfcDevice);
 
+    // Perform immediate mandatory actions for certain technology (Placeholder)
     switch (nfcDevice->type) {
-      /*******************************************************************************/
+
       case RFAL_NFC_LISTEN_TYPE_NFCA:
 
         switch (nfcDevice->dev.nfca.type) {
           case RFAL_NFCA_T1T:
             break;
-
           case RFAL_NFCA_T4T:
             break;
-
           case RFAL_NFCA_T4T_NFCDEP:
+            break;
           case RFAL_NFCA_NFCDEP:
             break;
           default:
             break;
         }
 
-      /*******************************************************************************/
       case RFAL_NFC_LISTEN_TYPE_NFCB:
         break;
 
-      /*******************************************************************************/
       case RFAL_NFC_LISTEN_TYPE_NFCF:
         break;
 
-      /*******************************************************************************/
       case RFAL_NFC_LISTEN_TYPE_NFCV:
         break;
 
-      /*******************************************************************************/
       case RFAL_NFC_LISTEN_TYPE_ST25TB:
         break;
 
-      /*******************************************************************************/
       case RFAL_NFC_LISTEN_TYPE_AP2P:
       case RFAL_NFC_POLL_TYPE_AP2P:
         break;
 
-      /*******************************************************************************/
-
-      /*******************************************************************************/
-
-      // Card emulators need to promptly respond to the reader commands, so when
-      // activated rfal worker is called seveal times untill back to back
-      // communication with the reader is completed. This may prolong the
-      // run_feed_worker service time compared to standard reader mode.
+      // Card emulators must respond to reader commands promptly. Once activated,
+      // the RFAL worker is called multiple times until back-to-back communication
+      // with the reader finishes. This can prolong the nfc_get_event() service
+      // time compared to standard reader mode.
       case RFAL_NFC_POLL_TYPE_NFCA:
       case RFAL_NFC_POLL_TYPE_NFCF:
 
@@ -436,59 +410,35 @@ nfc_status_t nfc_feed_worker() {
           // not supported yet
         } else {
           nfc_card_emulator_loop(nfcDevice);
+          rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY); // Automatically deactivate
         }
-        break;
+
+        return NFC_NO_EVENT;
 
         break;
 
-        break;
-      /*******************************************************************************/
       default:
         break;
     }
 
-    rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY);
+    return NFC_STATE_ACTIVATED;
+
   }
 
-  return NFC_OK;
+  return NFC_NO_EVENT;
 }
 
-static void nfc_card_emulator_loop(rfalNfcDevice *nfcDev) {
-  ReturnCode err = RFAL_ERR_INTERNAL;
-  uint8_t *rxData;
-  uint16_t *rcvLen;
-  uint8_t txBuf[150];
-  uint16_t txLen;
+nfc_status_t nfc_dev_deactivate(void) {
 
-  do {
-    rfalNfcWorker();
+  st25r3916b_driver_t drv = g_st25r3916b_driver;
 
-    switch (rfalNfcGetState()) {
-      case RFAL_NFC_STATE_ACTIVATED:
-        err = nfc_transcieve_blocking(NULL, 0, &rxData, &rcvLen, 0);
-        break;
+  if (!drv.initialized) {
+    return NFC_NOT_INITIALIZED;
+  }
 
-      case RFAL_NFC_STATE_DATAEXCHANGE:
-      case RFAL_NFC_STATE_DATAEXCHANGE_DONE:
+  rfalNfcDeactivate(RFAL_NFC_DEACTIVATE_DISCOVERY);
 
-        txLen = ((nfcDev->type == RFAL_NFC_POLL_TYPE_NFCA)
-                     ? card_emulation_t4t(rxData, *rcvLen, txBuf, sizeof(txBuf))
-                     : rfalConvBytesToBits(card_emulation_t3t(
-                           rxData, rfalConvBitsToBytes(*rcvLen), txBuf,
-                           sizeof(txBuf))));
-
-        err = nfc_transcieve_blocking(txBuf, txLen, &rxData, &rcvLen,
-                                      RFAL_FWT_NONE);
-        break;
-
-      case RFAL_NFC_STATE_START_DISCOVERY:
-        return;
-
-      case RFAL_NFC_STATE_LISTEN_SLEEP:
-      default:
-        break;
-    }
-  } while ((err == RFAL_ERR_NONE) || (err == RFAL_ERR_SLEEP_REQ));
+  return NFC_OK;
 }
 
 nfc_status_t nfc_transceive(const uint8_t *txData, uint16_t txDataLen,
@@ -514,11 +464,18 @@ nfc_status_t nfc_transceive(const uint8_t *txData, uint16_t txDataLen,
   return NFC_OK;
 }
 
-nfc_status_t nfc_def_write_ndef_uri() {
+nfc_status_t nfc_dev_write_ndef_uri(void) {
+
+  st25r3916b_driver_t *drv = &g_st25r3916b_driver;
+
+  if (!drv->initialized) {
+    return NFC_NOT_INITIALIZED;
+  }
+
   // NDEF message
   uint8_t ndef_message[128] = {0};
 
-  uint16_t buffer_len = create_ndef_uri("trezor.io/", ndef_message);
+  uint16_t buffer_len = ndef_create_uri("trezor.io/", ndef_message);
 
   for (uint8_t i = 0; i < buffer_len / 4; i++) {
     rfalT2TPollerWrite(4 + i, ndef_message + i * 4);
@@ -564,8 +521,12 @@ nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info) {
       return NFC_ERROR;
     }
 
-    char *uid_str = hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen);
-    memcpy(dev_info->uid, uid_str, nfcDevice->nfcidLen);
+    if (nfcDevice->nfcidLen <= NFC_MAX_UID_LEN) {
+      return NFC_ERROR;
+    }
+
+    // Copy the hex UID in printable string
+    cstr_encode_hex(dev_info->uid, NFC_MAX_UID_LEN, nfcDevice->nfcid, nfcDevice->nfcidLen);
 
   } else {
     // No device activated
@@ -575,58 +536,6 @@ nfc_status_t nfc_dev_read_info(nfc_dev_info_t *dev_info) {
   return NFC_OK;
 }
 
-// static void parse_tag_header(uint8_t *data, uint16_t dataLen) {
-//   nfc_device_header_t2t_t hdr;
-
-//   memcpy(hdr.UID, data, 3);
-//   hdr.BCC[0] = data[3];
-//   memcpy(hdr.UID + 3, data + 4, 4);
-//   memcpy(hdr.SYSTEM_AREA, data + 8, 2);
-//   memcpy(hdr.CC, data + 12, 4);
-
-// }
-
-static ReturnCode nfc_transcieve_blocking(uint8_t *txBuf, uint16_t txBufSize,
-                                          uint8_t **rxData, uint16_t **rcvLen,
-                                          uint32_t fwt) {
-  ReturnCode err;
-
-  err = rfalNfcDataExchangeStart(txBuf, txBufSize, rxData, rcvLen, fwt);
-  if (err == RFAL_ERR_NONE) {
-    do {
-      rfalNfcWorker();
-      err = rfalNfcDataExchangeGetStatus();
-    } while (err == RFAL_ERR_BUSY);
-  }
-  return err;
-}
-
-static char *hex2Str(unsigned char *data, size_t dataLen) {
-  {
-    unsigned char *pin = data;
-    const char *hex = "0123456789ABCDEF";
-    char *pout = hexStr[hexStrIdx];
-    uint8_t i = 0;
-    uint8_t idx = hexStrIdx;
-    if (dataLen == 0) {
-      pout[0] = 0;
-    } else {
-      for (; i < dataLen - 1; ++i) {
-        *pout++ = hex[(*pin >> 4) & 0xF];
-        *pout++ = hex[(*pin++) & 0xF];
-      }
-      *pout++ = hex[(*pin >> 4) & 0xF];
-      *pout++ = hex[(*pin) & 0xF];
-      *pout = 0;
-    }
-
-    hexStrIdx++;
-    hexStrIdx %= MAX_HEX_STR;
-
-    return hexStr[idx];
-  }
-}
-
 HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData,
                                            uint8_t *rxData, uint16_t length) {
   st25r3916b_driver_t *drv = &g_st25r3916b_driver;
@@ -644,22 +553,9 @@ HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData,
   return status;
 }
 
-uint32_t nfc_create_timer(uint16_t time) { return (systick_ms() + time); }
+uint32_t nfc_create_timer(uint16_t time) { return ticks_timeout(time); }
 
-bool nfc_timer_is_expired(uint32_t timer) {
-  uint32_t u_diff;
-  int32_t s_diff;
-
-  u_diff = (timer - systick_ms());  // Calculate the diff between the timers
-  s_diff = u_diff;                  // Convert the diff to a signed var
-
-  // Check if the given timer has expired already
-  if (s_diff < 0) {
-    return true;
-  }
-
-  return false;
-}
+bool nfc_timer_is_expired(uint32_t timer) { return ticks_expired(timer); }
 
 void nfc_ext_irq_set_callback(void (*cb)(void)) {
   st25r3916b_driver_t *drv = &g_st25r3916b_driver;
@@ -675,3 +571,58 @@ void NFC_EXTI_INTERRUPT_HANDLER(void) {
     drv->nfc_irq_callback();
   }
 }
+
+
+static void nfc_card_emulator_loop(rfalNfcDevice *nfcDev) {
+
+  ReturnCode err = RFAL_ERR_INTERNAL;
+  uint8_t *rxBuf;
+  uint16_t *rcvLen;
+  uint8_t txBuf[150];
+  uint16_t txLen;
+
+  do {
+    rfalNfcWorker();
+
+    switch (rfalNfcGetState()) {
+      case RFAL_NFC_STATE_ACTIVATED:
+        err = nfc_transcieve_blocking(NULL, 0, &rxBuf, &rcvLen, 0);
+        break;
+
+      case RFAL_NFC_STATE_DATAEXCHANGE:
+      case RFAL_NFC_STATE_DATAEXCHANGE_DONE:
+
+        txLen = ((nfcDev->type == RFAL_NFC_POLL_TYPE_NFCA)
+                     ? card_emulation_t4t(rxBuf, *rcvLen, txBuf, sizeof(txBuf))
+                     : rfalConvBytesToBits(card_emulation_t3t(
+                           rxBuf, rfalConvBitsToBytes(*rcvLen), txBuf,
+                           sizeof(txBuf))));
+
+        err = nfc_transcieve_blocking(txBuf, txLen, &rxBuf, &rcvLen,
+                                      RFAL_FWT_NONE);
+        break;
+
+      case RFAL_NFC_STATE_START_DISCOVERY:
+        return;
+
+      case RFAL_NFC_STATE_LISTEN_SLEEP:
+      default:
+        break;
+    }
+  } while ((err == RFAL_ERR_NONE) || (err == RFAL_ERR_SLEEP_REQ));
+}
+
+static ReturnCode nfc_transcieve_blocking(uint8_t *txBuf, uint16_t txBufSize,
+                                          uint8_t **rxBuf, uint16_t **rcvLen,
+                                          uint32_t fwt) {
+  ReturnCode err;
+
+  err = rfalNfcDataExchangeStart(txBuf, txBufSize, rxBuf, rcvLen, fwt);
+  if (err == RFAL_ERR_NONE) {
+    do {
+      rfalNfcWorker();
+      err = rfalNfcDataExchangeGetStatus();
+    } while (err == RFAL_ERR_BUSY);
+  }
+  return err;
+}
\ No newline at end of file
diff --git a/core/embed/io/nfc/st25r3916b/nfc_internal.h b/core/embed/io/nfc/st25r3916b/nfc_internal.h
index 579a786efa..7dd5e1bdb9 100644
--- a/core/embed/io/nfc/st25r3916b/nfc_internal.h
+++ b/core/embed/io/nfc/st25r3916b/nfc_internal.h
@@ -1,9 +1,8 @@
 
+#pragma once
+
 #include <trezor_bsp.h>
 
-#ifndef TREZORHAL_NFC_INTERNAL_H
-#define TREZORHAL_NFC_INTERNAL_H
-
 HAL_StatusTypeDef nfc_spi_transmit_receive(const uint8_t *txData,
                                            uint8_t *rxData, uint16_t length);
 
@@ -13,4 +12,3 @@ bool nfc_timer_is_expired(uint32_t timer);
 
 void nfc_ext_irq_set_callback(void (*cb)(void));
 
-#endif
diff --git a/core/embed/io/nfc/st25r3916b/rfal_platform.h b/core/embed/io/nfc/st25r3916b/rfal_platform.h
index d410e93001..8995a7e427 100644
--- a/core/embed/io/nfc/st25r3916b/rfal_platform.h
+++ b/core/embed/io/nfc/st25r3916b/rfal_platform.h
@@ -20,8 +20,7 @@
  *
  */
 
-#ifndef RFAL_PLATFORM_H
-#define RFAL_PLATFORM_H
+#pragma once
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,16 +33,13 @@ extern "C" {
 */
 
 #include <trezor_bsp.h>
-#include "stm32u5xx_hal.h"
-
+#include <trezor_types.h>
 #include <limits.h>
 #include <math.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/systimer.h>
 
+#include <sys/systimer.h>
 #include "io/nfc.h"
+
 #include "nfc_internal.h"
 
 /*
@@ -56,10 +52,10 @@ extern "C" {
 #define ST25R3916B
 
 // GPIO pin used for ST25R SPI SS
-#define ST25R_SS_PIN SPI_INSTANCE_3_NSS_PIN
+#define ST25R_SS_PIN NFC_SPI_NSS_PIN
 
 // GPIO port used for ST25R SPI SS port
-#define ST25R_SS_PORT SPI_INSTANCE_3_NSS_PORT
+#define ST25R_SS_PORT NFC_SPI_NSS_PORT
 
 // GPIO pin used for ST25R External Interrupt
 #define ST25R_INT_PIN NFC_INT_PIN
@@ -73,12 +69,10 @@ extern "C" {
 ******************************************************************************
 */
 #define platformProtectST25RComm() \
-  NVIC_DisableIRQ(EXTI10_IRQn)  // TODO: PRobably should be irq_lock instead //
-                                // Protect the unique access to communication
-                                // channel (disable IRQ on single thread)
+  NVIC_DisableIRQ(NFC_EXTI_INTERRUPT_NUM)
 
 #define platformUnprotectST25RComm() \
-  NVIC_EnableIRQ(EXTI10_IRQn)  // TODO: Use macro here /
+  NVIC_EnableIRQ(NFC_EXTI_INTERRUPT_NUM)
 
 #define platformProtectST25RIrqStatus()                                        \
   platformProtectST25RComm() /*!< Protect unique access to IRQ status var -    \
@@ -292,5 +286,3 @@ extern uint8_t globalCommProtectCnt; /* Global Protection Counter provided per
 #ifdef __cplusplus
 }
 #endif
-
-#endif /* RFAL_PLATFORM_H */
diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h
index c30a55d4e3..8745d8f906 100644
--- a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h
+++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h
@@ -166,22 +166,24 @@
 #define NRF_OUT_FW_RUNNING_PORT GPIOE
 #define NRF_OUT_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
 
-#define SPI_INSTANCE_3 SPI3
-#define SPI_INSTANCE_3_PIN_AF GPIO_AF6_SPI3
-#define SPI_INSTANCE_3_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
-#define SPI_INSTANCE_3_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
-#define SPI_INSTANCE_3_MISO_PORT GPIOB
-#define SPI_INSTANCE_3_MISO_PIN GPIO_PIN_4
-#define SPI_INSTANCE_3_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
-#define SPI_INSTANCE_3_MOSI_PORT GPIOB
-#define SPI_INSTANCE_3_MOSI_PIN GPIO_PIN_5
-#define SPI_INSTANCE_3_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
-#define SPI_INSTANCE_3_SCK_PORT GPIOG
-#define SPI_INSTANCE_3_SCK_PIN GPIO_PIN_9
-#define SPI_INSTANCE_3_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
-#define SPI_INSTANCE_3_NSS_PORT GPIOG
-#define SPI_INSTANCE_3_NSS_PIN GPIO_PIN_12
-#define SPI_INSTANCE_3_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+#define NFC_SPI_INSTANCE SPI3
+#define NFC_SPI_PIN_AF GPIO_AF6_SPI3
+#define NFC_SPI_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
+#define NFC_SPI_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
+#define NFC_SPI_FORCE_RESET __HAL_RCC_SPI3_FORCE_RESET
+#define NFC_SPI_RELEASE_RESET __HAL_RCC_SPI3_RELEASE_RESET
+#define NFC_SPI_MISO_PORT GPIOB
+#define NFC_SPI_MISO_PIN GPIO_PIN_4
+#define NFC_SPI_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define NFC_SPI_MOSI_PORT GPIOB
+#define NFC_SPI_MOSI_PIN GPIO_PIN_5
+#define NFC_SPI_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define NFC_SPI_SCK_PORT GPIOG
+#define NFC_SPI_SCK_PIN GPIO_PIN_9
+#define NFC_SPI_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+#define NFC_SPI_NSS_PORT GPIOG
+#define NFC_SPI_NSS_PIN GPIO_PIN_12
+#define NFC_SPI_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
 
 #define NFC_INT_PIN GPIO_PIN_10
 #define NFC_INT_PORT GPIOG
diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h
index 63f522633d..d2f0af4138 100644
--- a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h
+++ b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h
@@ -166,22 +166,24 @@
 #define NRF_OUT_FW_RUNNING_PORT GPIOE
 #define NRF_OUT_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
 
-#define SPI_INSTANCE_3 SPI3
-#define SPI_INSTANCE_3_PIN_AF GPIO_AF6_SPI3
-#define SPI_INSTANCE_3_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
-#define SPI_INSTANCE_3_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
-#define SPI_INSTANCE_3_MISO_PORT GPIOB
-#define SPI_INSTANCE_3_MISO_PIN GPIO_PIN_4
-#define SPI_INSTANCE_3_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
-#define SPI_INSTANCE_3_MOSI_PORT GPIOB
-#define SPI_INSTANCE_3_MOSI_PIN GPIO_PIN_5
-#define SPI_INSTANCE_3_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
-#define SPI_INSTANCE_3_SCK_PORT GPIOG
-#define SPI_INSTANCE_3_SCK_PIN GPIO_PIN_9
-#define SPI_INSTANCE_3_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
-#define SPI_INSTANCE_3_NSS_PORT GPIOG
-#define SPI_INSTANCE_3_NSS_PIN GPIO_PIN_12
-#define SPI_INSTANCE_3_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+#define NFC_SPI_INSTANCE SPI3
+#define NFC_SPI_PIN_AF GPIO_AF6_SPI3
+#define NFC_SPI_CLK_EN __HAL_RCC_SPI3_CLK_ENABLE
+#define NFC_SPI_CLK_DIS __HAL_RCC_SPI3_CLK_DISABLE
+#define NFC_SPI_FORCE_RESET __HAL_RCC_SPI3_FORCE_RESET
+#define NFC_SPI_RELEASE_RESET __HAL_RCC_SPI3_RELEASE_RESET
+#define NFC_SPI_MISO_PORT GPIOB
+#define NFC_SPI_MISO_PIN GPIO_PIN_4
+#define NFC_SPI_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define NFC_SPI_MOSI_PORT GPIOB
+#define NFC_SPI_MOSI_PIN GPIO_PIN_5
+#define NFC_SPI_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define NFC_SPI_SCK_PORT GPIOG
+#define NFC_SPI_SCK_PIN GPIO_PIN_9
+#define NFC_SPI_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+#define NFC_SPI_NSS_PORT GPIOG
+#define NFC_SPI_NSS_PIN GPIO_PIN_12
+#define NFC_SPI_NSS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
 
 #define NFC_INT_PIN GPIO_PIN_10
 #define NFC_INT_PORT GPIOG
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index c3ee5202d6..e5f6c0b468 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -545,3 +545,48 @@ Example:
 optiga-counter-read
 OK 0E
 ```
+
+
+### nfc-read-card
+Activate the NFC in reader mode for a given time. Read general information from firstly discovered NFC tag or exits on timeout.
+
+Example:
+```
+nfc-read-card <timeout_seconds>
+# NFC activated in reader mode for <timeout_seconds> seconds.
+# NFC card detected.
+# NFC Type A: UID: %s
+OK
+```
+
+
+### nfc-emulate-card
+Activate NFC in Card Emulator mode for given time.
+
+Example:
+```
+nfc-emulate-card <timeout_seconds>
+# Emulation started for <timeout_seconds>
+# Emulation over
+OK
+```
+
+### nfc-write-card
+Activates the NFC reader for given time. Writes the NDEF URI message into the first discovered NFC tag type A or exits on timeout.
+
+Example:
+```
+nfc-write_card <timeout_seconds>
+# NFC reader on, put the card on the reader (timeout <timeout_seconds> s)
+# Writting URI to NFC tag 7AF403
+OK
+```
+
+
+
+
+
+
+
+
+
diff --git a/core/embed/projects/prodtest/cmd/prodtest_nfc.c b/core/embed/projects/prodtest/cmd/prodtest_nfc.c
index 05201d5dd8..56176fdfba 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_nfc.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_nfc.c
@@ -25,21 +25,8 @@
 #include <rtl/cli.h>
 #include <sys/systick.h>
 
-static bool nfc_dev_activated = false;
 static nfc_dev_info_t dev_info = {0};
 
-static void nfc_activated_callback() {
-  nfc_dev_read_info(&dev_info);
-  nfc_dev_activated = true;
-}
-
-static void nfc_write_tag_callback() {
-  nfc_dev_info_t dev_info;
-  nfc_dev_read_info(&dev_info);
-
-  nfc_dev_activated = true;
-}
-
 static void prodtest_nfc_read_card(cli_t* cli) {
   uint32_t timeout = 0;
   memset(&dev_info, 0, sizeof(dev_info));
@@ -55,31 +42,41 @@ static void prodtest_nfc_read_card(cli_t* cli) {
     return;
   }
 
-  nfc_dev_activated = false;
-
   nfc_status_t ret = nfc_init();
   if (ret != NFC_OK) {
     cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
   } else {
-    cli_trace(cli, "NFC activated in reader mode for %d seconds.", timeout);
+    cli_trace(cli, "NFC activated in reader mode for %d ms.", timeout);
   }
 
   nfc_register_tech(NFC_POLLER_TECH_A | NFC_POLLER_TECH_B | NFC_POLLER_TECH_F |
                     NFC_POLLER_TECH_V);
-  nfc_register_event_callback(NFC_STATE_ACTIVATED, nfc_activated_callback);
   nfc_activate_stm();
 
-  uint32_t tick = systick_ms();
+  nfc_event_t nfc_event = NFC_NO_EVENT;
 
-  while (!nfc_dev_activated) {  // Todo, while timeout or device found
+  uint32_t expire_time = ticks_timeout(timeout);
 
-    if ((systick_ms() - tick) > (timeout * 1000)) {
+  while (true) {
+
+    if (ticks_expired(expire_time)) {
       nfc_deinit();
       cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout");
       return;
     }
 
-    nfc_feed_worker();
+    nfc_event = nfc_get_event();
+
+    if(nfc_event == NFC_STATE_ACTIVATED) {
+      nfc_dev_read_info(&dev_info);
+      nfc_dev_deactivate();
+      break;
+    }
+
+    if (cli_aborted(cli)) {
+      return;
+    }
+
   }
 
   cli_trace(cli, "NFC card detected.");
@@ -136,16 +133,21 @@ static void prodtest_nfc_emulate_card(cli_t* cli) {
   if (ret != NFC_OK) {
     cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
   } else {
-    cli_trace(cli, "Emulation started for %d seconds", timeout);
+    cli_trace(cli, "Emulation started for %d ms", timeout);
   }
 
   nfc_register_tech(NFC_CARD_EMU_TECH_A);
   nfc_activate_stm();
 
-  uint32_t tick = systick_ms();
+  uint32_t expire_time = ticks_timeout(timeout);
+
+  while (!ticks_expired(expire_time)) {
+    nfc_get_event();
+
+    if (cli_aborted(cli)) {
+      return;
+    }
 
-  while ((systick_ms() - tick) < (timeout * 1000)) {
-    nfc_feed_worker();
   }
 
   cli_trace(cli, "Emulation over");
@@ -170,41 +172,52 @@ static void prodtest_nfc_write_card(cli_t* cli) {
     return;
   }
 
-  nfc_dev_activated = false;
-
   nfc_status_t ret = nfc_init();
 
   if (ret != NFC_OK) {
     cli_error(cli, CLI_ERROR_FATAL, "NFC init failed");
   } else {
-    cli_trace(cli, "NFC reader on  put the card on the reader (timeout %d s)",
+    cli_trace(cli, "NFC reader on, put the card on the reader (timeout %d ms)",
               timeout);
   }
 
   nfc_register_tech(NFC_POLLER_TECH_A);
-  nfc_register_event_callback(NFC_STATE_ACTIVATED, nfc_write_tag_callback);
   nfc_activate_stm();
 
-  uint32_t tick = systick_ms();
+  nfc_event_t nfc_event = NFC_NO_EVENT;
+  uint32_t expire_time = ticks_timeout(timeout);
 
-  while (!nfc_dev_activated) {  // Todo, while timeout or device found
+  while (true) {
 
-    if ((systick_ms() - tick) > timeout * 1000) {
+    if (ticks_expired(expire_time)) {
       nfc_deinit();
       cli_error(cli, CLI_ERROR_TIMEOUT, "NFC timeout");
       return;
     }
 
-    nfc_feed_worker();
-  }
+    nfc_event = nfc_get_event();
+    if (nfc_event == NFC_STATE_ACTIVATED) {
 
-  if (dev_info.type != NFC_DEV_TYPE_A) {
-    cli_error(cli, CLI_ERROR, "Only NFC type A cards supported");
-    return;
-  }
+      nfc_dev_read_info(&dev_info);
 
-  cli_trace(cli, "Writting URI to NFC tag %s", dev_info.uid);
-  nfc_def_write_ndef_uri();
+      if (dev_info.type != NFC_DEV_TYPE_A) {
+        cli_error(cli, CLI_ERROR, "Only NFC type A cards supported");
+        return;
+      }
+
+      cli_trace(cli, "Writting URI to NFC tag %s", dev_info.uid);
+      nfc_dev_write_ndef_uri();
+
+      nfc_dev_deactivate();
+      break;
+
+    }
+
+    if (cli_aborted(cli)) {
+      return;
+    }
+
+  }
 
   nfc_deinit();