From 2b9a0c32479c78620adaed7e2e5ff1a487abf694 Mon Sep 17 00:00:00 2001 From: Kai Jan Kriegel Date: Mon, 23 Jan 2023 03:23:03 +0100 Subject: [PATCH] commit blob of doom --- Software/fab-reader2-c/.gitignore | 102 + Software/fab-reader2-c/CMakeLists.txt | 11 + .../components/rfal/CMakeLists.txt | 14 + .../components/rfal/Inc/rfal_analogConfig.h | 334 + .../rfal/Inc/rfal_analogConfigTbl.h | 426 + .../components/rfal/Inc/rfal_chip.h | 296 + .../components/rfal/Inc/rfal_crc.h | 75 + .../components/rfal/Inc/rfal_dpo.h | 209 + .../components/rfal/Inc/rfal_dpoTbl.h | 56 + .../components/rfal/Inc/rfal_features.h | 115 + .../components/rfal/Inc/rfal_iso15693_2.h | 202 + .../components/rfal/Inc/rfal_isoDep.h | 866 + .../components/rfal/Inc/rfal_nfc.h | 406 + .../components/rfal/Inc/rfal_nfcDep.h | 700 + .../components/rfal/Inc/rfal_nfca.h | 391 + .../components/rfal/Inc/rfal_nfcb.h | 398 + .../components/rfal/Inc/rfal_nfcf.h | 370 + .../components/rfal/Inc/rfal_nfcv.h | 772 + .../components/rfal/Inc/rfal_rf.h | 1539 + .../components/rfal/Inc/rfal_st25tb.h | 355 + .../components/rfal/Inc/rfal_st25xv.h | 729 + .../components/rfal/Inc/rfal_t1t.h | 187 + .../components/rfal/Inc/rfal_t2t.h | 153 + .../components/rfal/Inc/rfal_t4t.h | 365 + .../components/rfal/Src/rfal_analogConfig.c | 417 + .../components/rfal/Src/rfal_crc.c | 86 + .../components/rfal/Src/rfal_dpo.c | 240 + .../components/rfal/Src/rfal_iso15693_2.c | 534 + .../components/rfal/Src/rfal_isoDep.c | 2552 + .../components/rfal/Src/rfal_nfc.c | 1684 + .../components/rfal/Src/rfal_nfcDep.c | 2530 + .../components/rfal/Src/rfal_nfca.c | 630 + .../components/rfal/Src/rfal_nfcb.c | 504 + .../components/rfal/Src/rfal_nfcf.c | 546 + .../components/rfal/Src/rfal_nfcv.c | 874 + .../components/rfal/Src/rfal_rfst25r3911.c | 3733 + .../components/rfal/Src/rfal_st25tb.c | 551 + .../components/rfal/Src/rfal_st25xv.c | 528 + .../components/rfal/Src/rfal_t1t.c | 220 + .../components/rfal/Src/rfal_t2t.c | 242 + .../components/rfal/Src/rfal_t4t.c | 398 + .../components/st25r3911/CMakeLists.txt | 2 + .../components/st25r3911/Release_Notes.html | 177 + .../components/st25r3911/platform.h | 197 + .../components/st25r3911/st25r3911.c | 656 + .../components/st25r3911/st25r3911.h | 601 + .../components/st25r3911/st25r3911_com.c | 457 + .../components/st25r3911/st25r3911_com.h | 816 + .../st25r3911/st25r3911_interrupt.c | 249 + .../st25r3911/st25r3911_interrupt.h | 257 + .../components/st25r3911/st25r3911_spi.c | 34 + .../components/st25r3911/st25r3911_spi.h | 23 + .../components/st25r3911/st_errno.h | 164 + .../components/st25r3911/timer.c | 121 + .../components/st25r3911/timer.h | 128 + .../components/st25r3911/utils.c | 41 + .../components/st25r3911/utils.h | 113 + Software/fab-reader2-c/esp32s3.svd | 59821 ++++++++++++++++ Software/fab-reader2-c/gdbinit | 6 + Software/fab-reader2-c/main/CMakeLists.txt | 3 + Software/fab-reader2-c/main/fab-reader2.c | 102 + Software/fab-reader2-c/main/idf_component.yml | 17 + .../fab-reader2-c/main/pollingtagdetect.c | 264 + .../fab-reader2-c/main/pollingtagdetect.h | 21 + Software/fab-reader2-c/sdkconfig | 1401 + Software/fab-reader2-c/sdkconfig.old | 1602 + Software/fab-reader2/out.bin | Bin 0 -> 490256 bytes .../pervasive_epd/src/E2266CS0Cx/command.rs | 2 +- .../pervasive_epd/src/E2266CS0Cx/graphics.rs | 8 +- .../pervasive_epd/src/E2266CS0Cx/mod.rs | 69 +- .../fab-reader2/pervasive_epd/src/color.rs | 2 +- .../fab-reader2/pervasive_epd/src/graphics.rs | 8 +- .../pervasive_epd/src/interface.rs | 14 +- Software/fab-reader2/pervasive_epd/src/lib.rs | 7 +- .../fab-reader2/pervasive_epd/src/traits.rs | 21 +- Software/fab-reader2/rout.bin | Bin 0 -> 395712 bytes Software/fab-reader2/src/main.rs | 12 +- Software/fab-reader2/st25r3911b/Cargo.toml | 3 +- .../st25r3911b/src/analogConfig.rs | 143 - .../st25r3911b/src/analog_config.rs | 437 + .../fab-reader2/st25r3911b/src/constants.rs | 245 +- .../st25r3911b/src/device/iso_dep.rs | 3 + .../fab-reader2/st25r3911b/src/device/mod.rs | 94 + .../fab-reader2/st25r3911b/src/device/nfca.rs | 58 + .../fab-reader2/st25r3911b/src/interrupts.rs | 17 +- Software/fab-reader2/st25r3911b/src/lib.rs | 20 +- Software/fab-reader2/st25r3911b/src/rf.rs | 30 + Waveforms/default.txt | 11 + Waveforms/esp32.dwf3logicacq | Bin 0 -> 392690 bytes .../st25r3911b_commandparser/.idea/.gitignore | 8 + .../.idea/st25r3911b_commandparser.iml | 14 + Waveforms/st25r3911b_commandparser/README.md | 0 Waveforms/st25r3911b_commandparser/main.py | 0 .../st25r3911b_commandparser/requirements.txt | 0 Waveforms/stm32.dwf3logicacq | Bin 0 -> 423480 bytes Waveforms/stm32.dwf3work | Bin 0 -> 4973 bytes 96 files changed, 93559 insertions(+), 280 deletions(-) create mode 100644 Software/fab-reader2-c/.gitignore create mode 100644 Software/fab-reader2-c/CMakeLists.txt create mode 100644 Software/fab-reader2-c/components/rfal/CMakeLists.txt create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfig.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfigTbl.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_chip.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_crc.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_dpo.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_dpoTbl.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_features.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_iso15693_2.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_isoDep.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_nfc.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_nfcDep.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_nfca.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_nfcb.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_nfcf.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_nfcv.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_rf.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_st25tb.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_st25xv.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_t1t.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_t2t.h create mode 100644 Software/fab-reader2-c/components/rfal/Inc/rfal_t4t.h create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_analogConfig.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_crc.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_dpo.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_iso15693_2.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_isoDep.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_nfc.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_nfcDep.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_nfca.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_nfcb.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_nfcf.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_nfcv.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_rfst25r3911.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_st25tb.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_st25xv.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_t1t.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_t2t.c create mode 100644 Software/fab-reader2-c/components/rfal/Src/rfal_t4t.c create mode 100644 Software/fab-reader2-c/components/st25r3911/CMakeLists.txt create mode 100644 Software/fab-reader2-c/components/st25r3911/Release_Notes.html create mode 100644 Software/fab-reader2-c/components/st25r3911/platform.h create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911.c create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911.h create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911_com.c create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911_com.h create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.c create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.h create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911_spi.c create mode 100644 Software/fab-reader2-c/components/st25r3911/st25r3911_spi.h create mode 100644 Software/fab-reader2-c/components/st25r3911/st_errno.h create mode 100644 Software/fab-reader2-c/components/st25r3911/timer.c create mode 100644 Software/fab-reader2-c/components/st25r3911/timer.h create mode 100644 Software/fab-reader2-c/components/st25r3911/utils.c create mode 100644 Software/fab-reader2-c/components/st25r3911/utils.h create mode 100644 Software/fab-reader2-c/esp32s3.svd create mode 100644 Software/fab-reader2-c/gdbinit create mode 100644 Software/fab-reader2-c/main/CMakeLists.txt create mode 100644 Software/fab-reader2-c/main/fab-reader2.c create mode 100644 Software/fab-reader2-c/main/idf_component.yml create mode 100644 Software/fab-reader2-c/main/pollingtagdetect.c create mode 100644 Software/fab-reader2-c/main/pollingtagdetect.h create mode 100644 Software/fab-reader2-c/sdkconfig create mode 100644 Software/fab-reader2-c/sdkconfig.old create mode 100644 Software/fab-reader2/out.bin create mode 100644 Software/fab-reader2/rout.bin delete mode 100644 Software/fab-reader2/st25r3911b/src/analogConfig.rs create mode 100644 Software/fab-reader2/st25r3911b/src/analog_config.rs create mode 100644 Software/fab-reader2/st25r3911b/src/device/iso_dep.rs create mode 100644 Software/fab-reader2/st25r3911b/src/device/mod.rs create mode 100644 Software/fab-reader2/st25r3911b/src/device/nfca.rs create mode 100644 Software/fab-reader2/st25r3911b/src/rf.rs create mode 100644 Waveforms/default.txt create mode 100644 Waveforms/esp32.dwf3logicacq create mode 100644 Waveforms/st25r3911b_commandparser/.idea/.gitignore create mode 100644 Waveforms/st25r3911b_commandparser/.idea/st25r3911b_commandparser.iml create mode 100644 Waveforms/st25r3911b_commandparser/README.md create mode 100644 Waveforms/st25r3911b_commandparser/main.py create mode 100644 Waveforms/st25r3911b_commandparser/requirements.txt create mode 100644 Waveforms/stm32.dwf3logicacq create mode 100644 Waveforms/stm32.dwf3work diff --git a/Software/fab-reader2-c/.gitignore b/Software/fab-reader2-c/.gitignore new file mode 100644 index 0000000..ae9a17b --- /dev/null +++ b/Software/fab-reader2-c/.gitignore @@ -0,0 +1,102 @@ +.config +*.o +*.pyc + +# gtags +GTAGS +GRTAGS +GPATH + +# emacs +.dir-locals.el + +# emacs temp file suffixes +*~ +.#* +\#*# + +# eclipse setting +.settings + +# MacOS directory files +.DS_Store + +# cache dir +.cache/ + +# Components Unit Test Apps files +components/**/build/ +components/**/build_*_*/ +components/**/sdkconfig +components/**/sdkconfig.old + +# Example project files +examples/**/build/ +examples/**/build_esp*_*/ +examples/**/sdkconfig +examples/**/sdkconfig.old + +# Doc build artifacts +docs/_build/ +docs/doxygen_sqlite3.db + +# Downloaded font files +docs/_static/DejaVuSans.ttf +docs/_static/NotoSansSC-Regular.otf + +# Unit test app files +tools/unit-test-app/sdkconfig +tools/unit-test-app/sdkconfig.old +tools/unit-test-app/build +tools/unit-test-app/build_*_*/ +tools/unit-test-app/output +tools/unit-test-app/test_configs + +# Unit Test CMake compile log folder +log_ut_cmake + +# test application build files +tools/test_apps/**/build/ +tools/test_apps/**/build_*_*/ +tools/test_apps/**/sdkconfig +tools/test_apps/**/sdkconfig.old + +# IDF monitor test +tools/test_idf_monitor/outputs + +TEST_LOGS + +# gcov coverage reports +*.gcda +*.gcno +coverage.info +coverage_report/ + +test_multi_heap_host + +# VS Code Settings +.vscode/ + +# VIM files +*.swp +*.swo + +# Clion IDE CMake build & config +.idea/ +cmake-build-*/ + +# Results for the checking of the Python coding style and static analysis +.mypy_cache +flake8_output.txt + +# ESP-IDF default build directory name +build + +# lock files for examples and components +dependencies.lock + +# managed_components for examples +managed_components + +# pytest log +pytest_embedded_log/ diff --git a/Software/fab-reader2-c/CMakeLists.txt b/Software/fab-reader2-c/CMakeLists.txt new file mode 100644 index 0000000..a38c955 --- /dev/null +++ b/Software/fab-reader2-c/CMakeLists.txt @@ -0,0 +1,11 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(fab-reader2-c) + +set(COMPONENTS main) +#list(SET COMPONENTS "mqtt") diff --git a/Software/fab-reader2-c/components/rfal/CMakeLists.txt b/Software/fab-reader2-c/components/rfal/CMakeLists.txt new file mode 100644 index 0000000..26b4e4c --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/CMakeLists.txt @@ -0,0 +1,14 @@ +idf_component_register(SRCS "Src/rfal_nfc.c" + "Src/rfal_analogConfig.c" + "Src/rfal_crc.c" + "Src/rfal_dpo.c" + "Src/rfal_iso15693_2.c" + "Src/rfal_isoDep.c" + "Src/rfal_nfca.c" + "Src/rfal_nfcb.c" + "Src/rfal_rfst25r3911.c" + "Src/rfal_t1t.c" + "Src/rfal_t2t.c" + "Src/rfal_t4t.c" + INCLUDE_DIRS "Inc" + REQUIRES "st25r3911") diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfig.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfig.h new file mode 100644 index 0000000..6da5de9 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfig.h @@ -0,0 +1,334 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_AnalogConfig.h + * + * \author bkam + * + * \brief RF Chip Analog Configuration Settings + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup AnalogConfig + * \brief RFAL Analog Config Module + * @{ + * + */ + +#ifndef RFAL_ANALOG_CONFIG_H +#define RFAL_ANALOG_CONFIG_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +#define RFAL_ANALOG_CONFIG_LUT_SIZE (87U) /*!< Maximum number of Configuration IDs in the Loop Up Table */ +#define RFAL_ANALOG_CONFIG_LUT_NOT_FOUND (0xFFU) /*!< Index value indicating no Configuration IDs found */ + +#define RFAL_ANALOG_CONFIG_TBL_SIZE (1024U) /*!< Maximum number of Register-Mask-Value in the Setting List */ + + +#define RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK (0x8000U) /*!< Mask bit of Poll Mode in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_MASK (0x7F00U) /*!< Mask bits for Technology in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_MASK (0x00F0U) /*!< Mask bits for Bit rate in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_DIRECTION_MASK (0x0003U) /*!< Mask bits for Direction in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK (0x00FFU) /*!< Mask bits for Chip Specific Technology */ + +#define RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_SHIFT (15U) /*!< Shift value of Poll Mode in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_SHIFT (8U) /*!< Shift value for Technology in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_SHIFT (4U) /*!< Shift value for Technology in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_DIRECTION_SHIFT (0U) /*!< Shift value for Direction in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_POLL (0x0000U) /*!< Poll Mode bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_LISTEN (0x8000U) /*!< Listen Mode bit setting in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_TECH_CHIP (0x0000U) /*!< Chip-Specific bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCA (0x0100U) /*!< NFC-A Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCB (0x0200U) /*!< NFC-B Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCF (0x0400U) /*!< NFC-F Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_AP2P (0x0800U) /*!< AP2P Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCV (0x1000U) /*!< NFC-V Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_RFU (0x2000U) /*!< RFU for Technology bits */ + +#define RFAL_ANALOG_CONFIG_BITRATE_COMMON (0x0000U) /*!< Common settings for all bit rates in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_106 (0x0010U) /*!< 106kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_212 (0x0020U) /*!< 212kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_424 (0x0030U) /*!< 424kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_848 (0x0040U) /*!< 848kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_1695 (0x0050U) /*!< 1695kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_3390 (0x0060U) /*!< 3390kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_6780 (0x0070U) /*!< 6780kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_1OF4 (0x00C0U) /*!< 1 out of 4 for NFC-V setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_1OF256 (0x00D0U) /*!< 1 out of 256 for NFC-V setting in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_NO_DIRECTION (0x0000U) /*!< No direction setting in Analog Conf ID (Chip Specific only) */ +#define RFAL_ANALOG_CONFIG_TX (0x0001U) /*!< Transmission bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_RX (0x0002U) /*!< Reception bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_ANTICOL (0x0003U) /*!< Anticollision setting in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_CHIP_INIT (0x0000U) /*!< Chip-Specific event: Startup;Reset;Initialize */ +#define RFAL_ANALOG_CONFIG_CHIP_DEINIT (0x0001U) /*!< Chip-Specific event: Deinitialize */ +#define RFAL_ANALOG_CONFIG_CHIP_FIELD_ON (0x0002U) /*!< Chip-Specific event: Field On */ +#define RFAL_ANALOG_CONFIG_CHIP_FIELD_OFF (0x0003U) /*!< Chip-Specific event: Field Off */ +#define RFAL_ANALOG_CONFIG_CHIP_WAKEUP_ON (0x0004U) /*!< Chip-Specific event: Wake-up On */ +#define RFAL_ANALOG_CONFIG_CHIP_WAKEUP_OFF (0x0005U) /*!< Chip-Specific event: Wake-up Off */ +#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON (0x0006U) /*!< Chip-Specific event: Listen On */ +#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_OFF (0x0007U) /*!< Chip-Specific event: Listen Off */ +#define RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON (0x0008U) /*!< Chip-Specific event: Poll common */ +#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON (0x0009U) /*!< Chip-Specific event: Listen common */ + +#define RFAL_ANALOG_CONFIG_UPDATE_LAST (0x00U) /*!< Value indicating Last configuration set during update */ +#define RFAL_ANALOG_CONFIG_UPDATE_MORE (0x01U) /*!< Value indicating More configuration set coming during update */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +#define RFAL_ANALOG_CONFIG_ID_GET_POLL_LISTEN(id) (RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK & (id)) /*!< Check if id indicates Listen mode */ + +#define RFAL_ANALOG_CONFIG_ID_GET_TECH(id) (RFAL_ANALOG_CONFIG_TECH_MASK & (id)) /*!< Get the technology of Configuration ID */ +#define RFAL_ANALOG_CONFIG_ID_IS_CHIP(id) (RFAL_ANALOG_CONFIG_TECH_MASK & (id)) /*!< Check if ID indicates Chip-specific */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCA(id) (RFAL_ANALOG_CONFIG_TECH_NFCA & (id)) /*!< Check if ID indicates NFC-A */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCB(id) (RFAL_ANALOG_CONFIG_TECH_NFCB & (id)) /*!< Check if ID indicates NFC-B */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCF(id) (RFAL_ANALOG_CONFIG_TECH_NFCF & (id)) /*!< Check if ID indicates NFC-F */ +#define RFAL_ANALOG_CONFIG_ID_IS_AP2P(id) (RFAL_ANALOG_CONFIG_TECH_AP2P & (id)) /*!< Check if ID indicates AP2P */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCV(id) (RFAL_ANALOG_CONFIG_TECH_NFCV & (id)) /*!< Check if ID indicates NFC-V */ + +#define RFAL_ANALOG_CONFIG_ID_GET_BITRATE(id) (RFAL_ANALOG_CONFIG_BITRATE_MASK & (id)) /*!< Get Bitrate of Configuration ID */ +#define RFAL_ANALOG_CONFIG_ID_IS_COMMON(id) (RFAL_ANALOG_CONFIG_BITRATE_MASK & (id)) /*!< Check if ID indicates common bitrate */ +#define RFAL_ANALOG_CONFIG_ID_IS_106(id) (RFAL_ANALOG_CONFIG_BITRATE_106 & (id)) /*!< Check if ID indicates 106kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_212(id) (RFAL_ANALOG_CONFIG_BITRATE_212 & (id)) /*!< Check if ID indicates 212kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_424(id) (RFAL_ANALOG_CONFIG_BITRATE_424 & (id)) /*!< Check if ID indicates 424kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_848(id) (RFAL_ANALOG_CONFIG_BITRATE_848 & (id)) /*!< Check if ID indicates 848kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_1695(id) (RFAL_ANALOG_CONFIG_BITRATE_1695 & (id)) /*!< Check if ID indicates 1695kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_3390(id) (RFAL_ANALOG_CONFIG_BITRATE_3390 & (id)) /*!< Check if ID indicates 3390kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_6780(id) (RFAL_ANALOG_CONFIG_BITRATE_6780 & (id)) /*!< Check if ID indicates 6780kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_1OF4(id) (RFAL_ANALOG_CONFIG_BITRATE_1OF4 & (id)) /*!< Check if ID indicates 1 out of 4 bitrate */ +#define RFAL_ANALOG_CONFIG_ID_IS_1OF256(id) (RFAL_ANALOG_CONFIG_BITRATE_1OF256 & (id)) /*!< Check if ID indicates 1 out of 256 bitrate */ + +#define RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(id) (RFAL_ANALOG_CONFIG_DIRECTION_MASK & (id)) /*!< Get Direction of Configuration ID */ +#define RFAL_ANALOG_CONFIG_ID_IS_TX(id) (RFAL_ANALOG_CONFIG_TX & (id)) /*!< Check if id indicates TX */ +#define RFAL_ANALOG_CONFIG_ID_IS_RX(id) (RFAL_ANALOG_CONFIG_RX & (id)) /*!< Check if id indicates RX */ + +#define RFAL_ANALOG_CONFIG_CONFIG_NUM(x) (sizeof(x)/sizeof((x)[0])) /*!< Get Analog Config number */ + +/*! Set Analog Config ID value by: Mode, Technology, Bitrate and Direction */ +#define RFAL_ANALOG_CONFIG_ID_SET(mode, tech, br, direction) \ + ( RFAL_ANALOG_CONFIG_ID_GET_POLL_LISTEN(mode) \ + | RFAL_ANALOG_CONFIG_ID_GET_TECH(tech) \ + | RFAL_ANALOG_CONFIG_ID_GET_BITRATE(br) \ + | RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(direction) \ + ) + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +typedef uint8_t rfalAnalogConfigMode; /*!< Polling or Listening Mode of Configuration */ +typedef uint8_t rfalAnalogConfigTech; /*!< Technology of Configuration */ +typedef uint8_t rfalAnalogConfigBitrate; /*!< Bitrate of Configuration */ +typedef uint8_t rfalAnalogConfigDirection; /*!< Transmit/Receive direction of Configuration */ + +typedef uint8_t rfalAnalogConfigRegAddr[2]; /*!< Register Address to ST Chip */ +typedef uint8_t rfalAnalogConfigRegMask; /*!< Register Mask Value */ +typedef uint8_t rfalAnalogConfigRegVal; /*!< Register Value */ + +typedef uint16_t rfalAnalogConfigId; /*!< Analog Configuration ID */ +typedef uint16_t rfalAnalogConfigOffset; /*!< Analog Configuration offset address in the table */ +typedef uint8_t rfalAnalogConfigNum; /*!< Number of Analog settings for the respective Configuration ID */ + + +/*! Struct that contain the Register-Mask-Value set. Make sure that the whole structure size is even and unaligned! */ +typedef struct { + rfalAnalogConfigRegAddr addr; /*!< Register Address */ + rfalAnalogConfigRegMask mask; /*!< Register Mask Value */ + rfalAnalogConfigRegVal val; /*!< Register Value */ +} rfalAnalogConfigRegAddrMaskVal; + + +/*! Struct that represents the Analog Configs */ +typedef struct { + uint8_t id[sizeof(rfalAnalogConfigId)]; /*!< Configuration ID */ + rfalAnalogConfigNum num; /*!< Number of Config Sets to follow */ + rfalAnalogConfigRegAddrMaskVal regSet[]; /*!< Register-Mask-Value sets */ /* PRQA S 1060 # MISRA 18.7 - Flexible Array Members are the only meaningful way of denoting a variable length input buffer which follows a fixed header structure. */ +} rfalAnalogConfig; + + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize the Analog Configuration + * + * Reset the Analog Configuration LUT pointer to reference to default settings. + * + ***************************************************************************** + */ +void rfalAnalogConfigInitialize( void ); + + +/*! + ***************************************************************************** + * \brief Indicate if the current Analog Configuration Table is complete and ready to be used. + * + * \return true if current Analog Configuration Table is complete and ready to be used. + * \return false if current Analog Configuration Table is incomplete + * + ***************************************************************************** + */ +bool rfalAnalogConfigIsReady( void ); + +/*! + ***************************************************************************** + * \brief Write the whole Analog Configuration table in raw format + * + * Writes the Analog Configuration and Look Up Table with the given raw table + * + * NOTE: Function does not check the validity of the given Table contents + * + * \param[in] configTbl: location of config Table to be loaded + * \param[in] configTblSize: size of the config Table to be loaded + * + * \return ERR_NONE : if setting is updated + * \return ERR_PARAM : if configTbl is invalid + * \return ERR_NOMEM : if the given Table is bigger exceeds the max size + * \return ERR_REQUEST : if the update Configuration Id is disabled + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListWriteRaw( const uint8_t *configTbl, uint16_t configTblSize ); + +/*! + ***************************************************************************** + * \brief Write the Analog Configuration table with new analog settings. + * + * Writes the Analog Configuration and Look Up Table with the new list of register-mask-value + * and Configuration ID respectively. + * + * NOTE: Function does not check for the validity of the Register Address. + * + * \param[in] more: 0x00 indicates it is last Configuration ID settings; + * 0x01 indicates more Configuration ID setting(s) are coming. + * \param[in] *config: reference to the configuration list of current Configuraiton ID. + * + * \return ERR_PARAM : if Configuration ID or parameter is invalid + * \return ERR_NOMEM : if LUT is full + * \return ERR_REQUEST : if the update Configuration Id is disabled + * \return ERR_NONE : if setting is updated + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListWrite( uint8_t more, const rfalAnalogConfig *config ); + +/*! + ***************************************************************************** + * \brief Read the whole Analog Configuration table in raw format + * + * Reads the whole Analog Configuration Table in raw format + * + * \param[out] tblBuf: location to the buffer to place the Config Table + * \param[in] tblBufLen: length of the buffer to place the Config Table + * \param[out] configTblSize: Config Table size + * + * \return ERR_PARAM : if configTbl or configTblSize is invalid + * \return ERR_NOMEM : if configTblSize is not enough for the whole table + * \return ERR_NONE : if read is successful + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListReadRaw( uint8_t *tblBuf, uint16_t tblBufLen, uint16_t *configTblSize ); + +/*! + ***************************************************************************** + * \brief Read the Analog Configuration table. + * + * Read the Analog Configuration Table + * + * \param[in] configOffset: offset to the next Configuration ID in the List Table to be read. + * \param[out] more: 0x00 indicates it is last Configuration ID settings; + * 0x01 indicates more Configuration ID setting(s) are coming. + * \param[out] config: configuration id, number of configuration sets and register-mask-value sets + * \param[in] numConfig: the remaining configuration settings space available; + * + * \return ERR_NOMEM : if number of Configuration for respective Configuration ID is greater the the remaining configuration setting space available + * \return ERR_NONE : if read is successful + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListRead( rfalAnalogConfigOffset *configOffset, uint8_t *more, rfalAnalogConfig *config, rfalAnalogConfigNum numConfig ); + +/*! + ***************************************************************************** + * \brief Set the Analog settings of indicated Configuration ID. + * + * Update the chip with indicated analog settings of indicated Configuration ID. + * + * \param[in] configId: configuration ID + * + * \return ERR_PARAM if Configuration ID is invalid + * \return ERR_INTERNAL if error updating setting to chip + * \return ERR_NONE if new settings is applied to chip + * + ***************************************************************************** + */ +ReturnCode rfalSetAnalogConfig( rfalAnalogConfigId configId ); + + +#endif /* RFAL_ANALOG_CONFIG_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfigTbl.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfigTbl.h new file mode 100644 index 0000000..2c4d0a2 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_analogConfigTbl.h @@ -0,0 +1,426 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_analogConfig.h + * + * \author bkam + * + * \brief ST25R3911 Analog Configuration Settings + * + */ + +#ifndef ST25R3911_ANALOGCONFIG_H +#define ST25R3911_ANALOGCONFIG_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_analogConfig.h" +#include "st25r3911_com.h" + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Macro for Configuration Setting with only one register-mask-value set: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1] */ +#define MODE_ENTRY_1_REG(MODE, R0, M0, V0) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 1, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) + +/*! Macro for Configuration Setting with only two register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1] */ +#define MODE_ENTRY_2_REG(MODE, R0, M0, V0, R1, M1, V1) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 2, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) + +/*! Macro for Configuration Setting with only three register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_3_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 3, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + +/*! Macro for Configuration Setting with only four register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_4_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 4, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + +/*! Macro for Configuration Setting with only five register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_5_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 5, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + +/*! Macro for Configuration Setting with only six register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_6_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 6, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + +/*! Macro for Configuration Setting with only seven register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_7_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 7, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + +/*! Macro for Configuration Setting with only eight register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_8_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 8, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + , (uint8_t)((R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \ + +/*! Macro for Configuration Setting with only nine register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_9_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 9, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + , (uint8_t)((R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \ + , (uint8_t)((R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \ + +/*! Macro for Configuration Setting with only ten register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_10_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU),10, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + , (uint8_t)((R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \ + , (uint8_t)((R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \ + , (uint8_t)((R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \ + +/*! Macro for Configuration Setting with eleven register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_11_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU),11, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + , (uint8_t)((R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \ + , (uint8_t)((R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \ + , (uint8_t)((R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \ + , (uint8_t)((R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \ + +/*! Macro for Configuration Setting with twelve register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_12_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU),12, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + , (uint8_t)((R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \ + , (uint8_t)((R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \ + , (uint8_t)((R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \ + , (uint8_t)((R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \ + , (uint8_t)((R11) >> 8), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \ + +/*! Macro for Configuration Setting with thirteen register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_13_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11, R12, M12, V12) \ + (uint8_t)((MODE) >> 8), (uint8_t)((MODE) & 0xFFU),13, (uint8_t)((R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \ + , (uint8_t)((R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \ + , (uint8_t)((R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \ + , (uint8_t)((R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \ + , (uint8_t)((R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \ + , (uint8_t)((R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \ + , (uint8_t)((R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \ + , (uint8_t)((R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \ + , (uint8_t)((R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \ + , (uint8_t)((R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \ + , (uint8_t)((R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \ + , (uint8_t)((R11) >> 8), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \ + , (uint8_t)((R12) >> 8), (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12) \ + +/* Setting for approximately 14%: */ +#define AM_MOD_DRIVER_LEVEL_DEFAULT 0xb9 +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ +/* PRQA S 3406 1 # MISRA 8.6 - Externally generated table included by the library */ /* PRQA S 1514 1 # MISRA 8.9 - Externally generated table included by the library */ + const uint8_t rfalAnalogConfigDefaultSettings[] = { + //****** Default Analog Configuration for Chip-Specific Reset. ******/ + MODE_ENTRY_10_REG( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_INIT) + , ST25R3911_REG_OP_CONTROL, 0x30, 0x10 /* default to AM */ + , ST25R3911_REG_IO_CONF1, 0x06, 0x06 /* MCUCLK: HF clk off */ + , ST25R3911_REG_IO_CONF1, (ST25R3911_REG_IO_CONF1_mask_out_cl | ST25R3911_REG_IO_CONF1_lf_clk_off), 0x07 /* MCUCLK: LF clk off */ + , ST25R3911_REG_IO_CONF2, 0x18, 0x18 /* pull downs */ + , ST25R3911_REG_RX_CONF4, ST25R3911_REG_RX_CONF4_mask_rg2_pm, 0x1U<
© COPYRIGHT 2016 STMicroelectronics
+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_chip.h + * + * \author Gustavo Patricio + * + * \brief RF Chip specific Layer + * + * \warning This layer, which provides direct access to RF chip, should + * only be used for debug purposes and/or advanced features + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup Chip + * \brief RFAL RF Chip Module + * @{ + * + */ + + +#ifndef RFAL_CHIP_H +#define RFAL_CHIP_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + + +/***************************************************************************** + * RF Chip * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Writes a register on the RF Chip + * + * Checks if the given register is valid and if so, writes the value(s) + * on the RF Chip register + * + * \param[in] reg: register address to be written, or the first if len > 1 + * \param[in] values: pointer with content to be written on the register(s) + * \param[in] len: number of consecutive registers to be written + * + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Write done with no error + ***************************************************************************** + */ +ReturnCode rfalChipWriteReg( uint16_t reg, const uint8_t* values, uint8_t len ); + +/*! + ***************************************************************************** + * \brief Reads a register on the RF Chip + * + * Checks if the given register is valid and if so, reads the value(s) + * of the RF Chip register(s) + * + * \param[in] reg: register address to be read, or the first if len > 1 + * \param[out] values: pointer where the register(s) read content will be placed + * \param[in] len: number of consecutive registers to be read + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Read done with no error + ***************************************************************************** + */ +ReturnCode rfalChipReadReg( uint16_t reg, uint8_t* values, uint8_t len ); + +/*! + ***************************************************************************** + * \brief Change a register on the RF Chip + * + * Change the value of the register bits on the RF Chip Test set in the valueMask. + * + * \param[in] reg: register address to be modified + * \param[in] valueMask: mask value of the register bits to be changed + * \param[in] value: register value to be set + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_OK : Change done with no error + ***************************************************************************** + */ +ReturnCode rfalChipChangeRegBits( uint16_t reg, uint8_t valueMask, uint8_t value ); + +/*! + ***************************************************************************** + * \brief Writes a Test register on the RF Chip + * + * Writes the value on the RF Chip Test register + * + * \param[in] reg: register address to be written + * \param[in] value: value to be written on the register + * + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Write done with no error + ***************************************************************************** + */ +ReturnCode rfalChipWriteTestReg( uint16_t reg, uint8_t value ); + +/*! + ***************************************************************************** + * \brief Reads a Test register on the RF Chip + * + * Reads the value of the RF Chip Test register + * + * \param[in] reg: register address to be read + * \param[out] value: pointer where the register content will be placed + * + * \return ERR_PARAM :Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Read done with no error + ***************************************************************************** + */ +ReturnCode rfalChipReadTestReg( uint16_t reg, uint8_t* value ); + +/*! + ***************************************************************************** + * \brief Change a Test register on the RF Chip + * + * Change the value of the register bits on the RF Chip Test set in the valueMask. + * + * \param[in] reg: test register address to be modified + * \param[in] valueMask: mask value of the register bits to be changed + * \param[in] value: register value to be set + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_OK : Change done with no error + ***************************************************************************** + */ +ReturnCode rfalChipChangeTestRegBits( uint16_t reg, uint8_t valueMask, uint8_t value ); + +/*! + ***************************************************************************** + * \brief Execute command on the RF Chip + * + * Checks if the given command is valid and if so, executes it on + * the RF Chip + * + * \param[in] cmd: direct command to be executed + * + * \return ERR_PARAM : Invalid command or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Direct command executed with no error + ***************************************************************************** + */ +ReturnCode rfalChipExecCmd( uint16_t cmd ); + +/*! + ***************************************************************************** + * \brief Set RFO + * + * Sets the RFO value to be used when the field is on (unmodulated/active) + * + * \param[in] rfo : the RFO value to be used + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipSetRFO( uint8_t rfo ); + + +/*! + ***************************************************************************** + * \brief Get RFO + * + * Gets the RFO value used used when the field is on (unmodulated/active) + * + * \param[out] result : the current RFO value + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipGetRFO( uint8_t* result ); + + +/*! + ***************************************************************************** + * \brief Measure Amplitude + * + * Measures the RF Amplitude + * + * \param[out] result : result of RF measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasureAmplitude( uint8_t* result ); + + +/*! + ***************************************************************************** + * \brief Measure Phase + * + * Measures the Phase + * + * \param[out] result : result of Phase measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasurePhase( uint8_t* result ); + + +/*! + ***************************************************************************** + * \brief Measure Capacitance + * + * Measures the Capacitance + * + * \param[out] result : result of Capacitance measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasureCapacitance( uint8_t* result ); + + +/*! + ***************************************************************************** + * \brief Measure Power Supply + * + * Measures the Power Supply + * + * \param[in] param : measurement parameter (chip specific) + * \param[out] result : result of the measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasurePowerSupply( uint8_t param, uint8_t* result ); + + +#endif /* RFAL_CHIP_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_crc.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_crc.h new file mode 100644 index 0000000..a6ca124 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_crc.h @@ -0,0 +1,75 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_crc.h + * + * \author Ulrich Herrmann + * + * \brief CRC calculation module + * + */ +/*! + * + */ + +#ifndef RFAL_CRC_H_ +#define RFAL_CRC_H_ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Calculate CRC according to CCITT standard. + * + * This function takes \a length bytes from \a buf and calculates the CRC + * for this data. The result is returned. + * \note This implementation calculates the CRC with LSB first, i.e. all + * bytes are "read" from right to left. + * + * \param[in] preloadValue : Initial value of CRC calculation. + * \param[in] buf : buffer to calculate the CRC for. + * \param[in] length : size of the buffer. + * + * \return 16 bit long crc value. + * + ***************************************************************************** + */ +extern uint16_t rfalCrcCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length); + +#endif /* RFAL_CRC_H_ */ + diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_dpo.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_dpo.h new file mode 100644 index 0000000..8e7daaa --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_dpo.h @@ -0,0 +1,209 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_dpo.h + * + * \author Martin Zechleitner + * + * \brief Dynamic Power adjustment + * + * This module provides an interface to perform the power adjustment dynamically + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup DynamicPower + * \brief RFAL Dynamic Power Module + * @{ + * + */ + + +#ifndef RFAL_DPO_H +#define RFAL_DPO_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_DPO_TABLE_SIZE_MAX 15U /*!< Max DPO table size */ +#define RFAL_DPO_TABLE_PARAMETER 3U /*!< DPO table Parameter length */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! DPO table entry struct */ +typedef struct { + uint8_t rfoRes; /*!< Setting for the resistance level of the RFO */ + uint8_t inc; /*!< Threshold for incrementing the output power */ + uint8_t dec; /*!< Threshold for decrementing the output power */ +}rfalDpoEntry; + +/*! Function pointer to methode doing the reference measurement */ +typedef ReturnCode (*rfalDpoMeasureFunc)(uint8_t*); + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + + +/*! + ***************************************************************************** + * \brief Initialize dynamic power table + * + * This function sets the internal dynamic power table to the default + * values stored in rfal_DpoTbl.h + * + ***************************************************************************** + */ +void rfalDpoInitialize( void ); + +/*! + ***************************************************************************** + * \brief Set the measurement methode + * + * This function sets the measurement method used for reference measurement. + * Based on the measurement the power will then be adjusted + * + * \param[in] dpoMeasureFunc: callback of measurement function + * + ***************************************************************************** + */ +void rfalDpoSetMeasureCallback( rfalDpoMeasureFunc dpoMeasureFunc ); + +/*! + ***************************************************************************** + * \brief Write dynamic power table + * + * Load the dynamic power table + * + * \param[in] powerTbl: location of power Table to be loaded + * \param[in] powerTblEntries: number of entries of the power Table to be loaded + * + * \return ERR_NONE : No error + * \return ERR_PARAM : if configTbl is invalid + * \return ERR_NOMEM : if the given Table is bigger exceeds the max size + ***************************************************************************** + */ +ReturnCode rfalDpoTableWrite( rfalDpoEntry* powerTbl, uint8_t powerTblEntries ); + +/*! + ***************************************************************************** + * \brief Dynamic power table Read + * + * Read the dynamic power table + * + * \param[out] tblBuf: location to the rfalDpoEntry[] to place the Table + * \param[in] tblBufEntries: number of entries available in tblBuf to place the power Table + * \param[out] tableEntries: returned number of entries actually written into tblBuf + * + * \return ERR_NONE : No error + * \return ERR_PARAM : if configTbl is invalid or parameters are invalid + ***************************************************************************** + */ +ReturnCode rfalDpoTableRead( rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries ); + +/*! + ***************************************************************************** + * \brief Dynamic power adjust + * + * It measures the current output and adjusts the power accordingly to + * the dynamic power table + * + * \return ERR_NONE : No error + * \return ERR_PARAM : if configTbl is invalid or parameters are invalid + * \return ERR_WRONG_STATE : if the current state is valid for DPO Adjustment + ***************************************************************************** + */ +ReturnCode rfalDpoAdjust( void ); + +/*! + ***************************************************************************** + * \brief Get Current Dynamic power table entry + * + * Return current used DPO power table entry settings + * + * \return ERR_NONE : Current DpoEntry. This includes d_res, inc and dec + * + ***************************************************************************** + */ +rfalDpoEntry* rfalDpoGetCurrentTableEntry(void); + +/*! + ***************************************************************************** + * \brief Dynamic power set enabled state + * + * \param[in] enable: new active state + * + * Set state to enable or disable the Dynamic power adjustment + * + ***************************************************************************** + */ +void rfalDpoSetEnabled( bool enable ); + +/*! + ***************************************************************************** + * \brief Get the Dynamic power enabled state + * + * Get state of the Dynamic power adjustment + * + * \return true : enabled + * \return false : disabled + ***************************************************************************** + */ +bool rfalDpoIsEnabled(void); + +#endif /* RFAL_DPO_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_dpoTbl.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_dpoTbl.h new file mode 100644 index 0000000..f5c8981 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_dpoTbl.h @@ -0,0 +1,56 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + + +#ifndef ST25R3911_DYNAMICPOWER_H +#define ST25R3911_DYNAMICPOWER_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_dpo.h" + + +/* + ****************************************************************************** + * GLOBAL VARIABLES + ****************************************************************************** + */ + + /*! Default DPO table */ +const uint8_t rfalDpoDefaultSettings [] = { + 0x00, 255, 200, + 0x01, 210, 150, + 0x02, 160, 100, + 0x03, 110, 50, + 0x0E, 60, 0 +}; + +#endif /* ST25R3911_DYNAMICPOWER_H */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_features.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_features.h new file mode 100644 index 0000000..943da90 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_features.h @@ -0,0 +1,115 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief RFAL Features/Capabilities Definition for ST25R3911 + */ + + +#ifndef RFAL_FEATURES_H +#define RFAL_FEATURES_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define RFAL_SUPPORT_MODE_POLL_NFCA true /*!< RFAL Poll NFCA mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_NFCB true /*!< RFAL Poll NFCB mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_NFCF true /*!< RFAL Poll NFCF mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_NFCV true /*!< RFAL Poll NFCV mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P true /*!< RFAL Poll AP2P mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_NFCA false /*!< RFAL Listen NFCA mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_NFCB false /*!< RFAL Listen NFCB mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_NFCF false /*!< RFAL Listen NFCF mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_ACTIVE_P2P true /*!< RFAL Listen AP2P mode support switch */ + +/*******************************************************************************/ +/*! RFAL supported Card Emulation (CE) */ +#define RFAL_SUPPORT_CE ( RFAL_SUPPORT_MODE_LISTEN_NFCA || RFAL_SUPPORT_MODE_LISTEN_NFCB || RFAL_SUPPORT_MODE_LISTEN_NFCF ) + +/*! RFAL supported Reader/Writer (RW) */ +#define RFAL_SUPPORT_RW ( RFAL_SUPPORT_MODE_POLL_NFCA || RFAL_SUPPORT_MODE_POLL_NFCB || RFAL_SUPPORT_MODE_POLL_NFCF || RFAL_SUPPORT_MODE_POLL_NFCV ) + +/*! RFAL support for Active P2P (AP2P) */ +#define RFAL_SUPPORT_AP2P ( RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P || RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P ) + + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_RW_106 true /*!< RFAL RW 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_212 true /*!< RFAL RW 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_424 true /*!< RFAL RW 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_848 true /*!< RFAL RW 848 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_1695 true /*!< RFAL RW 1695 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_3390 true /*!< RFAL RW 3390 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_6780 false /*!< RFAL RW 6780 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_13560 false /*!< RFAL RW 6780 Bit Rate support switch */ + + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_AP2P_106 true /*!< RFAL AP2P 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_212 true /*!< RFAL AP2P 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_424 true /*!< RFAL AP2P 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_848 false /*!< RFAL AP2P 848 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_1695 false /*!< RFAL AP2P 1695 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_3390 false /*!< RFAL AP2P 3390 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_6780 false /*!< RFAL AP2P 6780 Bit Rate support switch */ + + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_CE_A_106 false /*!< RFAL CE A 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_A_212 false /*!< RFAL CE A 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_A_424 false /*!< RFAL CE A 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_A_848 false /*!< RFAL CE A 848 Bit Rate support switch */ + + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_CE_B_106 false /*!< RFAL CE B 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_B_212 false /*!< RFAL CE B 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_B_424 false /*!< RFAL CE B 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_B_848 false /*!< RFAL CE B 848 Bit Rate support switch */ + + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_CE_F_212 false /*!< RFAL CE F 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_F_424 false /*!< RFAL CE F 424 Bit Rate support switch */ + + +#endif /* RFAL_FEATURES_H */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_iso15693_2.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_iso15693_2.h new file mode 100644 index 0000000..da64117 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_iso15693_2.h @@ -0,0 +1,202 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_iso15693_2.h + * + * \author Ulrich Herrmann + * + * \brief Implementation of ISO-15693-2 + * + */ +/*! + * + */ + +#ifndef RFAL_ISO_15693_2_H +#define RFAL_ISO_15693_2_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" +#include "st_errno.h" + +/* +****************************************************************************** +* GLOBAL DATATYPES +****************************************************************************** +*/ +/*! Enum holding possible VCD codings */ +typedef enum +{ + ISO15693_VCD_CODING_1_4, + ISO15693_VCD_CODING_1_256 +}iso15693VcdCoding_t; + +/*! Enum holding possible VICC datarates */ + +/*! Configuration parameter used by #iso15693PhyConfigure */ +typedef struct +{ + iso15693VcdCoding_t coding; /*!< desired VCD coding */ + uint32_t speedMode; /*!< 0: normal mode, 1: 2^1 = x2 Fast mode, 2 : 2^2 = x4 mode, 3 : 2^3 = x8 mode - all rx pulse numbers and times are divided by 1,2,4,8 */ +}iso15693PhyConfig_t; + +/*! Parameters how the stream mode should work */ +struct iso15693StreamConfig { + uint8_t useBPSK; /*!< 0: subcarrier, 1:BPSK */ + uint8_t din; /*!< the divider for the in subcarrier frequency: fc/2^din */ + uint8_t dout; /*!< the divider for the in subcarrier frequency fc/2^dout */ + uint8_t report_period_length; /*!< the length of the reporting period 2^report_period_length*/ +}; +/* +****************************************************************************** +* GLOBAL CONSTANTS +****************************************************************************** +*/ + +#define ISO15693_REQ_FLAG_TWO_SUBCARRIERS 0x01U /*!< Flag indication that communication uses two subcarriers */ +#define ISO15693_REQ_FLAG_HIGH_DATARATE 0x02U /*!< Flag indication that communication uses high bitrate */ +#define ISO15693_MASK_FDT_LISTEN (65) /*!< t1min = 308,2us = 4192/fc = 65.5 * 64/fc */ + +/*! t1max = 323,3us = 4384/fc = 68.5 * 64/fc + * 12 = 768/fc unmodulated time of single subcarrior SoF */ +#define ISO15693_FWT (69 + 12) + + + + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Initialize the ISO15693 phy + * + * \param[in] config : ISO15693 phy related configuration (See #iso15693PhyConfig_t) + * \param[out] needed_stream_config : return a pointer to the stream config + * needed for this iso15693 config. To be used for configure RF chip. + * + * \return ERR_IO : Error during communication. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693PhyConfigure(const iso15693PhyConfig_t* config, + const struct iso15693StreamConfig ** needed_stream_config ); + +/*! + ***************************************************************************** + * \brief Return current phy configuration + * + * This function returns current Phy configuration previously + * set by #iso15693PhyConfigure + * + * \param[out] config : ISO15693 phy configuration. + * + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config); + +/*! + ***************************************************************************** + * \brief Code an ISO15693 compatible frame + * + * This function takes \a length bytes from \a buffer, perform proper + * encoding and sends out the frame to the ST25R391x. + * + * \param[in] buffer : data to send, modified to adapt flags. + * \param[in] length : number of bytes to send. + * \param[in] sendCrc : If set to true, CRC is appended to the frame + * \param[in] sendFlags: If set to true, flag field is sent according to + * ISO15693. + * \param[in] picopassMode : If set to true, the coding will be according to Picopass + * \param[out] subbit_total_length : Return the complete bytes which need to + * be send for the current coding + * \param[in,out] offset : Set to 0 for first transfer, function will update it to + point to next byte to be coded + * \param[out] outbuf : buffer where the function will store the coded subbit stream + * \param[out] outBufSize : the size of the output buffer + * \param[out] actOutBufSize : the amount of data stored into the buffer at this call + * + * \return ERR_IO : Error during communication. + * \return ERR_AGAIN : Data was not coded all the way. Call function again with a new/emptied buffer + * \return ERR_NO_MEM : In case outBuf is not big enough. Needs to have at + least 5 bytes for 1of4 coding and 65 bytes for 1of256 coding + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693VCDCode(uint8_t* buffer, uint16_t length, bool sendCrc, bool sendFlags, bool picopassMode, + uint16_t *subbit_total_length, uint16_t *offset, + uint8_t* outbuf, uint16_t outBufSize, uint16_t* actOutBufSize); + + +/*! + ***************************************************************************** + * \brief Receive an ISO15693 compatible frame + * + * This function receives an ISO15693 frame from the ST25R391x, decodes the frame + * and writes the raw data to \a buffer. + * \note Buffer needs to be big enough to hold CRC also (+2 bytes) + * + * \param[in] inBuf : buffer with the hamming coded stream to be decoded + * \param[in] inBufLen : number of bytes to decode (=length of buffer). + * \param[out] outBuf : buffer where received data shall be written to. + * \param[in] outBufLen : Length of output buffer, should be approx twice the size of inBuf + * \param[out] outBufPos : The number of decoded bytes. Could be used in + * extended implementation to allow multiple calls + * \param[out] bitsBeforeCol : in case of ERR_COLLISION this value holds the + * number of bits in the current byte where the collision happened. + * \param[in] ignoreBits : number of bits in the beginning where collisions will be ignored + * \param[in] picopassMode : if set to true, the decoding will be according to Picopass + * + * \return ERR_COLLISION : collision occured, data uncorrect + * \return ERR_CRC : CRC error, data uncorrect + * \return ERR_TIMEOUT : timeout waiting for data. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693VICCDecode(const uint8_t *inBuf, + uint16_t inBufLen, + uint8_t* outBuf, + uint16_t outBufLen, + uint16_t* outBufPos, + uint16_t* bitsBeforeCol, + uint16_t ignoreBits, + bool picopassMode ); + +#endif /* RFAL_ISO_15693_2_H */ + diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_isoDep.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_isoDep.h new file mode 100644 index 0000000..546d6fe --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_isoDep.h @@ -0,0 +1,866 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_isoDep.h + * + * \author Gustavo Patricio + * + * \brief Implementation of ISO-DEP protocol + * + * This implementation was based on the following specs: + * - ISO/IEC 14443-4 2nd Edition 2008-07-15 + * - NFC Forum Digital Protocol 1.1 2014-01-14 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup ISO-DEP + * \brief RFAL ISO-DEP Module + * @{ + * + */ + +#ifndef RFAL_ISODEP_H_ +#define RFAL_ISODEP_H_ +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "rfal_nfcb.h" +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +#define RFAL_ISODEP_PROLOGUE_SIZE (3U) /*!< Length of Prologue Field for I-Block Format */ + +#define RFAL_ISODEP_PCB_LEN (1U) /*!< PCB length */ +#define RFAL_ISODEP_DID_LEN (1U) /*!< DID length */ +#define RFAL_ISODEP_NAD_LEN (1U) /*!< NAD length */ +#define RFAL_ISODEP_NO_DID (0x00U) /*!< DID value indicating the ISO-DEP layer not to use DID */ +#define RFAL_ISODEP_NO_NAD (0xFFU) /*!< NAD value indicating the ISO-DEP layer not to use NAD */ + +#define RFAL_ISODEP_FWI_MASK (0xF0U) /*!< Mask bits of FWI */ +#define RFAL_ISODEP_FWI_SHIFT (4U) /*!< Shift val of FWI */ +#define RFAL_ISODEP_FWI_DEFAULT (4U) /*!< Default value for FWI Digital 1.0 11.6.2.17 */ +#define RFAL_ISODEP_ADV_FEATURE (0x0FU) /*!< Indicate 256 Bytes FSD and Advanc Proto Feature support:NAD & DID */ + +#define RFAL_ISODEP_DID_MAX (14U) /*!< Maximum DID value */ + +#define RFAL_ISODEP_BRI_MASK (0x07U) /*!< Mask bits for Poll to Listen Send bitrate */ +#define RFAL_ISODEP_BSI_MASK (0x70U) /*!< Mask bits for Listen to Poll Send bitrate */ +#define RFAL_ISODEP_SAME_BITRATE_MASK (0x80U) /*!< Mask bit indicate only same bit rate D for both direction support */ +#define RFAL_ISODEP_BITRATE_RFU_MASK (0x08U) /*!< Mask bit for RFU */ + +/*! Maximum Frame Waiting Time = ((256 * 16/fc) * 2^FWImax) = ((256*16/fc)*2^14) = (67108864)/fc = 2^26 (1/fc) */ +#define RFAL_ISODEP_MAX_FWT ((uint32_t)1U<<26) + + + +#define RFAL_ISODEP_FSDI_DEFAULT RFAL_ISODEP_FSXI_256 /*!< Default Frame Size Integer in Poll mode */ +#define RFAL_ISODEP_FSX_KEEP (0xFFU) /*!< Flag to keep FSX from activation */ +#define RFAL_ISODEP_DEFAULT_FSCI RFAL_ISODEP_FSXI_256 /*!< FSCI default value to be used in Listen Mode */ +#define RFAL_ISODEP_DEFAULT_FSC RFAL_ISODEP_FSX_256 /*!< FSC default value (aligned RFAL_ISODEP_DEFAULT_FSCI) */ +#define RFAL_ISODEP_DEFAULT_SFGI (0U) /*!< SFGI Default value to be used in Listen Mode */ +#define RFAL_ISODEP_DEFAULT_FWI (8U) /*!< Default Listener FWI (Max) Digital 2.0 B7 & B3 */ + +#define RFAL_ISODEP_APDU_MAX_LEN RFAL_ISODEP_FSX_1024 /*!< Max APDU length */ + +#define RFAL_ISODEP_ATTRIB_RES_MBLI_NO_INFO (0x00U) /*!< MBLI indicating no information on its internal input buffer size */ +#define RFAL_ISODEP_ATTRIB_REQ_PARAM1_DEFAULT (0x00U) /*!< Default values of Param 1 of ATTRIB_REQ Digital 1.0 12.6.1.3-5 */ +#define RFAL_ISODEP_ATTRIB_HLINFO_LEN (32U) /*!< Maximum Size of Higher Layer Information */ +#define RFAL_ISODEP_ATS_HB_MAX_LEN (15U) /*!< Maximum length of Historical Bytes Digital 1.1 13.6.2.23 */ +#define RFAL_ISODEP_ATTRIB_REQ_MIN_LEN (9U) /*!< Minimum Length of ATTRIB_REQ command */ +#define RFAL_ISODEP_ATTRIB_RES_MIN_LEN (1U) /*!< Minimum Length of ATTRIB_RES response */ + +#define RFAL_ISODEP_SPARAM_VALUES_MAX_LEN (16U) /*!< Maximum Length of the value field on S(PARAMETERS) */ +#define RFAL_ISODEP_SPARAM_TAG_BLOCKINFO (0xA0U) /*!< S(PARAMETERS) tag Block information */ +#define RFAL_ISODEP_SPARAM_TAG_BRREQ (0xA1U) /*!< S(PARAMETERS) tag Bit rates Request */ +#define RFAL_ISODEP_SPARAM_TAG_BRIND (0xA2U) /*!< S(PARAMETERS) tag Bit rates Indication */ +#define RFAL_ISODEP_SPARAM_TAG_BRACT (0xA3U) /*!< S(PARAMETERS) tag Bit rates Activation */ +#define RFAL_ISODEP_SPARAM_TAG_BRACK (0xA4U) /*!< S(PARAMETERS) tag Bit rates Acknowledgement */ + +#define RFAL_ISODEP_SPARAM_TAG_SUP_PCD2PICC (0x80U) /*!< S(PARAMETERS) tag Supported bit rates from PCD to PICC */ +#define RFAL_ISODEP_SPARAM_TAG_SUP_PICC2PCD (0x81U) /*!< S(PARAMETERS) tag Supported bit rates from PICC to PCD */ +#define RFAL_ISODEP_SPARAM_TAG_SUP_FRAME (0x82U) /*!< S(PARAMETERS) tag Supported framing options PICC to PCD */ +#define RFAL_ISODEP_SPARAM_TAG_SEL_PCD2PICC (0x83U) /*!< S(PARAMETERS) tag Selected bit rate from PCD to PICC */ +#define RFAL_ISODEP_SPARAM_TAG_SEL_PICC2PCD (0x84U) /*!< S(PARAMETERS) tag Selected bit rate from PICC to PCD */ +#define RFAL_ISODEP_SPARAM_TAG_SEL_FRAME (0x85U) /*!< S(PARAMETERS) tag Selected framing options PICC to PCD */ + +#define RFAL_ISODEP_SPARAM_TAG_LEN (1) /*!< S(PARAMETERS) Tag Length */ +#define RFAL_ISODEP_SPARAM_TAG_BRREQ_LEN (0U) /*!< S(PARAMETERS) tag Bit rates Request Length */ +#define RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN (2U) /*!< S(PARAMETERS) bit rates from PCD to PICC Length */ +#define RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN (2U) /*!< S(PARAMETERS) bit rates from PICC to PCD Length */ +#define RFAL_ISODEP_SPARAM_TAG_BRACK_LEN (0U) /*!< S(PARAMETERS) tag Bit rates Acknowledgement Length */ + +#define RFAL_ISODEP_ATS_TA_DPL_212 (0x01U) /*!< ATS TA DSI 212 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DPL_424 (0x02U) /*!< ATS TA DSI 424 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DPL_848 (0x04U) /*!< ATS TA DSI 848 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DLP_212 (0x10U) /*!< ATS TA DSI 212 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DLP_424 (0x20U) /*!< ATS TA DRI 424 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DLP_848 (0x40U) /*!< ATS TA DRI 848 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_SAME_D (0x80U) /*!< ATS TA same bit both directions bit mask */ +#define RFAL_ISODEP_ATS_TB_FWI_MASK (0xF0U) /*!< Mask bits for FWI (Frame Waiting Integer) in TB byte */ +#define RFAL_ISODEP_ATS_TB_SFGI_MASK (0x0FU) /*!< Mask bits for SFGI (Start-Up Frame Guard Integer) in TB byte */ + +#define RFAL_ISODEP_ATS_T0_TA_PRESENCE_MASK (0x10U) /*!< Mask bit for TA presence */ +#define RFAL_ISODEP_ATS_T0_TB_PRESENCE_MASK (0x20U) /*!< Mask bit for TB presence */ +#define RFAL_ISODEP_ATS_T0_TC_PRESENCE_MASK (0x40U) /*!< Mask bit for TC presence */ +#define RFAL_ISODEP_ATS_T0_FSCI_MASK (0x0FU) /*!< Mask bit for FSCI presence */ +#define RFAL_ISODEP_ATS_T0_OFFSET (0x01U) /*!< Offset of T0 in ATS Response */ + + +#define RFAL_ISODEP_MAX_I_RETRYS (2U) /*!< Number of retries for a I-Block Digital 1.1 15.2.5.4 */ +#define RFAL_ISODEP_MAX_R_RETRYS (3U) /*!< Number of retries for a R-Block Digital 1.1 A8 - nRETRY ACK/NAK: [2,5] */ +#define RFAL_ISODEP_MAX_S_RETRYS (3U) /*!< Number of retries for a S-Block Digital 1.1 A8 - nRETRY DESELECT: [0,5] WTX[2,5] */ +#define RFAL_ISODEP_RATS_RETRIES (1U) /*!< RATS retries upon fail Digital 1.1 A.6 - [0,1] */ + + +/*! Frame Size for Proximity Card Integer definitions */ +typedef enum +{ + RFAL_ISODEP_FSXI_16 = 0, /*!< Frame Size for Proximity Card Integer with 16 bytes */ + RFAL_ISODEP_FSXI_24 = 1, /*!< Frame Size for Proximity Card Integer with 24 bytes */ + RFAL_ISODEP_FSXI_32 = 2, /*!< Frame Size for Proximity Card Integer with 32 bytes */ + RFAL_ISODEP_FSXI_40 = 3, /*!< Frame Size for Proximity Card Integer with 40 bytes */ + RFAL_ISODEP_FSXI_48 = 4, /*!< Frame Size for Proximity Card Integer with 48 bytes */ + RFAL_ISODEP_FSXI_64 = 5, /*!< Frame Size for Proximity Card Integer with 64 bytes */ + RFAL_ISODEP_FSXI_96 = 6, /*!< Frame Size for Proximity Card Integer with 96 bytes */ + RFAL_ISODEP_FSXI_128 = 7, /*!< Frame Size for Proximity Card Integer with 128 bytes */ + RFAL_ISODEP_FSXI_256 = 8, /*!< Frame Size for Proximity Card Integer with 256 bytes */ + RFAL_ISODEP_FSXI_512 = 9, /*!< Frame Size for Proximity Card Integer with 512 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSXI_1024 = 10, /*!< Frame Size for Proximity Card Integer with 1024 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSXI_2048 = 11, /*!< Frame Size for Proximity Card Integer with 2048 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSXI_4096 = 12 /*!< Frame Size for Proximity Card Integer with 4096 bytes ISO14443-3 Amd2 2012 */ +} rfalIsoDepFSxI; + +/*! Frame Size for Proximity Card definitions */ +typedef enum +{ + RFAL_ISODEP_FSX_16 = 16, /*!< Frame Size for Proximity Card with 16 bytes */ + RFAL_ISODEP_FSX_24 = 24, /*!< Frame Size for Proximity Card with 24 bytes */ + RFAL_ISODEP_FSX_32 = 32, /*!< Frame Size for Proximity Card with 32 bytes */ + RFAL_ISODEP_FSX_40 = 40, /*!< Frame Size for Proximity Card with 40 bytes */ + RFAL_ISODEP_FSX_48 = 48, /*!< Frame Size for Proximity Card with 48 bytes */ + RFAL_ISODEP_FSX_64 = 64, /*!< Frame Size for Proximity Card with 64 bytes */ + RFAL_ISODEP_FSX_96 = 96, /*!< Frame Size for Proximity Card with 96 bytes */ + RFAL_ISODEP_FSX_128 = 128, /*!< Frame Size for Proximity Card with 128 bytes */ + RFAL_ISODEP_FSX_256 = 256, /*!< Frame Size for Proximity Card with 256 bytes */ + RFAL_ISODEP_FSX_512 = 512, /*!< Frame Size for Proximity Card with 512 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSX_1024 = 1024, /*!< Frame Size for Proximity Card with 1024 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSX_2048 = 2048, /*!< Frame Size for Proximity Card with 2048 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSX_4096 = 4096, /*!< Frame Size for Proximity Card with 4096 bytes ISO14443-3 Amd2 2012 */ +} rfalIsoDepFSx; + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +/*! RATS format Digital 1.1 13.6.1 */ +typedef struct +{ + uint8_t CMD; /*!< RATS command byte: 0xE0 */ + uint8_t PARAM; /*!< Param indicating FSDI and DID */ +} rfalIsoDepRats; + + +/*! ATS response format Digital 1.1 13.6.2 */ +typedef struct +{ + uint8_t TL; /*!< Length Byte, including TL byte itself */ + uint8_t T0; /*!< Format Byte T0 indicating if TA, TB, TC */ + uint8_t TA; /*!< Interface Byte TA(1) */ + uint8_t TB; /*!< Interface Byte TB(1) */ + uint8_t TC; /*!< Interface Byte TC(1) */ + uint8_t HB[RFAL_ISODEP_ATS_HB_MAX_LEN]; /*!< Historical Bytes */ +} rfalIsoDepAts; + + +/*! PPS Request format (Protocol and Parameter Selection) ISO14443-4 5.3 */ +typedef struct +{ + uint8_t PPSS; /*!< Start Byte: [ 1101b | CID[4b] ] */ + uint8_t PPS0; /*!< Parameter 0:[ 000b | PPS1[1n] | 0001b ] */ + uint8_t PPS1; /*!< Parameter 1:[ 0000b | DSI[2b] | DRI[2b] ]*/ +} rfalIsoDepPpsReq; + + +/*! PPS Response format (Protocol and Parameter Selection) ISO14443-4 5.4 */ +typedef struct +{ + uint8_t PPSS; /*!< Start Byte: [ 1101b | CID[4b] ] */ +} rfalIsoDepPpsRes; + + +/*! ATTRIB Command Format Digital 1.1 15.6.1 */ +typedef struct +{ + uint8_t cmd; /*!< ATTRIB_REQ command byte */ + uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFCID0 of the card to be selected */ + struct{ + uint8_t PARAM1; /*!< PARAM1 of ATTRIB command */ + uint8_t PARAM2; /*!< PARAM2 of ATTRIB command */ + uint8_t PARAM3; /*!< PARAM3 of ATTRIB command */ + uint8_t PARAM4; /*!< PARAM4 of ATTRIB command */ + }Param; /*!< Parameter of ATTRIB command */ + uint8_t HLInfo[RFAL_ISODEP_ATTRIB_HLINFO_LEN]; /*!< Higher Layer Information */ +} rfalIsoDepAttribCmd; + + +/*! ATTRIB Response Format Digital 1.1 15.6.2 */ +typedef struct +{ + uint8_t mbliDid; /*!< Contains MBLI and DID */ + uint8_t HLInfo[RFAL_ISODEP_ATTRIB_HLINFO_LEN]; /*!< Higher Layer Information */ +} rfalIsoDepAttribRes; + +/*! S(Parameters) Command Format ISO14443-4 (2016) Table 4 */ +typedef struct +{ + uint8_t tag; /*!< S(PARAMETERS) Tag field */ + uint8_t length; /*!< S(PARAMETERS) Length field */ + uint8_t value[RFAL_ISODEP_SPARAM_VALUES_MAX_LEN]; /*!< S(PARAMETERS) Value field */ +} rfalIsoDepSParameter; + + +/*! Activation info as Poller and Listener for NFC-A and NFC-B */ +typedef union {/* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently, device is only of type A or B at a time. Thus no problem can occur. */ + + /*! NFC-A information */ + union {/* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently, device is only PCD or PICC at a time. Thus no problem can occur. */ + struct { + rfalIsoDepAts ATS; /*!< ATS response (Poller mode) */ + uint8_t ATSLen; /*!< ATS response length (Poller mode) */ + }Listener; + struct { + rfalIsoDepRats RATS; /*!< RATS request (Listener mode) */ + }Poller; + }A; + + /*! NFC-B information */ + union {/* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently, device is only PCD or PICC at a time. Thus no problem can occur. */ + struct{ + rfalIsoDepAttribRes ATTRIB_RES; /*!< ATTRIB_RES (Poller mode) */ + uint8_t ATTRIB_RESLen; /*!< ATTRIB_RES length (Poller mode) */ + }Listener; + struct{ + rfalIsoDepAttribCmd ATTRIB; /*!< ATTRIB request (Listener mode) */ + uint8_t ATTRIBLen; /*!< ATTRIB request length (Listener mode) */ + }Poller; + }B; +}rfalIsoDepActivation; + + +/*! ISO-DEP device Info */ +typedef struct { + uint8_t FWI; /*!< Frame Waiting Integer */ + uint32_t FWT; /*!< Frame Waiting Time (1/fc) */ + uint32_t dFWT; /*!< Delta Frame Waiting Time (1/fc) */ + uint32_t SFGI; /*!< Start-up Frame Guard time Integer */ + uint32_t SFGT; /*!< Start-up Frame Guard Time (ms) */ + uint8_t FSxI; /*!< Frame Size Device/Card Integer (FSDI or FSCI) */ + uint16_t FSx; /*!< Frame Size Device/Card (FSD or FSC) */ + uint32_t MBL; /*!< Maximum Buffer Length (optional for NFC-B) */ + rfalBitRate DSI; /*!< Bit Rate coding from Listener (PICC) to Poller (PCD) */ + rfalBitRate DRI; /*!< Bit Rate coding from Poller (PCD) to Listener (PICC) */ + uint8_t DID; /*!< Device ID */ + uint8_t NAD; /*!< Node ADdress */ + bool supDID; /*!< DID supported flag */ + bool supNAD; /*!< NAD supported flag */ + bool supAdFt; /*!< Advanced Features supported flag */ +} rfalIsoDepInfo; + + +/*! ISO-DEP Device structure */ +typedef struct { + rfalIsoDepActivation activation; /*!< Activation Info */ + rfalIsoDepInfo info; /*!< ISO-DEP (ISO14443-4) device Info */ +} rfalIsoDepDevice; + + +/*! ATTRIB Response parameters */ +typedef struct +{ + uint8_t mbli; /*!< MBLI */ + uint8_t HLInfo[RFAL_ISODEP_ATTRIB_HLINFO_LEN]; /*!< Hi Layer Information */ + uint8_t HLInfoLen; /*!< Hi Layer Information Length */ +} rfalIsoDepAttribResParam; + + +/*! ATS Response parameter */ +typedef struct +{ + uint8_t fsci; /*!< Frame Size of Proximity Card Integer */ + uint8_t fwi; /*!< Frame Waiting Time Integer */ + uint8_t sfgi; /*!< Start-Up Frame Guard Time Integer */ + bool didSupport; /*!< DID Supported */ + uint8_t ta; /*!< Max supported bitrate both direction */ + uint8_t *hb; /*!< Historical Bytes data */ + uint8_t hbLen; /*!< Historical Bytes Length */ +} rfalIsoDepAtsParam; + + +/*! Structure of I-Block Buffer format from caller */ +typedef struct +{ + uint8_t prologue[RFAL_ISODEP_PROLOGUE_SIZE]; /*!< Prologue/SoD buffer */ + uint8_t inf[RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN]; /*!< INF/Payload buffer */ +} rfalIsoDepBufFormat; + + +/*! Structure of APDU Buffer format from caller */ +typedef struct +{ + uint8_t prologue[RFAL_ISODEP_PROLOGUE_SIZE]; /*!< Prologue/SoD buffer */ + uint8_t apdu[RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN]; /*!< APDU/Payload buffer */ +} rfalIsoDepApduBufFormat; + + +/*! Listen Activation Parameters Structure */ +typedef struct +{ + rfalIsoDepBufFormat *rxBuf; /*!< Receive Buffer struct reference */ + uint16_t *rxLen; /*!< Received INF data length in Bytes */ + bool *isRxChaining; /*!< Received data is not complete */ + rfalIsoDepDevice *isoDepDev; /*!< ISO-DEP device info */ +} rfalIsoDepListenActvParam; + + +/*! Structure of parameters used on ISO DEP Transceive */ +typedef struct +{ + rfalIsoDepBufFormat *txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in Bytes*/ + bool isTxChaining; /*!< Transmit data is not complete */ + rfalIsoDepBufFormat *rxBuf; /*!< Receive Buffer struct reference in Bytes */ + uint16_t *rxLen; /*!< Received INF data length in Bytes */ + bool *isRxChaining; /*!< Received data is not complete */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t ourFSx; /*!< Our device Frame Size (FSD or FSC) */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalIsoDepTxRxParam; + + +/*! Structure of parameters used on ISO DEP APDU Transceive */ +typedef struct +{ + rfalIsoDepApduBufFormat *txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in Bytes*/ + rfalIsoDepApduBufFormat *rxBuf; /*!< Receive Buffer struct reference in Bytes */ + uint16_t *rxLen; /*!< Received INF data length in Bytes */ + rfalIsoDepBufFormat *tmpBuf; /*!< Temp buffer for Rx I-Blocks (internal) */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint16_t ourFSx; /*!< Our device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalIsoDepApduTxRxParam; + +/* + ****************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + + +/*! + ****************************************************************************** + * \brief Initialize the ISO-DEP protocol + * + * Initialize the ISO-DEP protocol layer with default config + ****************************************************************************** + */ +void rfalIsoDepInitialize( void ); + + +/*! + ****************************************************************************** + * \brief Initialize the ISO-DEP protocol + * + * Initialize the ISO-DEP protocol layer with additional parameters allowing + * to customise the protocol layer for specific behaviours + * + * \param[in] compMode : compliance mode to be performed + * \param[in] maxRetriesR : Number of retries for a R-Block + * \param[in] maxRetriesS : Number of retries for a S-Block + * \param[in] maxRetriesI : Number of retries for a I-Block + * \param[in] maxRetriesRATS : Number of retries for RATS + * + ****************************************************************************** + */ +void rfalIsoDepInitializeWithParams( rfalComplianceMode compMode, uint8_t maxRetriesR, uint8_t maxRetriesS, uint8_t maxRetriesI, uint8_t maxRetriesRATS ); + + +/*! + ***************************************************************************** + * \brief FSxI to FSx + * + * Convert Frame Size for proximity coupling Device Integer (FSxI) to + * Frame Size for proximity coupling Device (FSx) + * + * FSD - maximum frame size for NFC Forum Device in Poll Mode + * FSC - maximum frame size for NFC Forum Device in Listen Mode + * + * FSxI = FSDI or FSCI + * FSx = FSD or FSC + * + * The FSD/FSC value includes the header and CRC + * + * \param[in] FSxI : Frame Size for proximity coupling Device Integer + * + * \return fsx : Frame Size for proximity coupling Device (FSD or FSC) + * + ***************************************************************************** + */ +uint16_t rfalIsoDepFSxI2FSx( uint8_t FSxI ); + + +/*! + ***************************************************************************** + * \brief FWI to FWT + * + * Convert Frame Waiting time Integer (FWI) to Frame Waiting Time (FWT) in + * 1/fc units + * + * \param[in] fwi : Frame Waiting time Integer + * + * \return fwt : Frame Waiting Time in 1/fc units + * + ***************************************************************************** + */ +uint32_t rfalIsoDepFWI2FWT( uint8_t fwi ); + + +/*! + ***************************************************************************** + * \brief Check if the buffer data contains a valid RATS command + * + * Check if it is a well formed RATS command with 2 bytes + * This function does not check the validity of FSDI and DID + * + * \param[in] buf : reference to buffer containing the data to be checked + * \param[in] bufLen : length of data in the buffer in bytes + * + * \return true if the data indicates a RATS command; false otherwise + ***************************************************************************** + */ +bool rfalIsoDepIsRats( const uint8_t *buf, uint8_t bufLen ); + + +/*! + ***************************************************************************** + * \brief Check if the buffer data contains a valid ATTRIB command + * + * Check if it is a well formed ATTRIB command, but does not check the + * validity of the information inside + * + * \param[in] buf : reference to buffer containing the data to be checked + * \param[in] bufLen : length of data in the buffer in bytes + * + * \return true if the data indicates a ATTRIB command; false otherwise + ***************************************************************************** + */ +bool rfalIsoDepIsAttrib( const uint8_t *buf, uint8_t bufLen ); + + +/*! + ***************************************************************************** + * \brief Start Listen Activation Handling + * + * Start Listen Activation Handling and setup to receive first I-block which may + * contain complete or partial APDU after activation is completed + * + * Pass in RATS for T4AT, or ATTRIB for T4BT, to handle ATS or ATTRIB Response respectively + * The Activation Handling handles ATS and ATTRIB Response; and additionally PPS Response + * if a PPS is received for T4AT. + * The method uses the current RFAL state machine to determine if it is expecting RATS or ATTRIB + * + * Activation is completed if PPS Response is sent or if first PDU is received in T4T-A + * Activation is completed if ATTRIB Response is sent in T4T-B + * + * \ref rfalIsoDepListenGetActivationStatus provide status if activation is completed. + * \ref rfalIsoDepStartTransceive shall be called right after activation is completed + * + * \param[in] atsParam : reference to ATS parameters + * \param[in] attribResParam : reference to ATTRIB_RES parameters + * \param[in] buf : reference to buffer containing RATS or ATTRIB + * \param[in] bufLen : length in bytes of the given bufffer + * \param[in] actParam : reference to incoming reception information will be placed + * + * + * \warning Once the Activation has been completed the method + * rfalIsoDepGetTransceiveStatus() must be called. + * If activation has completed due to reception of a data block (not PPS) the + * buffer owned by the caller and passed on actParam must still contain this data. + * The first data will be processed (I-Block or S-DSL) by rfalIsoDepGetTransceiveStatus() + * inform the caller and then for the next transaction use rfalIsoDepStartTransceive() + * + * \return ERR_NONE : RATS/ATTRIB is valid and activation has started + * \return ERR_PARAM : Invalid parameters + * \return ERR_PROTO : Invalid request + * \return ERR_NOTSUPP : Feature not supported + ***************************************************************************** + */ +ReturnCode rfalIsoDepListenStartActivation( rfalIsoDepAtsParam *atsParam, const rfalIsoDepAttribResParam *attribResParam, uint8_t *buf, uint16_t bufLen, rfalIsoDepListenActvParam actParam ); + + +/*! + ***************************************************************************** + * \brief Get the current Activation Status + * + * \return ERR_NONE if Activation is already completed + * \return ERR_BUSY if Activation is ongoing + * \return ERR_LINK_LOSS if Remote Field is turned off + ***************************************************************************** + */ +ReturnCode rfalIsoDepListenGetActivationStatus( void ); + + +/*! + ***************************************************************************** + * \brief Get the ISO-DEP Communication Information + * + * Gets the maximum INF length in bytes based on current Frame Size + * for proximity coupling Device (FSD or FSC) excluding the header and CRC + * + * \return maximum INF length in bytes + ***************************************************************************** + */ +uint16_t rfalIsoDepGetMaxInfLen( void ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Start Transceive + * + * This method triggers a ISO-DEP Transceive containing a complete or + * partial APDU + * It transmits the given message and handles all protocol retransmitions, + * error handling and control messages + * + * The txBuf contains a complete or partial APDU (INF) to be transmitted + * The Prologue field will be manipulated by the Transceive + * + * If the buffer contains a partial APDU and is not the last block, + * then isTxChaining must be set to true + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalIsoDepStartTransceive( rfalIsoDepTxRxParam param ); + + +/*! + ***************************************************************************** + * \brief Get the Transceive status + * + * Returns the status of the ISO-DEP Transceive + * + * \warning When the other device is performing chaining once a chained + * block is received the error ERR_AGAIN is sent. At this point + * caller must handle the received data immediately. + * When ERR_AGAIN is returned an ACK has already been sent to + * the other device and the next block might be incoming. + * If rfalWorker() is called frequently it will place the next + * block on the given buffer + * + * + * \return ERR_NONE : Transceive has been completed successfully + * \return ERR_BUSY : Transceive is ongoing + * \return ERR_PROTO : Protocol error occurred + * \return ERR_TIMEOUT : Timeout error occurred + * \return ERR_SLEEP_REQ : Deselect has been received and responded + * \return ERR_NOMEM : The received INF does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : Communication is lost because Reader/Writer + * has turned off its field + * \return ERR_AGAIN : received one chaining block, continue to call + * this method to retrieve the remaining blocks + ***************************************************************************** + */ +ReturnCode rfalIsoDepGetTransceiveStatus( void ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Start APDU Transceive + * + * This method triggers a ISO-DEP Transceive containing a complete APDU + * It transmits the given message and handles all protocol retransmitions, + * error handling and control messages + * + * The txBuf contains a complete APDU to be transmitted + * The Prologue field will be manipulated by the Transceive + * + * \warning the txBuf will be modified during the transmission + * \warning the maximum RF frame which can be received is limited by param.tmpBuf + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalIsoDepStartApduTransceive( rfalIsoDepApduTxRxParam param ); + + +/*! + ***************************************************************************** + * \brief Get the APDU Transceive status + * + * \return ERR_NONE : if Transceive has been completed successfully + * \return ERR_BUSY : if Transceive is ongoing + * \return ERR_PROTO : if a protocol error occurred + * \return ERR_TIMEOUT : if a timeout error occurred + * \return ERR_SLEEP_REQ : if Deselect is received and responded + * \return ERR_NOMEM : if the received INF does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : if communication is lost because Reader/Writer + * has turned off its field + ***************************************************************************** + */ +ReturnCode rfalIsoDepGetApduTransceiveStatus( void ); + +/*! + ***************************************************************************** + * \brief ISO-DEP Send RATS + * + * This sends a RATS to make a NFC-A Listen Device to enter + * ISO-DEP layer (ISO14443-4) and checks if the received ATS is valid + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[out] ats : pointer to place the ATS Response + * \param[out] atsLen : pointer to place the ATS length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, ATS received + ***************************************************************************** + */ +ReturnCode rfalIsoDepRATS( rfalIsoDepFSxI FSDI, uint8_t DID, rfalIsoDepAts *ats , uint8_t *atsLen ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Send PPS + * + * This sends a PPS to make a NFC-A Listen Device change the communications + * bit rate from 106kbps to one of the supported bit rates + * Additionally checks if the received PPS response is valid + * + * \param[in] DID : Device ID + * \param[in] DSI : DSI code the divisor from Listener (PICC) to Poller (PCD) + * \param[in] DRI : DRI code the divisor from Poller (PCD) to Listener (PICC) + * \param[out] ppsRes : pointer to place the PPS Response + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, PPS Response received + ***************************************************************************** + */ +ReturnCode rfalIsoDepPPS( uint8_t DID, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepPpsRes *ppsRes ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Send ATTRIB + * + * This sends a ATTRIB to make a NFC-B Listen Device to enter + * ISO-DEP layer (ISO14443-4) and checks if the received ATTRIB Response is valid + * + * \param[in] nfcid0 : NFCID0 to be used for the ATTRIB + * \param[in] PARAM1 : ATTRIB PARAM1 byte (communication parameters) + * \param[in] DSI : DSI code the divisor from Listener (PICC) to Poller (PCD) + * \param[in] DRI : DRI code the divisor from Poller (PCD) to Listener (PICC) + * \param[in] FSDI : PCD's Frame Size to be announced on the ATTRIB + * \param[in] PARAM3 : ATTRIB PARAM1 byte (protocol type) + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] HLInfo : pointer to Higher layer INF (NULL if none) + * \param[in] HLInfoLen : Length HLInfo + * \param[in] fwt : Frame Waiting Time to be used (from SENSB_RES) + * \param[out] attribRes : pointer to place the ATTRIB Response + * \param[out] attribResLen : pointer to place the ATTRIB Response length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, ATTRIB Response received + ***************************************************************************** + */ +ReturnCode rfalIsoDepATTRIB( const uint8_t* nfcid0, uint8_t PARAM1, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepFSxI FSDI, uint8_t PARAM3, uint8_t DID, const uint8_t* HLInfo, uint8_t HLInfoLen, uint32_t fwt, rfalIsoDepAttribRes *attribRes, uint8_t *attribResLen ); + + +/*! + ***************************************************************************** + * \brief Deselects PICC + * + * This function sends a deselect command to PICC and waits for it`s + * responce in a blocking way + * + * \return ERR_NONE : Deselect successfully sent and acknowledged by PICC + * \return ERR_TIMEOUT: No response rcvd from PICC + * + ***************************************************************************** + */ +ReturnCode rfalIsoDepDeselect( void ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Handle NFC-A Activation + * + * This performs a NFC-A Activation into ISO-DEP layer (ISO14443-4) with the given + * parameters. It sends RATS and if the higher bit rates are supported by + * both devices it additionally sends PPS + * Once Activated all details of the device are provided on isoDepDev + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] maxBR : Max bit rate supported by the Poller + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollAHandleActivation( rfalIsoDepFSxI FSDI, uint8_t DID, rfalBitRate maxBR, rfalIsoDepDevice *isoDepDev ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Handle NFC-B Activation + * + * This performs a NFC-B Activation into ISO-DEP layer (ISO14443-4) with the given + * parameters. It sends ATTRIB and calculates supported higher bit rates of both + * devices and performs activation. + * Once Activated all details of the device are provided on isoDepDev + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] maxBR : Max bit rate supported by the Poller + * \param[in] PARAM1 : ATTRIB PARAM1 byte (communication parameters) + * \param[in] nfcbDev : pointer to the NFC-B Device containing the SENSB_RES + * \param[in] HLInfo : pointer to Higher layer INF (NULL if none) + * \param[in] HLInfoLen : Length HLInfo + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollBHandleActivation( rfalIsoDepFSxI FSDI, uint8_t DID, rfalBitRate maxBR, uint8_t PARAM1, const rfalNfcbListenDevice *nfcbDev, const uint8_t* HLInfo, uint8_t HLInfoLen, rfalIsoDepDevice *isoDepDev ); + + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Handle S(Parameters) + * + * This checks if PICC supports S(PARAMETERS), retieves PICC's + * capabilities and sets the Bit Rate at the highest supported by both + * devices + * + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * \param[in] maxTxBR : Maximum Tx bit rate supported by PCD + * \param[in] maxRxBR : Maximum Rx bit rate supported by PCD + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, S(PARAMETERS) selection successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollHandleSParameters( rfalIsoDepDevice *isoDepDev, rfalBitRate maxTxBR, rfalBitRate maxRxBR ); + + +#endif /* RFAL_ISODEP_H_ */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_nfc.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfc.h new file mode 100644 index 0000000..e2cc059 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfc.h @@ -0,0 +1,406 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfc.h + * + * \brief RFAL NFC device + * + * This module provides the required features to behave as an NFC Poller + * or Listener device. It grants an easy to use interface for the following + * activities: Technology Detection, Collision Resolution, Activation, + * Data Exchange, and Deactivation + * + * This layer is influenced by (but not fully aligned with) the NFC Forum + * specifications, in particular: Activity 2.0 and NCI 2.0 + * + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup RF + * \brief RFAL RF Abstraction Layer + * @{ + * + */ + +#ifndef RFAL_NFC_H +#define RFAL_NFC_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" +#include "rfal_nfca.h" +#include "rfal_nfcb.h" +#include "rfal_nfcf.h" +#include "rfal_nfcv.h" +#include "rfal_st25tb.h" +#include "rfal_nfcDep.h" +#include "rfal_isoDep.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define RFAL_NFC_RF_BUF_LEN 255U /*!< No technology */ + +#define RFAL_NFC_TECH_NONE 0x0000U /*!< No technology */ +#define RFAL_NFC_POLL_TECH_A 0x0001U /*!< NFC-A technology Flag */ +#define RFAL_NFC_POLL_TECH_B 0x0002U /*!< NFC-B technology Flag */ +#define RFAL_NFC_POLL_TECH_F 0x0004U /*!< NFC-F technology Flag */ +#define RFAL_NFC_POLL_TECH_V 0x0008U /*!< NFC-V technology Flag */ +#define RFAL_NFC_POLL_TECH_AP2P 0x0010U /*!< AP2P technology Flag */ +#define RFAL_NFC_POLL_TECH_ST25TB 0x0020U /*!< ST25TB technology Flag */ +#define RFAL_NFC_LISTEN_TECH_A 0x1000U /*!< NFC-V technology Flag */ +#define RFAL_NFC_LISTEN_TECH_B 0x2000U /*!< NFC-V technology Flag */ +#define RFAL_NFC_LISTEN_TECH_F 0x4000U /*!< NFC-V technology Flag */ +#define RFAL_NFC_LISTEN_TECH_AP2P 0x8000U /*!< NFC-V technology Flag */ + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Checks if a device is currently activated */ +#define rfalNfcIsDevActivated( st ) ( ((st)>= RFAL_NFC_STATE_ACTIVATED) && ((st)= RFAL_NFC_STATE_START_DISCOVERY) && ((st)= 1. + * + * \param[in] disParams : discovery configuration parameters + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcDiscover( const rfalNfcDiscoverParam *disParams ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get State + * + * It returns the current state + * + * \return rfalNfcState : the current state + ***************************************************************************** + */ +rfalNfcState rfalNfcGetState( void ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get Devices Found + * + * It returns the location of the device list and the number of + * devices found. + * + * \param[out] devList : device list location + * \param[out] devCnt : number of devices found + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * Discovery still ongoing + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcGetDevicesFound( rfalNfcDevice **devList, uint8_t *devCnt ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get Active Device + * + * It returns the location of the device current Active device + * + * \param[out] dev : device info location + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * No device activated + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcGetActiveDevice( rfalNfcDevice **dev ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Select Device + * + * It selects the device to be activated. + * It shall be called when more than one device has been identified to + * indiacte which device shall be actived + * + * \param[in] devIdx : device index to be activated + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * Not in select state + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcSelect( uint8_t devIdx ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Start Data Exchange + * + * After a device has been activated, it starts a data exchange. + * It handles automatically which interface/protocol to be used and acts accordingly. + * + * In Listen mode the first frame/data shall be sent by the Reader/Initiator + * therefore this method must be called first with txDataLen set to zero + * to retrieve the rxData and rcvLen locations. + * + * + * \param[in] txData : data to be transmitted + * \param[in] txDataLen : size of the data to be transmitted + * \param[out] rxData : location of the received data after operation is completed + * \param[out] rvdLen : location of thelength of the received data + * \param[in] fwt : FWT to be used in case of RF interface. + * If ISO-DEP or NFC-DEP interface is used, this will be ignored + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcDataExchangeStart( uint8_t *txData, uint16_t txDataLen, uint8_t **rxData, uint16_t **rvdLen, uint32_t fwt ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get Data Exchange Status + * + * Gets current Data Exchange status + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_AGAIN : received one chaining block, copy received data + * and continue to call this method to retrieve the + * remaining blocks + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalNfcDataExchangeGetStatus( void ); + +/*! + ***************************************************************************** + * \brief RFAL NFC Deactivate + * + * It triggers the deactivation procedure to terminate communications with + * remote device. At the end the field will be turned off. + * + * \param[in] discovery : TRUE if after deactivation go back into discovery + * : FALSE if after deactivation remain in idle + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcDeactivate( bool discovery ); + +#endif /* RFAL_NFC_H */ + + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcDep.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcDep.h new file mode 100644 index 0000000..a897555 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcDep.h @@ -0,0 +1,700 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcDep.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-DEP protocol + * + * NFC-DEP is also known as NFCIP - Near Field Communication + * Interface and Protocol + * + * This implementation was based on the following specs: + * - NFC Forum Digital 1.1 + * - ECMA 340 3rd Edition 2013 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-DEP + * \brief RFAL NFC-DEP Module + * @{ + */ + +#ifndef RFAL_NFCDEP_H_ +#define RFAL_NFCDEP_H_ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define RFAL_NFCDEP_FRAME_SIZE_MAX_LEN 254U /*!< NFCIP Maximum Frame Size Digital 1.0 Table 91 */ +#define RFAL_NFCDEP_DEPREQ_HEADER_LEN 5U /*!< DEP_REQ header length: CMD_TYPE + CMD_CMD + PBF + DID + NAD */ + +/*! Length NFCIP DEP REQ or RES header (incl LEN) */ +#define RFAL_NFCDEP_DEP_HEADER ( RFAL_NFCDEP_LEN_LEN + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN + RFAL_NFCDEP_DEP_PFB_LEN ) +#define RFAL_NFCDEP_HEADER ( RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN ) /*!< NFCIP header length */ +#define RFAL_NFCDEP_SB_LEN 1U /*!< SB length on NFCIP fram for NFC-A */ +#define RFAL_NFCDEP_LEN_LEN 1U /*!< LEN length on NFCIP frame */ +#define RFAL_NFCDEP_CMDTYPE_LEN 1U /*!< Length of the cmd type (REQ | RES) on NFCIP frame */ +#define RFAL_NFCDEP_CMD_LEN 1U /*!< Length of the cmd on NFCIP frame */ +#define RFAL_NFCDEP_DID_LEN 1U /*!< Length of did on NFCIP frame */ +#define RFAL_NFCDEP_DEP_PFB_LEN 1U /*!< Length of the PFB field on NFCIP frame */ + +#define RFAL_NFCDEP_DSL_RLS_LEN_NO_DID (RFAL_NFCDEP_LEN_LEN + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN) /*!< Length of DSL_REQ and RLS_REQ with no DID */ +#define RFAL_NFCDEP_DSL_RLS_LEN_DID (RFAL_NFCDEP_DSL_RLS_LEN_NO_DID + RFAL_NFCDEP_DID_LEN) /*!< Length of DSL_REQ and RLS_REQ with DID */ + +#define RFAL_NFCDEP_FS_VAL_MIN 64U /*!< Minimum LR value */ +#define RFAL_NFCDEP_LR_VAL_MASK 0x03U /*!< Bit mask for a LR value */ +#define RFAL_NFCDEP_PP_LR_MASK 0x30U /*!< Bit mask for LR value in PP byte on a ATR REQ/RES */ +#define RFAL_NFCDEP_PP_LR_SHIFT 4U /*!< Position of LR value in PP byte on a ATR REQ/RES */ + +#define RFAL_NFCDEP_DID_MAX 14U /*!< Max DID value Digital 14.6.2.3 */ +#define RFAL_NFCDEP_DID_KEEP 0xFFU /*!< Keep DID value already configured */ +#define RFAL_NFCDEP_DID_NO 0x00U /*!< No DID shall be used */ +#define RFAL_NFCDEP_NAD_NO 0x00U /*!< No NAD shall be used */ + +#define RFAL_NFCDEP_OPER_RTOX_REQ_DIS 0x01U /*!< Operation config: RTOX REQ disable */ +#define RFAL_NFCDEP_OPER_RTOX_REQ_EN 0x00U /*!< Operation config: RTOX REQ enable */ + +#define RFAL_NFCDEP_OPER_ATN_DIS 0x00U /*!< Operation config: ATN disable */ +#define RFAL_NFCDEP_OPER_ATN_EN 0x02U /*!< Operation config: ATN enable */ + +#define RFAL_NFCDEP_OPER_EMPTY_DEP_DIS 0x04U /*!< Operation config: empty DEPs disable */ +#define RFAL_NFCDEP_OPER_EMPTY_DEP_EN 0x00U /*!< Operation config: empty DEPs enable */ + +#define RFAL_NFCDEP_OPER_FULL_MI_DIS 0x00U /*!< Operation config: full chaining DEPs disable */ +#define RFAL_NFCDEP_OPER_FULL_MI_EN 0x08U /*!< Operation config: full chaining DEPs enable */ + + +#define RFAL_NFCDEP_BRS_MAINTAIN 0xC0U /*!< Value signalling that BR is to be maintained (no PSL) */ +#define RFAL_NFCDEP_BRS_Dx_MASK 0x07U /*!< Value signalling that BR is to be maintained (no PSL) */ +#define RFAL_NFCDEP_BRS_DSI_POS 3U /*!< Value signalling that BR is to be maintained (no PSL) */ + +#define RFAL_NFCDEP_WT_DELTA (16U - RFAL_NFCDEP_WT_DELTA_ADJUST) /*!< NFC-DEP dWRT (adjusted) Digital 2.0 B.10 */ +#define RFAL_NFCDEP_WT_DELTA_ADJUST 4U /*!< dWRT value adjustment */ + + +#define RFAL_NFCDEP_ATR_REQ_NFCID3_POS 2U /*!< NFCID3 offset in ATR_REQ frame */ +#define RFAL_NFCDEP_NFCID3_LEN 10U /*!< NFCID3 Length */ + +#define RFAL_NFCDEP_LEN_MIN 3U /*!< Minimum length byte LEN value */ +#define RFAL_NFCDEP_LEN_MAX 255U /*!< Maximum length byte LEN value */ + +#define RFAL_NFCDEP_ATRRES_HEADER_LEN 2U /*!< ATR RES Header Len: CmdType: 0xD5 + Cod: 0x01 */ +#define RFAL_NFCDEP_ATRRES_MIN_LEN 17U /*!< Minimum length for an ATR RES */ +#define RFAL_NFCDEP_ATRRES_MAX_LEN 64U /*!< Maximum length for an ATR RES Digital 1.0 14.6.1 */ +#define RFAL_NFCDEP_ATRREQ_MIN_LEN 16U /*!< Minimum length for an ATR REQ */ +#define RFAL_NFCDEP_ATRREQ_MAX_LEN RFAL_NFCDEP_ATRRES_MAX_LEN /*!< Maximum length for an ATR REQ Digital 1.0 14.6.1 */ + +#define RFAL_NFCDEP_GB_MAX_LEN (RFAL_NFCDEP_ATRREQ_MAX_LEN - RFAL_NFCDEP_ATRREQ_MIN_LEN) /*!< Maximum length the General Bytes on ATR Digital 1.1 16.6.3 */ + +#define RFAL_NFCDEP_WT_INI_DEFAULT RFAL_NFCDEP_WT_INI_MAX /*!< WT Initiator default value Digital 1.0 14.6.3.8 */ +#define RFAL_NFCDEP_WT_INI_MIN 0U /*!< WT Initiator minimum value Digital 1.0 14.6.3.8 */ +#define RFAL_NFCDEP_WT_INI_MAX 14U /*!< WT Initiator maximum value Digital 1.0 14.6.3.8 A.10 */ +#define RFAL_NFCDEP_RWT_INI_MAX rfalNfcDepWT2RWT( RFAL_NFCDEP_WT_INI_MAX ) /*!< RWT Initiator maximum value */ + +#define RFAL_NFCDEP_WT_TRG_MAX_D10 8U /*!< WT target max Digital 1.0 14.6.3.8 A.10 */ +#define RFAL_NFCDEP_WT_TRG_MAX_D11 14U /*!< WT target max Digital 1.1 16.6.3.9 A.9 */ +#define RFAL_NFCDEP_WT_TRG_MAX RFAL_NFCDEP_WT_TRG_MAX_D11 /*!< WT target max Digital x.x */ +#define RFAL_NFCDEP_RWT_TRG_MAX rfalNfcDepWT2RWT( RFAL_NFCDEP_WT_TRG_MAX ) /*!< RWT Initiator maximum value */ + +/*! Maximum Frame Waiting Time = ((256 * 16/fc)*2^FWImax) = ((256*16/fc)*2^14) = (1048576 / 64)/fc = (100000h*64)/fc */ +#define RFAL_NFCDEP_MAX_FWT ((uint32_t)1U<<20) + +#define RFAL_NFCDEP_WT_MASK 0x0FU /*!< Bit mask for the Wait Time value */ + +#define RFAL_NFCDEP_BR_MASK_106 0x01U /*!< Enable mask bit rate 106 */ +#define RFAL_NFCDEP_BR_MASK_212 0x02U /*!< Enable mask bit rate 242 */ +#define RFAL_NFCDEP_BR_MASK_424 0x04U /*!< Enable mask bit rate 424 */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +#define rfalNfcDepWT2RWT( wt ) ( (uint32_t)1U << (((uint32_t)(wt) & RFAL_NFCDEP_WT_MASK) + 12U) ) /*!< Converts WT value to RWT (1/fc) */ + +/*! Returns the BRS value from the given bit rate */ +#define rfalNfcDepDx2BRS( br ) ( (((uint8_t)(br) & RFAL_NFCDEP_BRS_Dx_MASK) << RFAL_NFCDEP_BRS_DSI_POS) | ((uint8_t)(br) & RFAL_NFCDEP_BRS_Dx_MASK) ) + +#define rfalNfcDepBRS2DRI( brs ) (uint8_t)( (uint8_t)(brs) & RFAL_NFCDEP_BRS_Dx_MASK ) /*!< Returns the DRI value from the given BRS byte */ +#define rfalNfcDepBRS2DSI( brs ) (uint8_t)( ((uint8_t)(brs) >> RFAL_NFCDEP_BRS_DSI_POS) & RFAL_NFCDEP_BRS_Dx_MASK ) /*!< Returns the DSI value from the given BRS byte */ + +#define rfalNfcDepPP2LR( PPx ) ( ((uint8_t)(PPx) & RFAL_NFCDEP_PP_LR_MASK ) >> RFAL_NFCDEP_PP_LR_SHIFT) /*!< Returns the LR value from the given PPx byte */ +#define rfalNfcDepLR2PP( LRx ) ( ((uint8_t)(LRx) << RFAL_NFCDEP_PP_LR_SHIFT) & RFAL_NFCDEP_PP_LR_MASK) /*!< Returns the PP byte with the given LRx value */ + +/*! Returns the Frame size value from the given LRx value */ +#define rfalNfcDepLR2FS( LRx ) (uint16_t)(MIN( (RFAL_NFCDEP_FS_VAL_MIN * ((uint16_t)(LRx) + 1U) ), RFAL_NFCDEP_FRAME_SIZE_MAX_LEN )) + +/*! + * Despite DIGITAL 1.0 14.6.2.1 stating that the last two bytes may filled with + * any value, some devices (Samsung Google Nexus) only accept when these are 0 */ +#define rfalNfcDepSetNFCID( dst, src, len ) ST_MEMSET( (dst), 0x00, RFAL_NFCDEP_NFCID3_LEN ); \ + if( (len) > 0U ) {ST_MEMCPY( (dst), (src), (len) );} + +/* + ****************************************************************************** + * GLOBAL ENUMERATIONS + ****************************************************************************** + */ + +/*! Enumeration of NFC-DEP bit rate in ATR Digital 1.0 Table 93 and 94 */ +enum{ + RFAL_NFCDEP_Bx_NO_HIGH_BR = 0x00, /*!< Peer supports no high bit rates */ + RFAL_NFCDEP_Bx_08_848 = 0x01, /*!< Peer also supports 848 */ + RFAL_NFCDEP_Bx_16_1695 = 0x02, /*!< Peer also supports 1695 */ + RFAL_NFCDEP_Bx_32_3390 = 0x04, /*!< Peer also supports 3390 */ + RFAL_NFCDEP_Bx_64_6780 = 0x08 /*!< Peer also supports 6780 */ +}; + +/*! Enumeration of NFC-DEP bit rate Dividor in PSL Digital 1.0 Table 100 */ +enum{ + RFAL_NFCDEP_Dx_01_106 = RFAL_BR_106, /*!< Divisor D = 1 : bit rate = 106 */ + RFAL_NFCDEP_Dx_02_212 = RFAL_BR_212, /*!< Divisor D = 2 : bit rate = 212 */ + RFAL_NFCDEP_Dx_04_424 = RFAL_BR_424, /*!< Divisor D = 4 : bit rate = 424 */ + RFAL_NFCDEP_Dx_08_848 = RFAL_BR_848, /*!< Divisor D = 8 : bit rate = 848 */ + RFAL_NFCDEP_Dx_16_1695 = RFAL_BR_1695, /*!< Divisor D = 16 : bit rate = 1695 */ + RFAL_NFCDEP_Dx_32_3390 = RFAL_BR_3390, /*!< Divisor D = 32 : bit rate = 3390 */ + RFAL_NFCDEP_Dx_64_6780 = RFAL_BR_6780 /*!< Divisor D = 64 : bit rate = 6780 */ +}; + +/*! Enumeration of NFC-DEP Length Reduction (LR) Digital 1.0 Table 91 */ +enum{ + RFAL_NFCDEP_LR_64 = 0x00, /*!< Maximum payload size is 64 bytes */ + RFAL_NFCDEP_LR_128 = 0x01, /*!< Maximum payload size is 128 bytes */ + RFAL_NFCDEP_LR_192 = 0x02, /*!< Maximum payload size is 192 bytes */ + RFAL_NFCDEP_LR_254 = 0x03 /*!< Maximum payload size is 254 bytes */ +}; + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +/*! NFC-DEP callback to check if upper layer has deactivation pending */ +typedef bool (* rfalNfcDepDeactCallback)(void); + + +/*! Enumeration of the nfcip communication modes */ +typedef enum{ + RFAL_NFCDEP_COMM_PASSIVE, /*!< Passive communication mode */ + RFAL_NFCDEP_COMM_ACTIVE /*!< Active communication mode */ +} rfalNfcDepCommMode; + + +/*! Enumeration of the nfcip roles */ +typedef enum{ + RFAL_NFCDEP_ROLE_INITIATOR, /*!< Perform as Initiator */ + RFAL_NFCDEP_ROLE_TARGET /*!< Perform as Target */ +} rfalNfcDepRole; + + +/*! Struct that holds all NFCIP configs */ +typedef struct{ + + rfalNfcDepRole role; /*!< Current NFCIP role */ + rfalNfcDepCommMode commMode; /*!< Current NFCIP communication mode */ + uint8_t oper; /*!< Operation config similar to NCI 1.0 Table 81 */ + + uint8_t did; /*!< Current Device ID (DID) */ + uint8_t nad; /*!< Current Node Addressing (NAD) */ + uint8_t bs; /*!< Bit rate in Sending Direction */ + uint8_t br; /*!< Bit rate in Receiving Direction */ + uint8_t nfcid[RFAL_NFCDEP_NFCID3_LEN]; /*!< Pointer to the NFCID to be used */ + uint8_t nfcidLen; /*!< Length of the given NFCID in nfcid */ + uint8_t gb[RFAL_NFCDEP_GB_MAX_LEN]; /*!< Pointer General Bytes (GB) to be used */ + uint8_t gbLen; /*!< Length of the given GB in gb */ + uint8_t lr; /*!< Length Reduction (LR) to be used */ + uint8_t to; /*!< Timeout (TO) to be used */ + uint32_t fwt; /*!< Frame Waiting Time (FWT) to be used */ + uint32_t dFwt; /*!< Delta Frame Waiting Time (dFWT) to be used */ +} rfalNfcDepConfigs; + + +/*! ATR_REQ command Digital 1.1 16.6.2 */ +typedef struct { + uint8_t CMD1; /*!< Command format 0xD4 */ + uint8_t CMD2; /*!< Command Value */ + uint8_t NFCID3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 value */ + uint8_t DID; /*!< DID */ + uint8_t BSi; /*!< Sending Bitrate for Initiator */ + uint8_t BRi; /*!< Receiving Bitrate for Initiator */ + uint8_t PPi; /*!< Optional Parameters presence indicator */ + uint8_t GBi[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General Bytes */ +} rfalNfcDepAtrReq; + + +/*! ATR_RES response Digital 1.1 16.6.3 */ +typedef struct { + uint8_t CMD1; /*!< Response Byte 0xD5 */ + uint8_t CMD2; /*!< Command Value */ + uint8_t NFCID3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 value */ + uint8_t DID; /*!< DID */ + uint8_t BSt; /*!< Sending Bitrate for Initiator */ + uint8_t BRt; /*!< Receiving Bitrate for Initiator */ + uint8_t TO; /*!< Timeout */ + uint8_t PPt; /*!< Optional Parameters presence indicator */ + uint8_t GBt[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General Bytes */ +} rfalNfcDepAtrRes; + + +/*! Structure of transmit I-PDU Buffer format from caller */ +typedef struct +{ + uint8_t prologue[RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /*!< Prologue space for NFC-DEP header*/ + uint8_t inf[RFAL_NFCDEP_FRAME_SIZE_MAX_LEN]; /*!< INF | Data area of the buffer */ +} rfalNfcDepBufFormat; + + +/*! Activation info as Initiator and Target */ +typedef union { /* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently , device is only initiatior or target a time. No problem can occur. */ + struct { + rfalNfcDepAtrRes ATR_RES; /*!< ATR RES (Initiator mode) */ + uint8_t ATR_RESLen; /*!< ATR RES length (Initiator mode) */ + }Target; /*!< Target */ + struct { + rfalNfcDepAtrReq ATR_REQ; /*!< ATR REQ (Target mode) */ + uint8_t ATR_REQLen; /*!< ATR REQ length (Target mode) */ + }Initiator; /*!< Initiator */ +} rfalNfcDepActivation; + + +/*! NFC-DEP device Info */ +typedef struct { + uint8_t GBLen; /*!< General Bytes length */ + uint8_t WT; /*!< WT to be used (ignored in Listen Mode) */ + uint32_t FWT; /*!< FWT to be used (1/fc)(ignored Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used (1/fc) */ + uint8_t LR; /*!< Length Reduction coding the max payload */ + uint16_t FS; /*!< Frame Size */ + rfalBitRate DSI; /*!< Bit Rate coding from Initiator to Target */ + rfalBitRate DRI; /*!< Bit Rate coding from Target to Initiator */ + uint8_t DID; /*!< Device ID (RFAL_NFCDEP_DID_NO if no DID) */ + uint8_t NAD; /*!< Node ADdress (RFAL_NFCDEP_NAD_NO if no NAD)*/ +} rfalNfcDepInfo; + + +/*! NFC-DEP Device structure */ +typedef struct { + rfalNfcDepActivation activation; /*!< Activation Info */ + rfalNfcDepInfo info; /*!< NFC-DEP device Info */ +} rfalNfcDepDevice; + + +/*! NFCIP Protocol structure for P2P Target + * + * operParam : derives from NFC-Forum NCI NFC-DEP Operation Parameter + * NCI 1.1 Table 86: NFC-DEP Operation Parameter + * and it's a bit mask composed as: + * [ 0000b + * | Chain SHALL use max. Transport Data Byte[1b] + * | I-PDU with no Transport Data SHALL NOT be sent [1b] + * | NFC-DEP Target SHALL NOT send RTOX request [1b] + * ] + * + */ +typedef struct{ + rfalNfcDepCommMode commMode; /*!< Initiator in Active P2P or Passive P2P*/ + uint8_t operParam; /*!< NFC-DEP Operation Parameter */ + uint8_t* nfcid; /*!< Initiator's NFCID2 or NFCID3 */ + uint8_t nfcidLen; /*!< Initiator's NFCID length (NFCID2/3) */ + uint8_t DID; /*!< Initiator's Device ID DID */ + uint8_t NAD; /*!< Initiator's Node ID NAD */ + uint8_t BS; /*!< Initiator's Bit Rates supported in Tx */ + uint8_t BitRate; /*!< Initiator's Bit Rates supported in Rx */ + uint8_t LR; /*!< Initiator's Length reduction */ + uint8_t* GB; /*!< Initiator's General Bytes (Gi) */ + uint8_t GBLen; /*!< Initiator's General Bytes length */ +} rfalNfcDepAtrParam; + + +/*! Structure of parameters to be passed in for nfcDepListenStartActivation */ +typedef struct +{ + rfalNfcDepBufFormat *rxBuf; /*!< Receive Buffer struct reference */ + uint16_t *rxLen; /*!< Receive INF data length in bytes */ + bool *isRxChaining; /*!< Received data is not complete */ + rfalNfcDepDevice *nfcDepDev; /*!< NFC-DEP device info */ +} rfalNfcDepListenActvParam; + + +/*! NFCIP Protocol structure for P2P Target + * + * operParam : derives from NFC-Forum NCI NFC-DEP Operation Parameter + * NCI 1.1 Table 86: NFC-DEP Operation Parameter + * and it's a bit mask composed as: + * [ 0000b + * | Chain SHALL use max. Transport Data Byte[1b] + * | I-PDU with no Transport Data SHALL NOT be sent [1b] + * | NFC-DEP Target SHALL NOT send RTOX request [1b] + * ] + * + */ +typedef struct{ + rfalNfcDepCommMode commMode; /*!< Target in Active P2P or Passive P2P */ + uint8_t nfcid3[RFAL_NFCDEP_NFCID3_LEN]; /*!< Target's NFCID3 */ + uint8_t bst; /*!< Target's Bit Rates supported in Tx */ + uint8_t brt; /*!< Target's Bit Rates supported in Rx */ + uint8_t to; /*!< Target's timeout (TO) value */ + uint8_t ppt; /*!< Target's Presence optional Params(PPt)*/ + uint8_t GBt[RFAL_NFCDEP_GB_MAX_LEN]; /*!< Target's General Bytes (Gt) */ + uint8_t GBtLen; /*!< Target's General Bytes length */ + uint8_t operParam; /*!< NFC-DEP Operation Parameter */ +} rfalNfcDepTargetParam; + + +/*! Structure of parameters to be passed in for nfcDepStartIpduTransceive */ +typedef struct +{ + rfalNfcDepBufFormat *txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in bytes */ + bool isTxChaining; /*!< Transmit data is not complete */ + rfalNfcDepBufFormat *rxBuf; /*!< Receive Buffer struct reference */ + uint16_t *rxLen; /*!< Receive INF data length */ + bool *isRxChaining; /*!< Received data is not complete */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalNfcDepTxRxParam; + + +/* + * ***************************************************************************** + * GLOBAL VARIABLE DECLARATIONS + ****************************************************************************** + */ + + +/* + ****************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + +/*! + ****************************************************************************** + * \brief NFCIP Initialize + * + * This method resets all NFC-DEP inner states, counters and context and sets + * default values + * + ****************************************************************************** + */ +void rfalNfcDepInitialize( void ); + + +/*! + ****************************************************************************** + * \brief Set deactivating callback + * + * Sets the deactivating callback so that nfcip layer can check if upper layer + * has a deactivation pending, and not perform error recovery upon specific + * errors + * + * \param[in] pFunc : method pointer to deactivation flag check + ****************************************************************************** + */ +void rfalNfcDepSetDeactivatingCallback( rfalNfcDepDeactCallback pFunc ); + + +/*! + ****************************************************************************** + * \brief Calculate Response Waiting Time + * + * Calculates the Response Waiting Time (RWT) from the given Waiting Time (WT) + * + * \param[in] wt : the WT value to calculate RWT + * + * \return RWT value in 1/fc + ****************************************************************************** + */ +uint32_t rfalNfcDepCalculateRWT( uint8_t wt ); + + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator ATR (Attribute Request) + * + * This method configures the NFC-DEP layer with given parameters and then + * sends an ATR to the Target with and checks for a valid response response + * + * \param[in] param : parameters to initialize and compose the ATR + * \param[out] atrRes : location to store the ATR_RES + * \param[out] atrResLen : length of the ATR_RES received + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepATR( const rfalNfcDepAtrParam* param, rfalNfcDepAtrRes *atrRes, uint8_t* atrResLen ); + + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator PSL (Parameter Selection) + * + * This method sends a PSL to the Target with the given parameters and checks + * for a valid response response + * + * The parameters must be coded according to Digital 1.1 16.7.1 + * + * \param[in] BRS : the selected Bit Rates for Initiator and Target + * \param[in] FSL : the maximum length of Commands and Responses + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepPSL( uint8_t BRS, uint8_t FSL ); + + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator DSL (Deselect) + * + * This method checks if the NFCIP module is configured as initiator and if + * so sends a DSL REQ, waits the target's response and checks it + * + * In case of performing as target no action is taken + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_MAX_RERUNS : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepDSL( void ); + + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator RLS (Release) + * + * This method checks if the NFCIP module is configured as initiator and if + * so sends a RLS REQ, waits target's response and checks it + * + * In case of performing as target no action is taken + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_MAX_RERUNS : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepRLS( void ); + + +/*! + ***************************************************************************** + * \brief NFC-DEP Initiator Handle Activation + * + * This performs a Activation into NFC-DEP layer with the given + * parameters. It sends ATR_REQ and if the higher bit rates are supported by + * both devices it additionally sends PSL + * Once Activated all details of the device are provided on nfcDepDev + * + * \param[in] param : required parameters to initialize and send ATR_REQ + * \param[in] desiredBR : Desired bit rate supported by the Poller + * \param[out] nfcDepDev : NFC-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalNfcDepInitiatorHandleActivation( rfalNfcDepAtrParam* param, rfalBitRate desiredBR, rfalNfcDepDevice* nfcDepDev ); + + +/*! + ****************************************************************************** + * \brief Check if buffer contains valid ATR_REQ + * + * This method checks if the given ATR_REQ is valid + * + * + * \param[in] buf : buffer holding Initiator's received request + * \param[in] bufLen : size of the msg contained on the buf in Bytes + * \param[out] nfcid3 : pointer to where the NFCID3 may be outputed, + * nfcid3 has NFCF_SENSF_NFCID3_LEN as length + * Pass NULL if output parameter not desired + * + * \return true : Valid ATR_REQ received, the ATR_RES has been computed in txBuf + * \return false : Invalid protocol request + * + ****************************************************************************** + */ +bool rfalNfcDepIsAtrReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid3 ); + + +/*! + ****************************************************************************** + * \brief Check is Target has received ATR + * + * This method checks if the NFCIP module is configured as target and if a + * ATR REQ has been received ( whether is in activation or in data exchange) + * + * \return true : a ATR has already been received + * \return false : no ATR has been received + ****************************************************************************** + */ +bool rfalNfcDepTargetRcvdATR( void ); + +/*! + ***************************************************************************** + * \brief NFCDEP Start Listen Activation Handling + * + * Start Activation Handling and setup to receive first frame which may + * contain complete or partial DEP-REQ after activation is completed + * + * Pass in ATR_REQ for NFC-DEP to handle ATR_RES. The Activation Handling + * handles ATR_RES and PSL_RES if a PSL_REQ is received + * + * Activation is completed if PSL_RES is sent or if first I-PDU is received + * + * \ref rfalNfcDepListenGetActivationStatus() provide status of the + * ongoing activation + * + * \warning nfcDepGetTransceiveStatus() shall be called right after activation + * is completed (i.e. rfalNfcDepListenGetActivationStatus() return ERR_NONE) + * to check for first received frame. + * + * \param[in] param : Target parameters to be used + * \param[in] atrReq : reference to buffer containing ATR_REQ + * \param[in] atrReqLength: Length of ATR_REQ + * \param[out] rxParam : references to buffer, length and chaining indication + * for first complete LLCP to be received + * + * \return ERR_NONE : ATR_REQ is valid and activation ongoing + * \return ERR_PARAM : ATR_REQ or other params are invalid + * \return ERR_LINK_LOSS : Remote Field is turned off + ***************************************************************************** + */ +ReturnCode rfalNfcDepListenStartActivation( const rfalNfcDepTargetParam *param, const uint8_t *atrReq, uint16_t atrReqLength, rfalNfcDepListenActvParam rxParam ); + + +/*! + ***************************************************************************** + * \brief Get the current NFC-DEP Activation Status + * + * \return ERR_NONE : Activation has completed successfully + * \return ERR_BUSY : Activation is ongoing + * \return ERR_LINK_LOSS : Remote Field was turned off + ***************************************************************************** + */ +ReturnCode rfalNfcDepListenGetActivationStatus( void ); + +/*! + ***************************************************************************** + * \brief Start Transceive + * + * Transceives a complete or partial DEP block + * + * The txBuf contains complete or partial of DEP to be transmitted. + * The Prologue field of the I-PDU is handled internally + * + * If the buffer contains partial LLCP and is not the last block, then + * isTxChaining must be set to true + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalNfcDepStartTransceive( rfalNfcDepTxRxParam *param ); + + +/*! + ***************************************************************************** + * \brief Return the Transceive status + * + * Returns the status of the NFC-DEP Transceive + * + * \warning When the other device is performing chaining once a chained + * block is received the error ERR_AGAIN is sent. At this point + * caller must handle the received data immediately. + * When ERR_AGAIN is returned an ACK has already been sent to + * the other device and the next block might be incoming. + * If rfalWorker() is called frequently it will place the next + * block on the given buffer + * + * \return ERR_NONE : Transceive has been completed successfully + * \return ERR_BUSY : Transceive is ongoing + * \return ERR_PROTO : Protocol error occurred + * \return ERR_TIMEOUT : Timeout error occurred + * \return ERR_SLEEP_REQ : Deselect has been received and responded + * \return ERR_NOMEM : The received I-PDU does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : Communication is lost because Reader/Writer + * has turned off its field + * \return ERR_AGAIN : received one chaining block, continue to call + * this method to retrieve the remaining blocks + ***************************************************************************** + */ +ReturnCode rfalNfcDepGetTransceiveStatus( void ); + + +#endif /* RFAL_NFCDEP_H_ */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_nfca.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfca.h new file mode 100644 index 0000000..d834fce --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfca.h @@ -0,0 +1,391 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfca.h + * + * \author Gustavo Patricio + * + * \brief Provides several NFC-A convenience methods and definitions + * + * It provides a Poller (ISO14443A PCD) interface and as well as + * some NFC-A Listener (ISO14443A PICC) helpers. + * + * The definitions and helpers methods provided by this module are only + * up to ISO14443-3 layer + * + * + * An usage example is provided here: \ref exampleRfalNfca.c + * \example exampleRfalNfca.c + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-A + * \brief RFAL NFC-A Module + * @{ + * + */ + + +#ifndef RFAL_NFCA_H +#define RFAL_NFCA_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" +#include "rfal_t1t.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCA_CASCADE_1_UID_LEN 4U /*!< UID length of cascade level 1 only tag */ +#define RFAL_NFCA_CASCADE_2_UID_LEN 7U /*!< UID length of cascade level 2 only tag */ +#define RFAL_NFCA_CASCADE_3_UID_LEN 10U /*!< UID length of cascade level 3 only tag */ + +#define RFAL_NFCA_SENS_RES_PLATFORM_MASK 0x0FU /*!< SENS_RES (ATQA) platform configuration mask Digital 1.1 Table 10 */ +#define RFAL_NFCA_SENS_RES_PLATFORM_T1T 0x0CU /*!< SENS_RES (ATQA) T1T platform configuration Digital 1.1 Table 10 */ + +#define RFAL_NFCA_SEL_RES_CONF_MASK 0x60U /*!< SEL_RES (SAK) platform configuration mask Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_T2T 0x00U /*!< SEL_RES (SAK) T2T configuration Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_T4T 0x20U /*!< SEL_RES (SAK) T4T configuration Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_NFCDEP 0x40U /*!< SEL_RES (SAK) NFC-DEP configuration Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP 0x60U /*!< SEL_RES (SAK) T4T and NFC-DEP configuration Digital 1.1 Table 19 */ + + +/*! NFC-A minimum FDT(listen) = ((n * 128 + (84)) / fc) with n_min = 9 Digital 1.1 6.10.1 + * = (1236)/fc + * Relax with 3etu: (3*128)/fc as with multiple NFC-A cards, response may take longer (JCOP cards) + * = (1236 + 384)/fc = 1620 / fc */ +#define RFAL_NFCA_FDTMIN 1620U +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Checks if device is a T1T given its SENS_RES */ +#define rfalNfcaIsSensResT1T( sensRes ) ((((rfalNfcaSensRes*)(sensRes))->platformInfo & RFAL_NFCA_SENS_RES_PLATFORM_MASK) == RFAL_NFCA_SENS_RES_PLATFORM_T1T ) + +/*! Checks if device is a T2T given its SENS_RES */ +#define rfalNfcaIsSelResT2T( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T2T ) + +/*! Checks if device is a T4T given its SENS_RES */ +#define rfalNfcaIsSelResT4T( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T4T ) + +/*! Checks if device supports NFC-DEP protocol given its SENS_RES */ +#define rfalNfcaIsSelResNFCDEP( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_NFCDEP ) + +/*! Checks if device supports ISO-DEP and NFC-DEP protocol given its SENS_RES */ +#define rfalNfcaIsSelResT4TNFCDEP( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP ) + +/*! Checks if a NFC-A listener device supports multiple protocols (ISO-DEP and NFC-DEP) */ +#define rfalNfcaLisDevIsMultiProto( lisDev ) (((rfalNfcaListenDevice*)(lisDev))->type == RFAL_NFCA_T4T_NFCDEP ) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A Listen device types */ +typedef enum { + RFAL_NFCA_T1T = 0x01, /* Device configured for T1T Digital 1.1 Table 9 */ + RFAL_NFCA_T2T = 0x00, /* Device configured for T2T Digital 1.1 Table 19 */ + RFAL_NFCA_T4T = 0x20, /* Device configured for T4T Digital 1.1 Table 19 */ + RFAL_NFCA_NFCDEP = 0x40, /* Device configured for NFC-DEP Digital 1.1 Table 19 */ + RFAL_NFCA_T4T_NFCDEP = 0x60 /* Device configured for NFC-DEP and T4T Digital 1.1 Table 19 */ +} rfalNfcaListenDeviceType; + + +/*! SENS_RES (ATQA) format Digital 1.1 6.6.3 & Table 7 */ +typedef struct +{ + uint8_t anticollisionInfo; /*!< SENS_RES Anticollision Information */ + uint8_t platformInfo; /*!< SENS_RES Platform Information */ +} rfalNfcaSensRes; + + +/*! SDD_REQ (Anticollision) format Digital 1.1 6.7.1 & Table 11 */ +typedef struct +{ + uint8_t selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */ + uint8_t selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/ +} rfalNfcaSddReq; + + +/*! SDD_RES (UID CLn) format Digital 1.1 6.7.2 & Table 15 */ +typedef struct +{ + uint8_t nfcid1[RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 cascade level NFCID */ + uint8_t bcc; /*!< BCC Exclusive-OR over first 4 bytes of SDD_RES */ +} rfalNfcaSddRes; + + +/*! SEL_REQ (Select) format Digital 1.1 6.8.1 & Table 17 */ +typedef struct +{ + uint8_t selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */ + uint8_t selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/ + uint8_t nfcid1[RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 data */ + uint8_t bcc; /*!< Checksum calculated as exclusive-OR over the 4 bytes of NFCID1 CLn */ +} rfalNfcaSelReq; + + +/*! SEL_RES (SAK) format Digital 1.1 6.8.2 & Table 19 */ +typedef struct +{ + uint8_t sak; /*!< Select Acknowledge */ +} rfalNfcaSelRes; + + +/*! NFC-A listener device (PICC) struct */ +typedef struct +{ + rfalNfcaListenDeviceType type; /*!< NFC-A Listen device type */ + rfalNfcaSensRes sensRes; /*!< SENS_RES (ATQA) */ + rfalNfcaSelRes selRes; /*!< SEL_RES (SAK) */ + uint8_t nfcId1Len; /*!< NFCID1 Length */ + uint8_t nfcId1[RFAL_NFCA_CASCADE_3_UID_LEN]; /*!< NFCID1 (UID) */ +#ifdef RFAL_FEATURE_T1T + rfalT1TRidRes ridRes; /*!< RID_RES */ +#endif /* RFAL_FEATURE_T1T */ + bool isSleep; /*!< Device sleeping flag */ +} rfalNfcaListenDevice; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-A Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-A Poller/RW (ISO14443A PCD) including all default timings and bit rate + * to 106 kbps + + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerInitialize( void ); + + +/*! + ***************************************************************************** + * \brief NFC-A Poller Check Presence + * + * This method checks if a NFC-A Listen device (PICC) is present on the field + * by sending an ALL_REQ (WUPA) or SENS_REQ (REQA) + * + * \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ + * \param[out] sensRes : If received, the SENS_RES + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PAR : Parity error detected, one or more device in the field + * \return ERR_CRC : CRC error detected, one or more device in the field + * \return ERR_FRAMING : Framing error detected, one or more device in the field + * \return ERR_PROTO : Protocol error detected, one or more device in the field + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_NONE : No error, one or more device in the field + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerCheckPresence( rfal14443AShortFrameCmd cmd, rfalNfcaSensRes *sensRes ); + + +/*! + ***************************************************************************** + * \brief NFC-A Poller Select + * + * This method selects a NFC-A Listener device (PICC) + * + * \param[in] nfcid1 : Listener device NFCID1 to be selected + * \param[in] nfcidLen : Length of the NFCID1 to be selected + * \param[out] selRes : pointer to place the SEL_RES + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, SEL_RES received + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSelect( const uint8_t *nfcid1, uint8_t nfcidLen, rfalNfcaSelRes *selRes ); + + +/*! + ***************************************************************************** + * \brief NFC-A Poller Sleep + * + * This method sends a SLP_REQ (HLTA) + * No response is expected afterwards Digital 1.1 6.9.2.1 + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSleep( void ); + + +/*! + ***************************************************************************** + * \brief NFC-A Technology Detection + * + * This method performs NFC-A Technology Detection as defined in the spec + * given in the compliance mode + * + * \param[in] compMode : compliance mode to be performed + * \param[out] sensRes : location to store the SENS_RES, if received + * + * When compMode is set to ISO compliance a SLP_REQ (HLTA) is not sent + * after detection. When set to EMV a ALL_REQ (WUPA) is sent instead of + * a SENS_REQ (REQA) + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error, one or more device in the field + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcaSensRes *sensRes ); + + +/*! + ***************************************************************************** + * \brief NFC-A Poller Collision Resolution + * + * Collision resolution for one NFC-A Listener device/card (PICC) as + * defined in Activity 1.1 9.3.4 + * + * This method executes anti collision loop and select the device with higher NFCID1 + * + * When devLimit = 0 it is configured to perform collision detection only. Once a collision + * is detected the collision resolution is aborted immidiatly. If only one device is found + * with no collisions, it will properly resolved. + * + * \param[in] devLimit : device limit value (CON_DEVICES_LIMIT) + * \param[out] collPending : pointer to collision pending flag (INT_COLL_PEND) + * \param[out] selRes : location to store the last Select Response from listener device (PICC) + * \param[out] nfcId1 : location to store the NFCID1 (UID), ensure RFAL_NFCA_CASCADE_3_UID_LEN + * \param[out] nfcId1Len : pointer to length of NFCID1 (UID) + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_PROTO : Card length invalid + * \return ERR_IGNORE : conDevLimit is 0 and there is a collision + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len ); + + +/*! + ***************************************************************************** + * \brief NFC-A Poller Full Collision Resolution + * + * Performs a full Collision resolution as defined in Activity 1.0 or 1.1 9.3.4 + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcaDevList + * \param[out] nfcaDevList : NFC-A listener device info + * \param[out] devCnt : Devices found counter + * + * When compMode is set to ISO compliance it assumes that the device is + * not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning. + * + * When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent at + * the beginning and a proprietary behaviour also takes place. Once a device has been + * resolved an additional SLP_REQ (HLTA) is sent regardless if there was a collision + * (except if the number of devices found already equals the limit). + * This proprietary behaviour ensures proper activation of certain devices that suffer + * from influence of Type B commands as foreseen in ISO14443-3 5.2.3 + * + * + * When devLimit = 0 it is configured to perform collision detection only. Once a collision + * is detected the collision resolution is aborted immidiatly. If only one device is found + * with no collisions, it will properly resolved. + * + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt ); + + +/*! + ***************************************************************************** + * \brief NFC-A Listener is SLP_REQ + * + * Checks if the given buffer contains valid NFC-A SLP_REQ (HALT) + * + * \param[in] buf: buffer containing data + * \param[in] bufLen: length of the data in buffer to be checked + * + * \return true if data in buf contains a SLP_REQ ; false otherwise + ***************************************************************************** + */ +bool rfalNfcaListenerIsSleepReq( const uint8_t *buf, uint16_t bufLen ); + +#endif /* RFAL_NFCA_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcb.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcb.h new file mode 100644 index 0000000..ea4cab0 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcb.h @@ -0,0 +1,398 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcb.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-B (ISO14443B) helpers + * + * It provides a NFC-B Poller (ISO14443B PCD) interface and + * also provides some NFC-B Listener (ISO14443B PICC) helpers + * + * The definitions and helpers methods provided by this module are only + * up to ISO14443-3 layer (excluding ATTRIB) + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-B + * \brief RFAL NFC-B Module + * @{ + * + */ + + +#ifndef RFAL_NFCB_H +#define RFAL_NFCB_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCB_FWTSENSB 7680U /*!< NFC-B FWT(SENSB) Digital 2.0 B.3 */ +#define RFAL_NFCB_DFWT 49152U /*!< NFC-B dFWT Delta 2.0 7.9.1.3 & B.3 */ +#define RFAL_NFCB_DTPOLL_10 rfalConvMsTo1fc(20) /*!< NFC-B Delta Tb Poll Digital 1.0 A.2 */ +#define RFAL_NFCB_DTPOLL_20 rfalConvMsTo1fc(17) /*!< NFC-B Delta Tb Poll Digital 2.1 B.3 */ + +#define RFAL_NFCB_AFI 0x00U /*!< NFC-B default Application Family Digital 1.1 7.6.1.1 */ +#define RFAL_NFCB_PARAM 0x00U /*!< NFC-B default SENSB_REQ PARAM */ +#define RFAL_NFCB_CRC_LEN 2U /*!< NFC-B CRC length and CRC_B(AID) Digital 1.1 Table 28 */ +#define RFAL_NFCB_NFCID0_LEN 4U /*!< Length of NFC-B NFCID0 */ +#define RFAL_NFCB_CMD_LEN 1U /*!< Length of NFC-B Command */ + +#define RFAL_NFCB_SENSB_RES_LEN 12U /*!< Standard length of SENSB_RES without SFGI byte */ +#define RFAL_NFCB_SENSB_RES_EXT_LEN 13U /*!< Extended length of SENSB_RES with SFGI byte */ + +#define RFAL_NFCB_SENSB_REQ_ADV_FEATURE 0x20U /*!< Bit mask for Advance Feature in SENSB_REQ */ +#define RFAL_NFCB_SENSB_RES_FSCI_MASK 0x0FU /*!< Bit mask for FSCI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FSCI_SHIFT 4U /*!< Shift for FSCI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_RFU_MASK 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK 0x03U /*!< Bit mask for Protocol Type TR2 in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_TR2_SHIFT 1U /*!< Shift for Protocol Type TR2 in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK 0x01U /*!< Bit mask Protocol Type ISO14443 Compliant in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FWI_MASK 0x0FU /*!< Bit mask for FWI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FWI_SHIFT 4U /*!< Bit mask for FWI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_ADC_MASK 0x0CU /*!< Bit mask for ADC value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_ADC_ADV_FEATURE_MASK 0x08U /*!< Bit mask for ADC.Advanced Proto Features in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_ADC_PROPRIETARY_MASK 0x04U /*!< Bit mask for ADC.Proprietary Application in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FO_DID_MASK 0x01U /*!< Bit mask for DID in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FO_NAD_MASK 0x02U /*!< Bit mask for DID in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FO_MASK 0x03U /*!< Bit mask for FO value in SENSB_RES (NAD and DID) */ +#define RFAL_NFCB_SENSB_RES_SFGI_MASK 0x0FU /*!< Bit mask for SFGI in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_SFGI_SHIFT 4U /*!< Shift for SFGI in SENSB_RES */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Get device's FSCI given its SENSB_RES Digital 1.1 7.6.2 */ +#define rfalNfcbGetFSCI( sensbRes ) ((((rfalNfcbSensbRes*)(sensbRes))->protInfo.FsciProType >> RFAL_NFCB_SENSB_RES_FSCI_SHIFT) & RFAL_NFCB_SENSB_RES_FSCI_MASK ) + +/*! Checks if the given NFC-B device indicates ISO-DEP support */ +#define rfalNfcbIsIsoDepSupported( dev ) ( (((rfalNfcbListenDevice*)(dev))->sensbRes.protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK) != 0U ) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! SENSB_REQ and ALLB_REQ param Digital 1.1 7.6.1 */ +typedef enum +{ + RFAL_NFCB_SENS_CMD_ALLB_REQ = 0x08, /*!< ALLB_REQ (WUPB) */ + RFAL_NFCB_SENS_CMD_SENSB_REQ = 0x00 /*!< SENSB_REQ (REQB) */ +} rfalNfcbSensCmd; + + +/*! Number of Slots (NI) codes used for NFC-B anti collision Digital 1.1 Table 26 */ +typedef enum +{ + RFAL_NFCB_SLOT_NUM_1 = 0, /*!< N=0 : 1 slot */ + RFAL_NFCB_SLOT_NUM_2 = 1, /*!< N=1 : 2 slots */ + RFAL_NFCB_SLOT_NUM_4 = 2, /*!< N=2 : 4 slots */ + RFAL_NFCB_SLOT_NUM_8 = 3, /*!< N=3 : 8 slots */ + RFAL_NFCB_SLOT_NUM_16 = 4 /*!< N=4 : 16 slots */ +}rfalNfcbSlots; + + +/*! SENSB_RES (ATQB) Application Data Format Digital 1.1 Table 28 */ +typedef struct +{ + uint8_t AFI; /*!< Application Family Identifier */ + uint8_t CRC_B[RFAL_NFCB_CRC_LEN]; /*!< CRC_B of AID */ + uint8_t numApps; /*!< Number of Applications */ +} rfalNfcbSensbResAppData; + + +/*! SENSB_RES Protocol Info format Digital 1.1 Table 29 */ +typedef struct +{ + uint8_t BRC; /*!< Bit Rate Capability */ + uint8_t FsciProType; /*!< Frame Size Card Integer [4b] | Protocol Type[4 bits] */ + uint8_t FwiAdcFo; /*!< Frame Waiting Integer [4b] | Application Data Coding [2b] | Frame Options [2b] */ + uint8_t SFGI; /*!< Optional: Start-Up Frame Guard Time Integer[4b] | RFU [4b] */ +} rfalNfcbSensbResProtocolInfo; + + +/*! SENSB_RES format Digital 1.1 7.6.2 */ +typedef struct +{ + uint8_t cmd; /*!< SENSB_RES: 50h */ + uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/ + rfalNfcbSensbResAppData appData; /*!< Application Data */ + rfalNfcbSensbResProtocolInfo protInfo; /*!< Protocol Information */ +} rfalNfcbSensbRes; + + +/*! NFC-B listener device (PICC) struct */ +typedef struct +{ + uint8_t sensbResLen; /*!< SENSB_RES length */ + rfalNfcbSensbRes sensbRes; /*!< SENSB_RES */ + bool isSleep; /*!< Device sleeping flag */ +}rfalNfcbListenDevice; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-B Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-B Poller/RW (ISO14443B PCD) including all default timings + * + * It sets NFC-B parameters (AFI, PARAM) to default values + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerInitialize( void ); + + +/*! + ***************************************************************************** + * \brief Set NFC-B Poller parameters + * + * This methods configures RFAL RF layer to perform as a + * NFCA Poller/RW (ISO14443A PCD) including all default timings + * + * Additionally configures NFC-B specific parameters to be used on the + * following communications + * + * \param[in] AFI : Application Family Identifier to be used + * \param[in] PARAM : PARAM to be used, it announces whether Advanced + * Features or Extended SENSB_RES is supported + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerInitializeWithParams( uint8_t AFI, uint8_t PARAM ); + + +/*! + ***************************************************************************** + * \brief NFC-B Poller Check Presence + * + * This method checks if a NFC-B Listen device (PICC) is present on the field + * by sending an ALLB_REQ (WUPB) or SENSB_REQ (REQB) + * + * \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ + * \param[in] slots : The number of slots to be announced + * \param[out] sensbRes : If received, the SENSB_RES + * \param[out] sensbResLen : If received, the SENSB_RES length + * + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PAR : Parity error detected, one or more device in the field + * \return ERR_CRC : CRC error detected, one or more device in the field + * \return ERR_FRAMING : Framing error detected, one or more device in the field + * \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received + * \return ERR_NONE : No error, SENSB_RES received + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerCheckPresence( rfalNfcbSensCmd cmd, rfalNfcbSlots slots, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen ); + + +/*! + ***************************************************************************** + * \brief NFC-B Poller Sleep + * + * This function is used to send the SLPB_REQ (HLTB) command to put the PICC with + * the given NFCID0 to state HALT so that they do not reply to further SENSB_REQ + * commands (only to ALLB_REQ) + * + * \param[in] nfcid0 : NFCID of the device to be put to Sleep + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerSleep( const uint8_t* nfcid0 ); + + +/*! + ***************************************************************************** + * \brief NFC-B Poller Slot Marker + * + * This method selects a NFC-B Slot marker frame + * + * \param[in] slotCode : Slot Code [1-15] + * \param[out] sensbRes : If received, the SENSB_RES + * \param[out] sensbResLen : If received, the SENSB_RES length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, SEL_RES received + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerSlotMarker( uint8_t slotCode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen ); + +/*! + ***************************************************************************** + * \brief NFC-B Technology Detection + * + * This method performs NFC-B Technology Detection as defined in the spec + * given in the compliance mode + * + * \param[in] compMode : compliance mode to be performed + * \param[out] sensbRes : location to store the SENSB_RES, if received + * \param[out] sensbResLen : length of the SENSB_RES, if received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error, one or more device in the field + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen ); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Collision Resolution + * + * NFC-B Collision resolution Listener device/card (PICC) as + * defined in Activity 1.1 9.3.5 + * + * This function is used to perform collision resolution for detection in case + * of multiple NFC Forum Devices with Technology B detected. + * Target with valid SENSB_RES will be stored in devInfo and nfcbDevCount incremented. + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcbDevList + * \param[out] nfcbDevList : NFC-B listener device info + * \param[out] devCnt : devices found counter + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt ); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Collision Resolution Slotted + * + * NFC-B Collision resolution Listener device/card (PICC). The sequence can + * be configured to be according to NFC Forum Activity 1.1 9.3.5, ISO10373 + * or EMVCo + * + * This function is used to perform collision resolution for detection in case + * of multiple NFC Forum Devices with Technology B are detected. + * Target with valid SENSB_RES will be stored in devInfo and nfcbDevCount incremented. + * + * This method provides the means to perform a collision resolution loop with specific + * initial and end number of slots. This allows to user to start the loop already with + * greater number of slots, and or limit the end number of slots. At the end a flag + * indicating whether there were collisions pending is returned. + * + * If RFAL_COMPLIANCE_MODE_ISO is used \a initSlots must be set to RFAL_NFCB_SLOT_NUM_1 + * + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcbDevList + * \param[in] initSlots : number of slots to open initially + * \param[in] endSlots : number of slots when to stop collision resolution + * \param[out] nfcbDevList : NFC-B listener device info + * \param[out] devCnt : devices found counter + * \param[out] colPending : flag indicating whether collision are still pending + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerSlottedCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbSlots initSlots, rfalNfcbSlots endSlots, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt, bool *colPending ); + + +/*! + ***************************************************************************** + * \brief NFC-B TR2 code to FDT + * + * Converts the TR2 code as defined in Digital 1.1 Table 33 Minimum + * TR2 Coding to Frame Delay Time (FDT) in 1/Fc + * + * \param[in] tr2Code : TR2 code as defined in Digital 1.1 Table 33 + * + * \return FDT in 1/Fc + ***************************************************************************** + */ +uint32_t rfalNfcbTR2ToFDT( uint8_t tr2Code ); + + +#endif /* RFAL_NFCB_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcf.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcf.h new file mode 100644 index 0000000..936f941 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcf.h @@ -0,0 +1,370 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcf.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-F Poller (FeliCa PCD) device + * + * The definitions and helpers methods provided by this module are + * aligned with NFC-F (FeliCa - JIS X6319-4) + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-F + * \brief RFAL NFC-F Module + * @{ + * + */ + + +#ifndef RFAL_NFCF_H +#define RFAL_NFCF_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCF_NFCID2_LEN 8U /*!< NFCID2 (FeliCa IDm) length */ +#define RFAL_NFCF_SENSF_RES_LEN_MIN 16U /*!< SENSF_RES minimum length */ +#define RFAL_NFCF_SENSF_RES_LEN_MAX 18U /*!< SENSF_RES maximum length */ +#define RFAL_NFCF_SENSF_RES_PAD0_LEN 2U /*!< SENSF_RES PAD0 length */ +#define RFAL_NFCF_SENSF_RES_PAD1_LEN 2U /*!< SENSF_RES PAD1 length */ +#define RFAL_NFCF_SENSF_RES_RD_LEN 2U /*!< SENSF_RES Request Data length */ +#define RFAL_NFCF_SENSF_RES_BYTE1 1U /*!< SENSF_RES first byte value */ +#define RFAL_NFCF_SENSF_SC_LEN 2U /*!< Felica SENSF_REQ System Code length */ +#define RFAL_NFCF_SENSF_PARAMS_SC1_POS 0U /*!< System Code byte1 position in the SENSF_REQ */ +#define RFAL_NFCF_SENSF_PARAMS_SC2_POS 1U /*!< System Code byte2 position in the SENSF_REQ */ +#define RFAL_NFCF_SENSF_PARAMS_RC_POS 2U /*!< Request Code position in the SENSF_REQ */ +#define RFAL_NFCF_SENSF_PARAMS_TSN_POS 3U /*!< Time Slot Number position in the SENSF_REQ */ +#define RFAL_NFCF_POLL_MAXCARDS 16U /*!< Max number slots/cards 16 */ + + +#define RFAL_NFCF_CMD_POS 0U /*!< Command/Responce code length */ +#define RFAL_NFCF_CMD_LEN 1U /*!< Command/Responce code length */ +#define RFAL_NFCF_LENGTH_LEN 1U /*!< LEN field length */ +#define RFAL_NFCF_HEADER_LEN (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN) /*!< Header length*/ + + +#define RFAL_NFCF_SENSF_NFCID2_BYTE1_POS 0U /*!< NFCID2 byte1 position */ +#define RFAL_NFCF_SENSF_NFCID2_BYTE2_POS 1U /*!< NFCID2 byte2 position */ + +#define RFAL_NFCF_SENSF_NFCID2_PROT_TYPE_LEN 2U /*!< NFCID2 length for byte 1 and byte 2 indicating NFC-DEP or T3T support */ +#define RFAL_NFCF_SENSF_NFCID2_BYTE1_NFCDEP 0x01U /*!< NFCID2 byte1 NFC-DEP support Digital 1.0 Table 44 */ +#define RFAL_NFCF_SENSF_NFCID2_BYTE2_NFCDEP 0xFEU /*!< NFCID2 byte2 NFC-DEP support Digital 1.0 Table 44 */ + +#define RFAL_NFCF_SYSTEMCODE 0xFFFFU /*!< SENSF_RES Default System Code Digital 1.0 6.6.1.1 */ + +#define RFAL_NFCF_BLOCK_LEN 16U /*!< NFCF T3T Block size T3T 1.0 4.1 */ +#define RFAL_NFCF_CHECKUPDATE_RES_ST1_POS 9U /*!< Check|Update Res Status Flag 1 position T3T 1.0 Table 8 */ +#define RFAL_NFCF_CHECKUPDATE_RES_ST2_POS 10U /*!< Check|Update Res Status Flag 2 position T3T 1.0 Table 8 */ +#define RFAL_NFCF_CHECKUPDATE_RES_NOB_POS 11U /*!< Check|Update Res Number of Blocks position T3T 1.0 Table 8 */ + +#define RFAL_NFCF_STATUS_FLAG_SUCCESS 0x00U /*!< Check response Number of Blocks position T3T 1.0 Table 11 */ +#define RFAL_NFCF_STATUS_FLAG_ERROR 0xFFU /*!< Check response Number of Blocks position T3T 1.0 Table 11 */ + +#define RFAL_NFCF_BLOCKLISTELEM_LEN 0x80U /*!< Block List Element Length bit (2|3 bytes) T3T 1.0 5.6.1 */ + +#define RFAL_NFCF_SERVICECODE_RDONLY 0x000BU /*!< NDEF Service Code as Read-Only T3T 1.0 7.2.1 */ +#define RFAL_NFCF_SERVICECODE_RDWR 0x0009U /*!< NDEF Service Code as Read and Write T3T 1.0 7.2.1 */ + + +/*! NFC-F Felica command set JIS X6319-4 9.1 */ +enum +{ + RFAL_NFCF_CMD_POLLING = 0x00, /*!< SENSF_REQ (Felica Poll/REQC command to identify a card ) */ + RFAL_NFCF_CMD_POLLING_RES = 0x01, /*!< SENSF_RES (Felica Poll/REQC command response ) */ + RFAL_NFCF_CMD_REQUEST_SERVICE = 0x02, /*!< verify the existence of Area and Service */ + RFAL_NFCF_CMD_REQUEST_RESPONSE = 0x04, /*!< verify the existence of a card */ + RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION = 0x06, /*!< read Block Data from a Service that requires no authentication */ + RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES = 0x07, /*!< read Block Data response from a Service with no authentication */ + RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION = 0x08, /*!< write Block Data to a Service that requires no authentication */ + RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES = 0x09, /*!< write Block Data response to a Service with no authentication */ + RFAL_NFCF_CMD_REQUEST_SYSTEM_CODE = 0x0c, /*!< acquire the System Code registered to a card */ + RFAL_NFCF_CMD_AUTHENTICATION1 = 0x10, /*!< authenticate a card */ + RFAL_NFCF_CMD_AUTHENTICATION2 = 0x12, /*!< allow a card to authenticate a Reader/Writer */ + RFAL_NFCF_CMD_READ = 0x14, /*!< read Block Data from a Service that requires authentication */ + RFAL_NFCF_CMD_WRITE = 0x16, /*!< write Block Data to a Service that requires authentication */ +}; + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Checks if the given NFC-F device indicates NFC-DEP support */ +#define rfalNfcfIsNfcDepSupported( dev ) ( (((rfalNfcfListenDevice*)(dev))->sensfRes.NFCID2[RFAL_NFCF_SENSF_NFCID2_BYTE1_POS] == RFAL_NFCF_SENSF_NFCID2_BYTE1_NFCDEP) && \ + (((rfalNfcfListenDevice*)(dev))->sensfRes.NFCID2[RFAL_NFCF_SENSF_NFCID2_BYTE2_POS] == RFAL_NFCF_SENSF_NFCID2_BYTE2_NFCDEP) ) + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + + +/*! NFC-F SENSF_RES format Digital 1.1 8.6.2 */ +typedef struct +{ + uint8_t CMD; /*!< Command Code: 01h */ + uint8_t NFCID2[RFAL_NFCF_NFCID2_LEN]; /*!< NFCID2 */ + uint8_t PAD0[RFAL_NFCF_SENSF_RES_PAD0_LEN]; /*!< PAD0 */ + uint8_t PAD1[RFAL_NFCF_SENSF_RES_PAD1_LEN]; /*!< PAD1 */ + uint8_t MRTIcheck; /*!< MRTIcheck */ + uint8_t MRTIupdate; /*!< MRTIupdate */ + uint8_t PAD2; /*!< PAD2 */ + uint8_t RD[RFAL_NFCF_SENSF_RES_RD_LEN]; /*!< Request Data */ +} rfalNfcfSensfRes; + + +/*! NFC-F poller device (PCD) struct */ +typedef struct +{ + uint8_t NFCID2[RFAL_NFCF_NFCID2_LEN]; /*!< NFCID2 */ +} rfalNfcfPollDevice; + +/*! NFC-F listener device (PICC) struct */ +typedef struct +{ + uint8_t sensfResLen; /*!< SENF_RES length */ + rfalNfcfSensfRes sensfRes; /*!< SENF_RES */ +} rfalNfcfListenDevice; + +typedef uint16_t rfalNfcfServ; /*!< NFC-F Service Code */ + +/*! NFC-F Block List Element (2 or 3 bytes element) T3T 1.0 5.6.1 */ +typedef struct +{ + uint8_t conf; /*!< Access Mode | Serv Code List Order */ + uint16_t blockNum; /*!< Block Number */ +}rfalNfcfBlockListElem; + +/*! Check Update Service list and Block list parameter */ +typedef struct +{ + uint8_t numServ; /*!< Number of Services */ + rfalNfcfServ *servList; /*!< Service Code List */ + uint8_t numBlock; /*!< Number of Blocks */ + rfalNfcfBlockListElem *blockList; /*!< Block Number List */ +}rfalNfcfServBlockListParam; + + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-F Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-F Poller/RW (FeliCa PCD) including all default timings + * + * \param[in] bitRate : NFC-F bitrate to be initialize (212 or 424) + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Incorrect bitrate + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerInitialize( rfalBitRate bitRate ); + + +/*! + ***************************************************************************** + * \brief NFC-F Poller Check Presence + * + * This function sends a Poll/SENSF command according to NFC Activity spec + * It detects if a NCF-F device is within range + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_NONE : No error and some NFC-F device was detected + * + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerCheckPresence( void ); + + +/*! + ***************************************************************************** + * \brief NFC-F Poller Poll + * + * This function sends to all PICCs in field the POLL command with the given + * number of slots. + * + * \param[in] slots : the number of slots to be performed + * \param[in] sysCode : as given in FeliCa poll command + * \param[in] reqCode : FeliCa communication parameters + * \param[out] cardList : Parameter of type rfalFeliCaPollRes which will hold the cards found + * \param[out] devCnt : actual number of cards found + * \param[out] collisions : number of collisions encountered + * + * \warning the list cardList has to be as big as the number of slots for the Poll + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_NONE : No error and some NFC-F device was detected + * + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes *cardList, uint8_t *devCnt, uint8_t *collisions ); + + +/*! + ***************************************************************************** + * \brief NFC-F Poller Full Collision Resolution + * + * Performs a full Collision resolution as defined in Activity 1.1 9.3.4 + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcaDevList + * \param[out] nfcfDevList : NFC-F listener devices list + * \param[out] devCnt : Devices found counter + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcfListenDevice *nfcfDevList, uint8_t *devCnt ); + + +/*! + ***************************************************************************** + * \brief NFC-F Poller Check/Read + * + * It computes a Check / Read command accoring to T3T 1.0 and JIS X6319-4 and + * sends it to PICC. If sucessfully, the rxBuf will contain the the number of + * blocks in the first byte followed by the blocks data. + * + * \param[in] nfcid2 : nfcid2 of the device + * \param[in] servBlock : parameter containing the list of Services and + * Blocks to be addressed by this command + * \param[out] rxBuf : buffer to place check/read data + * \param[in] rxBufLen : size of the rxBuf + * \param[out] rcvdLen : length of data placed in rxBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_REQUEST : The request was executed with error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerCheck( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rcvdLen ); + + +/*! + ***************************************************************************** + * \brief NFC-F Poller Update/Write + * + * It computes a Update / Write command accoring to T3T 1.0 and JIS X6319-4 and + * sends it to PICC. + * + * \param[in] nfcid2 : nfcid2 of the device + * \param[in] servBlock : parameter containing the list of Services and + * Blocks to be addressed by this command + * \param[in] txBuf : buffer where the request will be composed + * \param[in] txBufLen : size of txBuf + * \param[in] blockData : data to written on the given block(s) + * \param[out] rxBuf : buffer to place check/read data + * \param[in] rxBufLen : size of the rxBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_REQUEST : The request was executed with error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerUpdate( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *txBuf, uint16_t txBufLen, const uint8_t *blockData, uint8_t *rxBuf, uint16_t rxBufLen); + +/*! + ***************************************************************************** + * \brief NFC-F Listener is T3T Request + * + * This method checks if the given data is a valid T3T command (Read or Write) + * and in case a valid request has been received it may output the request's NFCID2 + * + * \param[in] buf : buffer holding Initiator's received command + * \param[in] bufLen : length of received command in bytes + * \param[out] nfcid2 : pointer to where the NFCID2 may be outputed, + * nfcid2 has NFCF_SENSF_NFCID2_LEN as length + * Pass NULL if output parameter not desired + * + * \return true : Valid T3T command (Read or Write) received + * \return false : Invalid protocol request + * + ***************************************************************************** + */ +bool rfalNfcfListenerIsT3TReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2 ); + + +#endif /* RFAL_NFCF_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcv.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcv.h new file mode 100644 index 0000000..36875b1 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_nfcv.h @@ -0,0 +1,772 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcv.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-V Poller (ISO15693) device + * + * The definitions and helpers methods provided by this module + * are aligned with NFC-V Digital 2.1 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-V + * \brief RFAL NFC-V Module + * @{ + * + */ + +#ifndef RFAL_NFCV_H +#define RFAL_NFCV_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCV_UID_LEN 8U /*!< NFC-V UID length */ +#define RFAL_NFCV_MAX_BLOCK_LEN 32U /*!< Max Block size: can be of up to 256 bits ISO 15693 2000 5 */ +#define RFAL_NFCV_BNO_LEN 1U /*!< NFC-V Block Number length */ +#define RFAL_NFCV_CRC_LEN 2U /*!< NFC-V CRC length */ +#define RFAL_NFCV_MAX_GEN_DATA_LEN (RFAL_NFCV_MAX_BLOCK_LEN + RFAL_NFCV_BNO_LEN + RFAL_NFCV_UID_LEN) /*!
© COPYRIGHT 2016 STMicroelectronics
+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_rf.h + * + * \author Gustavo Patricio + * + * \brief RF Abstraction Layer (RFAL) + * + * RFAL (RF Abstraction Layer) provides several functionalities required to + * perform RF/NFC communications.
The RFAL encapsulates the different + * RF ICs (ST25R3911, ST25R391x, etc) into a common and easy to use interface. + * + * It provides interfaces to configure the RF IC, set/get timings, modes, bit rates, + * specific handlings, execute listen mode, etc. + * + * Furthermore it provides a common interface to perform a Transceive operations. + * The Transceive can be executed in a blocking or non blocking way.
+ * Additionally few specific Transceive methods are available to cope with the + * specifics of these particular operations. + * + * The most common interfaces are: + *
  rfalInitialize() + *
  rfalSetFDTPoll() + *
  rfalSetFDTListen() + *
  rfalSetGT() + *
  rfalSetBitRate() + *
  rfalSetMode() + *
  rfalFieldOnAndStartGT() + *
  rfalFieldOff() + *
  rfalStartTransceive() + *
  rfalGetTransceiveStatus() + *
  rfalTransceiveBlockingTxRx() + * + * An usage example is provided here: \ref exampleRfalPoller.c + * \example exampleRfalPoller.c + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup RF + * \brief RFAL RF Abstraction Layer + * @{ + * + */ + +#ifndef RFAL_RF_H +#define RFAL_RF_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" +#include "st_errno.h" +#include "rfal_features.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define RFAL_VERSION (uint32_t)0x02000aU /*!< RFAL Current Version: v2.0.10 */ + +#define RFAL_FWT_NONE 0xFFFFFFFFU /*!< Disabled FWT: Wait forever for a response */ +#define RFAL_GT_NONE RFAL_TIMING_NONE /*!< Disabled GT: No GT will be applied after Field On */ + +#define RFAL_TIMING_NONE 0x00U /*!< Timing disabled | Don't apply */ + +#define RFAL_1FC_IN_4096FC (uint32_t)4096U /*!< Number of 1/fc cycles in one 4096/fc */ +#define RFAL_1FC_IN_512FC (uint32_t)512U /*!< Number of 1/fc cycles in one 512/fc */ +#define RFAL_1FC_IN_64FC (uint32_t)64U /*!< Number of 1/fc cycles in one 64/fc */ +#define RFAL_1FC_IN_8FC (uint32_t)8U /*!< Number of 1/fc cycles in one 8/fc */ +#define RFAL_US_IN_MS (uint32_t)1000U /*!< Number of us in one ms */ +#define RFAL_1MS_IN_1FC (uint32_t)13560U /*!< Number of 1/fc cycles in 1ms */ +#define RFAL_BITS_IN_BYTE (uint16_t)8U /*!< Number of bits in one byte */ + +#define RFAL_CRC_LEN 2U /*!< RF CRC LEN */ + +/*! Default TxRx flags: Tx CRC automatic, Rx CRC removed, NFCIP1 mode off, AGC On, Tx Parity automatic, Rx Parity removed */ +#define RFAL_TXRX_FLAGS_DEFAULT ( (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + + + +#define RFAL_LM_MASK_NFCA (1U<<(uint8_t)RFAL_MODE_LISTEN_NFCA) /*!< Bitmask for Listen Mode enabling Listen NFCA */ +#define RFAL_LM_MASK_NFCB (1U<<(uint8_t)RFAL_MODE_LISTEN_NFCB) /*!< Bitmask for Listen Mode enabling Listen NFCB */ +#define RFAL_LM_MASK_NFCF (1U<<(uint8_t)RFAL_MODE_LISTEN_NFCF) /*!< Bitmask for Listen Mode enabling Listen NFCF */ +#define RFAL_LM_MASK_ACTIVE_P2P (1U<<(uint8_t)RFAL_MODE_LISTEN_ACTIVE_P2P) /*!< Bitmask for Listen Mode enabling Listen AP2P */ + +#define RFAL_LM_SENS_RES_LEN 2U /*!< NFC-A SENS_RES (ATQA) length */ +#define RFAL_LM_SENSB_RES_LEN 13U /*!< NFC-B SENSB_RES (ATQB) length */ +#define RFAL_LM_SENSF_RES_LEN 19U /*!< NFC-F SENSF_RES length */ +#define RFAL_LM_SENSF_SC_LEN 2U /*!< NFC-F System Code length */ + +#define RFAL_NFCID3_LEN 10U /*!< NFCID3 length */ +#define RFAL_NFCID2_LEN 8U /*!< NFCID2 length */ +#define RFAL_NFCID1_TRIPLE_LEN 10U /*!< NFCID1 length */ +#define RFAL_NFCID1_DOUBLE_LEN 7U /*!< NFCID1 length */ +#define RFAL_NFCID1_SIMPLE_LEN 4U /*!< NFCID1 length */ + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Returns the maximum supported bit rate for RW mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrRW() ( ((RFAL_SUPPORT_BR_RW_6780) ? RFAL_BR_6780 : ((RFAL_SUPPORT_BR_RW_3390) ? RFAL_BR_3390 : ((RFAL_SUPPORT_BR_RW_1695) ? RFAL_BR_1695 : ((RFAL_SUPPORT_BR_RW_848) ? RFAL_BR_848 : ((RFAL_SUPPORT_BR_RW_424) ? RFAL_BR_424 : ((RFAL_SUPPORT_BR_RW_212) ? RFAL_BR_212 : RFAL_BR_106 ) ) ) ) ) ) ) + +/*! Returns the maximum supported bit rate for AP2P mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrAP2P() ( ((RFAL_SUPPORT_BR_AP2P_848) ? RFAL_BR_848 : ((RFAL_SUPPORT_BR_AP2P_424) ? RFAL_BR_424 : ((RFAL_SUPPORT_BR_AP2P_212) ? RFAL_BR_212 : RFAL_BR_106 ) ) ) ) + +/*! Returns the maximum supported bit rate for CE-A mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrCEA() ( ((RFAL_SUPPORT_BR_CE_A_848) ? RFAL_BR_848 : ((RFAL_SUPPORT_BR_CE_A_424) ? RFAL_BR_424 : ((RFAL_SUPPORT_BR_CE_A_212) ? RFAL_BR_212 : RFAL_BR_106 ) ) ) ) + +/*! Returns the maximum supported bit rate for CE-B mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrCEB() ( ((RFAL_SUPPORT_BR_CE_B_848) ? RFAL_BR_848 : ((RFAL_SUPPORT_BR_CE_B_424) ? RFAL_BR_424 : ((RFAL_SUPPORT_BR_CE_B_212) ? RFAL_BR_212 : RFAL_BR_106 ) ) ) ) + +/*! Returns the maximum supported bit rate for CE-F mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrCEF() ( ((RFAL_SUPPORT_BR_CE_F_424) ? RFAL_BR_424 : RFAL_BR_212 ) ) + + +#define rfalIsModeActiveComm( md ) ( ((md) == RFAL_MODE_POLL_ACTIVE_P2P) || ((md) == RFAL_MODE_LISTEN_ACTIVE_P2P) ) /*!< Checks if mode md is Active Communication */ +#define rfalIsModePassiveComm( md ) ( !rfalIsModeActiveComm(md) ) /*!< Checks if mode md is Passive Communication */ +#define rfalIsModePassiveListen( md ) ( ((md) == RFAL_MODE_LISTEN_NFCA) || ((md) == RFAL_MODE_LISTEN_NFCB) || ((md) == RFAL_MODE_LISTEN_NFCF) ) /*!< Checks if mode md is Passive Listen */ +#define rfalIsModePassivePoll( md ) ( rfalIsModePassiveComm(md) && !rfalIsModePassiveListen(md) ) /*!< Checks if mode md is Passive Poll */ + + +#define rfalConv1fcTo8fc( t ) (uint32_t)( (uint32_t)(t) / RFAL_1FC_IN_8FC ) /*!< Converts the given t from 1/fc to 8/fc */ +#define rfalConv8fcTo1fc( t ) (uint32_t)( (uint32_t)(t) * RFAL_1FC_IN_8FC ) /*!< Converts the given t from 8/fc to 1/fc */ + +#define rfalConv1fcTo64fc( t ) (uint32_t)( (uint32_t)(t) / RFAL_1FC_IN_64FC ) /*!< Converts the given t from 1/fc to 64/fc */ +#define rfalConv64fcTo1fc( t ) (uint32_t)( (uint32_t)(t) * RFAL_1FC_IN_64FC ) /*!< Converts the given t from 64/fc to 1/fc */ + +#define rfalConv1fcTo512fc( t ) (uint32_t)( (uint32_t)(t) / RFAL_1FC_IN_512FC ) /*!< Converts the given t from 1/fc to 512/fc */ +#define rfalConv512fcTo1fc( t ) (uint32_t)( (uint32_t)(t) * RFAL_1FC_IN_512FC ) /*!< Converts the given t from 512/fc to 1/fc */ + +#define rfalConv1fcTo4096fc( t ) (uint32_t)( (uint32_t)(t) / RFAL_1FC_IN_4096FC ) /*!< Converts the given t from 1/fc to 4096/fc */ +#define rfalConv4096fcTo1fc( t ) (uint32_t)( (uint32_t)(t) * RFAL_1FC_IN_4096FC ) /*!< Converts the given t from 4096/fc to 1/fc */ + +#define rfalConv1fcToMs( t ) (uint32_t)( (uint32_t)(t) / RFAL_1MS_IN_1FC ) /*!< Converts the given t from 1/fc to ms */ +#define rfalConvMsTo1fc( t ) (uint32_t)( (uint32_t)(t) * RFAL_1MS_IN_1FC ) /*!< Converts the given t from ms to 1/fc */ + +#define rfalConv1fcToUs( t ) (uint32_t)( ((uint32_t)(t) * RFAL_US_IN_MS) / RFAL_1MS_IN_1FC) /*!< Converts the given t from 1/fc to us */ +#define rfalConvUsTo1fc( t ) (uint32_t)( ((uint32_t)(t) * RFAL_1MS_IN_1FC) / RFAL_US_IN_MS) /*!< Converts the given t from us to 1/fc */ + +#define rfalConv64fcToMs( t ) (uint32_t)( (uint32_t)(t) / (RFAL_1MS_IN_1FC / RFAL_1FC_IN_64FC) ) /*!< Converts the given t from 64/fc to ms */ +#define rfalConvMsTo64fc( t ) (uint32_t)( (uint32_t)(t) * (RFAL_1MS_IN_1FC / RFAL_1FC_IN_64FC) ) /*!< Converts the given t from ms to 64/fc */ + +#define rfalConvBitsToBytes( n ) (uint16_t)( ((uint16_t)(n)+(RFAL_BITS_IN_BYTE-1U)) / (RFAL_BITS_IN_BYTE) ) /*!< Converts the given n from bits to bytes */ +#define rfalConvBytesToBits( n ) (uint32_t)( (uint32_t)(n) * (RFAL_BITS_IN_BYTE) ) /*!< Converts the given n from bytes to bits */ + + + +/*! Computes a Transceive context \a ctx with default flags and the lengths + * in bytes with the given arguments + * \a ctx : Transceive context to be assigned + * \a tB : txBuf the pointer to the buffer to be sent + * \a tBL : txBuf length in bytes + * \a rB : rxBuf the pointer to the buffer to place the received frame + * \a rBL : rxBuf length in bytes + * \a rBL : rxBuf length in bytes + * \a t : FWT to be used on this transceive in 1/fc + */ +#define rfalCreateByteTxRxContext( ctx, tB, tBL, rB, rBL, rdL, t ) \ + (ctx).txBuf = (uint8_t*)(tB); \ + (ctx).txBufLen = (uint16_t)rfalConvBytesToBits(tBL); \ + (ctx).rxBuf = (uint8_t*)(rB); \ + (ctx).rxBufLen = (uint16_t)rfalConvBytesToBits(rBL); \ + (ctx).rxRcvdLen = (uint16_t*)(rdL); \ + (ctx).flags = (uint32_t)RFAL_TXRX_FLAGS_DEFAULT; \ + (ctx).fwt = (uint32_t)(t); + + +/*! Computes a Transceive context \a ctx using lengths in bytes + * with the given flags and arguments + * \a ctx : Transceive context to be assigned + * \a tB : txBuf the pointer to the buffer to be sent + * \a tBL : txBuf length in bytes + * \a rB : rxBuf the pointer to the buffer to place the received frame + * \a rBL : rxBuf length in bytes + * \a rBL : rxBuf length in bytes + * \a t : FWT to be used on this transceive in 1/fc + */ +#define rfalCreateByteFlagsTxRxContext( ctx, tB, tBL, rB, rBL, rdL, fl, t ) \ + (ctx).txBuf = (uint8_t*)(tB); \ + (ctx).txBufLen = (uint16_t)rfalConvBytesToBits(tBL); \ + (ctx).rxBuf = (uint8_t*)(rB); \ + (ctx).rxBufLen = (uint16_t)rfalConvBytesToBits(rBL); \ + (ctx).rxRcvdLen = (uint16_t*)(rdL); \ + (ctx).flags = (uint32_t)(fl); \ + (ctx).fwt = (uint32_t)(t); + + +#define rfalLogE(...) platformLog(__VA_ARGS__) /*!< Macro for the error log method */ +#define rfalLogW(...) platformLog(__VA_ARGS__) /*!< Macro for the warning log method */ +#define rfalLogI(...) platformLog(__VA_ARGS__) /*!< Macro for the info log method */ +#define rfalLogD(...) platformLog(__VA_ARGS__) /*!< Macro for the debug log method */ + + +/* +****************************************************************************** +* GLOBAL ENUMS +****************************************************************************** +*/ + +/* RFAL Guard Time (GT) default values */ +#define RFAL_GT_NFCA rfalConvMsTo1fc(5U) /*!< GTA Digital 2.0 6.10.4.1 & B.2 */ +#define RFAL_GT_NFCB rfalConvMsTo1fc(5U) /*!< GTB Digital 2.0 7.9.4.1 & B.3 */ +#define RFAL_GT_NFCF rfalConvMsTo1fc(20U) /*!< GTF Digital 2.0 8.7.4.1 & B.4 */ +#define RFAL_GT_NFCV rfalConvMsTo1fc(5U) /*!< GTV Digital 2.0 9.7.5.1 & B.5 */ +#define RFAL_GT_PICOPASS rfalConvMsTo1fc(1U) /*!< GT Picopass */ +#define RFAL_GT_AP2P rfalConvMsTo1fc(5U) /*!< TIRFG Ecma 340 11.1.1 */ +#define RFAL_GT_AP2P_ADJUSTED rfalConvMsTo1fc(5U+25U) /*!< Adjusted GT for greater interoperability (Sony XPERIA P, Nokia N9, Huawei P2) */ + +/* RFAL Frame Delay Time (FDT) Listen default values */ +#define RFAL_FDT_LISTEN_NFCA_POLLER 1172U /*!< FDTA,LISTEN,MIN (n=9) Last bit: Logic "1" - tnn,min/2 Digital 1.1 6.10 ; EMV CCP Spec Book D v2.01 4.8.1.3 */ +#define RFAL_FDT_LISTEN_NFCB_POLLER 1008U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define RFAL_FDT_LISTEN_NFCF_POLLER 2672U /*!< TR0F,LISTEN,MIN Digital 1.1 8.7.1.1 & A.4 */ +#define RFAL_FDT_LISTEN_NFCV_POLLER 4310U /*!< FDTV,LISTEN,MIN t1 min Digital 2.1 B.5 ; ISO15693-3 2009 9.1 */ +#define RFAL_FDT_LISTEN_PICOPASS_POLLER 3400U /*!< ISO15693 t1 min - observed adjustment */ +#define RFAL_FDT_LISTEN_AP2P_POLLER 64U /*!< FDT AP2P No actual FDTListen is required as fields switch and collision avoidance */ +#define RFAL_FDT_LISTEN_NFCA_LISTENER 1172U /*!< FDTA,LISTEN,MIN Digital 1.1 6.10 */ +#define RFAL_FDT_LISTEN_NFCB_LISTENER 1024U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define RFAL_FDT_LISTEN_NFCF_LISTENER 2688U /*!< TR0F,LISTEN,MIN Digital 1.1 8.7.1.1 & A.4 */ +#define RFAL_FDT_LISTEN_AP2P_LISTENER 64U /*!< FDT AP2P No actual FDTListen exists as fields switch and collision avoidance */ + +/* RFAL Frame Delay Time (FDT) Poll default values */ +#define RFAL_FDT_POLL_NFCA_POLLER 6780U /*!< FDTA,POLL,MIN Digital 1.1 6.10.3.1 & A.2 */ +#define RFAL_FDT_POLL_NFCA_T1T_POLLER 384U /*!< RRDDT1T,MIN,B1 Digital 1.1 10.7.1 & A.5 */ +#define RFAL_FDT_POLL_NFCB_POLLER 6780U /*!< FDTB,POLL,MIN = TR2B,MIN,DEFAULT Digital 1.1 7.9.3 & A.3 ; EMVCo 3.0 FDTB,PCD,MIN Table A.5 */ +#define RFAL_FDT_POLL_NFCF_POLLER 2672U /*!< FDTF,POLL,MIN Digital 1.1 8.7.3 & A.4 */ +#define RFAL_FDT_POLL_NFCV_POLLER 4192U /*!< FDTV,POLL Digital 2.1 9.7.3.1 & B.5 */ +#define RFAL_FDT_POLL_PICOPASS_POLLER 1790U /*!< FDT Max */ +#define RFAL_FDT_POLL_AP2P_POLLER 0U /*!< FDT AP2P No actual FDTPoll exists as fields switch and collision avoidance */ + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! RFAL modes */ +typedef enum { + RFAL_MODE_NONE = 0, /*!< No mode selected/defined */ + RFAL_MODE_POLL_NFCA = 1, /*!< Mode to perform as NFCA (ISO14443A) Poller (PCD) */ + RFAL_MODE_POLL_NFCA_T1T = 2, /*!< Mode to perform as NFCA T1T (Topaz) Poller (PCD) */ + RFAL_MODE_POLL_NFCB = 3, /*!< Mode to perform as NFCB (ISO14443B) Poller (PCD) */ + RFAL_MODE_POLL_B_PRIME = 4, /*!< Mode to perform as B' Calypso (Innovatron) (PCD) */ + RFAL_MODE_POLL_B_CTS = 5, /*!< Mode to perform as CTS Poller (PCD) */ + RFAL_MODE_POLL_NFCF = 6, /*!< Mode to perform as NFCF (FeliCa) Poller (PCD) */ + RFAL_MODE_POLL_NFCV = 7, /*!< Mode to perform as NFCV (ISO15963) Poller (PCD) */ + RFAL_MODE_POLL_PICOPASS = 8, /*!< Mode to perform as PicoPass / iClass Poller (PCD) */ + RFAL_MODE_POLL_ACTIVE_P2P = 9, /*!< Mode to perform as Active P2P (ISO18092) Initiator */ + RFAL_MODE_LISTEN_NFCA = 10, /*!< Mode to perform as NFCA (ISO14443A) Listener (PICC) */ + RFAL_MODE_LISTEN_NFCB = 11, /*!< Mode to perform as NFCA (ISO14443B) Listener (PICC) */ + RFAL_MODE_LISTEN_NFCF = 12, /*!< Mode to perform as NFCA (ISO15963) Listener (PICC) */ + RFAL_MODE_LISTEN_ACTIVE_P2P = 13 /*!< Mode to perform as Active P2P (ISO18092) Target */ +} rfalMode; + + +/*! RFAL Bit rates */ +typedef enum { + RFAL_BR_106 = 0, /*!< Bit Rate 106 kbit/s (fc/128) */ + RFAL_BR_212 = 1, /*!< Bit Rate 212 kbit/s (fc/64) */ + RFAL_BR_424 = 2, /*!< Bit Rate 424 kbit/s (fc/32) */ + RFAL_BR_848 = 3, /*!< Bit Rate 848 kbit/s (fc/16) */ + RFAL_BR_1695 = 4, /*!< Bit Rate 1695 kbit/s (fc/8) */ + RFAL_BR_3390 = 5, /*!< Bit Rate 3390 kbit/s (fc/4) */ + RFAL_BR_6780 = 6, /*!< Bit Rate 6780 kbit/s (fc/2) */ + RFAL_BR_13560 = 7, /*!< Bit Rate 13560 kbit/s (fc) */ + RFAL_BR_52p97 = 0xEB, /*!< Bit Rate 52.97 kbit/s (fc/256) Fast Mode VICC->VCD */ + RFAL_BR_26p48 = 0xEC, /*!< Bit Rate 26,48 kbit/s (fc/512) NFCV VICC->VCD & VCD->VICC 1of4 */ + RFAL_BR_1p66 = 0xED, /*!< Bit Rate 1,66 kbit/s (fc/8192) NFCV VCD->VICC 1of256 */ + RFAL_BR_KEEP = 0xFF /*!< Value indicating to keep the same previous bit rate */ +} rfalBitRate; + + +/*! RFAL Compliance modes for upper modules */ +typedef enum { + RFAL_COMPLIANCE_MODE_NFC, /*!< Perform with NFC Forum 1.1 compliance */ + RFAL_COMPLIANCE_MODE_EMV, /*!< Perform with EMVCo compliance */ + RFAL_COMPLIANCE_MODE_ISO /*!< Perform with ISO10373 compliance */ +}rfalComplianceMode; + + +/*! RFAL main states flags */ +typedef enum { + RFAL_STATE_IDLE = 0, + RFAL_STATE_INIT = 1, + RFAL_STATE_MODE_SET = 2, + + RFAL_STATE_TXRX = 3, + RFAL_STATE_LM = 4, + RFAL_STATE_WUM = 5 + +} rfalState; + +/*! RFAL transceive states */ +typedef enum { + RFAL_TXRX_STATE_IDLE = 0, + RFAL_TXRX_STATE_INIT = 1, + RFAL_TXRX_STATE_START = 2, + + RFAL_TXRX_STATE_TX_IDLE = 11, + RFAL_TXRX_STATE_TX_WAIT_GT = 12, + RFAL_TXRX_STATE_TX_WAIT_FDT = 13, + RFAL_TXRX_STATE_TX_TRANSMIT = 14, + RFAL_TXRX_STATE_TX_WAIT_WL = 15, + RFAL_TXRX_STATE_TX_RELOAD_FIFO = 16, + RFAL_TXRX_STATE_TX_WAIT_TXE = 17, + RFAL_TXRX_STATE_TX_DONE = 18, + RFAL_TXRX_STATE_TX_FAIL = 19, + + RFAL_TXRX_STATE_RX_IDLE = 81, + RFAL_TXRX_STATE_RX_WAIT_EON = 82, + RFAL_TXRX_STATE_RX_WAIT_RXS = 83, + RFAL_TXRX_STATE_RX_WAIT_RXE = 84, + RFAL_TXRX_STATE_RX_READ_FIFO = 85, + RFAL_TXRX_STATE_RX_ERR_CHECK = 86, + RFAL_TXRX_STATE_RX_READ_DATA = 87, + RFAL_TXRX_STATE_RX_WAIT_EOF = 88, + RFAL_TXRX_STATE_RX_DONE = 89, + RFAL_TXRX_STATE_RX_FAIL = 90, + +} rfalTransceiveState; + + +/*! RFAL transceive flags */ +enum { + RFAL_TXRX_FLAGS_CRC_TX_AUTO = (0U<<0), /*!< CRC will be generated automatic upon transmission */ + RFAL_TXRX_FLAGS_CRC_TX_MANUAL = (1U<<0), /*!< CRC was calculated manually, included in txBuffer */ + RFAL_TXRX_FLAGS_CRC_RX_KEEP = (1U<<1), /*!< Upon Reception keep the CRC in rxBuffer (reflected on rcvd length) */ + RFAL_TXRX_FLAGS_CRC_RX_REMV = (0U<<1), /*!< Upon Reception remove the CRC from rxBuffer */ + RFAL_TXRX_FLAGS_NFCIP1_ON = (1U<<2), /*!< Enable NFCIP1 mode: Add SB(F0) and LEN bytes during Tx and skip SB(F0) byte during Rx */ + RFAL_TXRX_FLAGS_NFCIP1_OFF = (0U<<2), /*!< Disable NFCIP1 mode: do not append protocol bytes while Tx nor skip while Rx */ + RFAL_TXRX_FLAGS_AGC_OFF = (1U<<3), /*!< Disable Automatic Gain Control, improving multiple devices collision detection */ + RFAL_TXRX_FLAGS_AGC_ON = (0U<<3), /*!< Enable Automatic Gain Control, improving single device reception */ + RFAL_TXRX_FLAGS_PAR_RX_KEEP = (1U<<4), /*!< Disable Parity and CRC check and keep the Parity and CRC bits in the received buffer */ + RFAL_TXRX_FLAGS_PAR_RX_REMV = (0U<<0), /*!< Enable Parity check and remove the parity bits from the received buffer */ + RFAL_TXRX_FLAGS_PAR_TX_NONE = (1U<<5), /*!< Disable automatic Parity generation (ISO14443A) and use the one provided in the buffer*/ + RFAL_TXRX_FLAGS_PAR_TX_AUTO = (0U<<5), /*!< Enable automatic Parity generation (ISO14443A) */ + RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL = (1U<<6), /*!< Disable automatic adaption of flag byte (ISO15693) according to current comm params */ + RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO = (0U<<6), /*!< Enable automatic adaption of flag byte (ISO115693) according to current comm params */ +}; + + +/*! RFAL error handling */ +typedef enum { + RFAL_ERRORHANDLING_NONE = 0, /*!< No special error handling will be performed */ + RFAL_ERRORHANDLING_NFC = 1, /*!< Error handling set to perform as NFC complaint device */ + RFAL_ERRORHANDLING_EMVCO = 2 /*!< Error handling set to perform as EMVCo complaint device */ +} rfalEHandling; + + +/*! Struct that holds all context to be used on a Transceive */ +typedef struct { + uint8_t* txBuf; /*!< (In) Buffer where outgoing message is located */ + uint16_t txBufLen; /*!< (In) Length of the outgoing message in bits */ + + uint8_t* rxBuf; /*!< (Out) Buffer where incoming message will be placed */ + uint16_t rxBufLen; /*!< (In) Maximum length of the incoming message in bits */ + uint16_t* rxRcvdLen; /*!< (Out) Actual received length in bits */ + + uint32_t flags; /*!< (In) TransceiveFlags indication special handling */ + uint32_t fwt; /*!< (In) Frame Waiting Time in 1/fc */ +} rfalTransceiveContext; + + +/*! System callback to indicate an event that requires a system reRun */ +typedef void (* rfalUpperLayerCallback)(void); + +/*! Callback to be executed before a Transceive */ +typedef void (* rfalPreTxRxCallback)(void); + +/*! Callback to be executed after a Transceive */ +typedef void (* rfalPostTxRxCallback)(void); + + +/*******************************************************************************/ +/* ISO14443A */ +/*******************************************************************************/ + +/*! RFAL ISO 14443A Short Frame Command */ +typedef enum +{ + RFAL_14443A_SHORTFRAME_CMD_WUPA = 0x52, /*!< ISO14443A WUPA / NFC-A ALL_REQ */ + RFAL_14443A_SHORTFRAME_CMD_REQA = 0x26 /*!< ISO14443A REQA / NFC-A SENS_REQ */ +} rfal14443AShortFrameCmd; + +/*******************************************************************************/ + + +/*******************************************************************************/ +/* FeliCa */ +/*******************************************************************************/ + +#define RFAL_FELICA_LEN_LEN 1U /*!< FeliCa LEN byte length */ +#define RFAL_FELICA_POLL_REQ_LEN (RFAL_FELICA_LEN_LEN + 1U + 2U + 1U + 1U) /*!< FeliCa Poll Request length (LEN + CMD + SC + RC + TSN) */ +#define RFAL_FELICA_POLL_RES_LEN (RFAL_FELICA_LEN_LEN + 1U + 8U + 8U + 2U) /*!< Maximum FeliCa Poll Response length (LEN + CMD + NFCID2 + PAD + RD) */ +#define RFAL_FELICA_POLL_MAX_SLOTS 16U /*!< Maximum number of slots (TSN) on FeliCa Poll */ + + +/*! NFC-F RC (Request Code) codes NFC Forum Digital 1.1 Table 42 */ +enum +{ + RFAL_FELICA_POLL_RC_NO_REQUEST = 0x00, /*!< RC: No System Code information requested */ + RFAL_FELICA_POLL_RC_SYSTEM_CODE = 0x01, /*!< RC: System Code information requested */ + RFAL_FELICA_POLL_RC_COM_PERFORMANCE = 0x02 /*!< RC: Advanced protocol features supported */ +}; + + +/*! NFC-F TSN (Time Slot Number) codes NFC Forum Digital 1.1 Table 43 */ +typedef enum +{ + RFAL_FELICA_1_SLOT = 0, /*!< TSN with number of Time Slots: 1 */ + RFAL_FELICA_2_SLOTS = 1, /*!< TSN with number of Time Slots: 2 */ + RFAL_FELICA_4_SLOTS = 3, /*!< TSN with number of Time Slots: 4 */ + RFAL_FELICA_8_SLOTS = 7, /*!< TSN with number of Time Slots: 8 */ + RFAL_FELICA_16_SLOTS = 15 /*!< TSN with number of Time Slots: 16 */ +} rfalFeliCaPollSlots; + + +/*! NFCF Poll Response NFC Forum Digital 1.1 Table 44 */ +typedef uint8_t rfalFeliCaPollRes[RFAL_FELICA_POLL_RES_LEN]; + + +/*******************************************************************************/ + + +/*******************************************************************************/ +/* Listen Mode */ +/*******************************************************************************/ + +/*! RFAL Listen Mode NFCID Length */ +typedef enum +{ + RFAL_LM_NFCID_LEN_04 = 4, /*!< Listen mode indicates 4 byte NFCID */ + RFAL_LM_NFCID_LEN_07 = 7, /*!< Listen mode indicates 7 byte NFCID */ + RFAL_LM_NFCID_LEN_10 = 10, /*!< Listen mode indicates 10 byte NFCID */ +} rfalLmNfcidLen; + + +/*! RFAL Listen Mode States */ +typedef enum +{ + RFAL_LM_STATE_NOT_INIT = 0x00, /*!< Not Initialized state */ + RFAL_LM_STATE_POWER_OFF = 0x01, /*!< Power Off state */ + RFAL_LM_STATE_IDLE = 0x02, /*!< Idle state Activity 1.1 5.2 */ + RFAL_LM_STATE_READY_A = 0x03, /*!< Ready A state Activity 1.1 5.3 5.4 & 5.5 */ + RFAL_LM_STATE_READY_B = 0x04, /*!< Ready B state Activity 1.1 5.11 5.12 */ + RFAL_LM_STATE_READY_F = 0x05, /*!< Ready F state Activity 1.1 5.15 */ + RFAL_LM_STATE_ACTIVE_A = 0x06, /*!< Active A state Activity 1.1 5.6 */ + RFAL_LM_STATE_CARDEMU_4A = 0x07, /*!< Card Emulation 4A state Activity 1.1 5.10 */ + RFAL_LM_STATE_CARDEMU_4B = 0x08, /*!< Card Emulation 4B state Activity 1.1 5.14 */ + RFAL_LM_STATE_CARDEMU_3 = 0x09, /*!< Card Emulation 3 state Activity 1.1 5.18 */ + RFAL_LM_STATE_TARGET_A = 0x0A, /*!< Target A state Activity 1.1 5.9 */ + RFAL_LM_STATE_TARGET_F = 0x0B, /*!< Target F state Activity 1.1 5.17 */ + RFAL_LM_STATE_SLEEP_A = 0x0C, /*!< Sleep A state Activity 1.1 5.7 */ + RFAL_LM_STATE_SLEEP_B = 0x0D, /*!< Sleep B state Activity 1.1 5.13 */ + RFAL_LM_STATE_READY_Ax = 0x0E, /*!< Ready A* state Activity 1.1 5.3 5.4 & 5.5 */ + RFAL_LM_STATE_ACTIVE_Ax = 0x0F, /*!< Active A* state Activity 1.1 5.6 */ + RFAL_LM_STATE_SLEEP_AF = 0x10, /*!< Sleep AF state Activity 1.1 5.19 */ +} rfalLmState; + + +/*! RFAL Listen Mode Passive A configs */ +typedef struct +{ + rfalLmNfcidLen nfcidLen; /*!< NFCID Len (00: 4bytes ; 01: 7bytes) */ + uint8_t nfcid[RFAL_NFCID1_TRIPLE_LEN]; /*!< NFCID */ + uint8_t SENS_RES[RFAL_LM_SENS_RES_LEN]; /*!< NFC-106k; SENS_REQ Response */ + uint8_t SEL_RES; /*!< SEL_RES (SAK) with complete NFCID1 (UID) */ +} rfalLmConfPA; + + +/*! RFAL Listen Mode Passive B configs */ +typedef struct +{ + uint8_t SENSB_RES[RFAL_LM_SENSB_RES_LEN]; /*!< SENSF_RES */ +} rfalLmConfPB; + + +/*! RFAL Listen Mode Passive F configs */ +typedef struct +{ + uint8_t SC[RFAL_LM_SENSF_SC_LEN]; /*!< System Code to listen for */ + uint8_t SENSF_RES[RFAL_LM_SENSF_RES_LEN]; /*!< SENSF_RES */ +} rfalLmConfPF; + +/*******************************************************************************/ + + +/*******************************************************************************/ +/* Wake-Up Mode */ +/*******************************************************************************/ + +#define RFAL_WUM_REFERENCE_AUTO 0xFFU /*!< Indicates new reference is set by the driver*/ + +/*! RFAL Wake-Up Mode States */ +typedef enum +{ + RFAL_WUM_STATE_NOT_INIT = 0x00, /*!< Not Initialized state */ + RFAL_WUM_STATE_ENABLED = 0x01, /*!< Wake-Up mode is enabled */ + RFAL_WUM_STATE_ENABLED_WOKE = 0x02, /*!< Wake-Up mode enabled and has received IRQ(s)*/ +} rfalWumState; + +/*! RFAL Wake-Up Period/Timer */ +typedef enum +{ + RFAL_WUM_PERIOD_10MS = 0x00, /*!< Wake-Up timer 10ms */ + RFAL_WUM_PERIOD_20MS = 0x01, /*!< Wake-Up timer 20ms */ + RFAL_WUM_PERIOD_30MS = 0x02, /*!< Wake-Up timer 30ms */ + RFAL_WUM_PERIOD_40MS = 0x03, /*!< Wake-Up timer 40ms */ + RFAL_WUM_PERIOD_50MS = 0x04, /*!< Wake-Up timer 50ms */ + RFAL_WUM_PERIOD_60MS = 0x05, /*!< Wake-Up timer 60ms */ + RFAL_WUM_PERIOD_70MS = 0x06, /*!< Wake-Up timer 70ms */ + RFAL_WUM_PERIOD_80MS = 0x07, /*!< Wake-Up timer 80ms */ + RFAL_WUM_PERIOD_100MS = 0x10, /*!< Wake-Up timer 100ms */ + RFAL_WUM_PERIOD_200MS = 0x11, /*!< Wake-Up timer 200ms */ + RFAL_WUM_PERIOD_300MS = 0x12, /*!< Wake-Up timer 300ms */ + RFAL_WUM_PERIOD_400MS = 0x13, /*!< Wake-Up timer 400ms */ + RFAL_WUM_PERIOD_500MS = 0x14, /*!< Wake-Up timer 500ms */ + RFAL_WUM_PERIOD_600MS = 0x15, /*!< Wake-Up timer 600ms */ + RFAL_WUM_PERIOD_700MS = 0x16, /*!< Wake-Up timer 700ms */ + RFAL_WUM_PERIOD_800MS = 0x17, /*!< Wake-Up timer 800ms */ +} rfalWumPeriod; + + +/*! RFAL Wake-Up Period/Timer */ +typedef enum +{ + RFAL_WUM_AA_WEIGHT_4 = 0x00, /*!< Wake-Up Auto Average Weight 4 */ + RFAL_WUM_AA_WEIGHT_8 = 0x01, /*!< Wake-Up Auto Average Weight 8 */ + RFAL_WUM_AA_WEIGHT_16 = 0x02, /*!< Wake-Up Auto Average Weight 16 */ + RFAL_WUM_AA_WEIGHT_32 = 0x03, /*!< Wake-Up Auto Average Weight 32 */ +} rfalWumAAWeight; + + +/*! RFAL Wake-Up Mode configuration */ +typedef struct +{ + rfalWumPeriod period; /*!< Wake-Up Timer period;how often measurement(s) is performed */ + bool irqTout; /*!< IRQ at every timeout will refresh the measurement(s) */ + bool swTagDetect;/*!< Use SW Tag Detection instead of HW Wake-Up mode */ + + struct{ + bool enabled; /*!< Inductive Amplitude measurement enabled */ + uint8_t delta; /*!< Delta between the reference and measurement to wake-up */ + uint8_t reference; /*!< Reference to be used;RFAL_WUM_REFERENCE_AUTO sets it auto */ + bool autoAvg; /*!< Use the HW Auto Averaging feature */ + bool aaInclMeas; /*!< When AutoAvg is enabled, include IRQ measurement */ + rfalWumAAWeight aaWeight; /*!< When AutoAvg is enabled, last measure weight */ + }indAmp; /*!< Inductive Amplitude Configuration */ + struct{ + bool enabled; /*!< Inductive Phase measurement enabled */ + uint8_t delta; /*!< Delta between the reference and measurement to wake-up */ + uint8_t reference; /*!< Reference to be used;RFAL_WUM_REFERENCE_AUTO sets it auto */ + bool autoAvg; /*!< Use the HW Auto Averaging feature */ + bool aaInclMeas; /*!< When AutoAvg is enabled, include IRQ measurement */ + rfalWumAAWeight aaWeight; /*!< When AutoAvg is enabled, last measure weight */ + }indPha; /*!< Inductive Phase Configuration */ + struct{ + bool enabled; /*!< Capacitive measurement enabled */ + uint8_t delta; /*!< Delta between the reference and measurement to wake-up */ + uint8_t reference; /*!< Reference to be used;RFAL_WUM_REFERENCE_AUTO sets it auto */ + bool autoAvg; /*!< Use the HW Auto Averaging feature */ + bool aaInclMeas; /*!< When AutoAvg is enabled, include IRQ measurement */ + rfalWumAAWeight aaWeight; /*!< When AutoAvg is enabled, last measure weight */ + }cap; /*!< Capacitive Configuration */ +} rfalWakeUpConfig; + + +/*******************************************************************************/ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + + +/*! + ***************************************************************************** + * \brief RFAL Initialize + * + * Initializes RFAL layer and the ST25R391x + * Ensures that ST25R391x is properly connected and returns error if any problem + * is detected + * + * \warning rfalAnalogConfigInitialize() should be called before so that + * the Analog config table has been previously initialized. + * + * \return ERR_HW_MISMATCH : Expected HW do not match or communication error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalInitialize( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Calibrate + * + * Performs necessary calibration of RF chip in case it is indicated by current + * register settings. E.g. antenna calibration and regulator calibration + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalCalibrate( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Adjust Regulators + * + * Adjusts ST25R391x regulators + * + * \param[out] result : the result of the calibrate antenna in mV + * NULL if result not requested + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalAdjustRegulators( uint16_t* result ); + + +/*! + ***************************************************************************** + * \brief RFAL Set System Callback + * + * Sets a callback for the driver to call when an event has occurred that + * may require the system to be notified + * + * \param[in] pFunc : method pointer for the upper layer callback + * + ***************************************************************************** + */ +void rfalSetUpperLayerCallback( rfalUpperLayerCallback pFunc ); + + +/*! + ***************************************************************************** + * \brief RFAL Set Pre Tx Callback + * + * Sets a callback for the driver to call before a Transceive + * + * \param[in] pFunc : method pointer for the Pre Tx callback + * + ***************************************************************************** + */ +void rfalSetPreTxRxCallback( rfalPreTxRxCallback pFunc ); + +/*! + ***************************************************************************** + * \brief RFAL Set Post Tx Callback + * + * Sets a callback for the driver to call after a Transceive + * + * \param[in] pFunc : method pointer for the Post Tx callback + * + ***************************************************************************** + */ +void rfalSetPostTxRxCallback( rfalPostTxRxCallback pFunc ); + +/*! + ***************************************************************************** + * \brief RFAL Deinitialize + * + * Deinitializes RFAL layer and the ST25R391x + * + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalDeinitialize( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Set Mode + * + * Sets the mode that RFAL will operate on the following communications. + * Proper initializations will be performed on the ST25R391x + * + * \warning bit rate value RFAL_BR_KEEP is not allowed, only in rfalSetBitRate() + * + * \warning the mode will be applied immediately on the RFchip regardless of + * any ongoing operations like Transceive, ListenMode + * + * \param[in] mode : mode for the RFAL/RFchip to perform + * \param[in] txBR : transmit bit rate + * \param[in] rxBR : receive bit rate + * + * \see rfalIsGTDone + * \see rfalMode + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalSetMode( rfalMode mode, rfalBitRate txBR, rfalBitRate rxBR ); + + +/*! + ***************************************************************************** + * \brief RFAL Get Mode + * + * Gets the mode that RFAL is set to operate + * + * \see rfalMode + * + * \return rfalMode : The current RFAL mode + ***************************************************************************** + */ +rfalMode rfalGetMode( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Set Bit Rate + * + * Sets the Tx and Rx bit rates with the given values + * The bit rate change is applied on the RF chip remaining in the same + * mode previous defined with rfalSetMode() + * + * If no mode is defined bit rates will not be applied and an error + * is returned + * + * \param[in] txBR : transmit bit rate + * \param[in] rxBR : receive bit rate + * + * \see rfalSetMode + * \see rfalMode + * \see rfalBitRate + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_PARAM : Invalid parameter + * \return ERR_NOT_IMPLEMENTED : Mode not implemented + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalSetBitRate( rfalBitRate txBR, rfalBitRate rxBR ); + + +/*! + ***************************************************************************** + * \brief RFAL Get Bit Rate + * + * Gets the Tx and Rx current bit rates + * + * If RFAL is not initialized or mode not set the bit rates return will + * be invalid RFAL_BR_KEEP + * + * \param[out] txBR : RFAL's current Tx Bit Rate + * \param[out] rxBR : RFAL's current Rx Bit Rate + * + * \see rfalSetBitRate + * \see rfalBitRate + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalGetBitRate( rfalBitRate *txBR, rfalBitRate *rxBR ); + + +/*! + ***************************************************************************** + * \brief Set Error Handling Mode + * + * Sets the error handling mode to be used by the RFAL + * + * \param[in] eHandling : the error handling mode + * + ***************************************************************************** + */ +void rfalSetErrorHandling( rfalEHandling eHandling ); + + +/*! + ***************************************************************************** + * \brief Get Error Handling Mode + * + * Gets the error handling mode currently used by the RFAL + * + * \return rfalEHandling : Current error handling mode + ***************************************************************************** + */ +rfalEHandling rfalGetErrorHandling( void ); + + +/*! + ***************************************************************************** + * \brief Set Observation Mode + * + * Sets ST25R391x observation modes for RF debug purposes + * + * \param[in] txMode : the observation mode to be used during transmission + * \param[in] rxMode : the observation mode to be used during reception + * + * \warning The Observation Mode is an advanced feature and should be set + * according to the documentation of the part number in use. + * Please refer to the corresponding Datasheet or Application Note(s) + ***************************************************************************** + */ +void rfalSetObsvMode( uint8_t txMode, uint8_t rxMode ); + + +/*! + ***************************************************************************** + * \brief Get Observation Mode + * + * Gets ST25R391x the current configured observation modes + * + * \param[in] txMode : the current observation mode configured for transmission + * \param[in] rxMode : the current observation mode configured for reception + * + ***************************************************************************** + */ +void rfalGetObsvMode( uint8_t* txMode, uint8_t* rxMode ); + + +/*! + ***************************************************************************** + * \brief Disable Observation Mode + * + * Disables the ST25R391x observation mode + ***************************************************************************** + */ +void rfalDisableObsvMode( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Poll + * + * Sets the Frame Delay Time (FDT) to be used on the following + * communications. + * + * FDT Poll is the minimum time following a Poll Frame during + * which no subsequent Poll Frame can be sent (without a response from + * the Listener in between) + * FDTx,PP,MIN - Digital 1.1 6.10.2 & 7.9.2 & 8.7.2 + * + * \param[in] FDTPoll : Frame Delay Time in 1/fc cycles + * + ***************************************************************************** + */ +void rfalSetFDTPoll( uint32_t FDTPoll ); + + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Poll + * + * Gets the current Frame Delay Time (FDT) + * + * FDT Poll is the minimum time following a Poll Frame during + * which no subsequent Poll Frame can be sent (without a response from + * the Listener in between) + * FDTx,PP,MIN - Digital 1.1 6.10.2 & 7.9.2 & 8.7.2 + * + * \return FDT : current FDT value in 1/fc cycles + * + ***************************************************************************** + */ +uint32_t rfalGetFDTPoll( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Listen + * + * Sets the Frame Delay Time (FDT) Listen minimum to be used on the + * following communications. + * + * FDT Listen is the minimum time between a Poll Frame and a Listen Frame + * FDTx,LISTEN,MIN - Digital 1.1 6.10.1 & 7.9.1 & 8.7.1 + * + * \param[in] FDTListen : Frame Delay Time in 1/fc cycles + * + ***************************************************************************** + */ +void rfalSetFDTListen( uint32_t FDTListen ); + + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Listen + * + * Gets the Frame Delay Time (FDT) Listen minimum + * + * FDT Listen is the minimum time between a Poll Frame and a Listen Frame + * FDTx,LISTEN,MIN - Digital 1.1 6.10.1 & 7.9.1 & 8.7.1 + * + * \return FDT : current FDT value in 1/fc cycles + * + ***************************************************************************** + */ +uint32_t rfalGetFDTListen( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Get GT + * + * Gets the current Guard Time (GT) + * + * GT is the minimum time when a device in Listen Mode is exposed to an + * unmodulated carrier + * + * \return GT : Guard Time in 1/fc cycles + * + ***************************************************************************** + */ +uint32_t rfalGetGT( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Set GT + * + * Sets the Guard Time (GT) to be used on the following communications. + * + * GT is the minimum time when a device in Listen Mode is exposed to an + * unmodulated carrier + * + * \param[in] GT : Guard Time in 1/fc cycles + * RFAL_GT_NONE if no GT should be applied + * + ***************************************************************************** + */ +void rfalSetGT( uint32_t GT ); + + +/*! + ***************************************************************************** + * \brief RFAL Is GT expired + * + * Checks whether the GT timer has expired + * + * \return true : GT has expired or not running + * \return false : GT is still running + * + ***************************************************************************** + */ +bool rfalIsGTExpired( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Turn Field On and Start GT + * + * Turns the Field On, performing Initial Collision Avoidance + * + * After Field On, if GT was set before, it starts the GT timer to be + * used on the following communications. + * + * \return ERR_RF_COLLISION : External field detected + * \return ERR_NONE : Field turned On + * + ***************************************************************************** + */ +ReturnCode rfalFieldOnAndStartGT( void ); + + +/*! + ***************************************************************************** + * \brief RFAL Turn Field Off + * + * Turns the Field Off + * + * \return ERR_NONE : Field turned Off + ***************************************************************************** + */ +ReturnCode rfalFieldOff( void ); + + + +/***************************************************************************** + * Transceive * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief RFAL Set transceive context + * + * Set the context that will be used for the following Transceive + * Output and input buffers have to be passed and all other details prior to + * the Transceive itself has been started + * + * This method only sets the context, once set rfalWorker has + * to be executed until is done + * + * \param[in] ctx : the context for the following Transceive + * + * \see rfalWorker + * \see rfalGetTransceiveStatus + * + * \return ERR_NONE : Done with no error + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter or configuration + ***************************************************************************** + */ +ReturnCode rfalStartTransceive( const rfalTransceiveContext *ctx ); + + +/*! + ***************************************************************************** + * \brief Get Transceive State + * + * Gets current Transceive internal State + * + * \return rfalTransceiveState : the current Transceive internal State + ***************************************************************************** + */ +rfalTransceiveState rfalGetTransceiveState( void ); + + +/*! + ***************************************************************************** + * \brief Get Transceive Status + * + * Gets current Transceive status + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalGetTransceiveStatus( void ); + + +/*! + ***************************************************************************** + * \brief Is Transceive in Tx + * + * Checks if Transceive is in Transmission state + * + * \return true Transmission ongoing + * \return false Not in transmission state + ***************************************************************************** + */ +bool rfalIsTransceiveInTx( void ); + + +/*! + ***************************************************************************** + * \brief Is Transceive in Rx + * + * Checks if Transceive is in Reception state + * + * \return true Transmission done/reception ongoing + * \return false Not in reception state + ***************************************************************************** + */ +bool rfalIsTransceiveInRx( void ); + + +/*! + ***************************************************************************** + * \brief Get Transceive RSSI + * + * Gets the RSSI value of the last executed Transceive in mV + * + * \param[out] rssi : RSSI value + * + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalGetTransceiveRSSI( uint16_t *rssi ); + + +/*! + ***************************************************************************** + * \brief RFAL Worker + * + * This runs RFAL layer, which drives the actual Transceive procedure + * It MUST be executed frequently in order to execute the RFAL internal + * states and perform the requested operations + * + ***************************************************************************** + */ +void rfalWorker( void ); + + +/***************************************************************************** + * ISO1443A * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Transceives an ISO14443A ShortFrame + * + * Sends REQA to detect if there is any PICC in the field + * + * \param[in] txCmd: Command to be sent: + * 0x52 WUPA / ALL_REQ + * 0x26 REQA / SENS_REQ + * + * \param[in] txCmd : type of short frame to be sent REQA or WUPA + * \param[out] rxBuf : buffer to place the response + * \param[in] rxBufLen : length of rxBuf + * \param[out] rxRcvdLen: received length + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \warning If fwt is set to RFAL_FWT_NONE it will make endlessly for + * a response, which on a blocking method may not be the + * desired usage + * + * \return ERR_NONE if there is response + * \return ERR_TIMEOUT if there is no response + * \return ERR_COLLISION collision has occurred + * + ***************************************************************************** + */ +ReturnCode rfalISO14443ATransceiveShortFrame( rfal14443AShortFrameCmd txCmd, uint8_t* rxBuf, uint8_t rxBufLen, uint16_t* rxRcvdLen, uint32_t fwt ); + + +/*! + ***************************************************************************** + * \brief Sends an ISO14443A Anticollision Frame + * + * This is use to perform ISO14443A anti-collision. + * \note Anticollision is sent without CRC + * + * + * \param[in] buf : reference to ANTICOLLISION command (with known UID if any) to be sent (also out param) + * reception will be place on this buf after bytesToSend + * \param[in] bytesToSend: reference number of full bytes to be sent (including CMD byte and SEL_PAR) + * if a collision occurs will contain the number of clear bytes + * \param[in] bitsToSend : reference to number of bits (0-7) to be sent; and received (also out param) + * if a collision occurs will indicate the number of clear bits (also out param) + * \param[out] rxLength : reference to the return the received length + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \return ERR_NONE if there is no error + ***************************************************************************** + */ +ReturnCode rfalISO14443ATransceiveAnticollisionFrame( uint8_t *buf, uint8_t *bytesToSend, uint8_t *bitsToSend, uint16_t *rxLength, uint32_t fwt ); + + +/***************************************************************************** + * FeliCa * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief FeliCa Poll + * + * Sends a Poll Request and collects all Poll Responses according to the + * given slots + * + * + * \param[in] slots : number of slots for the Poll Request + * \param[in] sysCode : system code (SC) for the Poll Request + * \param[in] reqCode : request code (RC) for the Poll Request + * \param[out] pollResList : list of all responses + * \param[in] pollResListSize : number of responses that can be placed in pollResList + * \param[out] devicesDetected : number of cards found + * \param[out] collisionsDetected: number of collisions detected + * + * \return ERR_NONE if there is no error + * \return ERR_TIMEOUT if there is no response + ***************************************************************************** + */ +ReturnCode rfalFeliCaPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes* pollResList, uint8_t pollResListSize, uint8_t *devicesDetected, uint8_t *collisionsDetected ); + + +/***************************************************************************** + * ISO15693 * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Sends an ISO15693 Anticollision Frame + * + * This send the Anticollision|Inventory frame (INVENTORY_REQ) + * + * \warning rxBuf must be able to contain the payload and CRC + * + * \param[in] txBuf : Buffer where outgoing message is located + * \param[in] txBufLen : Length of the outgoing message in bytes + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bits + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalISO15693TransceiveAnticollisionFrame( uint8_t *txBuf, uint8_t txBufLen, uint8_t *rxBuf, uint8_t rxBufLen, uint16_t *actLen ); + + +/*! + ***************************************************************************** + * \brief Sends an ISO15693 Anticollision EOF + * + * This sends the Anticollision|Inventory EOF used as a slot marker + * + * \warning rxBuf must be able to contain the payload and CRC + * + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bits + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalISO15693TransceiveEOFAnticollision( uint8_t *rxBuf, uint8_t rxBufLen, uint16_t *actLen ); + + +/*! + ***************************************************************************** + * \brief Sends an ISO15693 EOF + * + * This is method sends an ISO15693 (EoF) used for a Write operation + * + * \warning rxBuf must be able to contain the payload and CRC + * + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bytes + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalISO15693TransceiveEOF( uint8_t *rxBuf, uint8_t rxBufLen, uint16_t *actLen ); + + +/*! + ***************************************************************************** + * \brief Transceive Blocking Tx + * + * This is method triggers a Transceive and executes it blocking until the + * Tx has been completed + * + * \param[in] txBuf : Buffer where outgoing message is located + * \param[in] txBufLen : Length of the outgoing message in bytes + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bits + * \param[in] flags : TransceiveFlags indication special handling + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalTransceiveBlockingTx( uint8_t* txBuf, uint16_t txBufLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* actLen, uint32_t flags, uint32_t fwt ); + +/*! + ***************************************************************************** + * \brief Transceive Blocking Rx + * + * This is method executes the reception of an ongoing Transceive triggered + * before by rfalTransceiveBlockingTx() + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalTransceiveBlockingRx( void ); + +/*! + ***************************************************************************** + * \brief Transceive Blocking + * + * This is method triggers a Transceive and executes it blocking until it + * has been completed + * + * \param[in] txBuf : Buffer where outgoing message is located + * \param[in] txBufLen : Length of the outgoing message in bytes + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bytes + * \param[in] flags : TransceiveFlags indication special handling + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalTransceiveBlockingTxRx( uint8_t* txBuf, uint16_t txBufLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* actLen, uint32_t flags, uint32_t fwt ); + + + +/***************************************************************************** + * Listen Mode * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Is external Field On + * + * Checks if external field (other peer/device) is on/detected + * + * \return true External field is On + * \return false No external field is detected + * + ***************************************************************************** + */ +bool rfalIsExtFieldOn( void ); + + +/*! + ***************************************************************************** + * \brief Listen Mode start + * + * Configures RF Chip to go into listen mode enabling the given technologies + * + * + * \param[in] lmMask: mask with the enabled/disabled listen modes + * use: RFAL_LM_MASK_NFCA ; RFAL_LM_MASK_NFCB ; + * RFAL_LM_MASK_NFCF ; RFAL_LM_MASK_ACTIVE_P2P + * \param[in] confA: pointer to Passive A configurations (NULL if disabled) + * \param[in] confB: pointer to Passive B configurations (NULL if disabled) + * \param[in] confF: pointer to Passive F configurations (NULL if disabled) + * \param[in] rxBuf: buffer to place incoming data + * \param[in] rxBufLen: length in bits of rxBuf + * \param[in] rxLen: pointer to write the data length in bits placed into rxBuf + * + * + * \return ERR_PARAM Invalid parameter + * \return ERR_REQUEST Invalid listen mode mask + * \return ERR_NONE Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalListenStart( uint32_t lmMask, const rfalLmConfPA *confA, const rfalLmConfPB *confB, const rfalLmConfPF *confF, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rxLen ); + + +/*! + ***************************************************************************** + * \brief Listen Mode start Sleeping + * + * + ***************************************************************************** + */ +ReturnCode rfalListenSleepStart( rfalLmState sleepSt, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rxLen ); + + +/*! + ***************************************************************************** + * \brief Listen Mode Stop + * + * Disables the listen mode on the RF Chip + * + * \warning the listen mode will be disabled immediately on the RFchip regardless + * of any ongoing operations like Transceive + * + * \return ERR_NONE Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalListenStop( void ); + + +/*! + ***************************************************************************** + * \brief Listen Mode get state + * + * Sets the new state of the Listen Mode and applies the necessary changes + * on the RF Chip + * + * \param[out] dataFlag: indicates that Listen Mode has rcvd data and caller + * must process it. The received message is located + * at the rxBuf passed on rfalListenStart(). + * rfalListenSetState() will clear this flag + * if NULL output parameter will no be written/returned + * \param[out] lastBR: bit rate detected of the last initiator request + * if NULL output parameter will no be written/returned + * + * \return rfalLmState RFAL_LM_STATE_NOT_INIT : LM not initialized properly + * Any Other : LM State + * + ***************************************************************************** + */ +rfalLmState rfalListenGetState( bool *dataFlag, rfalBitRate *lastBR ); + + +/*! + ***************************************************************************** + * \brief Listen Mode set state + * + * Sets the new state of the Listen Mode and applies the necessary changes + * on the RF Chip + * + * \param[in] newSt : New state to go to + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalListenSetState( rfalLmState newSt ); + + +/***************************************************************************** + * Wake-Up Mode * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Wake-Up Mode Start + * + * Sets the RF Chip in Low Power Wake-Up Mode according to the given + * configuration. + * + * \param[in] config : Generic Wake-Up configuration provided by lower + * layers. If NULL will automatically configure the + * Wake-Up mode + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalWakeUpModeStart( const rfalWakeUpConfig *config ); + + +/*! + ***************************************************************************** + * \brief Wake-Up Has Woke + * + * Returns true if the Wake-Up mode is enabled and it has already received + * the indication from the RF Chip that the surrounding environment has changed + * and flagged at least one wake-Up interrupt + * + * \return true : Wake-Up mode enabled and has received a wake-up IRQ + * \return false : no Wake-Up IRQ has been received + * + ***************************************************************************** + */ +bool rfalWakeUpModeHasWoke( void ); + + +/*! + ***************************************************************************** + * \brief Wake-Up Mode Stop + * + * Stops the Wake-Up Mode + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalWakeUpModeStop( void ); + + +#endif /* RFAL_RF_H */ + + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_st25tb.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_st25tb.h new file mode 100644 index 0000000..12a18a8 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_st25tb.h @@ -0,0 +1,355 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25tb.h + * + * \author Gustavo Patricio + * + * \brief Implementation of ST25TB interface + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup ST25TB + * \brief RFAL ST25TB Module + * @{ + * + */ + + +#ifndef RFAL_ST25TB_H +#define RFAL_ST25TB_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" +#include "rfal_nfcb.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_ST25TB_CHIP_ID_LEN 1U /*!< ST25TB chip ID length */ +#define RFAL_ST25TB_CRC_LEN 2U /*!< ST25TB CRC length */ +#define RFAL_ST25TB_UID_LEN 8U /*!< ST25TB Unique ID length */ +#define RFAL_ST25TB_BLOCK_LEN 4U /*!< ST25TB Data Block length */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ +typedef uint8_t rfalSt25tbUID[RFAL_ST25TB_UID_LEN]; /*!< ST25TB UID type */ +typedef uint8_t rfalSt25tbBlock[RFAL_ST25TB_BLOCK_LEN]; /*!< ST25TB Block type */ + + +/*! ST25TB listener device (PICC) struct */ +typedef struct +{ + uint8_t chipID; /*!< Device's session Chip ID */ + rfalSt25tbUID UID; /*!< Device's UID */ + bool isDeselected; /*!< Device deselect flag */ +}rfalSt25tbListenDevice; + + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize ST25TB Poller mode + * + * This methods configures RFAL RF layer to perform as a + * ST25TB Poller/RW including all default timings + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerInitialize( void ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Check Presence + * + * This method checks if a ST25TB Listen device (PICC) is present on the field + * by sending an Initiate command + * + * \param[out] chipId : if successfully retrieved, the device's chip ID + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerCheckPresence( uint8_t *chipId ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Collision Resolution + * + * This method performs ST25TB Collision resolution, selects the each device, + * retrieves its UID and then deselects. + * In case only one device is identified the ST25TB device is left in select + * state. + * + * \param[in] devLimit : device limit value, and size st25tbDevList + * \param[out] st25tbDevList : ST35TB listener device info + * \param[out] devCnt : Devices found counter + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt ); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Initiate + * + * This method sends an Initiate command + * + * If a single device responds the chip ID will be retrieved + * + * \param[out] chipId : chip ID of the device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerInitiate( uint8_t *chipId ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Pcall + * + * This method sends a Pcall command + * If successful the device's chip ID will be retrieved + * + * \param[out] chipId : Chip ID of the device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerPcall( uint8_t *chipId ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Slot Marker + * + * This method sends a Slot Marker + * + * If a single device responds the chip ID will be retrieved + * + * \param[in] slotNum : Slot Number + * \param[out] chipIdRes : Chip ID of the device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerSlotMarker( uint8_t slotNum, uint8_t *chipIdRes ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Select + * + * This method sends a ST25TB Select command with the given chip ID. + * + * If the device is already in Selected state and receives an incorrect chip + * ID, it goes into Deselected state + * + * \param[in] chipId : chip ID of the device to be selected + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerSelect( uint8_t chipId ); + + +/*! + ***************************************************************************** + * \brief ST25TB Get UID + * + * This method sends a Get_UID command + * + * If a single device responds the chip UID will be retrieved + * + * \param[out] UID : UID of the found device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerGetUID( rfalSt25tbUID *UID ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Read Block + * + * This method reads a block of the ST25TB + * + * \param[in] blockAddress : address of the block to be read + * \param[out] blockData : location to place the data read from block + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerReadBlock( uint8_t blockAddress, rfalSt25tbBlock *blockData ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Write Block + * + * This method writes a block of the ST25TB + * + * \param[in] blockAddress : address of the block to be written + * \param[in] blockData : data to be written on the block + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerWriteBlock( uint8_t blockAddress, const rfalSt25tbBlock *blockData ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Completion + * + * This method sends a completion command to the ST25TB. After the + * completion the card no longer will reply to any command. + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerCompletion( void ); + + +/*! + ***************************************************************************** + * \brief ST25TB Poller Reset to Inventory + * + * This method sends a Reset to Inventory command to the ST25TB. + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerResetToInventory( void ); + + +#endif /* RFAL_ST25TB_H */ + +/** + * @} + * + * @} + * + * @} + */ + diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_st25xv.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_st25xv.h new file mode 100644 index 0000000..0927e0a --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_st25xv.h @@ -0,0 +1,729 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25xv.h + * + * \author Gustavo Patricio + * + * \brief NFC-V ST25 NFC-V Tag specific features + * + * This module provides support for ST's specific features available on + * NFC-V (ISO15693) tag families: ST25D, ST25TV, M24LR + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup ST25xV + * \brief RFAL ST25xV Module + * @{ + * + */ + +#ifndef RFAL_ST25xV_H +#define RFAL_ST25xV_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_nfc.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + + +#define RFAL_NFCV_BLOCKNUM_M24LR_LEN 2U /*!< Block Number length of MR24LR tags: 16 bits */ +#define RFAL_NFCV_ST_IC_MFG_CODE 0x02 /*!< ST IC Mfg code (used for custom commands) */ + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Single Block (M24LR) + * + * Reads a Single Block from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * default: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Single Block (M24LR) + * + * Reads a Single Block from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * default: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Single Block (M24LR) + * + * Writes a Single Block from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be written + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to write (16 bits) + * \param[in] wrData : data to be written on the given block + * \param[in] blockLen : number of bytes of a block + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Multiple Blocks (M24LR) + * + * Reads Multiple Blocks from a device from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read (16 bits) + * \param[in] numOfBlocks : number of block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Multiple Blocks (M24LR) + * + * Reads Multiple Blocks from a device from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read (16 bits) + * \param[in] numOfBlocks : number of block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Single Block + * + * Reads a Single Block from a device (VICC) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Multiple Blocks + * + * Reads Multiple Blocks from a device (VICC) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read + * \param[in] numOfBlocks : number of block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Extended Read Single Block + * + * Reads a Single Block from a device (VICC) supporting extended commands using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Extended Read Multiple Blocks + * + * Reads Multiple Blocks from a device (VICC) supporting extended commands using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read (16 bits) + * \param[in] numOfBlocks : number of consecutive blocks to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastExtReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Configuration + * + * Reads static configuration registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[out] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Configuration + * + * Writes static configuration registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[in] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerWriteConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ); + + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Dynamic Configuration + * + * Reads dynamic registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[out] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Dynamic Configuration + * + * Writes dynamic registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[in] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Dynamic Configuration + * + * Reads dynamic registers at the Pointer address using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[out] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Write Dynamic Configuration + * + * Writes dynamic registers at the Pointer address using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[in] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Present Password + * + * Sends the Present Password command + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pwdNum : Password number + * \param[in] pwd : Password + * \param[in] pwdLen : Password length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerPresentPassword( uint8_t flags, const uint8_t* uid, uint8_t pwdNum, const uint8_t* pwd, uint8_t pwdLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Get Random Number + * + * Returns a 16 bit random number + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerGetRandomNumber( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Message length + * + * Sends a Read Message Length message to retrieve the value of MB_LEN_Dyn + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[out] msgLen : Message Length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadMessageLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Message length + * + * Sends a Fast Read Message Length message to retrieve the value of MB_LEN_Dyn using ST Fast mode. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[out] msgLen : Message Length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadMsgLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Message + * + * Reads up to 256 bytes in the Mailbox from the location + * specified by MBpointer and sends back their value in the rxBuf response. + * First MailBox location is '00'. When Number of bytes is set to 00h + * and MBPointer is equals to 00h, the MB_LEN bytes of the full message + * are returned. Otherwise, Read Message command returns (Number of Bytes + 1) bytes + * (i.e. 01h returns 2 bytes, FFh returns 256 bytes). + * An error is reported if (Pointer + Nb of bytes + 1) is greater than the message length. + * RF Reading of the last byte of the mailbox message automatically clears b1 + * of MB_CTRL_Dyn HOST_PUT_MSG, and allows RF to put a new message. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] mbPointer : MPpointer + * \param[in] numBytes : number of bytes + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Message + * + * Reads up to 256 bytes in the Mailbox from the location + * specified by MBpointer and sends back their value in the rxBuf response using ST Fast mode. + * First MailBox location is '00'. When Number of bytes is set to 00h + * and MBPointer is equals to 00h, the MB_LEN bytes of the full message + * are returned. Otherwise, Read Message command returns (Number of Bytes + 1) bytes + * (i.e. 01h returns 2 bytes, FFh returns 256 bytes). + * An error is reported if (Pointer + Nb of bytes + 1) is greater than the message length. + * RF Reading of the last byte of the mailbox message automatically clears b1 + * of MB_CTRL_Dyn HOST_PUT_MSG, and allows RF to put a new message. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] mbPointer : MPpointer + * \param[in] numBytes : number of bytes + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Message + * + * Sends Write message Command + * + * On receiving the Write Message command, the ST25DVxxx puts the data contained + * in the request into the Mailbox buffer, update the MB_LEN_Dyn register, and + * set bit RF_PUT_MSG in MB_CTRL_Dyn register. It then reports if the write operation was successful + * in the response. The ST25DVxxx Mailbox contains up to 256 data bytes which are filled from the + * first location '00'. MSGlength parameter of the command is the number of + * Data bytes minus 1 (00 for 1 byte of data, FFh for 256 bytes of data). + * Write Message could be executed only when Mailbox is accessible by RF. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] msgLen : MSGLen number of Data bytes minus 1 + * \param[in] msgData : Message Data + * \param[out] txBuf : buffer to used to build the Write Message command + * \param[in] txBufLen : length of txBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen ); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Write Message + * + * Sends Fast Write message Command using ST Fast mode + * + * On receiving the Write Message command, the ST25DVxxx puts the data contained + * in the request into the Mailbox buffer, update the MB_LEN_Dyn register, and + * set bit RF_PUT_MSG in MB_CTRL_Dyn register. It then reports if the write operation was successful + * in the response. The ST25DVxxx Mailbox contains up to 256 data bytes which are filled from the + * first location '00'. MSGlength parameter of the command is the number of + * Data bytes minus 1 (00 for 1 byte of data, FFh for 256 bytes of data). + * Write Message could be executed only when Mailbox is accessible by RF. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] msgLen : MSGLen number of Data bytes minus 1 + * \param[in] msgData : Message Data + * \param[out] txBuf : buffer to used to build the Write Message command + * \param[in] txBufLen : length of txBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen ); + +#endif /* RFAL_ST25xV_H */ + +/** + * @} + * + * @} + * + * @} + */ + diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_t1t.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_t1t.h new file mode 100644 index 0000000..0f619f9 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_t1t.h @@ -0,0 +1,187 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t1t.h + * + * \author Gustavo Patricio + * + * \brief Provides NFC-A T1T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 1 Tag T1T (Topaz) + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup T1T + * \brief RFAL T1T Module + * @{ + * + */ + + +#ifndef RFAL_T1T_H +#define RFAL_T1T_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_T1T_UID_LEN 4 /*!< T1T UID length of cascade level 1 only tag */ +#define RFAL_T1T_HR_LENGTH 2 /*!< T1T HR(Header ROM) length */ + +#define RFAL_T1T_HR0_NDEF_MASK 0xF0 /*!< T1T HR0 NDEF capability mask T1T 1.2 2.2.2 */ +#define RFAL_T1T_HR0_NDEF_SUPPORT 0x10 /*!< T1T HR0 NDEF capable value T1T 1.2 2.2.2 */ + + +/*! NFC-A T1T (Topaz) command set */ +typedef enum +{ + RFAL_T1T_CMD_RID = 0x78, /*!< T1T Read UID */ + RFAL_T1T_CMD_RALL = 0x00, /*!< T1T Read All */ + RFAL_T1T_CMD_READ = 0x01, /*!< T1T Read */ + RFAL_T1T_CMD_WRITE_E = 0x53, /*!< T1T Write with erase (single byte) */ + RFAL_T1T_CMD_WRITE_NE = 0x1A /*!< T1T Write with no erase (single byte) */ +} rfalT1Tcmds; + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + + +/*! NFC-A T1T (Topaz) RID_RES Digital 1.1 10.6.2 & Table 50 */ +typedef struct +{ + uint8_t hr0; /*!< T1T Header ROM: HR0 */ + uint8_t hr1; /*!< T1T Header ROM: HR1 */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< T1T UID */ +} rfalT1TRidRes; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + + +/*! + ***************************************************************************** + * \brief Initialize NFC-A T1T Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-A T1T Poller/RW (Topaz) including all default timings + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerInitialize( void ); + + +/*! + ***************************************************************************** + * \brief NFC-A T1T Poller RID + * + * This method reads the UID of a NFC-A T1T Listener device + * + * + * \param[out] ridRes : pointer to place the RID_RES + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerRid( rfalT1TRidRes *ridRes ); + + +/*! + ***************************************************************************** + * \brief NFC-A T1T Poller RALL + * + * This method send a Read All command to a NFC-A T1T Listener device + * + * + * \param[in] uid : the UID of the device to read data + * \param[out] rxBuf : pointer to place the read data + * \param[in] rxBufLen : size of rxBuf + * \param[out] rxRcvdLen : actual received data + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerRall( const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rxRcvdLen ); + + +/*! + ***************************************************************************** + * \brief NFC-A T1T Poller Write + * + * This method writes the given data on the address of a NFC-A T1T Listener device + * + * + * \param[in] uid : the UID of the device to read data + * \param[in] address : address to write the data + * \param[in] data : the data to be written + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerWrite( const uint8_t* uid, uint8_t address, uint8_t data ); + +#endif /* RFAL_T1T_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_t2t.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_t2t.h new file mode 100644 index 0000000..c153a89 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_t2t.h @@ -0,0 +1,153 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t2t.h + * + * \author Gustavo Patricio + * + * \brief Provides NFC-A T2T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 2 Tag T2T + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup T2T + * \brief RFAL T2T Module + * @{ + * + */ + + +#ifndef RFAL_T2T_H +#define RFAL_T2T_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_T2T_BLOCK_LEN 4U /*!< T2T block length */ +#define RFAL_T2T_READ_DATA_LEN (4U * RFAL_T2T_BLOCK_LEN) /*!< T2T READ data length */ +#define RFAL_T2T_WRITE_DATA_LEN RFAL_T2T_BLOCK_LEN /*!< T2T WRITE data length */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief NFC-A T2T Poller Read + * + * This method sends a Read command to a NFC-A T2T Listener device + * + * + * \param[in] blockNum : Number of the block to read + * \param[out] rxBuf : pointer to place the read data + * \param[in] rxBufLen : size of rxBuf (RFAL_T2T_READ_DATA_LEN) + * \param[out] rcvLen : actual received data + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT2TPollerRead( uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); + + +/*! + ***************************************************************************** + * \brief NFC-A T2T Poller Write + * + * This method sends a Write command to a NFC-A T2T Listener device + * + * + * \param[in] blockNum : Number of the block to write + * \param[in] wrData : data to be written on the given block + * size must be of RFAL_T2T_WRITE_DATA_LEN + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT2TPollerWrite( uint8_t blockNum, const uint8_t* wrData ); + + +/*! + ***************************************************************************** + * \brief NFC-A T2T Poller Sector Select + * + * This method sends a Sector Select commands to a NFC-A T2T Listener device + * + * \param[in] sectorNum : Sector Number + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ + ReturnCode rfalT2TPollerSectorSelect( uint8_t sectorNum ); + +#endif /* RFAL_T2T_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Inc/rfal_t4t.h b/Software/fab-reader2-c/components/rfal/Inc/rfal_t4t.h new file mode 100644 index 0000000..0b49339 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Inc/rfal_t4t.h @@ -0,0 +1,365 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t4t.h + * + * \author Gustavo Patricio + * + * \brief Provides convenience methods and definitions for T4T (ISO7816-4) + * + * This module provides an interface to exchange T4T APDUs according to + * NFC Forum T4T and ISO7816-4 + * + * This implementation was based on the following specs: + * - ISO/IEC 7816-4 3rd Edition 2013-04-15 + * - NFC Forum T4T Technical Specification 1.0 2017-08-28 + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup T4T + * \brief RFAL T4T Module + * @{ + * + */ + + +#ifndef RFAL_T4T_H +#define RFAL_T4T_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "platform.h" +#include "st_errno.h" +#include "rfal_rf.h" +#include "rfal_isoDep.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN 4U /*!< Command-APDU prologue length (CLA INS P1 P2) */ +#define RFAL_T4T_LE_LEN 1U /*!< Le Expected Response Length (short field coding) */ +#define RFAL_T4T_LC_LEN 1U /*!< Lc Data field length (short field coding) */ +#define RFAL_T4T_MAX_RAPDU_SW1SW2_LEN 2U /*!< SW1 SW2 length */ +#define RFAL_T4T_CLA 0x00U /*!< Class byte (contains 00h because secure message are not used) */ + +#define RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME 0x04U /*!< P1 value for Select by name */ +#define RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID 0x00U /*!< P1 value for Select by file identifier */ +#define RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE 0x00U /*!< b2b1 P2 value for First or only occurence */ +#define RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE 0x00U /*!< b4b3 P2 value for Return FCI template */ +#define RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA 0x0CU /*!< b4b3 P2 value for No responce data */ + +#define RFAL_T4T_ISO7816_STATUS_COMPLETE 0x9000U /*!< Command completed \ Normal processing - No further qualification*/ + + +/* +****************************************************************************** +* GLOBAL VARIABLES +****************************************************************************** +*/ + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ +/*! NFC-A T4T Command-APDU structure */ +typedef struct +{ + uint8_t CLA; /*!< Class byte */ + uint8_t INS; /*!< Instruction byte */ + uint8_t P1; /*!< Parameter byte 1 */ + uint8_t P2; /*!< Parameter byte 2 */ + uint8_t Lc; /*!< Data field length */ + bool LcFlag; /*!< Lc flag (append Lc when true) */ + uint8_t Le; /*!< Expected Response Length */ + bool LeFlag; /*!< Le flag (append Le when true) */ + + rfalIsoDepApduBufFormat *cApduBuf; /*!< Command-APDU buffer (Tx) */ + uint16_t *cApduLen; /*!< Command-APDU Length */ +}rfalT4tCApduParam; + +/*! NFC-A T4T Response-APDU structure */ +typedef struct +{ + rfalIsoDepApduBufFormat *rApduBuf; /*!< Response-APDU buffer (Rx) */ + uint16_t rcvdLen; /*!< Full response length */ + uint16_t rApduBodyLen; /*!< Response body length */ + uint16_t statusWord; /*!< R-APDU Status Word SW1|SW2 */ +}rfalT4tRApduParam; + + + +/*! NFC-A T4T command set T4T 1.0 & ISO7816-4 2013 Table 4 */ +typedef enum +{ + RFAL_T4T_INS_SELECT = 0xA4U, /*!< T4T Select */ + RFAL_T4T_INS_READBINARY = 0xB0U, /*!< T4T ReadBinary */ + RFAL_T4T_INS_UPDATEBINARY = 0xD6U, /*!< T4T UpdateBinay */ + RFAL_T4T_INS_READBINARY_ODO = 0xB1U, /*!< T4T ReadBinary using ODO */ + RFAL_T4T_INS_UPDATEBINARY_ODO = 0xD7U /*!< T4T UpdateBinay using ODO */ +} rfalT4tCmds; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief T4T Compose APDU + * + * This method computes a C-APDU according to NFC Forum T4T and ISO7816-4. + * + * If C-APDU contains data to be sent, it must be placed inside the buffer + * rfalT4tTxRxApduParam.txRx.cApduBuf.apdu and signaled by Lc + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * \see rfalT4TPollerParseRAPDU() + * + * \warning The ISO-DEP module is used to perform the tranceive. Usually + * activation has been done via ISO-DEP activatiavtion. If not + * please call rfalIsoDepInitialize() before. + * + * \param[in,out] apduParam : APDU parameters + * apduParam.cApduLen will contain the APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeCAPDU( rfalT4tCApduParam *apduParam ); + + +/*! + ***************************************************************************** + * \brief T4T Parse R-APDU + * + * This method parses a R-APDU according to NFC Forum T4T and ISO7816-4. + * It will extract the data length and check if the Satus word is expected. + * + * \param[in,out] apduParam : APDU parameters + * apduParam.rApduBodyLen will contain the data length + * apduParam.statusWord will contain the SW1 and SW2 + * + * \return ERR_REQUEST : Status word (SW1 SW2) different from 9000 + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerParseRAPDU( rfalT4tRApduParam *apduParam ); + +/*! + ***************************************************************************** + * \brief T4T Compose Select Application APDU + * + * This method computes a Select Application APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] aid : Application ID to be used + * \param[in] aidLen : Application ID length + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeSelectAppl( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* aid, uint8_t aidLen, uint16_t *cApduLen ); + +/*! + ***************************************************************************** + * \brief T4T Compose Select File APDU + * + * This method computes a Select File APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] fid : File ID to be used + * \param[in] fidLen : File ID length + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeSelectFile( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen ); + +/*! + ***************************************************************************** + * \brief T4T Compose Select File APDU for Mapping Version 1 + * + * This method computes a Select File APDU according to NFC Forum T4TOP_v1.0 + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] fid : File ID to be used + * \param[in] fidLen : File ID length + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeSelectFileV1Mapping( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen ); + +/*! + ***************************************************************************** + * \brief T4T Compose Read Data APDU + * + * This method computes a Read Data APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] expLen : Expected length (Le) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeReadData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, uint8_t expLen, uint16_t *cApduLen ); + +/*! + ***************************************************************************** + * \brief T4T Compose Read Data ODO APDU + * + * This method computes a Read Data ODO APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] expLen : Expected length (Le) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeReadDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, uint8_t expLen, uint16_t *cApduLen ); + +/*! + ***************************************************************************** + * \brief T4T Compose Write Data APDU + * + * This method computes a Write Data APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] data : Data to be written + * \param[in] dataLen : Data length to be written (Lc) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeWriteData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen ); + +/*! + ***************************************************************************** + * \brief T4T Compose Write Data ODO APDU + * + * This method computes a Write Data ODO sAPDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] data : Data to be written + * \param[in] dataLen : Data length to be written (Lc) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeWriteDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen ); + +#endif /* RFAL_T4T_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_analogConfig.c b/Software/fab-reader2-c/components/rfal/Src/rfal_analogConfig.c new file mode 100644 index 0000000..64b646b --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_analogConfig.c @@ -0,0 +1,417 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_analogConfig.c + * + * \author bkam + * + * \brief Funcitons to manage and set analog settings. + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_analogConfig.h" +#include "rfal_chip.h" +#include "st_errno.h" +#include "platform.h" +#include "utils.h" + + +/* Check whether the Default Analog settings are to be used or custom ones */ +#ifdef RFAL_ANALOG_CONFIG_CUSTOM + extern const uint8_t* rfalAnalogConfigCustomSettings; + extern const uint16_t rfalAnalogConfigCustomSettingsLength; +#else + #include "rfal_analogConfigTbl.h" +#endif + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + + +#define RFAL_TEST_REG 0x0080U /*!< Test Register indicator */ + +/* + ****************************************************************************** + * MACROS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG + static uint8_t gRfalAnalogConfig[RFAL_ANALOG_CONFIG_TBL_SIZE]; /*!< Analog Configuration Settings List */ +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + + +/*! Struct for Analog Config Look Up Table Update */ +typedef struct { + const uint8_t *currentAnalogConfigTbl; /*!< Reference to start of current Analog Configuration */ + uint16_t configTblSize; /*!< Total size of Analog Configuration */ + bool ready; /*!< Indicate if Look Up Table is complete and ready for use */ +} rfalAnalogConfigMgmt; + +static rfalAnalogConfigMgmt gRfalAnalogConfigMgmt; /*!< Analog Configuration LUT management */ + +/* + ****************************************************************************** + * LOCAL TABLES + ****************************************************************************** + */ + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ +static rfalAnalogConfigNum rfalAnalogConfigSearch( rfalAnalogConfigId configId, uint16_t *configOffset ); + +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG + static void rfalAnalogConfigPtrUpdate( const uint8_t* analogConfigTbl ); +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + +/* + ****************************************************************************** + * GLOBAL VARIABLE DEFINITIONS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +void rfalAnalogConfigInitialize( void ) +{ + /* Use default Analog configuration settings in Flash by default. */ + +/* Check whether the Default Analog settings are to be used or custom ones */ +#ifdef RFAL_ANALOG_CONFIG_CUSTOM + gRfalAnalogConfigMgmt.currentAnalogConfigTbl = (const uint8_t *)&rfalAnalogConfigCustomSettings; + gRfalAnalogConfigMgmt.configTblSize = rfalAnalogConfigCustomSettingsLength; +#else + gRfalAnalogConfigMgmt.currentAnalogConfigTbl = (const uint8_t *)&rfalAnalogConfigDefaultSettings; + gRfalAnalogConfigMgmt.configTblSize = sizeof(rfalAnalogConfigDefaultSettings); +#endif + + gRfalAnalogConfigMgmt.ready = true; +} /* rfalAnalogConfigInitialize() */ + + +bool rfalAnalogConfigIsReady( void ) +{ + return gRfalAnalogConfigMgmt.ready; +} + +ReturnCode rfalAnalogConfigListWriteRaw( const uint8_t *configTbl, uint16_t configTblSize ) +{ +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG + + /* Check if the Configuration Table exceed the Table size */ + if ( configTblSize >= RFAL_ANALOG_CONFIG_TBL_SIZE ) + { + rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */ + return ERR_NOMEM; + } + + /* Check for invalid parameters */ + if( (configTbl == NULL) || (configTblSize == 0U) ) + { + return ERR_PARAM; + } + + /* NOTE: Function does not check for the validity of the Table contents (conf IDs, conf sets, register address) */ + ST_MEMCPY( gRfalAnalogConfig, configTbl, configTblSize ); + + /* Update the total size of configuration settings */ + gRfalAnalogConfigMgmt.configTblSize = configTblSize; + + rfalAnalogConfigPtrUpdate(gRfalAnalogConfig); + return ERR_NONE; + +#else + + // If Analog Configuration Update is to be disabled + NO_WARNING(configTbl); + NO_WARNING(configTblSize); + return ERR_REQUEST; + +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ +} + +ReturnCode rfalAnalogConfigListWrite( uint8_t more, const rfalAnalogConfig *config ) +{ +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG + + rfalAnalogConfigId configId; + rfalAnalogConfigNum numConfig; + uint8_t configSize; + + if (true == gRfalAnalogConfigMgmt.ready) + { /* First Update to the Configuration list. */ + gRfalAnalogConfigMgmt.ready = false; // invalidate the config List + gRfalAnalogConfigMgmt.configTblSize = 0; // Clear the config List + } + + configId = GETU16(config->id); + + /* Check validity of the Configuration ID. */ + if ( (RFAL_ANALOG_CONFIG_TECH_RFU <= RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) + ||((RFAL_ANALOG_CONFIG_BITRATE_6780 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId)) && (RFAL_ANALOG_CONFIG_BITRATE_1OF4 > RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId))) + ||(RFAL_ANALOG_CONFIG_BITRATE_1OF256 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId)) + ) + { + rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */ + return ERR_PARAM; + } + + numConfig = config->num; + configSize = (uint8_t)(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + (numConfig * sizeof(rfalAnalogConfigRegAddrMaskVal))); + + /* Check if the Configuration Set exceed the Table size. */ + if ( RFAL_ANALOG_CONFIG_TBL_SIZE <= (gRfalAnalogConfigMgmt.configTblSize + configSize) ) + { + rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */ + return ERR_NOMEM; + } + + /* NOTE: Function does not check for the validity of the Register Address. */ + ST_MEMCPY(&gRfalAnalogConfig[gRfalAnalogConfigMgmt.configTblSize], (const uint8_t*)config, configSize); + + /* Increment the total size of configuration settings. */ + gRfalAnalogConfigMgmt.configTblSize += configSize; + + /* Check if it is the last Analog Configuration to load. */ + if (RFAL_ANALOG_CONFIG_UPDATE_LAST == more) + { /* Update the Analog Configuration to the new settings. */ + rfalAnalogConfigPtrUpdate(gRfalAnalogConfig); + } + + return ERR_NONE; + +#else + + // If Analog Configuration Update is to be disabled + NO_WARNING(config); + NO_WARNING(more); + return ERR_DISABLED; + +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + +} /* rfalAnalogConfigListUpdate() */ + +ReturnCode rfalAnalogConfigListReadRaw( uint8_t *tblBuf, uint16_t tblBufLen, uint16_t *configTblSize ) +{ + /* Check if the the current table will fit into the given buffer */ + if( tblBufLen < gRfalAnalogConfigMgmt.configTblSize ) + { + return ERR_NOMEM; + } + + /* Check for invalid parameters */ + if( configTblSize == NULL ) + { + return ERR_PARAM; + } + + /* Copy the whole Table to the given buffer */ + if( gRfalAnalogConfigMgmt.configTblSize > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( tblBuf, gRfalAnalogConfigMgmt.currentAnalogConfigTbl, gRfalAnalogConfigMgmt.configTblSize ); + } + *configTblSize = gRfalAnalogConfigMgmt.configTblSize; + + return ERR_NONE; +} + +ReturnCode rfalAnalogConfigListRead( rfalAnalogConfigOffset *configOffset, uint8_t *more, rfalAnalogConfig *config, rfalAnalogConfigNum numConfig ) +{ + uint16_t configSize; + rfalAnalogConfigOffset offset = *configOffset; + rfalAnalogConfigNum numConfigSet; + + /* Check if the number of register-mask-value settings for the respective Configuration ID will fit into the buffer passed in. */ + if (gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)] > numConfig) + { + return ERR_NOMEM; + } + + /* Get the number of Configuration set */ + numConfigSet = gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)]; + + /* Pass Configuration Register-Mask-Value sets */ + configSize = (sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal))); + ST_MEMCPY( (uint8_t*) config + , &gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset] + , configSize + ); + *configOffset = offset + configSize; + + /* Check if it is the last Analog Configuration in the Table.*/ + *more = (uint8_t)((*configOffset >= gRfalAnalogConfigMgmt.configTblSize) ? RFAL_ANALOG_CONFIG_UPDATE_LAST + : RFAL_ANALOG_CONFIG_UPDATE_MORE); + + return ERR_NONE; +} /* rfalAnalogConfigListRead() */ + + +ReturnCode rfalSetAnalogConfig( rfalAnalogConfigId configId ) +{ + rfalAnalogConfigOffset configOffset = 0; + rfalAnalogConfigNum numConfigSet; + rfalAnalogConfigRegAddrMaskVal *configTbl; + ReturnCode retCode = ERR_NONE; + rfalAnalogConfigNum i; + + if (true != gRfalAnalogConfigMgmt.ready) + { + return ERR_REQUEST; + } + + /* Search LUT for the specific Configuration ID. */ + while(true) + { + numConfigSet = rfalAnalogConfigSearch(configId, &configOffset); + if( RFAL_ANALOG_CONFIG_LUT_NOT_FOUND == numConfigSet ) + { + break; + } + + configTbl = (rfalAnalogConfigRegAddrMaskVal *)( (uint32_t)gRfalAnalogConfigMgmt.currentAnalogConfigTbl + (uint32_t)configOffset); + /* Increment the offset to the next index to search from. */ + configOffset += (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal)); + + if ((gRfalAnalogConfigMgmt.configTblSize + 1U) < configOffset) + { /* Error check make sure that the we do not access outside the configuration Table Size */ + return ERR_NOMEM; + } + + for ( i = 0; i < numConfigSet; i++) + { + if( (GETU16(configTbl[i].addr) & RFAL_TEST_REG) != 0U ) + { + EXIT_ON_ERR(retCode, rfalChipChangeTestRegBits( (GETU16(configTbl[i].addr) & ~RFAL_TEST_REG), configTbl[i].mask, configTbl[i].val) ); + } + else + { + EXIT_ON_ERR(retCode, rfalChipChangeRegBits( GETU16(configTbl[i].addr), configTbl[i].mask, configTbl[i].val) ); + } + } + + } /* while(found Analog Config Id) */ + + return retCode; + +} /* rfalSetAnalogConfig() */ + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +/*! + ***************************************************************************** + * \brief Update the link to Analog Configuration LUT + * + * Update the link to the Analog Configuration LUT for the subsequent search + * of Analog Settings. + * + * \param[in] analogConfigTbl: reference to the start of the new Analog Configuration Table + * + ***************************************************************************** + */ +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG +static void rfalAnalogConfigPtrUpdate( const uint8_t* analogConfigTbl ) +{ + + gRfalAnalogConfigMgmt.currentAnalogConfigTbl = analogConfigTbl; + gRfalAnalogConfigMgmt.ready = true; + +} /* rfalAnalogConfigPtrUpdate() */ +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + + +/*! + ***************************************************************************** + * \brief Search the Analog Configuration LUT for a specific Configuration ID. + * + * Search the Analog Configuration LUT for the Configuration ID. + * + * \param[in] configId: Configuration ID to search for. + * \param[in] configOffset: Configuration Offset in Table + * + * \return number of Configuration Sets + * \return #RFAL_ANALOG_CONFIG_LUT_NOT_FOUND in case Configuration ID is not found. + ***************************************************************************** + */ +static rfalAnalogConfigNum rfalAnalogConfigSearch( rfalAnalogConfigId configId, uint16_t *configOffset ) +{ + rfalAnalogConfigId foundConfigId; + rfalAnalogConfigId configIdMaskVal; + const uint8_t *configTbl; + const uint8_t *currentConfigTbl; + uint16_t i; + + currentConfigTbl = gRfalAnalogConfigMgmt.currentAnalogConfigTbl; + configIdMaskVal = ((RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_BITRATE_MASK) + |((RFAL_ANALOG_CONFIG_TECH_CHIP == RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) ? (RFAL_ANALOG_CONFIG_TECH_MASK | RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK) : configId) + |((RFAL_ANALOG_CONFIG_NO_DIRECTION == RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId)) ? RFAL_ANALOG_CONFIG_DIRECTION_MASK : configId) + ); + + i = *configOffset; + while (i < gRfalAnalogConfigMgmt.configTblSize) + { + configTbl = ¤tConfigTbl[i]; + foundConfigId = GETU16(configTbl); + if (configId == (foundConfigId & configIdMaskVal)) + { + *configOffset = (uint16_t)(i + sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum)); + return configTbl[sizeof(rfalAnalogConfigId)]; + } + + /* If Config Id does not match, increment to next Configuration Id */ + i += (uint16_t)( sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + + (configTbl[sizeof(rfalAnalogConfigId)] * sizeof(rfalAnalogConfigRegAddrMaskVal) ) + ); + } /* for */ + + return RFAL_ANALOG_CONFIG_LUT_NOT_FOUND; +} /* rfalAnalogConfigSearch() */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_crc.c b/Software/fab-reader2-c/components/rfal/Src/rfal_crc.c new file mode 100644 index 0000000..27384ff --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_crc.c @@ -0,0 +1,86 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_crc.c + * + * \author Oliver Regenfelder + * + * \brief CRC calculation implementation + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "rfal_crc.h" + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static uint16_t rfalCrcUpdateCcitt(uint16_t crcSeed, uint8_t dataByte); + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +uint16_t rfalCrcCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length) +{ + uint16_t crc = preloadValue; + uint16_t index; + + for (index = 0; index < length; index++) + { + crc = rfalCrcUpdateCcitt(crc, buf[index]); + } + + return crc; +} + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ +static uint16_t rfalCrcUpdateCcitt(uint16_t crcSeed, uint8_t dataByte) +{ + uint16_t crc = crcSeed; + uint8_t dat = dataByte; + + dat ^= (uint8_t)(crc & 0xFFU); + dat ^= (dat << 4); + + crc = (crc >> 8)^(((uint16_t) dat) << 8)^(((uint16_t) dat) << 3)^(((uint16_t) dat) >> 4); + + return crc; +} + diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_dpo.c b/Software/fab-reader2-c/components/rfal/Src/rfal_dpo.c new file mode 100644 index 0000000..95f3b5e --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_dpo.c @@ -0,0 +1,240 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_dpo.c + * + * \author Martin Zechleitner + * + * \brief Functions to manage and set dynamic power settings. + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_dpoTbl.h" +#include "rfal_dpo.h" +#include "platform.h" +#include "rfal_rf.h" +#include "rfal_chip.h" +#include "utils.h" + + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_DPO + #define RFAL_FEATURE_DPO false /* Dynamic Power Module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_DPO + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +static bool gRfalDpoIsEnabled = false; +static uint8_t* gRfalCurrentDpo; +static uint8_t gRfalDpoTableEntries; +static uint8_t gRfalDpo[RFAL_DPO_TABLE_SIZE_MAX]; +static uint8_t gRfalDpoTableEntry; +static rfalDpoMeasureFunc gRfalDpoMeasureCallback = NULL; + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ +void rfalDpoInitialize( void ) +{ + /* Use the default Dynamic Power values */ + gRfalCurrentDpo = (uint8_t*) rfalDpoDefaultSettings; + gRfalDpoTableEntries = (sizeof(rfalDpoDefaultSettings) / RFAL_DPO_TABLE_PARAMETER); + + ST_MEMCPY( gRfalDpo, gRfalCurrentDpo, sizeof(rfalDpoDefaultSettings) ); + + /* by default use amplitude measurement */ + gRfalDpoMeasureCallback = rfalChipMeasureAmplitude; + + /* by default DPO is disabled */ + gRfalDpoIsEnabled = false; + + gRfalDpoTableEntry = 0; +} + +void rfalDpoSetMeasureCallback( rfalDpoMeasureFunc pMeasureFunc ) +{ + gRfalDpoMeasureCallback = pMeasureFunc; +} + +/*******************************************************************************/ +ReturnCode rfalDpoTableWrite( rfalDpoEntry* powerTbl, uint8_t powerTblEntries ) +{ + uint8_t entry = 0; + + /* check if the table size parameter is too big */ + if( (powerTblEntries * RFAL_DPO_TABLE_PARAMETER) > RFAL_DPO_TABLE_SIZE_MAX) + { + return ERR_NOMEM; + } + + /* check if the first increase entry is 0xFF */ + if( (powerTblEntries == 0) || (powerTbl == NULL) ) + { + return ERR_PARAM; + } + + /* check if the entries of the dynamic power table are valid */ + for (entry = 0; entry < powerTblEntries; entry++) + { + if(powerTbl[entry].inc < powerTbl[entry].dec) + { + return ERR_PARAM; + } + } + + /* copy the data set */ + ST_MEMCPY( gRfalDpo, powerTbl, (powerTblEntries * RFAL_DPO_TABLE_PARAMETER) ); + gRfalCurrentDpo = gRfalDpo; + gRfalDpoTableEntries = powerTblEntries; + + if(gRfalDpoTableEntry > powerTblEntries) + { + /* is always greater then zero, otherwise we already returned ERR_PARAM */ + gRfalDpoTableEntry = (powerTblEntries - 1); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalDpoTableRead( rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries ) +{ + /* wrong request */ + if( (tblBuf == NULL) || (tblBufEntries < gRfalDpoTableEntries) || (tableEntries == NULL) ) + { + return ERR_PARAM; + } + + /* Copy the whole Table to the given buffer */ + ST_MEMCPY( tblBuf, gRfalCurrentDpo, (tblBufEntries * RFAL_DPO_TABLE_PARAMETER) ); + *tableEntries = gRfalDpoTableEntries; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalDpoAdjust( void ) +{ + uint8_t refValue = 0; + rfalDpoEntry* dpoTable = (rfalDpoEntry*) gRfalCurrentDpo; + + /* Check if the Power Adjustment is disabled and * + * if the callback to the measurement method is properly set */ + if( (gRfalCurrentDpo == NULL) || (!gRfalDpoIsEnabled) || (gRfalDpoMeasureCallback == NULL) ) + { + return ERR_PARAM; + } + + /* Ensure that the current mode is Passive Poller */ + if( !rfalIsModePassivePoll( rfalGetMode() ) ) + { + return ERR_WRONG_STATE; + } + + /* Ensure a proper measure reference value */ + if( ERR_NONE != gRfalDpoMeasureCallback( &refValue ) ) + { + return ERR_IO; + } + + + /* Increase the output power */ + if( refValue >= dpoTable[gRfalDpoTableEntry].inc ) + { + /* the top of the table represents the highest amplitude value*/ + if( gRfalDpoTableEntry == 0 ) + { + /* check if the maximum driver value has been reached */ + return ERR_NONE; + } + /* go up in the table to decrease the driver resistance */ + gRfalDpoTableEntry--; + } + else + { + /* decrease the output power */ + if(refValue <= dpoTable[gRfalDpoTableEntry].dec) + { + /* The bottom is the highest possible value */ + if( (gRfalDpoTableEntry + 1) >= gRfalDpoTableEntries) + { + /* check if the minimum driver value has been reached */ + return ERR_NONE; + } + /* go down in the table to increase the driver resistance */ + gRfalDpoTableEntry++; + } + else + { + /* do not write the driver again with the same value */ + } + } + + /* get the new value for RFO resistance form the table and apply the new RFO resistance setting */ + rfalChipSetRFO( dpoTable[gRfalDpoTableEntry].rfoRes ); + return ERR_NONE; +} + +/*******************************************************************************/ +rfalDpoEntry* rfalDpoGetCurrentTableEntry( void ) +{ + rfalDpoEntry* dpoTable = (rfalDpoEntry*) gRfalCurrentDpo; + return &dpoTable[gRfalDpoTableEntry]; +} + +/*******************************************************************************/ +void rfalDpoSetEnabled( bool enable ) +{ + gRfalDpoIsEnabled = enable; +} + +/*******************************************************************************/ +bool rfalDpoIsEnabled( void ) +{ + return gRfalDpoIsEnabled; +} + +#endif /* RFAL_FEATURE_DPO */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_iso15693_2.c b/Software/fab-reader2-c/components/rfal/Src/rfal_iso15693_2.c new file mode 100644 index 0000000..94ea414 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_iso15693_2.c @@ -0,0 +1,534 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_iso15693_2.c + * + * \author Ulrich Herrmann + * + * \brief Implementation of ISO-15693-2 + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "rfal_iso15693_2.h" +#include "rfal_crc.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCV + #define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCV + +/* +****************************************************************************** +* LOCAL MACROS +****************************************************************************** +*/ + +//#define ISO_15693_DEBUG dbgLog +#define ISO_15693_DEBUG(...) /*!< Macro for the log method */ + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ +#define ISO15693_DAT_SOF_1_4 0x21 /* LSB constants */ +#define ISO15693_DAT_EOF_1_4 0x04 +#define ISO15693_DAT_00_1_4 0x02 +#define ISO15693_DAT_01_1_4 0x08 +#define ISO15693_DAT_10_1_4 0x20 +#define ISO15693_DAT_11_1_4 0x80 + +#define ISO15693_DAT_SOF_1_256 0x81 +#define ISO15693_DAT_EOF_1_256 0x04 +#define ISO15693_DAT_SLOT0_1_256 0x02 +#define ISO15693_DAT_SLOT1_1_256 0x08 +#define ISO15693_DAT_SLOT2_1_256 0x20 +#define ISO15693_DAT_SLOT3_1_256 0x80 + +#define ISO15693_PHY_DAT_MANCHESTER_1 0xaaaa + +#define ISO15693_PHY_BIT_BUFFER_SIZE 1000 /*!< size of the receiving buffer. Might be adjusted if longer datastreams are expected. */ + + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ +static iso15693PhyConfig_t iso15693PhyConfig; /*!< current phy configuration */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen); +static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen); + + + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +ReturnCode iso15693PhyConfigure(const iso15693PhyConfig_t* config, const struct iso15693StreamConfig ** needed_stream_config ) +{ + static struct iso15693StreamConfig stream_config = { /* MISRA 8.9 */ + .useBPSK = 0, /* 0: subcarrier, 1:BPSK */ + .din = 5, /* 2^5*fc = 423750 Hz: divider for the in subcarrier frequency */ + .dout = 7, /*!< 2^7*fc = 105937 : divider for the in subcarrier frequency */ + .report_period_length = 3, /*!< 8=2^3 the length of the reporting period */ + }; + + + /* make a copy of the configuration */ + ST_MEMCPY( (uint8_t*)&iso15693PhyConfig, (const uint8_t*)config, sizeof(iso15693PhyConfig_t)); + + if ( config->speedMode <= 3U) + { /* If valid speed mode adjust report period accordingly */ + stream_config.report_period_length = (3U - (uint8_t)config->speedMode); + } + else + { /* If invalid default to normal (high) speed */ + stream_config.report_period_length = 3; + } + + *needed_stream_config = &stream_config; + + return ERR_NONE; +} + +ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config) +{ + ST_MEMCPY(config, &iso15693PhyConfig, sizeof(iso15693PhyConfig_t)); + + return ERR_NONE; +} + +ReturnCode iso15693VCDCode(uint8_t* buffer, uint16_t length, bool sendCrc, bool sendFlags, bool picopassMode, + uint16_t *subbit_total_length, uint16_t *offset, + uint8_t* outbuf, uint16_t outBufSize, uint16_t* actOutBufSize) +{ + ReturnCode err = ERR_NONE; + uint8_t eof, sof; + uint8_t transbuf[2]; + uint16_t crc = 0; + ReturnCode (*txFunc)(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen); + uint8_t crc_len; + uint8_t* outputBuf; + uint16_t outputBufSize; + + crc_len = (uint8_t)((sendCrc)?2:0); + + *actOutBufSize = 0; + + if (ISO15693_VCD_CODING_1_4 == iso15693PhyConfig.coding) + { + sof = ISO15693_DAT_SOF_1_4; + eof = ISO15693_DAT_EOF_1_4; + txFunc = iso15693PhyVCDCode1Of4; + *subbit_total_length = ( + ( 1U /* SOF */ + + ((length + (uint16_t)crc_len) * 4U) + + 1U) /* EOF */ + ); + if (outBufSize < 5U) { /* 5 should be safe: enough for sof + 1byte data in 1of4 */ + return ERR_NOMEM; + } + } + else + { + sof = ISO15693_DAT_SOF_1_256; + eof = ISO15693_DAT_EOF_1_256; + txFunc = iso15693PhyVCDCode1Of256; + *subbit_total_length = ( + ( 1U /* SOF */ + + ((length + (uint16_t)crc_len) * 64U) + + 1U) /* EOF */ + ); + + if (*offset != 0U) + { + if (outBufSize < 64U) { /* 64 should be safe: enough a single byte data in 1of256 */ + return ERR_NOMEM; + } + } + else + { + if (outBufSize < 65U) { /* At beginning of a frame we need at least 65 bytes to start: enough for sof + 1byte data in 1of256 */ + return ERR_NOMEM; + } + } + } + + if (length == 0U) + { + *subbit_total_length = 1; + } + + if ((length != 0U) && (0U == *offset) && sendFlags && !picopassMode) + { + /* set high datarate flag */ + buffer[0] |= (uint8_t)ISO15693_REQ_FLAG_HIGH_DATARATE; + /* clear sub-carrier flag - we only support single sub-carrier */ + buffer[0] = (uint8_t)(buffer[0] & ~ISO15693_REQ_FLAG_TWO_SUBCARRIERS); /* MISRA 10.3 */ + } + + outputBuf = outbuf; /* MISRA 17.8: Use intermediate variable */ + outputBufSize = outBufSize; /* MISRA 17.8: Use intermediate variable */ + + /* Send SOF if at 0 offset */ + if ((length != 0U) && (0U == *offset)) + { + *outputBuf = sof; + (*actOutBufSize)++; + outputBufSize--; + outputBuf++; + } + + while ((*offset < length) && (err == ERR_NONE)) + { + uint16_t filled_size; + /* send data */ + err = txFunc(buffer[*offset], outputBuf, outputBufSize, &filled_size); + (*actOutBufSize) += filled_size; + outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */ + outputBufSize -= filled_size; + if (err == ERR_NONE) { + (*offset)++; + } + } + if (err != ERR_NONE) { + return ERR_AGAIN; + } + + while ((err == ERR_NONE) && sendCrc && (*offset < (length + 2U))) + { + uint16_t filled_size; + if (0U==crc) + { + crc = rfalCrcCalculateCcitt( (uint16_t) ((picopassMode) ? 0xE012U : 0xFFFFU), /* In PicoPass Mode a different Preset Value is used */ + ((picopassMode) ? (buffer + 1U) : buffer), /* CMD byte is not taken into account in PicoPass mode */ + ((picopassMode) ? (length - 1U) : length)); /* CMD byte is not taken into account in PicoPass mode */ + + crc = (uint16_t)((picopassMode) ? crc : ~crc); + } + /* send crc */ + transbuf[0] = (uint8_t)(crc & 0xffU); + transbuf[1] = (uint8_t)((crc >> 8) & 0xffU); + err = txFunc(transbuf[*offset - length], outputBuf, outputBufSize, &filled_size); + (*actOutBufSize) += filled_size; + outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */ + outputBufSize -= filled_size; + if (err == ERR_NONE) { + (*offset)++; + } + } + if (err != ERR_NONE) { + return ERR_AGAIN; + } + + if ((!sendCrc && (*offset == length)) + || (sendCrc && (*offset == (length + 2U)))) + { + *outputBuf = eof; + (*actOutBufSize)++; + outputBufSize--; + outputBuf++; + } + else + { + return ERR_AGAIN; + } + + return err; +} + +ReturnCode iso15693VICCDecode(const uint8_t *inBuf, + uint16_t inBufLen, + uint8_t* outBuf, + uint16_t outBufLen, + uint16_t* outBufPos, + uint16_t* bitsBeforeCol, + uint16_t ignoreBits, + bool picopassMode ) +{ + ReturnCode err = ERR_NONE; + uint16_t crc; + uint16_t mp; /* Current bit position in manchester bit inBuf*/ + uint16_t bp; /* Current bit position in outBuf */ + + *bitsBeforeCol = 0; + *outBufPos = 0; + + /* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */ + if ((inBuf[0] & 0x1fU) != 0x17U) + { + ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]); + return ERR_FRAMING; + } + ISO_15693_DEBUG("SOF\n"); + + if (outBufLen == 0U) + { + return ERR_NONE; + } + + mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */ + bp = 0; + + ST_MEMSET(outBuf,0,outBufLen); + + if (inBufLen == 0U) + { + return ERR_CRC; + } + + for ( ; mp < ((inBufLen * 8U) - 2U); mp+=2U ) + { + bool isEOF = false; + + uint8_t man; + man = (inBuf[mp/8U] >> (mp%8U)) & 0x1U; + man |= ((inBuf[(mp+1U)/8U] >> ((mp+1U)%8U)) & 0x1U) << 1; + if (1U == man) + { + bp++; + } + if (2U == man) + { + outBuf[bp/8U] = (uint8_t)(outBuf[bp/8U] | (1U <<(bp%8U))); /* MISRA 10.3 */ + bp++; + } + if ((bp%8U) == 0U) + { /* Check for EOF */ + ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp/8U], inBuf[mp/8+1]); + if ( ((inBuf[mp/8U] & 0xe0U) == 0xa0U) + &&(inBuf[(mp/8U)+1U] == 0x03U)) + { /* Now we know that it was 10111000 = EOF */ + ISO_15693_DEBUG("EOF\n"); + isEOF = true; + } + } + if ( ((0U == man) || (3U == man)) && !isEOF ) + { + if (bp >= ignoreBits) + { + err = ERR_RF_COLLISION; + } + else + { + /* ignored collision: leave as 0 */ + bp++; + } + } + if ( (bp >= (outBufLen * 8U)) || (err == ERR_RF_COLLISION) || isEOF ) + { /* Don't write beyond the end */ + break; + } + } + + *outBufPos = (bp / 8U); + *bitsBeforeCol = bp; + + if (err != ERR_NONE) + { + return err; + } + + if ((bp%8U) != 0U) + { + return ERR_CRC; + } + + if (*outBufPos > 2U) + { + /* finally, check crc */ + ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf); + ISO_15693_DEBUG("0x%x ", *outBufPos - 2); + + crc = rfalCrcCalculateCcitt(((picopassMode) ? 0xE012U : 0xFFFFU), outBuf, *outBufPos - 2U); + crc = (uint16_t)((picopassMode) ? crc : ~crc); + + if (((crc & 0xffU) == outBuf[*outBufPos-2U]) && + (((crc >> 8U) & 0xffU) == outBuf[*outBufPos-1U])) + { + err = ERR_NONE; + ISO_15693_DEBUG("OK\n"); + } + else + { + ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc); + ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos-2], outBuf[*outBufPos-1]); + err = ERR_CRC; + } + } + else + { + err = ERR_CRC; + } + + return err; +} + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Perform 1 of 4 coding and send coded data + * + * This function takes \a length bytes from \a buffer, perform 1 of 4 coding + * (see ISO15693-2 specification) and sends the data using stream mode. + * + * \param[in] sendSof : send SOF prior to data. + * \param[in] buffer : data to send. + * \param[in] length : number of bytes to send. + * + * \return ERR_IO : Error during communication. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen) +{ + uint8_t tmp; + ReturnCode err = ERR_NONE; + uint16_t a; + uint8_t* outbuf = outbuffer; + + *outBufLen = 0; + + if (maxOutBufLen < 4U) { + return ERR_NOMEM; + } + + tmp = data; + for (a = 0; a < 4U; a++) + { + switch (tmp & 0x3U) + { + case 0: + *outbuf = ISO15693_DAT_00_1_4; + break; + case 1: + *outbuf = ISO15693_DAT_01_1_4; + break; + case 2: + *outbuf = ISO15693_DAT_10_1_4; + break; + case 3: + *outbuf = ISO15693_DAT_11_1_4; + break; + default: + /* MISRA 16.4: mandatory default statement */ + break; + } + outbuf++; + (*outBufLen)++; + tmp >>= 2; + } + return err; +} + +/*! + ***************************************************************************** + * \brief Perform 1 of 256 coding and send coded data + * + * This function takes \a length bytes from \a buffer, perform 1 of 256 coding + * (see ISO15693-2 specification) and sends the data using stream mode. + * \note This function sends SOF prior to the data. + * + * \param[in] sendSof : send SOF prior to data. + * \param[in] buffer : data to send. + * \param[in] length : number of bytes to send. + * + * \return ERR_IO : Error during communication. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen) +{ + uint8_t tmp; + ReturnCode err = ERR_NONE; + uint16_t a; + uint8_t* outbuf = outbuffer; + + *outBufLen = 0; + + if (maxOutBufLen < 64U) { + return ERR_NOMEM; + } + + tmp = data; + for (a = 0; a < 64U; a++) + { + switch (tmp) + { + case 0: + *outbuf = ISO15693_DAT_SLOT0_1_256; + break; + case 1: + *outbuf = ISO15693_DAT_SLOT1_1_256; + break; + case 2: + *outbuf = ISO15693_DAT_SLOT2_1_256; + break; + case 3: + *outbuf = ISO15693_DAT_SLOT3_1_256; + break; + default: + *outbuf = 0; + break; + } + outbuf++; + (*outBufLen)++; + tmp -= 4U; + } + + return err; +} + +#endif /* RFAL_FEATURE_NFCV */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_isoDep.c b/Software/fab-reader2-c/components/rfal/Src/rfal_isoDep.c new file mode 100644 index 0000000..2048841 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_isoDep.c @@ -0,0 +1,2552 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: NFCC firmware + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_isoDep.c + * + * \author Gustavo Patricio + * + * \brief Implementation of ISO-DEP protocol + * + * This implementation was based on the following specs: + * - ISO/IEC 14443-4 2nd Edition 2008-07-15 + * - NFC Forum Digital Protocol 1.1 2014-01-14 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ + +#include "rfal_isoDep.h" +#include "rfal_rf.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_ISO_DEP + #define RFAL_FEATURE_ISO_DEP false /* ISO-DEP module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_ISO_DEP + +#if ( !RFAL_FEATURE_ISO_DEP_POLL && !RFAL_FEATURE_ISO_DEP_LISTEN ) + #error " RFAL: Invalid ISO-DEP Configuration. Please select at least one mode: Poller and/or Listener. " +#endif + +/* Check for valid I-Block length [RFAL_ISODEP_FSX_16 ; RFAL_ISODEP_FSX_4096]*/ +#if( (RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN > 4096 ) || (RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN < 16) ) + #error " RFAL: Invalid ISO-DEP IBlock Max length. Please change RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN. " +#endif + +/* Check for valid APDU length, It must be n*IBlock */ +#if( (RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN < RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN) || (RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN % RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN) ) + #error " RFAL: Invalid ISO-DEP APDU Max length. Please change RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN. " +#endif + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define ISODEP_CRC_LEN RFAL_CRC_LEN /*!< ISO1443 CRC Length */ + + +#define ISODEP_PCB_POS (0U) /*!< PCB position on message header*/ +#define ISODEP_SWTX_INF_POS (1U) /*!< INF position in a S-WTX */ + +#define ISODEP_DID_POS (1U) /*!< DID position on message header*/ +#define ISODEP_SWTX_PARAM_LEN (1U) /*!< SWTX parameter length */ + +#define ISODEP_DSL_MAX_LEN ( RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN ) /*!< Deselect Req/Res length */ + +#define ISODEP_PCB_xBLOCK_MASK (0xC0U) /*!< Bit mask for Block type */ +#define ISODEP_PCB_IBLOCK (0x00U) /*!< Bit mask indicating a I-Block */ +#define ISODEP_PCB_RBLOCK (0x80U) /*!< Bit mask indicating a R-Block */ +#define ISODEP_PCB_SBLOCK (0xC0U) /*!< Bit mask indicating a S-Block */ +#define ISODEP_PCB_INVALID (0x40U) /*!< Bit mask of an Invalid PCB */ + +#define ISODEP_HDR_MAX_LEN (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN + RFAL_ISODEP_NAD_LEN) /*!< Max header length (PCB + DID + NAD) */ + +#define ISODEP_PCB_IB_VALID_MASK (ISODEP_PCB_B6_BIT | ISODEP_PCB_B2_BIT) /*!< Bit mask for the MUST bits on I-Block */ +#define ISODEP_PCB_IB_VALID_VAL (ISODEP_PCB_B2_BIT) /*!< Value for the MUST bits on I-Block */ +#define ISODEP_PCB_RB_VALID_MASK (ISODEP_PCB_B6_BIT | ISODEP_PCB_B3_BIT | ISODEP_PCB_B2_BIT) /*!< Bit mask for the MUST bits on R-Block */ +#define ISODEP_PCB_RB_VALID_VAL (ISODEP_PCB_B6_BIT | ISODEP_PCB_B2_BIT) /*!< Value for the MUST bits on R-Block */ +#define ISODEP_PCB_SB_VALID_MASK (ISODEP_PCB_B3_BIT | ISODEP_PCB_B2_BIT | ISODEP_PCB_B1_BIT) /*!< Bit mask for the MUST bits on I-Block */ +#define ISODEP_PCB_SB_VALID_VAL (ISODEP_PCB_B2_BIT) /*!< Value for the MUST bits on I-Block */ + + +#define ISODEP_PCB_B1_BIT (0x01U) /*!< Bit mask for the RFU S Blocks */ +#define ISODEP_PCB_B2_BIT (0x02U) /*!< Bit mask for the RFU bit2 in I,S,R Blocks */ +#define ISODEP_PCB_B3_BIT (0x04U) /*!< Bit mask for the RFU bit3 in R Blocks */ +#define ISODEP_PCB_B6_BIT (0x20U) /*!< Bit mask for the RFU bit2 in R Blocks */ +#define ISODEP_PCB_CHAINING_BIT (0x10U) /*!< Bit mask for the chaining bit of an ISO DEP I-Block in PCB. */ +#define ISODEP_PCB_DID_BIT (0x08U) /*!< Bit mask for the DID presence bit of an ISO DEP I,S,R Blocks PCB. */ +#define ISODEP_PCB_NAD_BIT (0x04U) /*!< Bit mask for the NAD presence bit of an ISO DEP I,S,R Blocks in PCB */ +#define ISODEP_PCB_BN_MASK (0x01U) /*!< Bit mask for the block number of an ISO DEP I,R Block in PCB */ + +#define ISODEP_SWTX_PL_MASK (0xC0U) /*!< Bit mask for the Power Level bits of the inf byte of an WTX request or response */ +#define ISODEP_SWTX_WTXM_MASK (0x3FU) /*!< Bit mask for the WTXM bits of the inf byte of an WTX request or response */ + + +#define ISODEP_RBLOCK_INF_LEN (0U) /*!< INF length of R-Block Digital 1.1 15.1.3 */ +#define ISODEP_SDSL_INF_LEN (0U) /*!< INF length of S(DSL) Digital 1.1 15.1.3 */ +#define ISODEP_SWTX_INF_LEN (1U) /*!< INF length of S(WTX) Digital 1.1 15.2.2 */ + +#define ISODEP_WTXM_MIN (1U) /*!< Minimum allowed value for the WTXM, Digital 1.0 13.2.2 */ +#define ISODEP_WTXM_MAX (59U) /*!< Maximum allowed value for the WTXM, Digital 1.0 13.2.2 */ + +#define ISODEP_PCB_Sxx_MASK (0x30U) /*!< Bit mask for the S-Block type */ +#define ISODEP_PCB_DESELECT (0x00U) /*!< Bit mask for S-Block indicating Deselect */ +#define ISODEP_PCB_WTX (0x30U) /*!< Bit mask for S-Block indicating Waiting Time eXtension */ + +#define ISODEP_PCB_Rx_MASK (0x10U) /*!< Bit mask for the R-Block type */ +#define ISODEP_PCB_ACK (0x00U) /*!< Bit mask for R-Block indicating ACK */ +#define ISODEP_PCB_NAK (0x10U) /*!< Bit mask for R-Block indicating NAK */ + +/*! Maximum length of control message (no INF) */ +#define ISODEP_CONTROLMSG_BUF_LEN (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN + RFAL_ISODEP_NAD_LEN + ISODEP_SWTX_PARAM_LEN) + +#define ISODEP_FWT_DEACTIVATION (71680U) /*!< FWT to be used after DESELECT, Digital 1.0 A9 */ +#define ISODEP_MAX_RERUNS (0x0FFFFFFFU)/*!< Maximum rerun retrys for a blocking protocol run*/ + + +#define ISODEP_PCBSBLOCK ( 0x00U | ISODEP_PCB_SBLOCK | ISODEP_PCB_B2_BIT ) /*!< PCB Value of a S-Block */ +#define ISODEP_PCB_SDSL ( ISODEP_PCBSBLOCK | ISODEP_PCB_DESELECT ) /*!< PCB Value of a S-Block with DESELECT */ +#define ISODEP_PCB_SWTX ( ISODEP_PCBSBLOCK | ISODEP_PCB_WTX ) /*!< PCB Value of a S-Block with WTX */ +#define ISODEP_PCB_SPARAMETERS ( ISODEP_PCB_SBLOCK | ISODEP_PCB_WTX ) /*!< PCB Value of a S-Block with PARAMETERS */ + +#define ISODEP_FWI_LIS_MAX_NFC 8U /*!< FWT Listener Max FWIT4ATmax FWIBmax Digital 1.1 A6 & A3 */ +#define ISODEP_FWI_LIS_MAX_EMVCO 7U /*!< FWT Listener Max FWIMAX EMVCo 2.6 A.5 */ +#define ISODEP_FWI_LIS_MAX (uint8_t)((gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) ? ISODEP_FWI_LIS_MAX_EMVCO : ISODEP_FWI_LIS_MAX_NFC) /*!< FWI Listener Max as NFC / EMVCo */ +#define ISODEP_FWT_LIS_MAX rfalIsoDepFWI2FWT(ISODEP_FWI_LIS_MAX) /*!< FWT Listener Max */ + +#define ISODEP_FWI_MIN_10 (1U) /*!< Minimum value for FWI Digital 1.0 11.6.2.17 */ +#define ISODEP_FWI_MIN_11 (0U) /*!< Default value for FWI Digital 1.1 13.6.2 */ +#define ISODEP_FWI_MAX (14U) /*!< Maximum value for FWI Digital 1.0 11.6.2.17 */ +#define ISODEP_SFGI_MIN (0U) /*!< Default value for FWI Digital 1.1 13.6.2.22 */ +#define ISODEP_SFGI_MAX (14U) /*!< Maximum value for FWI Digital 1.1 13.6.2.22 */ + + +#define RFAL_ISODEP_SPARAM_TVL_HDR_LEN (2U) /*!< S(PARAMETERS) TVL header length: Tag + Len */ +#define RFAL_ISODEP_SPARAM_HDR_LEN (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_SPARAM_TVL_HDR_LEN) /*!< S(PARAMETERS) header length: PCB + Tag + Len */ + + +/**********************************************************************************************************************/ +/**********************************************************************************************************************/ +#define RFAL_ISODEP_NO_PARAM (0U) /*!< No parameter flag for isoDepHandleControlMsg() */ + +#define RFAL_ISODEP_CMD_RATS (0xE0U) /*!< RATS command Digital 1.1 13.6.1 */ + +#define RFAL_ISODEP_ATS_MIN_LEN (1U) /*!< Minimum ATS length Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_HDR_LEN (5U) /*!< ATS headerlength Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_MAX_LEN (RFAL_ISODEP_ATS_HDR_LEN + RFAL_ISODEP_ATS_HB_MAX_LEN) /*!< Maximum ATS length Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_T0_FSCI_MASK (0x0FU) /*!< ATS T0's FSCI mask Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_TB_FWI_SHIFT (4U) /*!< ATS TB's FWI shift Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_FWI_MASK (0x0FU) /*!< ATS TB's FWI shift Digital 1.1 13.6.2 */ + + +#define RFAL_ISODEP_PPS_SB (0xD0U) /*!< PPS REQ PPSS's SB value (no CID) ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_MASK (0xF0U) /*!< PPS REQ PPSS's SB mask ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_SB_DID_MASK (0x0FU) /*!< PPS REQ PPSS's DID|CID mask ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_PPS0_PPS1_PRESENT (0x11U) /*!< PPS REQ PPS0 indicating that PPS1 is present */ +#define RFAL_ISODEP_PPS_PPS1 (0x00U) /*!< PPS REQ PPS1 fixed value ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_PPS1_DSI_SHIFT (2U) /*!< PPS REQ PPS1 fixed value ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_PPS1_DXI_MASK (0x0FU) /*!< PPS REQ PPS1 fixed value ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_RES_LEN (1U) /*!< PPS Response length ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS_STARTBYTE_POS (0U) /*!< PPS REQ PPSS's byte position ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS_PPS0_POS (1U) /*!< PPS REQ PPS0's byte position ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS_PPS1_POS (2U) /*!< PPS REQ PPS1's byte position ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS0_VALID_MASK (0xEFU) /*!< PPS REQ PPS0 valid coding mask ISO14443-4 5.4 */ + +#define RFAL_ISODEP_CMD_ATTRIB (0x1DU) /*!< ATTRIB command Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_DSI_SHIFT (6U) /*!< ATTRIB PARAM2 DSI shift Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_DRI_SHIFT (4U) /*!< ATTRIB PARAM2 DRI shift Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_DXI_MASK (0xF0U) /*!< ATTRIB PARAM2 DxI mask Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_FSDI_MASK (0x0FU) /*!< ATTRIB PARAM2 FSDI mask Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM4_DID_MASK (0x0FU) /*!< ATTRIB PARAM4 DID mask Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_HDR_LEN (9U) /*!< ATTRIB REQ header length Digital 1.1 14.6.1 */ + +#define RFAL_ISODEP_ATTRIB_RES_HDR_LEN (1U) /*!< ATTRIB RES header length Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_DID_MASK (0x0FU) /*!< ATTRIB RES DID mask Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_MBLI_MASK (0x0FU) /*!< ATTRIB RES MBLI mask Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_MBLI_SHIFT (4U) /*!< ATTRIB RES MBLI shift Digital 1.1 14.6.2 */ + +#define RFAL_ISODEP_DID_MASK (0x0FU) /*!< ISODEP's DID mask */ +#define RFAL_ISODEP_DID_00 (0U) /*!< ISODEP's DID value 0 */ + +#define RFAL_ISODEP_FSDI_MAX_NFC (8U) /*!< Max FSDI value Digital 2.0 14.6.1.9 & B7 & B8 */ +#define RFAL_ISODEP_FSDI_MAX_EMV (0x0CU) /*!< Max FSDI value EMVCo 3.0 5.7.2.5 */ + +#define RFAL_ISODEP_RATS_PARAM_FSDI_MASK (0xF0U) /*!< Mask bits for FSDI in RATS */ +#define RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT (4U) /*!< Shift for FSDI in RATS */ +#define RFAL_ISODEP_RATS_PARAM_DID_MASK (0x0FU) /*!< Mask bits for DID in RATS */ + +#define RFAL_ISODEP_ATS_TL_OFFSET (0x00U) /*!< Offset of TL on ATS */ +#define RFAL_ISODEP_ATS_TA_OFFSET (0x02U) /*!< Offset of TA if it is present on ATS */ +#define RFAL_ISODEP_ATS_TB_OFFSET (0x03U) /*!< Offset of TB if both TA and TB is present on ATS */ +#define RFAL_ISODEP_ATS_TC_OFFSET (0x04U) /*!< Offset of TC if both TA,TB & TC are present on ATS */ +#define RFAL_ISODEP_ATS_HIST_OFFSET (0x05U) /*!< Offset of Historical Bytes if TA, TB & TC are present on ATS */ +#define RFAL_ISODEP_ATS_TC_ADV_FEAT (0x10U) /*!< Bit mask indicating support for Advanced protocol features: DID & NAD */ +#define RFAL_ISODEP_ATS_TC_DID (0x02U) /*!< Bit mask indicating support for DID */ +#define RFAL_ISODEP_ATS_TC_NAD (0x01U) /*!< Bit mask indicating support for NAD */ + +#define RFAL_ISODEP_PPS0_PPS1_PRESENT (0x11U) /*!< PPS0 byte indicating that PPS1 is present */ +#define RFAL_ISODEP_PPS0_PPS1_NOT_PRESENT (0x01U) /*!< PPS0 byte indicating that PPS1 is NOT present */ +#define RFAL_ISODEP_PPS1_DRI_MASK (0x03U) /*!< PPS1 byte DRI mask bits */ +#define RFAL_ISODEP_PPS1_DSI_MASK (0x0CU) /*!< PPS1 byte DSI mask bits */ +#define RFAL_ISODEP_PPS1_DSI_SHIFT (2U) /*!< PPS1 byte DSI shift */ +#define RFAL_ISODEP_PPS1_DxI_MASK (0x03U) /*!< PPS1 byte DSI/DRS mask bits */ + + +/*! Delta Time for polling during Activation (ATS) : 20ms Digital 1.0 11.7.1.1 & A.7 */ +#define RFAL_ISODEP_T4T_DTIME_POLL_10 rfalConvMsTo1fc(20) + +/*! Delta Time for polling during Activation (ATS) : 16.4ms Digital 1.1 13.8.1.1 & A.6 + * Use 16 ms as testcase T4AT_BI_10_03 sends a frame exactly at the border */ +#define RFAL_ISODEP_T4T_DTIME_POLL_11 216960U + +/*! Activation frame waiting time FWT(act) = 71680/fc (~5286us) Digital 1.1 13.8.1.1 & A.6 */ +#define RFAL_ISODEP_T4T_FWT_ACTIVATION (71680U + RFAL_ISODEP_T4T_DTIME_POLL_11) + + +/*! Delta frame waiting time = 16/fc Digital 1.0 11.7.1.3 & A.7*/ +#define RFAL_ISODEP_DFWT_10 16U + +/*! Delta frame waiting time = 16/fc Digital 2.0 14.8.1.3 & B.7*/ +#define RFAL_ISODEP_DFWT_20 49152U + +/* + ****************************************************************************** + * MACROS + ****************************************************************************** + */ + +#define isoDep_PCBisIBlock( pcb ) ( ((pcb) & (ISODEP_PCB_xBLOCK_MASK | ISODEP_PCB_IB_VALID_MASK)) == (ISODEP_PCB_IBLOCK | ISODEP_PCB_IB_VALID_VAL)) /*!< Checks if pcb is a I-Block */ +#define isoDep_PCBisRBlock( pcb ) ( ((pcb) & (ISODEP_PCB_xBLOCK_MASK | ISODEP_PCB_RB_VALID_MASK)) == (ISODEP_PCB_RBLOCK | ISODEP_PCB_RB_VALID_VAL)) /*!< Checks if pcb is a R-Block */ +#define isoDep_PCBisSBlock( pcb ) ( ((pcb) & (ISODEP_PCB_xBLOCK_MASK | ISODEP_PCB_SB_VALID_MASK)) == (ISODEP_PCB_SBLOCK | ISODEP_PCB_SB_VALID_VAL)) /*!< Checks if pcb is a S-Block */ + +#define isoDep_PCBisChaining( pcb ) ( ((pcb) & ISODEP_PCB_CHAINING_BIT) == ISODEP_PCB_CHAINING_BIT) /*!< Checks if pcb is indicating chaining */ + +#define isoDep_PCBisDeselect( pcb ) ( ((pcb) & ISODEP_PCB_Sxx_MASK) == ISODEP_PCB_DESELECT) /*!< Checks if pcb is indicating DESELECT */ +#define isoDep_PCBisWTX( pcb ) ( ((pcb) & ISODEP_PCB_Sxx_MASK) == ISODEP_PCB_WTX) /*!< Checks if pcb is indicating WTX */ + +#define isoDep_PCBisACK( pcb ) ( ((pcb) & ISODEP_PCB_Rx_MASK) == ISODEP_PCB_ACK) /*!< Checks if pcb is indicating ACK */ +#define isoDep_PCBisNAK( pcb ) ( ((pcb) & ISODEP_PCB_Rx_MASK) == ISODEP_PCB_NAK) /*!< Checks if pcb is indicating ACK */ + +#define isoDep_PCBhasDID( pcb ) ( ((pcb) & ISODEP_PCB_DID_BIT) == ISODEP_PCB_DID_BIT) /*!< Checks if pcb is indicating DID */ +#define isoDep_PCBhasNAD( pcb ) ( ((pcb) & ISODEP_PCB_NAD_BIT) == ISODEP_PCB_NAD_BIT) /*!< Checks if pcb is indicating NAD */ + + +#define isoDep_PCBisIChaining( pcb ) ( isoDep_PCBisIBlock(pcb) && isoDep_PCBisChaining(pcb) ) /*!< Checks if pcb is I-Block indicating chaining*/ + +#define isoDep_PCBisSDeselect( pcb ) ( isoDep_PCBisSBlock(pcb) && isoDep_PCBisDeselect(pcb) ) /*!< Checks if pcb is S-Block indicating DESELECT*/ +#define isoDep_PCBisSWTX( pcb ) ( isoDep_PCBisSBlock(pcb) && isoDep_PCBisWTX(pcb) ) /*!< Checks if pcb is S-Block indicating WTX */ + +#define isoDep_PCBisRACK( pcb ) ( isoDep_PCBisRBlock(pcb) && isoDep_PCBisACK(pcb) ) /*!< Checks if pcb is R-Block indicating ACK */ +#define isoDep_PCBisRNAK( pcb ) ( isoDep_PCBisRBlock(pcb) && isoDep_PCBisNAK(pcb) ) /*!< Checks if pcb is R-Block indicating NAK */ + + +#define isoDep_PCBIBlock( bn ) ( (uint8_t)( 0x00U | ISODEP_PCB_IBLOCK | ISODEP_PCB_B2_BIT | ((bn) & ISODEP_PCB_BN_MASK) )) /*!< Returns an I-Block with the given block number (bn) */ +#define isoDep_PCBIBlockChaining( bn ) ( (uint8_t)(isoDep_PCBIBlock(bn) | ISODEP_PCB_CHAINING_BIT)) /*!< Returns an I-Block with the given block number (bn) indicating chaining */ + +#define isoDep_PCBRBlock( bn ) ( (uint8_t)( 0x00U | ISODEP_PCB_RBLOCK | ISODEP_PCB_B6_BIT | ISODEP_PCB_B2_BIT | ((bn) & ISODEP_PCB_BN_MASK) ) ) /*!< Returns an R-Block with the given block number (bn) */ +#define isoDep_PCBRACK( bn ) ( (uint8_t)( isoDep_PCBRBlock( bn ) | ISODEP_PCB_ACK ) ) /*!< Returns an R-Block with the given block number (bn) indicating ACK */ +#define isoDep_PCBRNAK( bn ) ( (uint8_t)( isoDep_PCBRBlock( bn ) | ISODEP_PCB_NAK ) ) /*!< Returns an R-Block with the given block number (bn) indicating NAK */ + + +#define isoDep_GetBN( pcb ) ( (uint8_t) ((pcb) & ISODEP_PCB_BN_MASK ) ) /*!< Returns the block number (bn) from the given pcb */ +#define isoDep_GetWTXM( inf ) ( (uint8_t) ((inf) & ISODEP_SWTX_WTXM_MASK) ) /*!< Returns the WTX value from the given inf byte */ +#define isoDep_isWTXMValid( wtxm ) (((wtxm) >= ISODEP_WTXM_MIN) && ((wtxm) <= ISODEP_WTXM_MAX)) /*!< Checks if the given wtxm is valid */ + +#define isoDep_WTXMListenerMax( fwt ) ( MIN( (uint8_t)(ISODEP_FWT_LIS_MAX / (fwt)), ISODEP_WTXM_MAX) ) /*!< Calculates the Max WTXM value for the given fwt as a Listener */ + +#define isoDepCalcdSGFT( s ) (384U * ((uint32_t)1U << (s))) /*!< Calculates the dSFGT with given SFGI Digital 1.1 13.8.2.1 & A.6*/ +#define isoDepCalcSGFT( s ) (4096U * ((uint32_t)1U << (s))) /*!< Calculates the SFGT with given SFGI Digital 1.1 13.8.2 */ + +#define isoDep_PCBNextBN( bn ) (((uint8_t)(bn)^0x01U) & ISODEP_PCB_BN_MASK) /*!< Returns the value of the next block number based on bn */ +#define isoDep_PCBPrevBN( bn ) isoDep_PCBNextBN(bn) /*!< Returns the value of the previous block number based on bn */ +#define isoDep_ToggleBN( bn ) ((bn) = (((bn)^0x01U) & ISODEP_PCB_BN_MASK) ) /*!< Toggles the block number value of the given bn */ + +#define isoDep_WTXAdjust( v ) ((v) - ((v)>>3)) /*!< Adjust WTX timer value to a percentage of the total, current 88% */ + + +/*! ISO 14443-4 7.5.6.2 & Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ +#define isoDepReEnableRx( rxB, rxBL, rxL ) rfalTransceiveBlockingTx( NULL, 0, rxB, rxBL, rxL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FWT_NONE ) + +#define isoDepTimerStart( timer, time_ms ) (timer) = platformTimerCreate((uint16_t)(time_ms)) /*!< Configures and starts the WTX timer */ +#define isoDepTimerisExpired( timer ) platformTimerIsExpired( timer ) /*!< Checks WTX timer has expired */ + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + + /*! Internal structure to be used in handling of S(PARAMETRS) only */ +typedef struct +{ + uint8_t pcb; /*!< PCB byte */ + rfalIsoDepSParameter sParam; /*!< S(PARAMETERS) */ +} rfalIsoDepControlMsgSParam; + +/*! Enumeration of the possible control message types */ +typedef enum +{ + ISODEP_R_ACK, /*!< R-ACK Acknowledge */ + ISODEP_R_NAK, /*!< R-NACK Negative acknowledge */ + ISODEP_S_WTX, /*!< S-WTX Waiting Time Extension */ + ISODEP_S_DSL /*!< S-DSL Deselect */ +} rfalIsoDepControlMsg; + +/*! Enumeration of the IsoDep roles */ +typedef enum +{ + ISODEP_ROLE_PCD, /*!< Perform as Reader/PCD */ + ISODEP_ROLE_PICC /*!< Perform as Card/PICC */ +} rfalIsoDepRole; + +/*! ISO-DEP layer states */ +typedef enum +{ + ISODEP_ST_IDLE, /*!< Idle State */ + ISODEP_ST_PCD_TX, /*!< PCD Transmission State */ + ISODEP_ST_PCD_RX, /*!< PCD Reception State */ + ISODEP_ST_PCD_WAIT_DSL, /*!< PCD Wait for DSL response */ + + ISODEP_ST_PICC_ACT_ATS, /*!< PICC has replied to RATS (ATS) */ + ISODEP_ST_PICC_ACT_ATTRIB, /*!< PICC has replied to ATTRIB */ + ISODEP_ST_PICC_RX, /*!< PICC REception State */ + ISODEP_ST_PICC_SWTX, /*!< PICC Waiting Time eXtension */ + ISODEP_ST_PICC_TX, /*!< PICC Transmission State */ +} rfalIsoDepState; + + + + +/*! Holds all ISO-DEP data(counters, buffers, ID, timeouts, frame size) */ +typedef struct{ + rfalIsoDepState state; /*!< ISO-DEP module state */ + rfalIsoDepRole role; /*!< Current ISO-DEP role */ + + uint8_t blockNumber; /*!< Current block number */ + uint8_t did; /*!< Current DID */ + uint8_t nad; /*!< Current DID */ + uint8_t cntIRetrys; /*!< I-Block retry counter */ + uint8_t cntRRetrys; /*!< R-Block retry counter */ + uint8_t cntSRetrys; /*!< S-Block retry counter */ + uint32_t fwt; /*!< Current FWT (Frame Waiting Time) */ + uint32_t dFwt; /*!< Current delta FWT */ + uint16_t fsx; /*!< Current FSx FSC or FSD (max Frame size) */ + bool isTxChaining; /*!< Flag for chaining on Tx */ + bool isRxChaining; /*!< Flag for chaining on Rx */ + uint8_t* txBuf; /*!< Tx buffer pointer */ + uint8_t* rxBuf; /*!< Rx buffer pointer */ + uint16_t txBufLen; /*!< Tx buffer length */ + uint16_t rxBufLen; /*!< Rx buffer length */ + uint8_t txBufInfPos; /*!< Start of payload in txBuf */ + uint8_t rxBufInfPos; /*!< Start of payload in rxBuf */ + + + uint16_t ourFsx; /*!< Our current FSx FSC or FSD (Frame size) */ + uint8_t lastPCB; /*!< Last PCB sent */ + uint8_t lastWTXM; /*!< Last WTXM sent */ + uint8_t atsTA; /*!< TA on ATS */ + uint8_t hdrLen; /*!< Current ISO-DEP length */ + rfalBitRate txBR; /*!< Current Tx Bit Rate */ + rfalBitRate rxBR; /*!< Current Rx Bit Rate */ + uint16_t *rxLen; /*!< Output parameter ptr to Rx length */ + bool *rxChaining; /*!< Output parameter ptr to Rx chaining flag */ + uint32_t WTXTimer; /*!< Timer used for WTX */ + bool lastDID00; /*!< Last PCD block had DID flag (for DID = 0) */ + + bool isTxPending; /*!< Flag pending Block while waiting WTX Ack */ + bool isWait4WTX; /*!< Flag for waiting WTX Ack */ + + uint32_t SFGTTimer; /*!< Timer used for SFGT */ + + uint8_t maxRetriesI; /*!< Number of retries for a I-Block */ + uint8_t maxRetriesS; /*!< Number of retries for a S-Block */ + uint8_t maxRetriesR; /*!< Number of retries for a R-Block */ + uint8_t maxRetriesRATS;/*!< Number of retries for RATS */ + + rfalComplianceMode compMode; /*!< Compliance mode */ + + uint8_t ctrlRxBuf[ISODEP_CONTROLMSG_BUF_LEN]; /*!< Control msg buf */ + uint16_t ctrlRxLen; /*!< Control msg rcvd len (used only for DSL) */ + + + rfalIsoDepListenActvParam actvParam; /*!< Listen Activation context */ + + rfalIsoDepApduTxRxParam APDUParam; /*!< APDU TxRx params */ + uint16_t APDUTxPos; /*!< APDU Tx position */ + uint16_t APDURxPos; /*!< APDU Rx position */ + bool isAPDURxChaining; /*!< APDU Transceive chaining flag */ + +}rfalIsoDep; + + + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + +static rfalIsoDep gIsoDep; /*!< ISO-DEP Module instance */ + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ +static void isoDepClearCounters( void ); +static ReturnCode isoDepTx( uint8_t pcb, const uint8_t* txBuf, uint8_t *infBuf, uint16_t infLen, uint32_t fwt ); +static ReturnCode isoDepHandleControlMsg( rfalIsoDepControlMsg controlMsg, uint8_t param ); +static void rfalIsoDepApdu2IBLockParam( rfalIsoDepApduTxRxParam apduParam, rfalIsoDepTxRxParam *iBlockParam, uint16_t txPos, uint16_t rxPos ); + +#if RFAL_FEATURE_ISO_DEP_POLL + static ReturnCode isoDepDataExchangePCD( uint16_t *outActRxLen, bool *outIsChaining ); + static void rfalIsoDepCalcBitRate(rfalBitRate maxAllowedBR, uint8_t piccBRCapability, rfalBitRate *dsi, rfalBitRate *dri); + static uint32_t rfalIsoDepSFGI2SFGT( uint8_t sfgi ); +#endif +#if RFAL_FEATURE_ISO_DEP_LISTEN + static ReturnCode isoDepDataExchangePICC( void ); + static ReturnCode isoDepReSendControlMsg( void ); +#endif + + + + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +static void isoDepClearCounters( void ) +{ + gIsoDep.cntIRetrys = 0; + gIsoDep.cntRRetrys = 0; + gIsoDep.cntSRetrys = 0; +} + +/*******************************************************************************/ +static ReturnCode isoDepTx( uint8_t pcb, const uint8_t* txBuf, uint8_t *infBuf, uint16_t infLen, uint32_t fwt ) +{ + uint8_t *txBlock; + uint16_t txBufLen; + uint8_t computedPcb; + + + txBlock = infBuf; /* Point to beginning of the INF, and go backwards */ + gIsoDep.lastPCB = pcb; /* Store the last PCB sent */ + + + if ( infLen > 0U ) + { + if ( ((uint32_t)infBuf - (uint32_t)txBuf) < gIsoDep.hdrLen ) /* Check that we can fit the header in the given space */ + { + return ERR_NOMEM; + } + } + + + /*******************************************************************************/ + /* Compute optional PCB bits */ + computedPcb = pcb; + if ((gIsoDep.did != RFAL_ISODEP_NO_DID) || ((gIsoDep.did == RFAL_ISODEP_DID_00) && gIsoDep.lastDID00) ) { computedPcb |= ISODEP_PCB_DID_BIT; } + if (gIsoDep.nad != RFAL_ISODEP_NO_NAD) { computedPcb |= ISODEP_PCB_NAD_BIT; } + if ((gIsoDep.isTxChaining) && (isoDep_PCBisIBlock(computedPcb)) ) { computedPcb |= ISODEP_PCB_CHAINING_BIT; } + + + /*******************************************************************************/ + /* Compute Payload on the given txBuf, start by the PCB | DID | NAD | before INF */ + + if (gIsoDep.nad != RFAL_ISODEP_NO_NAD) + { + *(--txBlock) = gIsoDep.nad; /* NAD is optional */ + } + + if ( (gIsoDep.did != RFAL_ISODEP_NO_DID) || ((gIsoDep.did == RFAL_ISODEP_DID_00) && gIsoDep.lastDID00) ) + { + *(--txBlock) = gIsoDep.did; /* DID is optional */ + } + + *(--txBlock) = computedPcb; /* PCB always present */ + + txBufLen = (infLen + (uint16_t)((uint32_t)infBuf - (uint32_t)txBlock)); /* Calculate overall buffer size */ + + if ( txBufLen > (gIsoDep.fsx - ISODEP_CRC_LEN) ) /* Check if msg length violates the maximum frame size FSC */ + { + return ERR_NOTSUPP; + } + + return rfalTransceiveBlockingTx( txBlock, txBufLen, gIsoDep.rxBuf, gIsoDep.rxBufLen, gIsoDep.rxLen, RFAL_TXRX_FLAGS_DEFAULT, ((gIsoDep.role == ISODEP_ROLE_PICC) ? RFAL_FWT_NONE : fwt ) ); +} + +/*******************************************************************************/ +static ReturnCode isoDepHandleControlMsg( rfalIsoDepControlMsg controlMsg, uint8_t param ) +{ + uint8_t pcb; + uint8_t ctrlMsgBuf[ISODEP_CONTROLMSG_BUF_LEN]; + uint8_t infLen; + uint32_t fwtTemp; + + infLen = 0; + fwtTemp = (gIsoDep.fwt + gIsoDep.dFwt); + ST_MEMSET( ctrlMsgBuf, 0x00, ISODEP_CONTROLMSG_BUF_LEN ); + + switch( controlMsg ) + { + /*******************************************************************************/ + case ISODEP_R_ACK: + + if( gIsoDep.cntRRetrys++ > gIsoDep.maxRetriesR ) + { + return ERR_PROTO; + } + + pcb = isoDep_PCBRACK( gIsoDep.blockNumber ); + break; + + /*******************************************************************************/ + case ISODEP_R_NAK: + if( gIsoDep.cntRRetrys++ > gIsoDep.maxRetriesR ) + { + return ERR_TIMEOUT; + } + + pcb = isoDep_PCBRNAK( gIsoDep.blockNumber ); + break; + + /*******************************************************************************/ + case ISODEP_S_WTX: + if( gIsoDep.cntSRetrys++ > gIsoDep.maxRetriesS ) + { + return ERR_PROTO; + } + + /* Check if WTXM is valid */ + if( ! isoDep_isWTXMValid(param) ) + { + return ERR_PROTO; + } + + if( gIsoDep.role == ISODEP_ROLE_PCD ) + { + /* Calculate temp Wait Time eXtension */ + fwtTemp = (gIsoDep.fwt * param); + fwtTemp = MIN( RFAL_ISODEP_MAX_FWT, fwtTemp ); + fwtTemp += gIsoDep.dFwt; + } + + pcb = ISODEP_PCB_SWTX; + ctrlMsgBuf[ RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN + infLen++] = param; + break; + + /*******************************************************************************/ + case ISODEP_S_DSL: + if( gIsoDep.cntSRetrys++ > gIsoDep.maxRetriesS ) + { + return ERR_PROTO; + } + + if( gIsoDep.role == ISODEP_ROLE_PCD ) + { + /* Digital 1.0 - 13.2.7.3 Poller must wait fwtDEACTIVATION */ + fwtTemp = ISODEP_FWT_DEACTIVATION; + gIsoDep.state = ISODEP_ST_PCD_WAIT_DSL; + } + pcb = ISODEP_PCB_SDSL; + break; + + /*******************************************************************************/ + default: + return ERR_INTERNAL; + } + + return isoDepTx( pcb, ctrlMsgBuf, &ctrlMsgBuf[RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN], infLen, fwtTemp ); +} + +#if RFAL_FEATURE_ISO_DEP_LISTEN +/*******************************************************************************/ +static ReturnCode isoDepReSendControlMsg( void ) +{ + if( isoDep_PCBisRACK( gIsoDep.lastPCB ) ) + { + return isoDepHandleControlMsg( ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM ); + } + + if( isoDep_PCBisRNAK( gIsoDep.lastPCB ) ) + { + return isoDepHandleControlMsg( ISODEP_R_NAK, RFAL_ISODEP_NO_PARAM ); + } + + if( isoDep_PCBisSDeselect( gIsoDep.lastPCB ) ) + { + return isoDepHandleControlMsg( ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM ); + } + + if( isoDep_PCBisSWTX( gIsoDep.lastPCB ) ) + { + return isoDepHandleControlMsg( ISODEP_S_WTX, gIsoDep.lastWTXM ); + } + return ERR_WRONG_STATE; +} +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + + +/*******************************************************************************/ +void rfalIsoDepInitialize( void ) +{ + gIsoDep.state = ISODEP_ST_IDLE; + gIsoDep.role = ISODEP_ROLE_PCD; + gIsoDep.did = RFAL_ISODEP_NO_DID; + gIsoDep.nad = RFAL_ISODEP_NO_NAD; + gIsoDep.blockNumber = 0; + gIsoDep.isTxChaining = false; + gIsoDep.isRxChaining = false; + gIsoDep.lastDID00 = false; + gIsoDep.lastPCB = ISODEP_PCB_INVALID; + gIsoDep.fsx = (uint16_t)RFAL_ISODEP_FSX_16; + gIsoDep.ourFsx = (uint16_t)RFAL_ISODEP_FSX_16; + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + + gIsoDep.rxLen = NULL; + gIsoDep.rxBuf = NULL; + + gIsoDep.isTxPending = false; + gIsoDep.isWait4WTX = false; + + gIsoDep.compMode = RFAL_COMPLIANCE_MODE_NFC; + gIsoDep.maxRetriesR = RFAL_ISODEP_MAX_R_RETRYS; + gIsoDep.maxRetriesS = RFAL_ISODEP_MAX_S_RETRYS; + gIsoDep.maxRetriesI = RFAL_ISODEP_MAX_I_RETRYS; + gIsoDep.maxRetriesRATS = RFAL_ISODEP_RATS_RETRIES; + + isoDepClearCounters(); +} + + +/*******************************************************************************/ +void rfalIsoDepInitializeWithParams( rfalComplianceMode compMode, uint8_t maxRetriesR, uint8_t maxRetriesS, uint8_t maxRetriesI, uint8_t maxRetriesRATS ) +{ + rfalIsoDepInitialize(); + + gIsoDep.compMode = compMode; + gIsoDep.maxRetriesR = maxRetriesR; + gIsoDep.maxRetriesS = maxRetriesS; + gIsoDep.maxRetriesI = maxRetriesI; + gIsoDep.maxRetriesRATS = maxRetriesRATS; +} + + +#if RFAL_FEATURE_ISO_DEP_POLL +/*******************************************************************************/ +static ReturnCode isoDepDataExchangePCD( uint16_t *outActRxLen, bool *outIsChaining ) +{ + ReturnCode ret; + uint8_t rxPCB; + + /* Check out parameters */ + if( (outActRxLen == NULL) || (outIsChaining == NULL) ) + { + return ERR_PARAM; + } + + *outIsChaining = false; + + /* Calculate header required and check if the buffers InfPositions are suitable */ + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + if (gIsoDep.did != RFAL_ISODEP_NO_DID) { gIsoDep.hdrLen += RFAL_ISODEP_DID_LEN; } + if (gIsoDep.nad != RFAL_ISODEP_NO_NAD) { gIsoDep.hdrLen += RFAL_ISODEP_NAD_LEN; } + + /* check if there is enough space before the infPos to append ISO-DEP headers on rx and tx */ + if( (gIsoDep.rxBufInfPos < gIsoDep.hdrLen) || (gIsoDep.txBufInfPos < gIsoDep.hdrLen) ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Wait until SFGT has been fulfilled (as a PCD) */ + if(gIsoDep.SFGTTimer != 0U) + { + if( !isoDepTimerisExpired( gIsoDep.SFGTTimer ) ) + { + return ERR_BUSY; + } + } + /* Once done, clear SFGT timer */ + gIsoDep.SFGTTimer = 0; + + + /*******************************************************************************/ + switch( gIsoDep.state ) + { + /*******************************************************************************/ + case ISODEP_ST_IDLE: + return ERR_NONE; + + /*******************************************************************************/ + case ISODEP_ST_PCD_TX: + ret = isoDepTx( isoDep_PCBIBlock( gIsoDep.blockNumber ), gIsoDep.txBuf, &gIsoDep.txBuf[gIsoDep.txBufInfPos], gIsoDep.txBufLen, (gIsoDep.fwt + gIsoDep.dFwt) ); + switch( ret ) + { + case ERR_NONE: + gIsoDep.state = ISODEP_ST_PCD_RX; + break; + + default: + return ret; + } + /* fall through */ + + /*******************************************************************************/ + case ISODEP_ST_PCD_WAIT_DSL: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + case ISODEP_ST_PCD_RX: + + ret = rfalGetTransceiveStatus(); + switch( ret ) + { + /* Data rcvd with error or timeout -> Send R-NAK */ + case ERR_TIMEOUT: + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: /* added to handle test cases scenario TC_POL_NFCB_T4AT_BI_82_x_y & TC_POL_NFCB_T4BT_BI_82_x_y */ + case ERR_INCOMPLETE_BYTE: /* added to handle test cases scenario TC_POL_NFCB_T4AT_BI_82_x_y & TC_POL_NFCB_T4BT_BI_82_x_y */ + + if( gIsoDep.isRxChaining ) + { /* Rule 5 - In PICC chaining when a invalid/timeout occurs -> R-ACK */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM ) ); + } + else if( gIsoDep.state == ISODEP_ST_PCD_WAIT_DSL ) + { /* Rule 8 - If s-Deselect response fails MAY retransmit */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM ) ); + } + else + { /* Rule 4 - When a invalid block or timeout occurs -> R-NACK */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_NAK, RFAL_ISODEP_NO_PARAM ) ); + } + return ERR_BUSY; + + case ERR_NONE: + break; + + case ERR_BUSY: + return ERR_BUSY; /* Debug purposes */ + + default: + return ret; + } + + /*******************************************************************************/ + /* No error, process incoming msg */ + /*******************************************************************************/ + + (*outActRxLen) = rfalConvBitsToBytes( *outActRxLen ); + + + /* Check rcvd msg length, cannot be less then the expected header */ + if( ((*outActRxLen) < gIsoDep.hdrLen) || ((*outActRxLen) >= gIsoDep.ourFsx) ) + { + return ERR_PROTO; + } + + /* Grab rcvd PCB */ + rxPCB = gIsoDep.rxBuf[ ISODEP_PCB_POS ]; + + + /* EMVCo doesn't allow usage of for CID or NAD EMVCo 2.6 TAble 10.2 */ + if( (gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) && ( isoDep_PCBhasDID(rxPCB) || isoDep_PCBhasNAD(rxPCB)) ) + { + return ERR_PROTO; + } + + /* If we are expecting DID, check if PCB signals its presence and if device ID match*/ + if( (gIsoDep.did != RFAL_ISODEP_NO_DID) && ( !isoDep_PCBhasDID(rxPCB) || (gIsoDep.did != gIsoDep.rxBuf[ ISODEP_DID_POS ])) ) + { + return ERR_PROTO; + } + + + /*******************************************************************************/ + /* Process S-Block */ + /*******************************************************************************/ + if( isoDep_PCBisSBlock(rxPCB) ) + { + /* Check if is a Wait Time eXtension */ + if( isoDep_PCBisSWTX(rxPCB) ) + { + /* Rule 3 - respond to S-block: get 1st INF byte S(STW): Power + WTXM */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_S_WTX, isoDep_GetWTXM(gIsoDep.rxBuf[gIsoDep.hdrLen]) ) ); + return ERR_BUSY; + } + + /* Check if is a deselect response */ + if( isoDep_PCBisSDeselect(rxPCB) ) + { + if( gIsoDep.state == ISODEP_ST_PCD_WAIT_DSL ) + { + rfalIsoDepInitialize(); /* Session finished reInit vars */ + return ERR_NONE; + } + + /* Deselect response not expected */ + /* fall through to PROTO error */ + } + /* Unexpected S-Block */ + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Process R-Block */ + /*******************************************************************************/ + else if( isoDep_PCBisRBlock(rxPCB) ) + { + if( isoDep_PCBisRACK(rxPCB) ) /* Check if is a R-ACK */ + { + if( isoDep_GetBN(rxPCB) == gIsoDep.blockNumber ) /* Expected block number */ + { + /* Rule B - ACK with expected bn -> Increment block number */ + gIsoDep.blockNumber = isoDep_PCBNextBN( gIsoDep.blockNumber ); + + /* R-ACK only allowed when PCD chaining */ + if( !gIsoDep.isTxChaining ) + { + return ERR_PROTO; + } + + /* Rule 7 - Chaining transaction done, continue chaining */ + isoDepClearCounters(); + return ERR_NONE; /* This block has been transmitted */ + } + else + { + /* Rule 6 - R-ACK with wrong block number retransmit */ + if( gIsoDep.cntIRetrys++ < gIsoDep.maxRetriesI ) + { + gIsoDep.cntRRetrys = 0; /* Clear R counter only */ + gIsoDep.state = ISODEP_ST_PCD_TX; + return ERR_BUSY; + } + return ERR_PROTO; + } + } + else /* Unexcpected R-Block */ + { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Process I-Block */ + /*******************************************************************************/ + else if( isoDep_PCBisIBlock(rxPCB) ) + { + /*******************************************************************************/ + /* is PICC performing chaining */ + if( isoDep_PCBisChaining(rxPCB) ) + { + gIsoDep.isRxChaining = true; + *outIsChaining = true; + + if( isoDep_GetBN(rxPCB) == gIsoDep.blockNumber ) + { + /* Rule B - ACK with correct block number -> Increase Block number */ + isoDep_ToggleBN( gIsoDep.blockNumber ); + + isoDepClearCounters(); /* Clear counters in case R counter is already at max */ + + /* Rule 2 - Send ACK */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM ) ); + + /* Received I-Block with chaining, send current data to DH */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *outActRxLen -= gIsoDep.hdrLen; + if( (gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*outActRxLen > 0U) ) + { + ST_MEMMOVE( &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], &gIsoDep.rxBuf[gIsoDep.hdrLen], *outActRxLen ); + } + + isoDepClearCounters(); + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived */ + } + else + { + /* Rule 5 - PICC chaining invalid I-Block -> R-ACK */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM ) ); + } + return ERR_BUSY; + } + + gIsoDep.isRxChaining = false; /* clear PICC chaining flag */ + + if( isoDep_GetBN(rxPCB) == gIsoDep.blockNumber ) + { + /* Rule B - I-Block with correct block number -> Increase Block number */ + isoDep_ToggleBN( gIsoDep.blockNumber ); + + /* I-Block transaction done successfully */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *outActRxLen -= gIsoDep.hdrLen; + if( (gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*outActRxLen > 0U) ) + { + ST_MEMMOVE( &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], &gIsoDep.rxBuf[gIsoDep.hdrLen], *outActRxLen ); + } + + gIsoDep.state = ISODEP_ST_IDLE; + isoDepClearCounters(); + return ERR_NONE; + } + else + { + if( (gIsoDep.compMode != RFAL_COMPLIANCE_MODE_ISO) ) + { + /* Invalid Block (not chaining) -> Raise error Digital 1.1 15.2.6.4 EMVCo 2.6 10.3.5.4 */ + return ERR_PROTO; + } + + /* Rule 4 - Invalid Block -> R-NAK */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_NAK, RFAL_ISODEP_NO_PARAM ) ); + return ERR_BUSY; + } + } + else /* not S/R/I - Block */ + { + return ERR_PROTO; + } + /* fall through */ + + /*******************************************************************************/ + default: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + /* MISRA 16.4: no empty default (comment will suffice) */ + break; + } + + return ERR_INTERNAL; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepDeselect( void ) +{ + ReturnCode ret; + uint32_t cntRerun; + bool dummyB; + + /*******************************************************************************/ + /* Check if rx parameters have been set before, otherwise use global variable * + * To cope with a Deselect after RATS\ATTRIB without any I-Block exchanged */ + if( (gIsoDep.rxLen == NULL) || (gIsoDep.rxBuf == NULL) ) + { + /* Using local vars would be safe as rfalIsoDepInitialize will clear the * + * reference to local vars before exiting (no EXIT_ON_ERR), * + * but MISRA 18.6 3217 would be still be flagged. Using static variables */ + gIsoDep.rxLen = &gIsoDep.ctrlRxLen; + gIsoDep.rxBuf = gIsoDep.ctrlRxBuf; + + gIsoDep.rxBufLen = ISODEP_CONTROLMSG_BUF_LEN; + gIsoDep.rxBufInfPos = (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN); + gIsoDep.txBufInfPos = (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN); + } + + + /*******************************************************************************/ + /* The Deselect process is being done blocking, Digital 1.0 - 13.2.7.1 MUST wait response and retry*/ + /* Set the maximum reruns while we will wait for a response */ + cntRerun = ISODEP_MAX_RERUNS; + + /* Send DSL request and run protocol until get a response, error or "timeout" */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM )); + do{ + ret = isoDepDataExchangePCD( gIsoDep.rxLen, &dummyB ); + rfalWorker(); + } + while( ((cntRerun--) != 0U) && (ret == ERR_BUSY) ); + + rfalIsoDepInitialize(); + return ((cntRerun == 0U) ? ERR_TIMEOUT : ret); +} + +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + + +/*******************************************************************************/ +uint32_t rfalIsoDepFWI2FWT( uint8_t fwi ) +{ + uint32_t result; + uint8_t tmpFWI; + + tmpFWI = fwi; + + /* RFU values -> take the default value + * Digital 1.0 11.6.2.17 FWI[1,14] + * Digital 1.1 7.6.2.22 FWI[0,14] + * EMVCo 2.6 Table A.5 FWI[0,14] */ + if( tmpFWI > ISODEP_FWI_MAX ) + { + tmpFWI = RFAL_ISODEP_FWI_DEFAULT; + } + + /* FWT = (256 x 16/fC) x 2^FWI => 2^(FWI+12) Digital 1.1 13.8.1 & 7.9.1 */ + + result = ((uint32_t)1U << (tmpFWI + 12U)); + result = MIN( RFAL_ISODEP_MAX_FWT, result); /* Maximum Frame Waiting Time must be fulfilled */ + + return result; +} + + +/*******************************************************************************/ +uint16_t rfalIsoDepFSxI2FSx( uint8_t FSxI ) +{ + uint16_t fsx; + uint8_t fsi; + + /* Enforce maximum FSxI/FSx allowed - NFC Forum and EMVCo differ */ + fsi = (( gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV ) ? MIN( FSxI, RFAL_ISODEP_FSDI_MAX_EMV ) : MIN( FSxI, RFAL_ISODEP_FSDI_MAX_NFC )); + + switch( fsi ) + { + case (uint8_t)RFAL_ISODEP_FSXI_16: fsx = (uint16_t)RFAL_ISODEP_FSX_16; break; + case (uint8_t)RFAL_ISODEP_FSXI_24: fsx = (uint16_t)RFAL_ISODEP_FSX_24; break; + case (uint8_t)RFAL_ISODEP_FSXI_32: fsx = (uint16_t)RFAL_ISODEP_FSX_32; break; + case (uint8_t)RFAL_ISODEP_FSXI_40: fsx = (uint16_t)RFAL_ISODEP_FSX_40; break; + case (uint8_t)RFAL_ISODEP_FSXI_48: fsx = (uint16_t)RFAL_ISODEP_FSX_48; break; + case (uint8_t)RFAL_ISODEP_FSXI_64: fsx = (uint16_t)RFAL_ISODEP_FSX_64; break; + case (uint8_t)RFAL_ISODEP_FSXI_96: fsx = (uint16_t)RFAL_ISODEP_FSX_96; break; + case (uint8_t)RFAL_ISODEP_FSXI_128: fsx = (uint16_t)RFAL_ISODEP_FSX_128; break; + case (uint8_t)RFAL_ISODEP_FSXI_256: fsx = (uint16_t)RFAL_ISODEP_FSX_256; break; + case (uint8_t)RFAL_ISODEP_FSXI_512: fsx = (uint16_t)RFAL_ISODEP_FSX_512; break; + case (uint8_t)RFAL_ISODEP_FSXI_1024: fsx = (uint16_t)RFAL_ISODEP_FSX_1024; break; + case (uint8_t)RFAL_ISODEP_FSXI_2048: fsx = (uint16_t)RFAL_ISODEP_FSX_2048; break; + case (uint8_t)RFAL_ISODEP_FSXI_4096: fsx = (uint16_t)RFAL_ISODEP_FSX_4096; break; + default: fsx = (uint16_t)RFAL_ISODEP_FSX_256; break; + } + return fsx; +} + + +#if RFAL_FEATURE_ISO_DEP_LISTEN + +/*******************************************************************************/ +bool rfalIsoDepIsRats( const uint8_t *buf, uint8_t bufLen ) +{ + if(buf != NULL) + { + if ((RFAL_ISODEP_CMD_RATS == (uint8_t)*buf) && (sizeof(rfalIsoDepRats) == bufLen)) + { + return true; + } + } + return false; +} + + +/*******************************************************************************/ +bool rfalIsoDepIsAttrib( const uint8_t *buf, uint8_t bufLen ) +{ + if(buf != NULL) + { + if ( (RFAL_ISODEP_CMD_ATTRIB == (uint8_t)*buf) && + (RFAL_ISODEP_ATTRIB_REQ_MIN_LEN <= bufLen) && + ((RFAL_ISODEP_ATTRIB_REQ_MIN_LEN + RFAL_ISODEP_ATTRIB_HLINFO_LEN) >= bufLen) ) + { + return true; + } + } + return false; +} + + + +/*******************************************************************************/ +ReturnCode rfalIsoDepListenStartActivation( rfalIsoDepAtsParam *atsParam, const rfalIsoDepAttribResParam *attribResParam, uint8_t *buf, uint16_t bufLen, rfalIsoDepListenActvParam actParam) +{ + uint8_t *txBuf; + uint8_t bufIt; + uint8_t *buffer = buf; + + /*******************************************************************************/ + bufIt = 0; + txBuf = (uint8_t*)actParam.rxBuf; /* Use the rxBuf as TxBuf as well, the struct enforces a size enough MAX( NFCA_ATS_MAX_LEN, NFCB_ATTRIB_RES_MAX_LEN ) */ + gIsoDep.txBR = RFAL_BR_106; + gIsoDep.rxBR = RFAL_BR_106; + + /* Check for a valid buffer pointer */ + if( buffer == NULL ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + if( *buffer == RFAL_ISODEP_CMD_RATS ) + { + /* Check ATS parameters */ + if( atsParam == NULL ) + { + return ERR_PARAM; + } + + /* If requested copy RATS to device info */ + if( actParam.isoDepDev != NULL ) + { + ST_MEMCPY( (uint8_t*)&actParam.isoDepDev->activation.A.Poller.RATS, buffer, sizeof(rfalIsoDepRats) ); /* Copy RATS' CMD + PARAM */ + } + + + /*******************************************************************************/ + /* Process RATS */ + buffer++; + gIsoDep.fsx = rfalIsoDepFSxI2FSx( (((*buffer) & RFAL_ISODEP_RATS_PARAM_FSDI_MASK) >> RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT) ); + gIsoDep.did = (*buffer & RFAL_ISODEP_DID_MASK); + + + /*******************************************************************************/ + /* Digital 1.1 13.6.1.8 - DID as to between 0 and 14 */ + if( gIsoDep.did > RFAL_ISODEP_DID_MAX ) + { + return ERR_PROTO; + } + + /* Check if we are configured to support DID */ + if( (gIsoDep.did != RFAL_ISODEP_DID_00) && (!atsParam->didSupport) ) + { + return ERR_NOTSUPP; + } + + + /*******************************************************************************/ + /* Check RFAL supported bit rates */ + if( (!(RFAL_SUPPORT_BR_CE_A_212) && (((atsParam->ta & RFAL_ISODEP_ATS_TA_DPL_212) != 0U) || ((atsParam->ta & RFAL_ISODEP_ATS_TA_DLP_212) != 0U))) || + (!(RFAL_SUPPORT_BR_CE_A_424) && (((atsParam->ta & RFAL_ISODEP_ATS_TA_DPL_424) != 0U) || ((atsParam->ta & RFAL_ISODEP_ATS_TA_DLP_424) != 0U))) || + (!(RFAL_SUPPORT_BR_CE_A_848) && (((atsParam->ta & RFAL_ISODEP_ATS_TA_DPL_848) != 0U) || ((atsParam->ta & RFAL_ISODEP_ATS_TA_DLP_848) != 0U))) ) + { + return ERR_NOTSUPP; + } + + /* Enforce proper FWI configuration */ + if( atsParam->fwi > ISODEP_FWI_LIS_MAX) + { + atsParam->fwi = ISODEP_FWI_LIS_MAX; + } + + gIsoDep.atsTA = atsParam->ta; + gIsoDep.fwt = rfalIsoDepFWI2FWT(atsParam->fwi); + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx(atsParam->fsci); + + + /* Ensure proper/maximum Historical Bytes length */ + atsParam->hbLen = MIN( RFAL_ISODEP_ATS_HB_MAX_LEN, atsParam->hbLen ); + + /*******************************************************************************/ + /* Compute ATS */ + + txBuf[ bufIt++ ] = (RFAL_ISODEP_ATS_HIST_OFFSET + atsParam->hbLen); /* TL */ + txBuf[ bufIt++ ] = ( (RFAL_ISODEP_ATS_T0_TA_PRESENCE_MASK | RFAL_ISODEP_ATS_T0_TB_PRESENCE_MASK | + RFAL_ISODEP_ATS_T0_TC_PRESENCE_MASK)| atsParam->fsci ); /* T0 */ + txBuf[ bufIt++ ] = atsParam->ta; /* TA */ + txBuf[ bufIt++ ] = ( (atsParam->fwi << RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT) | + (atsParam->sfgi & RFAL_ISODEP_RATS_PARAM_FSDI_MASK) ); /* TB */ + txBuf[ bufIt++ ] = (uint8_t)((atsParam->didSupport) ? RFAL_ISODEP_ATS_TC_DID : 0U); /* TC */ + + if( atsParam->hbLen > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( &txBuf[bufIt], atsParam->hb, atsParam->hbLen ); /* T1-Tk */ + bufIt += atsParam->hbLen; + } + + gIsoDep.state = ISODEP_ST_PICC_ACT_ATS; + + } + /*******************************************************************************/ + else if( *buffer == RFAL_ISODEP_CMD_ATTRIB ) + { + /* Check ATTRIB parameters */ + if( attribResParam == NULL ) + { + return ERR_PARAM; + } + + /* REMARK: ATTRIB handling */ + NO_WARNING(attribResParam); + NO_WARNING(bufLen); + return ERR_NOT_IMPLEMENTED; + } + else + { + return ERR_PARAM; + } + + gIsoDep.actvParam = actParam; + + + /*******************************************************************************/ + /* If requested copy to ISO-DEP device info */ + if( actParam.isoDepDev != NULL ) + { + actParam.isoDepDev->info.DID = gIsoDep.did; + actParam.isoDepDev->info.FSx = gIsoDep.fsx; + actParam.isoDepDev->info.FWT = gIsoDep.fwt; + actParam.isoDepDev->info.dFWT = 0; + actParam.isoDepDev->info.DSI = gIsoDep.txBR; + actParam.isoDepDev->info.DRI = gIsoDep.rxBR; + } + + return rfalTransceiveBlockingTx( txBuf, bufIt, (uint8_t*)actParam.rxBuf, sizeof( rfalIsoDepBufFormat ), actParam.rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FWT_NONE ); +} + + +/*******************************************************************************/ +ReturnCode rfalIsoDepListenGetActivationStatus( void ) +{ + ReturnCode err; + uint8_t* txBuf; + uint8_t bufIt; + + rfalBitRate dsi; + rfalBitRate dri; + + + /* Check if Activation is running */ + if( gIsoDep.state < ISODEP_ST_PICC_ACT_ATS ) + { + return ERR_WRONG_STATE; + } + + /* Check if Activation has finished already */ + if( gIsoDep.state >= ISODEP_ST_PICC_RX ) + { + return ERR_NONE; + } + + + /*******************************************************************************/ + /* Check for incoming msg */ + err = rfalGetTransceiveStatus(); + switch( err ) + { + /*******************************************************************************/ + case ERR_NONE: + break; + + /*******************************************************************************/ + case ERR_LINK_LOSS: + case ERR_BUSY: + return err; + + /*******************************************************************************/ + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + + /* ISO14443 4 5.6.2.2 2 If ATS has been replied upon a invalid block, PICC disables the PPS responses */ + if( gIsoDep.state == ISODEP_ST_PICC_ACT_ATS ) + { + gIsoDep.state = ISODEP_ST_PICC_RX; + break; + } + /* fall through */ + + /*******************************************************************************/ + default: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + /* ReEnable the receiver and wait for another frame */ + isoDepReEnableRx( (uint8_t*)gIsoDep.actvParam.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.actvParam.rxLen ); + + return ERR_BUSY; + } + + + txBuf = (uint8_t*)gIsoDep.actvParam.rxBuf; /* Use the rxBuf as TxBuf as well, the struct enforces a size enough MAX(NFCA_PPS_RES_LEN, ISODEP_DSL_MAX_LEN) */ + dri = RFAL_BR_KEEP; /* The RFAL_BR_KEEP is used to check if PPS with BR change was requested */ + dsi = RFAL_BR_KEEP; /* MISRA 9.1 */ + bufIt = 0; + + + /*******************************************************************************/ + gIsoDep.role = ISODEP_ROLE_PICC; + + /*******************************************************************************/ + if( gIsoDep.state == ISODEP_ST_PICC_ACT_ATS ) + { + /* Check for a PPS ISO 14443-4 5.3 */ + if( ( ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_STARTBYTE_POS] & RFAL_ISODEP_PPS_MASK) == RFAL_ISODEP_PPS_SB ) + { + /* ISO 14443-4 5.3.1 Check if the we are the addressed DID/CID */ + /* ISO 14443-4 5.3.2 Check for a valid PPS0 */ + if( (( ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_STARTBYTE_POS] & RFAL_ISODEP_DID_MASK) != gIsoDep.did) || + (( ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS0_POS] & RFAL_ISODEP_PPS0_VALID_MASK) != RFAL_ISODEP_PPS0_PPS1_NOT_PRESENT) ) + { + /* Invalid DID on PPS request or Invalid PPS0, reEnable the receiver and wait another frame */ + isoDepReEnableRx( (uint8_t*)gIsoDep.actvParam.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.actvParam.rxLen ); + + return ERR_BUSY; + } + + /*******************************************************************************/ + /* Check PPS1 presence */ + if( ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS0_POS] == RFAL_ISODEP_PPS0_PPS1_PRESENT ) + { + uint8_t newdri = ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS1_POS] & RFAL_ISODEP_PPS1_DxI_MASK; /* MISRA 10.8 */ + uint8_t newdsi = (((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS1_POS] >> RFAL_ISODEP_PPS1_DSI_SHIFT) & RFAL_ISODEP_PPS1_DxI_MASK; /* MISRA 10.8 */ + /* PRQA S 4342 2 # MISRA 10.5 - Layout of enum rfalBitRate and above masks guarantee no invalid enum values to be created */ + dri = (rfalBitRate) (newdri); + dsi = (rfalBitRate) (newdsi); + + if( (!(RFAL_SUPPORT_BR_CE_A_106) && (( dsi == RFAL_BR_106 ) || ( dri == RFAL_BR_106 ))) || + (!(RFAL_SUPPORT_BR_CE_A_212) && (( dsi == RFAL_BR_212 ) || ( dri == RFAL_BR_212 ))) || + (!(RFAL_SUPPORT_BR_CE_A_424) && (( dsi == RFAL_BR_424 ) || ( dri == RFAL_BR_424 ))) || + (!(RFAL_SUPPORT_BR_CE_A_848) && (( dsi == RFAL_BR_848 ) || ( dri == RFAL_BR_848 ))) ) + { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Compute and send PPS RES / Ack */ + txBuf[ bufIt++ ] = ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_STARTBYTE_POS]; + + rfalTransceiveBlockingTx( txBuf, bufIt, (uint8_t*)gIsoDep.actvParam.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.actvParam.rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FWT_NONE ); + + /*******************************************************************************/ + /* Exchange the bit rates if requested */ + if( dri != RFAL_BR_KEEP ) + { + rfalSetBitRate( dsi, dri ); /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset above (RFAL_SUPPORT_BR_CE_A_xxx) */ + + gIsoDep.txBR = dsi; /* DSI codes the divisor from PICC to PCD */ + gIsoDep.rxBR = dri; /* DRI codes the divisor from PCD to PICC */ + + + if(gIsoDep.actvParam.isoDepDev != NULL) + { + gIsoDep.actvParam.isoDepDev->info.DSI = dsi; + gIsoDep.actvParam.isoDepDev->info.DRI = dri; + } + } + } + /* Check for a S-Deselect is done on Data Exchange Activity */ + } + + /*******************************************************************************/ + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + gIsoDep.hdrLen += RFAL_ISODEP_DID_LEN; /* Always assume DID to be aligned with Digital 1.1 15.1.2 and ISO14443 4 5.6.3 #454 */ + gIsoDep.hdrLen += (uint8_t)((gIsoDep.nad != RFAL_ISODEP_NO_NAD) ? RFAL_ISODEP_NAD_LEN : 0U); + + /*******************************************************************************/ + /* Rule C - The PICC block number shall be initialized to 1 at activation */ + gIsoDep.blockNumber = 1; + + /* Activation done, keep the rcvd data in, reMap the activation buffer to the global to be retrieved by the DEP method */ + gIsoDep.rxBuf = (uint8_t*)gIsoDep.actvParam.rxBuf; + gIsoDep.rxBufLen = sizeof( rfalIsoDepBufFormat ); + gIsoDep.rxBufInfPos = (uint8_t)((uint32_t)gIsoDep.actvParam.rxBuf->inf - (uint32_t)gIsoDep.actvParam.rxBuf->prologue); + gIsoDep.rxLen = gIsoDep.actvParam.rxLen; + gIsoDep.rxChaining = gIsoDep.actvParam.isRxChaining; + + gIsoDep.state = ISODEP_ST_PICC_RX; + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + + +/*******************************************************************************/ +uint16_t rfalIsoDepGetMaxInfLen( void ) +{ + /* Check whether all parameters are valid, otherwise return minimum default value */ + if( (gIsoDep.fsx < (uint16_t)RFAL_ISODEP_FSX_16) || (gIsoDep.fsx > (uint16_t)RFAL_ISODEP_FSX_4096) || (gIsoDep.hdrLen > ISODEP_HDR_MAX_LEN) ) + { + uint16_t isodepFsx16 = (uint16_t)RFAL_ISODEP_FSX_16; /* MISRA 10.1 */ + return (isodepFsx16 - RFAL_ISODEP_PCB_LEN - ISODEP_CRC_LEN); + } + + return (gIsoDep.fsx - gIsoDep.hdrLen - ISODEP_CRC_LEN); +} + + +/*******************************************************************************/ +ReturnCode rfalIsoDepStartTransceive( rfalIsoDepTxRxParam param ) +{ + gIsoDep.txBuf = param.txBuf->prologue; + gIsoDep.txBufInfPos = (uint8_t)((uint32_t)param.txBuf->inf - (uint32_t)param.txBuf->prologue); + gIsoDep.txBufLen = param.txBufLen; + gIsoDep.isTxChaining = param.isTxChaining; + + gIsoDep.rxBuf = param.rxBuf->prologue; + gIsoDep.rxBufInfPos = (uint8_t)((uint32_t)param.rxBuf->inf - (uint32_t)param.rxBuf->prologue); + gIsoDep.rxBufLen = sizeof(rfalIsoDepBufFormat); + + gIsoDep.rxLen = param.rxLen; + gIsoDep.rxChaining = param.isRxChaining; + + + gIsoDep.fwt = param.FWT; + gIsoDep.dFwt = param.dFWT; + gIsoDep.fsx = param.FSx; + gIsoDep.did = param.DID; + + /* Only change the FSx from activation if no to Keep */ + gIsoDep.ourFsx = (( param.ourFSx != RFAL_ISODEP_FSX_KEEP ) ? param.ourFSx : gIsoDep.ourFsx); + + /* Clear inner control params for next dataExchange */ + gIsoDep.isRxChaining = false; + isoDepClearCounters(); + + if(gIsoDep.role == ISODEP_ROLE_PICC) + { + if(gIsoDep.txBufLen > 0U) + { + /* Ensure that an RTOX Ack is not being expected at moment */ + if( !gIsoDep.isWait4WTX ) + { + gIsoDep.state = ISODEP_ST_PICC_TX; + return ERR_NONE; + } + else + { + /* If RTOX Ack is expected, signal a pending Tx to be transmitted right after */ + gIsoDep.isTxPending = true; + } + } + + /* Digital 1.1 15.2.5.1 The first block SHALL be sent by the Reader/Writer */ + gIsoDep.state = ISODEP_ST_PICC_RX; + return ERR_NONE; + } + + gIsoDep.state = ISODEP_ST_PCD_TX; + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalIsoDepGetTransceiveStatus( void ) +{ + if( gIsoDep.role == ISODEP_ROLE_PICC) + { +#if RFAL_FEATURE_ISO_DEP_LISTEN + return isoDepDataExchangePICC(); +#else + return ERR_NOTSUPP; +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + } + else + { +#if RFAL_FEATURE_ISO_DEP_POLL + return isoDepDataExchangePCD( gIsoDep.rxLen, gIsoDep.rxChaining ); +#else + return ERR_NOTSUPP; +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + } +} + + +#if RFAL_FEATURE_ISO_DEP_LISTEN + +/*******************************************************************************/ +static ReturnCode isoDepDataExchangePICC( void ) +{ + uint8_t rxPCB; + ReturnCode ret; + + switch( gIsoDep.state ) + { + /*******************************************************************************/ + case ISODEP_ST_IDLE: + return ERR_NONE; + + + /*******************************************************************************/ + case ISODEP_ST_PICC_TX: + + ret = isoDepTx( isoDep_PCBIBlock( gIsoDep.blockNumber ), gIsoDep.txBuf, &gIsoDep.txBuf[gIsoDep.txBufInfPos], gIsoDep.txBufLen, RFAL_FWT_NONE ); + + /* Clear pending Tx flag */ + gIsoDep.isTxPending = false; + + switch( ret ) + { + case ERR_NONE: + gIsoDep.state = ISODEP_ST_PICC_RX; + return ERR_BUSY; + + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + return ret; + + + /*******************************************************************************/ + case ISODEP_ST_PICC_RX: + + ret = rfalGetTransceiveStatus(); + switch( ret ) + { + /*******************************************************************************/ + /* Data rcvd with error or timeout -> mute */ + case ERR_TIMEOUT: + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + + /* Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ + isoDepReEnableRx( (uint8_t*)gIsoDep.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.rxLen ); + + return ERR_BUSY; + + /*******************************************************************************/ + case ERR_LINK_LOSS: + return ret; /* Debug purposes */ + + case ERR_BUSY: + return ret; /* Debug purposes */ + + /*******************************************************************************/ + case ERR_NONE: + *gIsoDep.rxLen = rfalConvBitsToBytes( *gIsoDep.rxLen ); + break; + + /*******************************************************************************/ + default: + return ret; + } + break; + + + /*******************************************************************************/ + case ISODEP_ST_PICC_SWTX: + + if( !isoDepTimerisExpired( gIsoDep.WTXTimer ) ) /* Do nothing until WTX timer has expired */ + { + return ERR_BUSY; + } + + /* Set waiting for WTX Ack Flag */ + gIsoDep.isWait4WTX = true; + + /* Digital 1.1 15.2.2.9 - Calculate the WTXM such that FWTtemp <= FWTmax */ + gIsoDep.lastWTXM = (uint8_t)isoDep_WTXMListenerMax( gIsoDep.fwt ); + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_S_WTX, gIsoDep.lastWTXM ) ); + + gIsoDep.state = ISODEP_ST_PICC_RX; /* Go back to Rx to process WTX ack */ + return ERR_BUSY; + + + /*******************************************************************************/ + default: + return ERR_INTERNAL; + } + + /* ISO 14443-4 7.5.6.2 CE SHALL NOT attempt error recovery -> clear counters */ + isoDepClearCounters(); + + /*******************************************************************************/ + /* No error, process incoming msg */ + /*******************************************************************************/ + + /* Grab rcvd PCB */ + rxPCB = gIsoDep.rxBuf[ ISODEP_PCB_POS ]; + + + /*******************************************************************************/ + /* When DID=0 PCD may or may not use DID, therefore check whether current PCD request + * has DID present to be reflected on max INF length #454 */ + + /* ReCalculate Header Length */ + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + gIsoDep.hdrLen += (uint8_t)( (isoDep_PCBhasDID(rxPCB)) ? RFAL_ISODEP_DID_LEN : 0U ); + gIsoDep.hdrLen += (uint8_t)( (isoDep_PCBhasNAD(rxPCB)) ? RFAL_ISODEP_NAD_LEN : 0U ); + + /* Store whether last PCD block had DID. for PICC special handling of DID = 0 */ + if( gIsoDep.did == RFAL_ISODEP_DID_00 ) + { + gIsoDep.lastDID00 = ( (isoDep_PCBhasDID(rxPCB)) ? true : false ); + } + + /*******************************************************************************/ + /* Check rcvd msg length, cannot be less then the expected header OR * + * if the rcvd msg exceeds our announced frame size (FSD) */ + if( ((*gIsoDep.rxLen) < gIsoDep.hdrLen) || ((*gIsoDep.rxLen) > (gIsoDep.ourFsx - ISODEP_CRC_LEN)) ) + { + isoDepReEnableRx( (uint8_t*)gIsoDep.actvParam.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.actvParam.rxLen ); + return ERR_BUSY; /* ERR_PROTO Ignore this protocol request */ + } + + /* If we are expecting DID, check if PCB signals its presence and if device ID match OR + * If our DID=0 and DID is sent but with an incorrect value */ + if( ((gIsoDep.did != RFAL_ISODEP_DID_00) && ( !isoDep_PCBhasDID(rxPCB) || (gIsoDep.did != gIsoDep.rxBuf[ ISODEP_DID_POS ]))) || + ((gIsoDep.did == RFAL_ISODEP_DID_00) && isoDep_PCBhasDID(rxPCB) && (RFAL_ISODEP_DID_00 != gIsoDep.rxBuf[ ISODEP_DID_POS ]) ) ) + { + isoDepReEnableRx( (uint8_t*)gIsoDep.actvParam.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.actvParam.rxLen ); + return ERR_BUSY; /* Ignore a wrong DID request */ + } + + /* If we aren't expecting NAD and it's received */ + if( (gIsoDep.nad == RFAL_ISODEP_NO_NAD) && isoDep_PCBhasNAD(rxPCB) ) + { + isoDepReEnableRx( (uint8_t*)gIsoDep.actvParam.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.actvParam.rxLen ); + return ERR_BUSY; /* Ignore a unexpected NAD request */ + } + + /*******************************************************************************/ + /* Process S-Block */ + /*******************************************************************************/ + if( isoDep_PCBisSBlock(rxPCB) ) + { + /* Check if is a Wait Time eXtension */ + if( isoDep_PCBisSWTX(rxPCB) ) + { + /* Check if we're expecting a S-WTX */ + if( isoDep_PCBisWTX( gIsoDep.lastPCB ) ) + { + /* Digital 1.1 15.2.2.11 S(WTX) Ack with different WTXM -> Protocol Error * + * Power level indication also should be set to 0 */ + if( ( gIsoDep.rxBuf[ gIsoDep.hdrLen ] == gIsoDep.lastWTXM) && ((*gIsoDep.rxLen - gIsoDep.hdrLen) == ISODEP_SWTX_INF_LEN) ) + { + /* Clear waiting for RTOX Ack Flag */ + gIsoDep.isWait4WTX = false; + + /* Check if a Tx is already pending */ + if( gIsoDep.isTxPending ) + { + /* Has a pending Tx, go immediately to TX */ + gIsoDep.state = ISODEP_ST_PICC_TX; + return ERR_BUSY; + } + + /* Set WTX timer */ + isoDepTimerStart( gIsoDep.WTXTimer, isoDep_WTXAdjust( (gIsoDep.lastWTXM * rfalConv1fcToMs( gIsoDep.fwt )) ) ); + + gIsoDep.state = ISODEP_ST_PICC_SWTX; + return ERR_BUSY; + } + } + /* Unexpected/Incorrect S-WTX, fall into reRenable */ + } + + /* Check if is a deselect request */ + if( isoDep_PCBisSDeselect(rxPCB) && ((*gIsoDep.rxLen - gIsoDep.hdrLen) == ISODEP_SDSL_INF_LEN) ) + { + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM ) ); + + rfalIsoDepInitialize(); /* Session finished reInit vars */ + return ERR_SLEEP_REQ; + } + + /* Unexpected S-Block, fall into reRenable */ + } + + /*******************************************************************************/ + /* Process R-Block */ + /*******************************************************************************/ + else if( isoDep_PCBisRBlock(rxPCB) && ((*gIsoDep.rxLen - gIsoDep.hdrLen) == ISODEP_RBLOCK_INF_LEN)) + { + if( isoDep_PCBisRACK(rxPCB) ) /* Check if is a R-ACK */ + { + if( isoDep_GetBN(rxPCB) == gIsoDep.blockNumber ) /* Check block number */ + { + /* Rule 11 - R(ACK) with current bn -> re-transmit */ + if( !isoDep_PCBisIBlock(gIsoDep.lastPCB) ) + { + isoDepReSendControlMsg(); + } + else + { + gIsoDep.state = ISODEP_ST_PICC_TX; + } + + return ERR_BUSY; + } + else + { + if( !gIsoDep.isTxChaining ) + { + /* Rule 13 violation R(ACK) without performing chaining */ + isoDepReEnableRx( (uint8_t*)gIsoDep.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.rxLen ); + return ERR_BUSY; + } + + /* Rule E - R(ACK) with not current bn -> toogle bn */ + isoDep_ToggleBN( gIsoDep.blockNumber ); + + /* This block has been transmitted and acknowledged, perform WTX until next data is provided */ + + /* Rule 9 - PICC is allowed to send an S(WTX) instead of an I-block or an R(ACK) */ + isoDepTimerStart( gIsoDep.WTXTimer, isoDep_WTXAdjust( rfalConv1fcToMs( gIsoDep.fwt )) ); + gIsoDep.state = ISODEP_ST_PICC_SWTX; + + /* Rule 13 - R(ACK) with not current bn -> continue chaining */ + return ERR_NONE; /* This block has been transmitted */ + } + } + else if( isoDep_PCBisRNAK(rxPCB) ) /* Check if is a R-NACK */ + { + if( isoDep_GetBN(rxPCB) == gIsoDep.blockNumber ) /* Check block number */ + { + /* Rule 11 - R(NAK) with current bn -> re-transmit last x-Block */ + if( !isoDep_PCBisIBlock(gIsoDep.lastPCB) ) + { + isoDepReSendControlMsg(); + } + else + { + gIsoDep.state = ISODEP_ST_PICC_TX; + } + + return ERR_BUSY; + } + else + { + /* Rule 12 - R(NAK) with not current bn -> R(ACK) */ + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM ) ); + + return ERR_BUSY; + } + } + else + { + /* MISRA 15.7 - Empty else */ + } + + /* Unexpected R-Block, fall into reRenable */ + } + + /*******************************************************************************/ + /* Process I-Block */ + /*******************************************************************************/ + else if( isoDep_PCBisIBlock(rxPCB) ) + { + /* Rule D - When an I-block is received, the PICC shall toggle its block number before sending a block */ + isoDep_ToggleBN( gIsoDep.blockNumber ); + + /*******************************************************************************/ + /* Check if the block number is the one expected */ + /* Check if PCD sent an I-Block instead ACK/NACK when we are chaining */ + if( (isoDep_GetBN(rxPCB) != gIsoDep.blockNumber) || (gIsoDep.isTxChaining) ) + { + /* Remain in the same Block Number */ + isoDep_ToggleBN( gIsoDep.blockNumber ); + + /* ISO 14443-4 7.5.6.2 & Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ + isoDepReEnableRx( (uint8_t*)gIsoDep.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.rxLen ); + return ERR_BUSY; + } + + /*******************************************************************************/ + /* is PCD performing chaining ? */ + if( isoDep_PCBisChaining(rxPCB) ) + { + gIsoDep.isRxChaining = true; + *gIsoDep.rxChaining = true; /* Output Parameter*/ + + EXIT_ON_ERR( ret, isoDepHandleControlMsg( ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM ) ); + + /* Received I-Block with chaining, send current data to DH */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *gIsoDep.rxLen -= gIsoDep.hdrLen; + if( (gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*gIsoDep.rxLen > 0U) ) + { + ST_MEMMOVE( &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], &gIsoDep.rxBuf[gIsoDep.hdrLen], *gIsoDep.rxLen ); + } + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived*/ + } + + + /*******************************************************************************/ + /* PCD is not performing chaining */ + gIsoDep.isRxChaining = false; /* clear PCD chaining flag */ + *gIsoDep.rxChaining = false; /* Output Parameter */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *gIsoDep.rxLen -= gIsoDep.hdrLen; + if( (gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*gIsoDep.rxLen > 0U) ) + { + ST_MEMMOVE( &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], &gIsoDep.rxBuf[gIsoDep.hdrLen], *gIsoDep.rxLen ); + } + + + /*******************************************************************************/ + /* Reception done, send data back and start WTX timer */ + isoDepTimerStart( gIsoDep.WTXTimer, isoDep_WTXAdjust( rfalConv1fcToMs( gIsoDep.fwt )) ); + + gIsoDep.state = ISODEP_ST_PICC_SWTX; + return ERR_NONE; + } + else + { + /* MISRA 15.7 - Empty else */ + } + + /* Unexpected/Unknown Block */ + /* ISO 14443-4 7.5.6.2 & Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ + isoDepReEnableRx( (uint8_t*)gIsoDep.rxBuf, sizeof( rfalIsoDepBufFormat ), gIsoDep.rxLen ); + + return ERR_BUSY; +} +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + + +#if RFAL_FEATURE_ISO_DEP_POLL + +#if RFAL_FEATURE_NFCA + +/*******************************************************************************/ +ReturnCode rfalIsoDepRATS( rfalIsoDepFSxI FSDI, uint8_t DID, rfalIsoDepAts *ats , uint8_t *atsLen) +{ + uint16_t rcvLen; + ReturnCode ret; + rfalIsoDepRats ratsReq; + + if( ats == NULL ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Compose RATS */ + ratsReq.CMD = RFAL_ISODEP_CMD_RATS; + ratsReq.PARAM = (((uint8_t)FSDI << RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT) & RFAL_ISODEP_RATS_PARAM_FSDI_MASK) | (DID & RFAL_ISODEP_RATS_PARAM_DID_MASK); + + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&ratsReq, sizeof(rfalIsoDepRats), (uint8_t*)ats, sizeof(rfalIsoDepAts), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ISODEP_T4T_FWT_ACTIVATION ); + + if( ret == ERR_NONE ) + { + /* Check for valid ATS length Digital 1.1 13.6.2.1 & 13.6.2.3 */ + if( (rcvLen < RFAL_ISODEP_ATS_MIN_LEN) || (rcvLen > RFAL_ISODEP_ATS_MAX_LEN) || (ats->TL != rcvLen) ) + { + return ERR_PROTO; + } + + /* Assign our FSx, in case the a Deselect is send without Transceive */ + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx( (uint8_t)FSDI ); + } + + /* Check and assign if ATS length was requested (length also available on TL) */ + if( atsLen != NULL ) + { + *atsLen = (uint8_t)rcvLen; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalIsoDepPPS( uint8_t DID, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepPpsRes *ppsRes ) +{ + uint16_t rcvLen; + ReturnCode ret; + rfalIsoDepPpsReq ppsReq; + + if( (ppsRes == NULL) || (DSI > RFAL_BR_848) || (DRI > RFAL_BR_848) || (DID > RFAL_ISODEP_DID_MAX) ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Compose PPS Request */ + ppsReq.PPSS = (RFAL_ISODEP_PPS_SB | (DID & RFAL_ISODEP_PPS_SB_DID_MASK)); + ppsReq.PPS0 = RFAL_ISODEP_PPS_PPS0_PPS1_PRESENT; + ppsReq.PPS1 = (RFAL_ISODEP_PPS_PPS1 | ((((uint8_t)DSI<PPSS != ppsReq.PPSS) ) + { + return ERR_PROTO; + } + } + return ret; +} + +#endif /* RFAL_FEATURE_NFCA */ + + +#if RFAL_FEATURE_NFCB + +/*******************************************************************************/ +ReturnCode rfalIsoDepATTRIB( const uint8_t* nfcid0, uint8_t PARAM1, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepFSxI FSDI, uint8_t PARAM3, uint8_t DID, const uint8_t* HLInfo, uint8_t HLInfoLen, uint32_t fwt, rfalIsoDepAttribRes *attribRes, uint8_t *attribResLen ) +{ + uint16_t rcvLen; + ReturnCode ret; + rfalIsoDepAttribCmd attribCmd; + + + if( (attribRes == NULL) || (attribResLen == NULL) || (DSI > RFAL_BR_848) || (DRI > RFAL_BR_848) || (DID > RFAL_ISODEP_DID_MAX) ) + { + return ERR_NONE; + } + + /*******************************************************************************/ + /* Compose ATTRIB command */ + attribCmd.cmd = RFAL_ISODEP_CMD_ATTRIB; + attribCmd.Param.PARAM1 = PARAM1; + attribCmd.Param.PARAM2 = ( ((((uint8_t)DSI< 0U) ) + { + ST_MEMCPY(attribCmd.HLInfo, HLInfo, MIN(HLInfoLen, RFAL_ISODEP_ATTRIB_HLINFO_LEN) ); + } + + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&attribCmd, (RFAL_ISODEP_ATTRIB_HDR_LEN + MIN((uint16_t)HLInfoLen, RFAL_ISODEP_ATTRIB_HLINFO_LEN)), (uint8_t*)attribRes, sizeof(rfalIsoDepAttribRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, fwt ); + + *attribResLen = (uint8_t)rcvLen; + + if( ret == ERR_NONE ) + { + /* Check a for valid ATTRIB Response Digital 1.1 15.6.2.1 */ + if( (rcvLen < RFAL_ISODEP_ATTRIB_RES_HDR_LEN) || ((attribRes->mbliDid & RFAL_ISODEP_ATTRIB_RES_DID_MASK) != DID) ) + { + return ERR_PROTO; + } + } + + return ret; +} + +#endif /* RFAL_FEATURE_NFCB */ + + +#if RFAL_FEATURE_NFCA + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollAHandleActivation( rfalIsoDepFSxI FSDI, uint8_t DID, rfalBitRate maxBR, rfalIsoDepDevice *isoDepDev ) +{ + uint8_t RATSretries; + uint8_t msgIt; + ReturnCode ret; + rfalIsoDepPpsRes ppsRes; + + if( isoDepDev == NULL ) + { + return ERR_PARAM; + } + + /* Enable EMD handling according Digital 1.1 4.1.1.1 ; EMVCo 2.6 4.9.2 */ + rfalSetErrorHandling( RFAL_ERRORHANDLING_EMVCO ); + + RATSretries = gIsoDep.maxRetriesRATS; + + /***************************************************************************/ + /* Send RATS */ + do + { + /* Digital 1.1 13.7.1.1 and ISO 14443-4 5.6.1.1 - Upon a failed RATS it may be retransmited [0,1] */ + ret = rfalIsoDepRATS( FSDI, DID, &isoDepDev->activation.A.Listener.ATS, &isoDepDev->activation.A.Listener.ATSLen ); + + /* EMVCo 2.6 9.6.1.1 & 9.6.1.2 If a timeout error is detected retransmit, on transmission error abort */ + if( (gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) && (ret != ERR_NONE) && (ret != ERR_TIMEOUT) ) + { + break; + } + + platformDelay(1); + } + while( ((RATSretries--) != 0U) && (ret != ERR_NONE) ); + + + + /* Switch between NFC Forum and ISO14443-4 behaviour #595 + * ISO14443-4 5.6.1 If RATS fails, a Deactivation sequence should be performed as defined on clause 8 + * Activity 1.1 9.6 Device Deactivation Activity is to be only performed when there's an active device */ + if( ret != ERR_NONE ) + { + if( gIsoDep.compMode == RFAL_COMPLIANCE_MODE_ISO ) + { + rfalIsoDepDeselect(); + } + return ret; + } + + /*******************************************************************************/ + /* Process ATS Response */ + isoDepDev->info.FWI = RFAL_ISODEP_FWI_DEFAULT; /* Default value EMVCo 2.6 5.7.2.6 */ + isoDepDev->info.SFGI = 0; + isoDepDev->info.MBL = 0; + isoDepDev->info.DSI = RFAL_BR_106; + isoDepDev->info.DRI = RFAL_BR_106; + isoDepDev->info.FSxI = (uint8_t)RFAL_ISODEP_FSXI_32; /* FSC default value is 32 bytes ISO14443-A 5.2.3 */ + + + /*******************************************************************************/ + /* Check for ATS optional fields */ + if( isoDepDev->activation.A.Listener.ATS.TL > RFAL_ISODEP_ATS_MIN_LEN ) + { + msgIt = RFAL_ISODEP_ATS_MIN_LEN; + + /* Format byte T0 is optional, if present assign FSDI */ + isoDepDev->info.FSxI = (isoDepDev->activation.A.Listener.ATS.T0 & RFAL_ISODEP_ATS_T0_FSCI_MASK); + + /* T0 has already been processed, always the same position */ + msgIt++; + + /* Check if TA is present */ + if( (isoDepDev->activation.A.Listener.ATS.T0 & RFAL_ISODEP_ATS_T0_TA_PRESENCE_MASK) != 0U ) + { + rfalIsoDepCalcBitRate( maxBR, ((uint8_t*)&isoDepDev->activation.A.Listener.ATS)[msgIt++], &isoDepDev->info.DSI, &isoDepDev->info.DRI ); + } + + /* Check if TB is present */ + if( (isoDepDev->activation.A.Listener.ATS.T0 & RFAL_ISODEP_ATS_T0_TB_PRESENCE_MASK) != 0U ) + { + isoDepDev->info.SFGI = ((uint8_t*)&isoDepDev->activation.A.Listener.ATS)[msgIt++]; + isoDepDev->info.FWI = (uint8_t)((isoDepDev->info.SFGI >> RFAL_ISODEP_ATS_TB_FWI_SHIFT) & RFAL_ISODEP_ATS_FWI_MASK); + isoDepDev->info.SFGI &= RFAL_ISODEP_ATS_TB_SFGI_MASK; + } + + /* Check if TC is present */ + if( (isoDepDev->activation.A.Listener.ATS.T0 & RFAL_ISODEP_ATS_T0_TC_PRESENCE_MASK) != 0U ) + { + /* Check for Protocol features support */ + /* Advanced protocol features defined on Digital 1.0 Table 69, removed after */ + isoDepDev->info.supAdFt = (((((uint8_t*)&isoDepDev->activation.A.Listener.ATS)[msgIt] & RFAL_ISODEP_ATS_TC_ADV_FEAT) != 0U) ? true : false); + isoDepDev->info.supDID = (((((uint8_t*)&isoDepDev->activation.A.Listener.ATS)[msgIt] & RFAL_ISODEP_ATS_TC_DID) != 0U) ? true : false); + isoDepDev->info.supNAD = (((((uint8_t*)&isoDepDev->activation.A.Listener.ATS)[msgIt++] & RFAL_ISODEP_ATS_TC_NAD) != 0U) ? true : false); + } + } + + isoDepDev->info.FSx = rfalIsoDepFSxI2FSx(isoDepDev->info.FSxI); + + isoDepDev->info.SFGT = rfalIsoDepSFGI2SFGT( (uint8_t)isoDepDev->info.SFGI ); + isoDepTimerStart( gIsoDep.SFGTTimer, isoDepDev->info.SFGT ); + + isoDepDev->info.FWT = rfalIsoDepFWI2FWT( isoDepDev->info.FWI ); + isoDepDev->info.dFWT = RFAL_ISODEP_DFWT_20; + + isoDepDev->info.DID = ( (isoDepDev->info.supDID) ? DID : RFAL_ISODEP_NO_DID); + isoDepDev->info.NAD = RFAL_ISODEP_NO_NAD; + + + /*******************************************************************************/ + /* If higher bit rates are supported by both devices, send PPS */ + if( (isoDepDev->info.DSI != RFAL_BR_106) || (isoDepDev->info.DRI != RFAL_BR_106) ) + { + /* Wait until SFGT has been fulfilled */ + while( !isoDepTimerisExpired( gIsoDep.SFGTTimer ) ) { /* MISRA 15.6: mandatory brackets */ }; + + ret = rfalIsoDepPPS( isoDepDev->info.DID, isoDepDev->info.DSI, isoDepDev->info.DRI, &ppsRes ); + + if( ret == ERR_NONE ) + { + /* DSI code the divisor from PICC to PCD */ + /* DRI code the divisor from PCD to PICC */ + rfalSetBitRate( isoDepDev->info.DRI, isoDepDev->info.DSI ); + } + else + { + isoDepDev->info.DSI = RFAL_BR_106; + isoDepDev->info.DRI = RFAL_BR_106; + } + } + + /*******************************************************************************/ + /* Store already FS info, rfalIsoDepGetMaxInfLen() may be called before setting TxRx params */ + gIsoDep.fsx = isoDepDev->info.FSx; + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx( (uint8_t)FSDI ); + + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCB + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollBHandleActivation( rfalIsoDepFSxI FSDI, uint8_t DID, rfalBitRate maxBR, uint8_t PARAM1, const rfalNfcbListenDevice *nfcbDev, const uint8_t* HLInfo, uint8_t HLInfoLen, rfalIsoDepDevice *isoDepDev ) +{ + ReturnCode ret; + uint8_t mbli; + + /***************************************************************************/ + /* Initialize ISO-DEP Device with info from SENSB_RES */ + isoDepDev->info.FWI = ((nfcbDev->sensbRes.protInfo.FwiAdcFo >> RFAL_NFCB_SENSB_RES_FWI_SHIFT) & RFAL_NFCB_SENSB_RES_FWI_MASK); + isoDepDev->info.FWT = rfalIsoDepFWI2FWT( isoDepDev->info.FWI ); + isoDepDev->info.dFWT = RFAL_NFCB_DFWT; + isoDepDev->info.SFGI = (((uint32_t)nfcbDev->sensbRes.protInfo.SFGI >> RFAL_NFCB_SENSB_RES_SFGI_SHIFT) & RFAL_NFCB_SENSB_RES_SFGI_MASK); + isoDepDev->info.SFGT = rfalIsoDepSFGI2SFGT( (uint8_t)isoDepDev->info.SFGI ); + isoDepDev->info.FSxI = ((nfcbDev->sensbRes.protInfo.FsciProType >> RFAL_NFCB_SENSB_RES_FSCI_SHIFT) & RFAL_NFCB_SENSB_RES_FSCI_MASK); + isoDepDev->info.FSx = rfalIsoDepFSxI2FSx(isoDepDev->info.FSxI); + isoDepDev->info.DID = DID; + isoDepDev->info.supDID = ((( nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_FO_DID_MASK ) != 0U) ? true : false); + isoDepDev->info.supNAD = ((( nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_FO_NAD_MASK ) != 0U) ? true : false); + + + /* Check if DID requested is supported by PICC */ + if( (DID != RFAL_ISODEP_NO_DID) && (!isoDepDev->info.supDID) ) + { + return ERR_PARAM; + } + + /* Enable EMD handling according Digital 2.1 4.1.1.1 ; EMVCo 3.0 4.9.2 */ + rfalSetErrorHandling( RFAL_ERRORHANDLING_EMVCO ); + + /***************************************************************************/ + /* Set FDT Poll to be used on upcoming communications */ + if( gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV ) + { + /* Disregard Minimum TR2 returned by PICC, always use FDTb MIN EMVCo 3.0 6.3.2.10 */ + rfalSetFDTPoll( RFAL_FDT_POLL_NFCB_POLLER ); + } + else + { + /* Apply minimum TR2 from SENSB_RES Digital 2.1 7.6.2.23 */ + rfalSetFDTPoll( rfalNfcbTR2ToFDT(((nfcbDev->sensbRes.protInfo.FsciProType >>RFAL_NFCB_SENSB_RES_PROTO_TR2_SHIFT) & RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK)) ); + } + + + /* Calculate max Bit Rate */ + rfalIsoDepCalcBitRate( maxBR, nfcbDev->sensbRes.protInfo.BRC, &isoDepDev->info.DSI, &isoDepDev->info.DRI ); + + /***************************************************************************/ + /* Send ATTRIB Command */ + ret = rfalIsoDepATTRIB( (const uint8_t*)&nfcbDev->sensbRes.nfcid0, + (((nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_ADC_ADV_FEATURE_MASK) != 0U) ? PARAM1 : RFAL_ISODEP_ATTRIB_REQ_PARAM1_DEFAULT), + isoDepDev->info.DSI, + isoDepDev->info.DRI, + FSDI, + (gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) ? RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK : (nfcbDev->sensbRes.protInfo.FsciProType & ( (RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK<info.FWT + isoDepDev->info.dFWT), + &isoDepDev->activation.B.Listener.ATTRIB_RES, + &isoDepDev->activation.B.Listener.ATTRIB_RESLen + ); + + /***************************************************************************/ + /* Process ATTRIB Response */ + if( ret == ERR_NONE ) + { + /* Digital 1.1 14.6.2.3 - Check if received DID match */ + if( (isoDepDev->activation.B.Listener.ATTRIB_RES.mbliDid & RFAL_ISODEP_ATTRIB_RES_DID_MASK) != DID ) + { + return ERR_PROTO; + } + + /* Retrieve MBLI and calculate new FDS/MBL (Maximum Buffer Length) */ + mbli = ((isoDepDev->activation.B.Listener.ATTRIB_RES.mbliDid >> RFAL_ISODEP_ATTRIB_RES_MBLI_SHIFT) & RFAL_ISODEP_ATTRIB_RES_MBLI_MASK); + if( mbli > 0U) + { + /* Digital 1.1 14.6.2 Calculate Maximum Buffer Length MBL = FSC x 2^(MBLI-1) */ + isoDepDev->info.MBL = (isoDepDev->info.FSx * ((uint32_t)1U<<(mbli-1U))); + } + + /* DSI code the divisor from PICC to PCD */ + /* DRI code the divisor from PCD to PICC */ + rfalSetBitRate( isoDepDev->info.DRI, isoDepDev->info.DSI ); + + + if( (nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_ADC_ADV_FEATURE_MASK) != 0U ) + { + /* REMARK: SoF EoF TR0 and TR1 are not passed on to RF layer */ + } + + /* Start the SFGT timer */ + isoDepTimerStart( gIsoDep.SFGTTimer, isoDepDev->info.SFGT ); + } + else + { + isoDepDev->info.DSI = RFAL_BR_106; + isoDepDev->info.DRI = RFAL_BR_106; + } + + /*******************************************************************************/ + /* Store already FS info, rfalIsoDepGetMaxInfLen() may be called before setting TxRx params */ + gIsoDep.fsx = isoDepDev->info.FSx; + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx( (uint8_t)FSDI ); + + return ret; +} + +#endif /* RFAL_FEATURE_NFCB */ + + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollHandleSParameters( rfalIsoDepDevice *isoDepDev, rfalBitRate maxTxBR, rfalBitRate maxRxBR ) +{ + uint8_t it; + uint8_t supPCD2PICC; + uint8_t supPICC2PCD; + uint8_t currenttxBR; + uint8_t currentrxBR; + rfalBitRate txBR; + rfalBitRate rxBR; + uint16_t rcvLen; + ReturnCode ret; + rfalIsoDepControlMsgSParam sParam; + + + if( (isoDepDev == NULL) || (maxTxBR > RFAL_BR_13560) || (maxRxBR > RFAL_BR_13560) ) + { + return ERR_PARAM; + } + + it = 0; + supPICC2PCD = 0x00; + supPCD2PICC = 0x00; + txBR = RFAL_BR_106; + rxBR = RFAL_BR_106; + sParam.pcb = ISODEP_PCB_SPARAMETERS; + + /*******************************************************************************/ + /* Send S(PARAMETERS) - Block Info */ + sParam.sParam.tag = RFAL_ISODEP_SPARAM_TAG_BLOCKINFO; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_BRREQ; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_BRREQ_LEN; + sParam.sParam.length = it; + + EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&sParam, (RFAL_ISODEP_SPARAM_HDR_LEN + (uint16_t)it), (uint8_t*)&sParam, sizeof(rfalIsoDepControlMsgSParam), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, (isoDepDev->info.FWT + isoDepDev->info.dFWT) )); + + it = 0; + + /*******************************************************************************/ + /* Check S(PARAMETERS) response */ + if( (sParam.pcb != ISODEP_PCB_SPARAMETERS) || (sParam.sParam.tag != RFAL_ISODEP_SPARAM_TAG_BLOCKINFO) || + (sParam.sParam.value[it] != RFAL_ISODEP_SPARAM_TAG_BRIND) || (rcvLen < RFAL_ISODEP_SPARAM_HDR_LEN) || + (rcvLen != ((uint16_t)sParam.sParam.length + RFAL_ISODEP_SPARAM_HDR_LEN)) ) + { + return ERR_PROTO; + } + + /* Retrieve PICC's bit rate PICC capabilities */ + for( it=0; it<(rcvLen-(uint16_t)RFAL_ISODEP_SPARAM_TAG_LEN); it++ ) + { + if( (sParam.sParam.value[it] == RFAL_ISODEP_SPARAM_TAG_SUP_PCD2PICC) && (sParam.sParam.value[it+(uint16_t)RFAL_ISODEP_SPARAM_TAG_LEN] == RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN) ) + { + supPCD2PICC = sParam.sParam.value[it + RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN]; + } + + if( (sParam.sParam.value[it] == RFAL_ISODEP_SPARAM_TAG_SUP_PICC2PCD) && (sParam.sParam.value[it+(uint16_t)RFAL_ISODEP_SPARAM_TAG_LEN] == RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN) ) + { + supPICC2PCD = sParam.sParam.value[it + RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN]; + } + } + + /*******************************************************************************/ + /* Check if requested bit rates are supported by PICC */ + if( (supPICC2PCD == 0x00U) || (supPCD2PICC == 0x00U) ) + { + return ERR_PROTO; + } + + for( it=0; it<=(uint8_t)maxTxBR; it++ ) + { + if( (supPCD2PICC & (0x01U << it)) != 0U ) + { + txBR = (rfalBitRate)it; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and above clamping of maxTxBR guarantee no invalid enum values to be created */ + } + } + for( it=0; it<=(uint8_t)maxRxBR; it++ ) + { + if( (supPICC2PCD & (0x01U << it)) != 0U ) + { + rxBR = (rfalBitRate)it; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and above clamping of maxTxBR guarantee no invalid enum values to be created */ + } + } + + it = 0; + currenttxBR = (uint8_t)txBR; + currentrxBR = (uint8_t)rxBR; + + /*******************************************************************************/ + /* Send S(PARAMETERS) - Bit rates Activation */ + sParam.sParam.tag = RFAL_ISODEP_SPARAM_TAG_BLOCKINFO; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_BRACT; + sParam.sParam.value[it++] = ( RFAL_ISODEP_SPARAM_TVL_HDR_LEN + RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN + RFAL_ISODEP_SPARAM_TVL_HDR_LEN + RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN); + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_SEL_PCD2PICC; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN; + sParam.sParam.value[it++] = ((uint8_t)0x01U << currenttxBR); + sParam.sParam.value[it++] = 0x00U; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_SEL_PICC2PCD; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN; + sParam.sParam.value[it++] = ((uint8_t)0x01U << currentrxBR); + sParam.sParam.value[it++] = 0x00U; + sParam.sParam.length = it; + + EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&sParam, (RFAL_ISODEP_SPARAM_HDR_LEN + (uint16_t)it), (uint8_t*)&sParam, sizeof(rfalIsoDepControlMsgSParam), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, (isoDepDev->info.FWT + isoDepDev->info.dFWT) )); + + it = 0; + + /*******************************************************************************/ + /* Check S(PARAMETERS) Acknowledge */ + if( (sParam.pcb != ISODEP_PCB_SPARAMETERS) || (sParam.sParam.tag != RFAL_ISODEP_SPARAM_TAG_BLOCKINFO) || + (sParam.sParam.value[it] != RFAL_ISODEP_SPARAM_TAG_BRACK) || (rcvLen < RFAL_ISODEP_SPARAM_HDR_LEN) ) + { + return ERR_PROTO; + } + + EXIT_ON_ERR( ret, rfalSetBitRate( txBR, rxBR ) ); + + isoDepDev->info.DRI = txBR; + isoDepDev->info.DSI = rxBR; + + return ERR_NONE; +} + + +/*******************************************************************************/ +static void rfalIsoDepCalcBitRate( rfalBitRate maxAllowedBR, uint8_t piccBRCapability, rfalBitRate *dsi, rfalBitRate *dri ) +{ + uint8_t driMask; + uint8_t dsiMask; + int8_t i; + bool bitrateFound; + rfalBitRate curMaxBR; + + curMaxBR = maxAllowedBR; + + do + { + bitrateFound = true; + + (*dsi) = RFAL_BR_106; + (*dri) = RFAL_BR_106; + + /* Digital 1.0 5.6.2.5 & 11.6.2.14: A received RFU value of b4 = 1b MUST be interpreted as if b7 to b1 ? 0000000b (only 106 kbits/s in both direction) */ + if( ((RFAL_ISODEP_BITRATE_RFU_MASK & piccBRCapability) != 0U) || (curMaxBR > RFAL_BR_848) ) + { + return; + } + + /***************************************************************************/ + /* Determine Listen->Poll bit rate */ + dsiMask = (piccBRCapability & RFAL_ISODEP_BSI_MASK); + for( i = 2; i >= 0; i-- ) // Check supported bit rate from the highest + { + if (((dsiMask & (0x10U << (uint8_t)i)) != 0U) && (((uint8_t)i+1U) <= (uint8_t)curMaxBR)) + { + uint8_t newdsi = ((uint8_t) i) + 1U; + (*dsi) = (rfalBitRate)newdsi; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and range of loop variable guarantee no invalid enum values to be created */ + break; + } + } + + /***************************************************************************/ + /* Determine Poll->Listen bit rate */ + driMask = (piccBRCapability & RFAL_ISODEP_BRI_MASK); + for( i = 2; i >= 0; i-- ) /* Check supported bit rate from the highest */ + { + if (((driMask & (0x01U << (uint8_t)i)) != 0U) && (((uint8_t)i+1U) <= (uint8_t)curMaxBR)) + { + uint8_t newdri = ((uint8_t) i) + 1U; + (*dri) = (rfalBitRate)newdri; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and range of loop variable guarantee no invalid enum values to be created */ + break; + } + } + + /***************************************************************************/ + /* Check if different bit rate is supported */ + + /* Digital 1.0 Table 67: if b8=1b, then only the same bit rate divisor for both directions is supported */ + if( (piccBRCapability & RFAL_ISODEP_SAME_BITRATE_MASK) != 0U ) + { + (*dsi) = MIN((*dsi), (*dri)); + (*dri) = (*dsi); + /* Check that the baudrate is supported */ + if( (RFAL_BR_106 != (*dsi)) && ( !(((dsiMask & (0x10U << ((uint8_t)(*dsi) - 1U))) != 0U) && ((driMask & (0x01U << ((uint8_t)(*dri) - 1U))) != 0U)) ) ) + { + bitrateFound = false; + curMaxBR = (*dsi); /* set allowed bitrate to be lowest and determine bit rate again */ + } + } + } while (!(bitrateFound)); + +} + +/*******************************************************************************/ +static uint32_t rfalIsoDepSFGI2SFGT( uint8_t sfgi ) +{ + uint32_t sfgt; + uint8_t tmpSFGI; + + tmpSFGI = sfgi; + + if (tmpSFGI > ISODEP_SFGI_MAX) + { + tmpSFGI = ISODEP_SFGI_MIN; + } + + if (tmpSFGI != ISODEP_SFGI_MIN) + { + /* If sfgi != 0 wait SFGT + dSFGT Digital 1.1 13.8.2.1 */ + sfgt = isoDepCalcSGFT(sfgi) + isoDepCalcdSGFT(sfgi); + } + /* Otherwise use FDTPoll min Digital 1.1 13.8.2.3*/ + else + { + sfgt = RFAL_FDT_POLL_NFCA_POLLER; + } + + /* Convert carrier cycles to milli seconds */ + return (rfalConv1fcToMs(sfgt) + 1U); +} + +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + + + /*******************************************************************************/ + static void rfalIsoDepApdu2IBLockParam( rfalIsoDepApduTxRxParam apduParam, rfalIsoDepTxRxParam *iBlockParam, uint16_t txPos, uint16_t rxPos ) +{ + NO_WARNING(rxPos); /* Keep this param for future use */ + + iBlockParam->DID = apduParam.DID; + iBlockParam->FSx = apduParam.FSx; + iBlockParam->ourFSx = apduParam.ourFSx; + iBlockParam->FWT = apduParam.FWT; + iBlockParam->dFWT = apduParam.dFWT; + + if( (apduParam.txBufLen - txPos) > rfalIsoDepGetMaxInfLen() ) + { + iBlockParam->isTxChaining = true; + iBlockParam->txBufLen = rfalIsoDepGetMaxInfLen(); + } + else + { + iBlockParam->isTxChaining = false; + iBlockParam->txBufLen = (apduParam.txBufLen - txPos); + } + + /* TxBuf is moved to the beginning for every I-Block */ + iBlockParam->txBuf = (rfalIsoDepBufFormat*)apduParam.txBuf; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */ + iBlockParam->rxBuf = apduParam.tmpBuf; /* Simply using the apdu buffer is not possible because of current ACK handling */ + iBlockParam->isRxChaining = &gIsoDep.isAPDURxChaining; + iBlockParam->rxLen = apduParam.rxLen; +} + + +/*******************************************************************************/ +ReturnCode rfalIsoDepStartApduTransceive( rfalIsoDepApduTxRxParam param ) +{ + rfalIsoDepTxRxParam txRxParam; + + /* Initialize and store APDU context */ + gIsoDep.APDUParam = param; + gIsoDep.APDUTxPos = 0; + gIsoDep.APDURxPos = 0; + + /* Assign current FSx to calculate INF length */ + gIsoDep.ourFsx = param.ourFSx; + gIsoDep.fsx = param.FSx; + + /* Convert APDU TxRxParams to I-Block TxRxParams */ + rfalIsoDepApdu2IBLockParam( gIsoDep.APDUParam, &txRxParam, gIsoDep.APDUTxPos, gIsoDep.APDURxPos ); + + return rfalIsoDepStartTransceive( txRxParam ); +} + + +/*******************************************************************************/ +ReturnCode rfalIsoDepGetApduTransceiveStatus( void ) +{ + ReturnCode ret; + rfalIsoDepTxRxParam txRxParam; + + ret = rfalIsoDepGetTransceiveStatus(); + switch( ret ) + { + /*******************************************************************************/ + case ERR_NONE: + + /* Check if we are still doing chaining on Tx */ + if( gIsoDep.isTxChaining ) + { + /* Add already Tx bytes */ + gIsoDep.APDUTxPos += gIsoDep.txBufLen; + + /* Convert APDU TxRxParams to I-Block TxRxParams */ + rfalIsoDepApdu2IBLockParam( gIsoDep.APDUParam, &txRxParam, gIsoDep.APDUTxPos, gIsoDep.APDURxPos ); + + if( txRxParam.txBufLen > 0U ) /* MISRA 21.18 */ + { + /* Move next I-Block to beginning of APDU Tx buffer */ + ST_MEMCPY( gIsoDep.APDUParam.txBuf->apdu, &gIsoDep.APDUParam.txBuf->apdu[gIsoDep.APDUTxPos], txRxParam.txBufLen ); + } + + rfalIsoDepStartTransceive( txRxParam ); + return ERR_BUSY; + } + + if( *gIsoDep.APDUParam.rxLen > 0U ) /* MISRA 21.18 */ + { + /* Copy packet from tmp buffer to APDU buffer */ + ST_MEMCPY( &gIsoDep.APDUParam.rxBuf->apdu[gIsoDep.APDURxPos], gIsoDep.APDUParam.tmpBuf->inf, *gIsoDep.APDUParam.rxLen ); + gIsoDep.APDURxPos += *gIsoDep.APDUParam.rxLen; + } + + /* APDU TxRx is done */ + break; + + /*******************************************************************************/ + case ERR_AGAIN: + + if( *gIsoDep.APDUParam.rxLen > 0U ) /* MISRA 21.18 */ + { + /* Copy chained packet from tmp buffer to APDU buffer */ + ST_MEMCPY( &gIsoDep.APDUParam.rxBuf->apdu[gIsoDep.APDURxPos], gIsoDep.APDUParam.tmpBuf->inf, *gIsoDep.APDUParam.rxLen ); + gIsoDep.APDURxPos += *gIsoDep.APDUParam.rxLen; + } + + /* Wait for next I-Block */ + return ERR_BUSY; + + /*******************************************************************************/ + default: + return ret; + } + + *gIsoDep.APDUParam.rxLen = gIsoDep.APDURxPos; + + return ERR_NONE; + } + +#endif /* RFAL_FEATURE_ISO_DEP */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_nfc.c b/Software/fab-reader2-c/components/rfal/Src/rfal_nfc.c new file mode 100644 index 0000000..26223d1 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_nfc.c @@ -0,0 +1,1684 @@ +/** + ****************************************************************************** + * + * COPYRIGHT(c) 2017 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/*! \file rfal_nfc.c + * + * \author Gustavo Patricio + * + * \brief RFAL NFC device + * + * This module provides the required features to behave as an NFC Poller + * or Listener device. It grants an easy to use interface for the following + * activities: Technology Detection, Collision Resollution, Activation, + * Data Exchange, and Deactivation + * + * This layer is influenced by (but not fully aligned with) the NFC Forum + * specifications, in particular: Activity 2.0 and NCI 2.0 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_nfc.h" +#include "utils.h" +#include "rfal_analogConfig.h" + + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define RFAL_NFC_MAX_DEVICES 5U /* Max number of devices supported */ + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define rfalNfcIsRemDevPoller( tp ) ( ((tp)>= RFAL_NFC_POLL_TYPE_NFCA) && ((tp)<=RFAL_NFC_POLL_TYPE_AP2P ) ) +#define rfalNfcIsRemDevListener( tp ) ( /*((tp)>= RFAL_NFC_LISTEN_TYPE_NFCA) && */ ((tp)<=RFAL_NFC_LISTEN_TYPE_AP2P) ) + +#define rfalNfcNfcNotify( st ) if( gNfcDev.disc.notifyCb != NULL ) gNfcDev.disc.notifyCb( st ) + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +typedef struct{ + rfalNfcState state; /* Main state */ + uint16_t techsFound; /* Technologies found bitmask */ + uint16_t techs2do; /* Technologies still to be performed */ + rfalBitRate ap2pBR; /* Bit rate to poll for AP2P */ + uint8_t selDevIdx; /* Selected device index */ + rfalNfcDevice *activeDev; /* Active device pointer */ + rfalNfcDiscoverParam disc; /* Discovery parameters pointer */ + rfalNfcDevice devList[RFAL_NFC_MAX_DEVICES]; /*!< Location of device list */ + uint8_t devCnt; /* Decices found counter */ + uint32_t discTmr; /* Discovery Total duration timer */ + ReturnCode dataExErr; /* Last Data Exchange error */ + bool discRestart; /* Restart discover after deactivation flag */ + bool isRxChaining; /* Flag indicating Other device is chaining */ + uint32_t lmMask; /* Listen Mode mask */ + + rfalNfcBuffer txBuf; /* Tx buffer for Data Exchange */ + rfalNfcBuffer rxBuf; /* Rx buffer for Data Exchange */ + uint16_t rxLen; /* Length of received data on Data Exchange */ +}rfalNfc; + + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ +static rfalNfc gNfcDev; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode rfalNfcPollTechDetetection( void ); +static ReturnCode rfalNfcPollCollResolution( void ); +static ReturnCode rfalNfcPollActivation( uint8_t devIt ); +static ReturnCode rfalNfcDeactivation( void ); + +#if RFAL_FEATURE_NFC_DEP +static ReturnCode rfalNfcNfcDepActivate( rfalNfcDevice *device, rfalNfcDepCommMode commMode, const uint8_t *atrReq, uint16_t atrReqLen ); +#endif /* RFAL_FEATURE_NFC_DEP */ + +#if RFAL_FEATURE_LISTEN_MODE +static ReturnCode rfalNfcListenActivation( void ); +#endif /* RFAL_FEATURE_LISTEN_MODE*/ + + +/*******************************************************************************/ +ReturnCode rfalNfcInitialize( void ) +{ + ReturnCode err; + + gNfcDev.state = RFAL_NFC_STATE_NOTINIT; + + rfalAnalogConfigInitialize(); /* Initialize RFAL's Analog Configs */ + EXIT_ON_ERR( err, rfalInitialize() ); /* Initialize RFAL */ + + gNfcDev.state = RFAL_NFC_STATE_IDLE; /* Go to initialized */ + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDiscover( const rfalNfcDiscoverParam *disParams ) +{ + /* Check if initialization has been performed */ + if( gNfcDev.state != RFAL_NFC_STATE_IDLE ) + { + return ERR_WRONG_STATE; + } + + /* Check valid parameters */ + if( (disParams == NULL) || (disParams->devLimit > RFAL_NFC_MAX_DEVICES) || (disParams->devLimit == 0U) || + ( ((disParams->techs2Find & RFAL_NFC_POLL_TECH_F) != 0U) && (disParams->nfcfBR != RFAL_BR_212) && (disParams->nfcfBR != RFAL_BR_424) ) || + ( (((disParams->techs2Find & RFAL_NFC_POLL_TECH_AP2P) != 0U) && (disParams->ap2pBR > RFAL_BR_424)) || (disParams->GBLen > RFAL_NFCDEP_GB_MAX_LEN)) ) + { + return ERR_PARAM; + } + + if( (((disParams->techs2Find & RFAL_NFC_POLL_TECH_A) != 0U) && !((bool)RFAL_FEATURE_NFCA)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_B) != 0U) && !((bool)RFAL_FEATURE_NFCB)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_F) != 0U) && !((bool)RFAL_FEATURE_NFCF)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_V) != 0U) && !((bool)RFAL_FEATURE_NFCV)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_ST25TB) != 0U) && !((bool)RFAL_FEATURE_ST25TB)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_AP2P) != 0U) && !((bool)RFAL_FEATURE_NFC_DEP)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_A) != 0U) && !((bool)RFAL_FEATURE_NFCA)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_B) != 0U) && !((bool)RFAL_FEATURE_NFCB)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_F) != 0U) && !((bool)RFAL_FEATURE_NFCF)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_AP2P) != 0U) && !((bool)RFAL_FEATURE_NFC_DEP)) ) + { + return ERR_DISABLED; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ + } + + /* Initialize context for discovery */ + gNfcDev.activeDev = NULL; + gNfcDev.techsFound = RFAL_NFC_TECH_NONE; + gNfcDev.devCnt = 0; + gNfcDev.discRestart = true; + gNfcDev.disc = *disParams; + + + /* Calculate Listen Mask */ + gNfcDev.lmMask = 0U; + gNfcDev.lmMask |= (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_A) != 0U) ? RFAL_LM_MASK_NFCA : 0U); + gNfcDev.lmMask |= (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_B) != 0U) ? RFAL_LM_MASK_NFCB : 0U); + gNfcDev.lmMask |= (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_F) != 0U) ? RFAL_LM_MASK_NFCF : 0U); + gNfcDev.lmMask |= (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_AP2P) != 0U) ? RFAL_LM_MASK_ACTIVE_P2P : 0U); + +#if !RFAL_FEATURE_LISTEN_MODE + /* Check if Listen Mode is supported/Enabled */ + if( gNfcDev.lmMask != 0U ) + { + return ERR_NOTSUPP; + } +#endif + + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDeactivate( bool discovery ) +{ + /* Check for valid state */ + if( gNfcDev.state <= RFAL_NFC_STATE_IDLE ) + { + return ERR_WRONG_STATE; + } + + /* Check if discovery is to continue afterwards */ + if( discovery == true ) + { + /* If so let the state machine continue*/ + gNfcDev.discRestart = discovery; + gNfcDev.state = RFAL_NFC_STATE_DEACTIVATION; + } + else + { + /* Otherwise deactivate immediately and go to IDLE */ + rfalNfcDeactivation(); + gNfcDev.state = RFAL_NFC_STATE_IDLE; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcSelect( uint8_t devIdx ) +{ + /* Check for valid state */ + if( gNfcDev.state != RFAL_NFC_STATE_POLL_SELECT ) + { + return ERR_WRONG_STATE; + } + + gNfcDev.selDevIdx = devIdx; + gNfcDev.state = RFAL_NFC_STATE_POLL_ACTIVATION; + + return ERR_NONE; +} + +/*******************************************************************************/ +rfalNfcState rfalNfcGetState( void ) +{ + return gNfcDev.state; +} + +/*******************************************************************************/ +ReturnCode rfalNfcGetDevicesFound( rfalNfcDevice **devList, uint8_t *devCnt ) +{ + /* Check for valid state */ + if( gNfcDev.state < RFAL_NFC_STATE_POLL_SELECT ) + { + return ERR_WRONG_STATE; + } + + /* Check valid parameters */ + if( (devList == NULL) || (devCnt == NULL) ) + { + return ERR_PARAM; + } + + *devCnt = gNfcDev.devCnt; + *devList = gNfcDev.devList; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcGetActiveDevice( rfalNfcDevice **dev ) +{ + /* Check for valid state */ + if( gNfcDev.state < RFAL_NFC_STATE_ACTIVATED ) + { + return ERR_WRONG_STATE; + } + + /* Check valid parameter */ + if( dev == NULL ) + { + return ERR_PARAM; + } + + /* Check for valid state */ + if( (gNfcDev.devCnt == 0U) || (gNfcDev.activeDev == NULL) ) + { + return ERR_REQUEST; + } + + *dev = gNfcDev.activeDev; + return ERR_NONE; +} + +/*******************************************************************************/ +void rfalNfcWorker( void ) +{ + ReturnCode err; + + rfalWorker(); /* Execute RFAL process */ + + switch( gNfcDev.state ) + { + /*******************************************************************************/ + case RFAL_NFC_STATE_NOTINIT: + case RFAL_NFC_STATE_IDLE: + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_START_DISCOVERY: + + /* Initialize context for discovery cycle */ + gNfcDev.devCnt = 0; + gNfcDev.selDevIdx = 0; + gNfcDev.techsFound = RFAL_NFC_TECH_NONE; + gNfcDev.techs2do = gNfcDev.disc.techs2Find; + gNfcDev.state = RFAL_NFC_STATE_POLL_TECHDETECT; + + #if RFAL_FEATURE_WAKEUP_MODE + /* Check if Low power Wake-Up is to be performed */ + if( gNfcDev.disc.wakeupEnabled ) + { + /* Initialize Low power Wake-up mode and wait */ + err = rfalWakeUpModeStart( (gNfcDev.disc.wakeupConfigDefault ? NULL : &gNfcDev.disc.wakeupConfig) ); + if( err == ERR_NONE ) + { + gNfcDev.state = RFAL_NFC_STATE_WAKEUP_MODE; + rfalNfcNfcNotify( gNfcDev.state ); /* Notify caller that WU was started */ + } + } + #endif /* RFAL_FEATURE_WAKEUP_MODE */ + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_WAKEUP_MODE: + + #if RFAL_FEATURE_WAKEUP_MODE + /* Check if the Wake-up mode has woke */ + if( rfalWakeUpModeHasWoke() ) + { + rfalWakeUpModeStop(); /* Disable Wake-up mode */ + gNfcDev.state = RFAL_NFC_STATE_POLL_TECHDETECT; /* Go to Technology detection */ + + rfalNfcNfcNotify( gNfcDev.state ); /* Notify caller that WU has woke */ + } + #endif /* RFAL_FEATURE_WAKEUP_MODE */ + + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_POLL_TECHDETECT: + + /* Start total duration timer */ + gNfcDev.discTmr = (uint32_t)platformTimerCreate( gNfcDev.disc.totalDuration ); + + err = rfalNfcPollTechDetetection(); /* Perform Technology Detection */ + if( err != ERR_BUSY ) /* Wait until all technologies are performed */ + { + if( ( err != ERR_NONE) || (gNfcDev.techsFound == RFAL_NFC_TECH_NONE) )/* Check if any error occurred or no techs were found */ + { + rfalFieldOff(); + gNfcDev.state = RFAL_NFC_STATE_LISTEN_TECHDETECT; /* Nothing found as poller, go to listener */ + break; + } + + gNfcDev.techs2do = gNfcDev.techsFound; /* Store the found technologies for collision resolution */ + gNfcDev.state = RFAL_NFC_STATE_POLL_COLAVOIDANCE; /* One or more devices found, go to Collision Avoidance */ + } + break; + + + /*******************************************************************************/ + case RFAL_NFC_STATE_POLL_COLAVOIDANCE: + + err = rfalNfcPollCollResolution(); /* Resolve any eventual collision */ + if( err != ERR_BUSY ) /* Wait until all technologies are performed */ + { + if( (err != ERR_NONE) || (gNfcDev.devCnt == 0U) ) /* Check if any error occurred or no devices were found */ + { + gNfcDev.state = RFAL_NFC_STATE_DEACTIVATION; + break; /* Unable to retrieve any device, restart loop */ + } + + /* Check if more than one device has been found */ + if( gNfcDev.devCnt > 1U ) + { + /* If more than one device was found inform upper layer to choose which one to activate */ + if( gNfcDev.disc.notifyCb != NULL ) + { + gNfcDev.state = RFAL_NFC_STATE_POLL_SELECT; + gNfcDev.disc.notifyCb( gNfcDev.state ); + break; + } + } + + /* If only one device or no callback has been set, activate the first device found */ + gNfcDev.selDevIdx = 0U; + gNfcDev.state = RFAL_NFC_STATE_POLL_ACTIVATION; + } + break; + + + /*******************************************************************************/ + case RFAL_NFC_STATE_POLL_ACTIVATION: + + if( rfalNfcPollActivation( gNfcDev.selDevIdx ) != ERR_NONE ) /* Activate selected device */ + { + gNfcDev.state = RFAL_NFC_STATE_DEACTIVATION; /* If Activation failed, restart loop */ + break; + } + + gNfcDev.state = RFAL_NFC_STATE_ACTIVATED; /* Device has been properly activated */ + rfalNfcNfcNotify( gNfcDev.state ); /* Inform upper layer that a device has been activated */ + break; + + + /*******************************************************************************/ + case RFAL_NFC_STATE_DATAEXCHANGE: + + rfalNfcDataExchangeGetStatus(); /* Run the internal state machine */ + + if( gNfcDev.dataExErr != ERR_BUSY ) /* If Dataexchange has terminated */ + { + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; /* Go to done state */ + rfalNfcNfcNotify( gNfcDev.state ); /* And notify caller */ + } + if( gNfcDev.dataExErr == ERR_SLEEP_REQ ) /* Check if Listen mode has to go to Sleep */ + { + gNfcDev.state = RFAL_NFC_STATE_LISTEN_SLEEP; /* Go to Listen Sleep state */ + rfalNfcNfcNotify( gNfcDev.state ); /* And notify caller */ + } + break; + + + /*******************************************************************************/ + case RFAL_NFC_STATE_DEACTIVATION: + + rfalNfcDeactivation(); /* Deactivate current device */ + + gNfcDev.state = ((gNfcDev.discRestart) ? RFAL_NFC_STATE_START_DISCOVERY : RFAL_NFC_STATE_IDLE); + rfalNfcNfcNotify( gNfcDev.state ); /* Notify caller */ + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_LISTEN_TECHDETECT: + + if( platformTimerIsExpired( gNfcDev.discTmr ) ) + { + #if RFAL_FEATURE_LISTEN_MODE + rfalListenStop(); + #else + rfalFieldOff(); + #endif /* RFAL_FEATURE_LISTEN_MODE */ + + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; /* Restart the discovery loop */ + break; + } + + #if RFAL_FEATURE_LISTEN_MODE + err = rfalListenStart( gNfcDev.lmMask, &gNfcDev.disc.lmConfigPA, NULL, &gNfcDev.disc.lmConfigPF, (uint8_t*)&gNfcDev.rxBuf.rfBuf, sizeof(gNfcDev.rxBuf.rfBuf), &gNfcDev.rxLen ); + if( err == ERR_NONE ) + { + gNfcDev.state = RFAL_NFC_STATE_LISTEN_COLAVOIDANCE; /* Wait for listen mode to be activated */ + } + break; + + + /*******************************************************************************/ + case RFAL_NFC_STATE_LISTEN_COLAVOIDANCE: + + if( platformTimerIsExpired( gNfcDev.discTmr ) ) /* Check if the total duration has been reached */ + { + rfalListenStop(); + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; /* Restart the discovery loop */ + break; + } + + /* Check for external field */ + if( rfalListenGetState( NULL, NULL ) >= RFAL_LM_STATE_IDLE ) + { + gNfcDev.state = RFAL_NFC_STATE_LISTEN_ACTIVATION; /* Wait for listen mode to be activated */ + } + break; + + + /*******************************************************************************/ + case RFAL_NFC_STATE_LISTEN_ACTIVATION: + case RFAL_NFC_STATE_LISTEN_SLEEP: + + err = rfalNfcListenActivation(); + if( err != ERR_BUSY ) + { + if( err == ERR_NONE ) + { + gNfcDev.activeDev = gNfcDev.devList; /* Assign the active device to be used further on */ + gNfcDev.devCnt++; + + gNfcDev.state = RFAL_NFC_STATE_ACTIVATED; /* Device has been properly activated */ + rfalNfcNfcNotify( gNfcDev.state ); /* Inform upper layer that a device has been activated */ + } + else + { + rfalListenStop(); + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; /* Restart the discovery loop */ + } + } + #endif /* RFAL_FEATURE_LISTEN_MODE */ + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_ACTIVATED: + case RFAL_NFC_STATE_POLL_SELECT: + case RFAL_NFC_STATE_DATAEXCHANGE_DONE: + default: + return; + } +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDataExchangeStart( uint8_t *txData, uint16_t txDataLen, uint8_t **rxData, uint16_t **rvdLen, uint32_t fwt ) +{ + ReturnCode err; + rfalTransceiveContext ctx; + + /*******************************************************************************/ + /* The Data Exchange is divided in two different moments, the trigger/Start of * + * the transfer followed by the check until its completion */ + if( (gNfcDev.state >= RFAL_NFC_STATE_ACTIVATED) && (gNfcDev.activeDev != NULL) ) + { + + /*******************************************************************************/ + /* In Listen mode is the Poller that initiates the communicatation */ + /* Assign output parameters and rfalNfcDataExchangeGetStatus will return */ + /* incoming data from Poller/Initiator */ + if( (gNfcDev.state == RFAL_NFC_STATE_ACTIVATED) && rfalNfcIsRemDevPoller( gNfcDev.activeDev->type ) ) + { + if( txDataLen > 0U ) + { + return ERR_WRONG_STATE; + } + + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + *rxData = (uint8_t*)( (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? gNfcDev.rxBuf.isoDepBuf.inf : + ((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? gNfcDev.rxBuf.nfcDepBuf.inf : gNfcDev.rxBuf.rfBuf) ); + return ERR_NONE; + } + + + /*******************************************************************************/ + switch( gNfcDev.activeDev->rfInterface ) /* Check which RF interface shall be used/has been activated */ + { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + + rfalCreateByteFlagsTxRxContext( ctx, (uint8_t*)txData, txDataLen, gNfcDev.rxBuf.rfBuf, sizeof(gNfcDev.rxBuf.rfBuf), &gNfcDev.rxLen, RFAL_TXRX_FLAGS_DEFAULT, fwt ); + *rxData = (uint8_t*)gNfcDev.rxBuf.rfBuf; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + err = rfalStartTransceive( &ctx ); + break; + + #if RFAL_FEATURE_ISO_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_ISODEP: + { + rfalIsoDepTxRxParam isoDepTxRx; + + if( txDataLen > 0U ) + { + ST_MEMCPY( (uint8_t*)gNfcDev.txBuf.isoDepBuf.inf, txData, txDataLen ); + } + + isoDepTxRx.DID = RFAL_ISODEP_NO_DID; + isoDepTxRx.ourFSx = RFAL_ISODEP_FSX_KEEP; + isoDepTxRx.FSx = gNfcDev.activeDev->proto.isoDep.info.FSx; + isoDepTxRx.dFWT = gNfcDev.activeDev->proto.isoDep.info.dFWT; + isoDepTxRx.FWT = gNfcDev.activeDev->proto.isoDep.info.FWT; + isoDepTxRx.txBuf = &gNfcDev.txBuf.isoDepBuf; + isoDepTxRx.txBufLen = txDataLen; + isoDepTxRx.isTxChaining = false; + isoDepTxRx.rxBuf = &gNfcDev.rxBuf.isoDepBuf; + isoDepTxRx.rxLen = &gNfcDev.rxLen; + isoDepTxRx.isRxChaining = &gNfcDev.isRxChaining; + *rxData = (uint8_t*)gNfcDev.rxBuf.isoDepBuf.inf; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + + /*******************************************************************************/ + /* Trigger a RFAL ISO-DEP Transceive */ + err = rfalIsoDepStartTransceive( isoDepTxRx ); + break; + } + #endif /* RFAL_FEATURE_ISO_DEP */ + + #if RFAL_FEATURE_NFC_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_NFCDEP: + { + rfalNfcDepTxRxParam nfcDepTxRx; + + if( txDataLen > 0U) + { + ST_MEMCPY( (uint8_t*)gNfcDev.txBuf.nfcDepBuf.inf, txData, txDataLen ); + } + + nfcDepTxRx.DID = RFAL_NFCDEP_DID_KEEP; + nfcDepTxRx.FSx = rfalNfcDepLR2FS( (uint8_t)rfalNfcDepPP2LR( gNfcDev.activeDev->proto.nfcDep.activation.Target.ATR_RES.PPt ) ); + nfcDepTxRx.dFWT = gNfcDev.activeDev->proto.nfcDep.info.dFWT; + nfcDepTxRx.FWT = gNfcDev.activeDev->proto.nfcDep.info.FWT; + nfcDepTxRx.txBuf = &gNfcDev.txBuf.nfcDepBuf; + nfcDepTxRx.txBufLen = txDataLen; + nfcDepTxRx.isTxChaining = false; + nfcDepTxRx.rxBuf = &gNfcDev.rxBuf.nfcDepBuf; + nfcDepTxRx.rxLen = &gNfcDev.rxLen; + nfcDepTxRx.isRxChaining = &gNfcDev.isRxChaining; + *rxData = (uint8_t*)gNfcDev.rxBuf.nfcDepBuf.inf; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + + /*******************************************************************************/ + /* Trigger a RFAL NFC-DEP Transceive */ + err = rfalNfcDepStartTransceive( &nfcDepTxRx ); + break; + } + #endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + default: + err = ERR_PARAM; + break; + } + + /* If a transceive has succesfully started flag Data Exchange as ongoing */ + if( err == ERR_NONE ) + { + gNfcDev.dataExErr = ERR_BUSY; + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE; + } + + return err; + } + + return ERR_WRONG_STATE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDataExchangeGetStatus( void ) +{ + /*******************************************************************************/ + /* Check if it's the first frame received in Listen mode */ + if( gNfcDev.state == RFAL_NFC_STATE_ACTIVATED ) + { + /* Continue data exchange as normal */ + gNfcDev.dataExErr = ERR_BUSY; + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE; + + /* Check if we performing in T3T CE */ + if( (gNfcDev.activeDev->type == RFAL_NFC_POLL_TYPE_NFCF) && (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_RF) ) + { + /* The first frame has been retrieved by rfalListenMode, flag data immediately */ + /* Can only call rfalGetTransceiveStatus() after starting a transceive with rfalStartTransceive */ + gNfcDev.dataExErr = ERR_NONE; + } + } + + + /*******************************************************************************/ + /* Check if we are in we have been placed to sleep, and return last error */ + if( gNfcDev.state == RFAL_NFC_STATE_LISTEN_SLEEP ) + { + return gNfcDev.dataExErr; /* ERR_SLEEP_REQ */ + } + + + /*******************************************************************************/ + /* Check if Data exchange has been started */ + if( (gNfcDev.state != RFAL_NFC_STATE_DATAEXCHANGE) && (gNfcDev.state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) ) + { + return ERR_WRONG_STATE; + } + + /* Check if Data exchange is still ongoing */ + if( gNfcDev.dataExErr == ERR_BUSY ) + { + switch( gNfcDev.activeDev->rfInterface ) + { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + gNfcDev.dataExErr = rfalGetTransceiveStatus(); + break; + + #if RFAL_FEATURE_ISO_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_ISODEP: + gNfcDev.dataExErr = rfalIsoDepGetTransceiveStatus(); + break; + #endif /* RFAL_FEATURE_ISO_DEP */ + + /*******************************************************************************/ + #if RFAL_FEATURE_NFC_DEP + case RFAL_NFC_INTERFACE_NFCDEP: + gNfcDev.dataExErr = rfalNfcDepGetTransceiveStatus(); + break; + #endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + default: + gNfcDev.dataExErr = ERR_PARAM; + break; + } + + + #if RFAL_FEATURE_LISTEN_MODE + /*******************************************************************************/ + /* If a Sleep request has been received (Listen Mode) go to sleep immediately */ + if( gNfcDev.dataExErr == ERR_SLEEP_REQ ) + { + EXIT_ON_ERR( gNfcDev.dataExErr, rfalListenSleepStart( RFAL_LM_STATE_SLEEP_A, gNfcDev.rxBuf.rfBuf, sizeof(gNfcDev.rxBuf.rfBuf), &gNfcDev.rxLen ) ); + + /* If set Sleep was succesfull keep restore the Sleep request signal */ + gNfcDev.dataExErr = ERR_SLEEP_REQ; + } + #endif /* RFAL_FEATURE_LISTEN_MODE */ + + } + + return gNfcDev.dataExErr; +} + +/*! + ****************************************************************************** + * \brief Poller Technology Detection + * + * This method implements the Technology Detection / Poll for different + * device technologies. + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcPollTechDetetection( void ) +{ + ReturnCode err; + + err = ERR_NONE; + + /* Supress warning when specific RFAL features have been disabled */ + NO_WARNING(err); + + + /*******************************************************************************/ + /* AP2P Technology Detection */ + /*******************************************************************************/ + if( ((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_AP2P) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_AP2P) != 0U) ) + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_AP2P; + + #if RFAL_FEATURE_NFC_DEP + + EXIT_ON_ERR( err, rfalSetMode( RFAL_MODE_POLL_ACTIVE_P2P, gNfcDev.disc.ap2pBR, gNfcDev.disc.ap2pBR ) ); + rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); + rfalSetFDTListen( RFAL_FDT_LISTEN_AP2P_POLLER ); + rfalSetFDTPoll( RFAL_TIMING_NONE ); + rfalSetGT( RFAL_GT_AP2P_ADJUSTED ); + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* Turns the Field On and starts GT timer */ + + err = rfalNfcNfcDepActivate( gNfcDev.devList, RFAL_NFCDEP_COMM_ACTIVE, NULL, 0 );/* Poll for NFC-A devices */ + if( err == ERR_NONE ) + { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_AP2P; + + gNfcDev.devList->type = RFAL_NFC_LISTEN_TYPE_AP2P; + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_NFCDEP; + gNfcDev.devCnt++; + + return ERR_NONE; + } + + rfalFieldOff(); + return ERR_BUSY; + + #endif /* RFAL_FEATURE_NFC_DEP */ + } + + + /*******************************************************************************/ + /* Passive NFC-A Technology Detection */ + /*******************************************************************************/ + if( ((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_A) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_A) != 0U) ) + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_A; + + #if RFAL_FEATURE_NFCA + { + rfalNfcaSensRes sensRes; + + EXIT_ON_ERR( err, rfalNfcaPollerInitialize() ); /* Initialize RFAL for NFC-A */ + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* Turns the Field On and starts GT timer */ + + err = rfalNfcaPollerTechnologyDetection( gNfcDev.disc.compMode, &sensRes );/* Poll for NFC-A devices */ + if( err == ERR_NONE ) + { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_A; + } + + return ERR_BUSY; + } + + #endif /* RFAL_FEATURE_NFCA */ + } + + + /*******************************************************************************/ + /* Passive NFC-B Technology Detection */ + /*******************************************************************************/ + if( ((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_B) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_B) != 0U) ) + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_B; + + #if RFAL_FEATURE_NFCB + { + rfalNfcbSensbRes sensbRes; + uint8_t sensbResLen; + + EXIT_ON_ERR( err, rfalNfcbPollerInitialize() ); /* Initialize RFAL for NFC-B */ + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* As field is already On only starts GT timer */ + + err = rfalNfcbPollerTechnologyDetection( gNfcDev.disc.compMode, &sensbRes, &sensbResLen ); /* Poll for NFC-B devices */ + if( err == ERR_NONE ) + { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_B; + } + + return ERR_BUSY; + } + + #endif /* RFAL_FEATURE_NFCB */ + } + + /*******************************************************************************/ + /* Passive NFC-F Technology Detection */ + /*******************************************************************************/ + if( ((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_F) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_F) != 0U) ) + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_F; + + #if RFAL_FEATURE_NFCF + + EXIT_ON_ERR( err, rfalNfcfPollerInitialize( gNfcDev.disc.nfcfBR ) ); /* Initialize RFAL for NFC-F */ + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* As field is already On only starts GT timer */ + + err = rfalNfcfPollerCheckPresence(); /* Poll for NFC-F devices */ + if( err == ERR_NONE ) + { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_F; + } + + return ERR_BUSY; + + #endif /* RFAL_FEATURE_NFCF */ + } + + + /*******************************************************************************/ + /* Passive NFC-V Technology Detection */ + /*******************************************************************************/ + if( ((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_V) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_V) != 0U) ) + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_V; + + #if RFAL_FEATURE_NFCV + { + rfalNfcvInventoryRes invRes; + + EXIT_ON_ERR( err, rfalNfcvPollerInitialize() ); /* Initialize RFAL for NFC-V */ + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* As field is already On only starts GT timer */ + + err = rfalNfcvPollerCheckPresence( &invRes ); /* Poll for NFC-V devices */ + if( err == ERR_NONE ) + { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_V; + } + + return ERR_BUSY; + } + + #endif /* RFAL_FEATURE_NFCV */ + } + + + /*******************************************************************************/ + /* Passive Proprietary Technology ST25TB */ + /*******************************************************************************/ + if( ((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_ST25TB) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_ST25TB) != 0U) ) + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_ST25TB; + + #if RFAL_FEATURE_ST25TB + + EXIT_ON_ERR( err, rfalSt25tbPollerInitialize() ); /* Initialize RFAL for NFC-V */ + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* As field is already On only starts GT timer */ + + err = rfalSt25tbPollerCheckPresence( NULL ); /* Poll for ST25TB devices */ + if( err == ERR_NONE ) + { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_ST25TB; + } + + #endif /* RFAL_FEATURE_ST25TB */ + } + + return ERR_NONE; +} + +/*! + ****************************************************************************** + * \brief Poller Collision Resolution + * + * This method implements the Collision Resolution on all technologies that + * have been detected before. + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcPollCollResolution( void ) +{ + uint8_t i; + uint8_t devCnt; + ReturnCode err; + + err = ERR_NONE; + devCnt = 0; + i = 0; + + /* Supress warning when specific RFAL features have been disabled */ + NO_WARNING(err); + NO_WARNING(devCnt); + NO_WARNING(i); + + /* Check if device limit has been reached */ + if( gNfcDev.devCnt >= gNfcDev.disc.devLimit ) + { + return ERR_NONE; + } + + /*******************************************************************************/ + /* NFC-A Collision Resolution */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCA + if( ((gNfcDev.techsFound & RFAL_NFC_POLL_TECH_A) != 0U) && ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_A) != 0U) ) /* If a NFC-A device was found/detected, perform Collision Resolution */ + { + rfalNfcaListenDevice nfcaDevList[RFAL_NFC_MAX_DEVICES]; + + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_A; + + EXIT_ON_ERR( err, rfalNfcaPollerInitialize()); /* Initialize RFAL for NFC-A */ + EXIT_ON_ERR( err, rfalFieldOnAndStartGT() ); /* Ensure GT again as other technologies have also been polled */ + + err = rfalNfcaPollerFullCollisionResolution( gNfcDev.disc.compMode, (gNfcDev.disc.devLimit - gNfcDev.devCnt), nfcaDevList, &devCnt ); + if( (err == ERR_NONE) && (devCnt != 0U) ) + { + for( i=0; i gNfcDev.devCnt ) + { + return ERR_WRONG_STATE; + } + + switch( gNfcDev.devList[devIt].type ) + { + /*******************************************************************************/ + /* AP2P Activation */ + /*******************************************************************************/ + #if RFAL_FEATURE_NFC_DEP + case RFAL_NFC_LISTEN_TYPE_AP2P: + /* Activation has already been perfomed (ATR_REQ) */ + + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].proto.nfcDep.activation.Target.ATR_RES.NFCID3; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + break; + #endif /* RFAL_FEATURE_NFC_DEP */ + + + /*******************************************************************************/ + /* Passive NFC-A Activation */ + /*******************************************************************************/ + #if RFAL_FEATURE_NFCA + case RFAL_NFC_LISTEN_TYPE_NFCA: + + rfalNfcaPollerInitialize(); + if( gNfcDev.devList[devIt].dev.nfca.isSleep ) /* Check if desired device is in Sleep */ + { + rfalNfcaSensRes sensRes; + rfalNfcaSelRes selRes; + + EXIT_ON_ERR( err, rfalNfcaPollerCheckPresence( RFAL_14443A_SHORTFRAME_CMD_WUPA, &sensRes ) ); /* Wake up all cards */ + EXIT_ON_ERR( err, rfalNfcaPollerSelect( gNfcDev.devList[devIt].dev.nfca.nfcId1, gNfcDev.devList[devIt].dev.nfca.nfcId1Len, &selRes ) ); /* Select specific device */ + } + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfca.nfcId1; + gNfcDev.devList[devIt].nfcidLen = gNfcDev.devList[devIt].dev.nfca.nfcId1Len; + + /*******************************************************************************/ + /* Perform protocol specific activation */ + switch( gNfcDev.devList[devIt].dev.nfca.type ) + { + /*******************************************************************************/ + case RFAL_NFCA_T1T: + + /* No further activation needed for T1T (RID already performed) */ + + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfca.ridRes.uid; + gNfcDev.devList[devIt].nfcidLen = RFAL_T1T_UID_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; + break; + + case RFAL_NFCA_T2T: + + /* No further activation needed for a T2T */ + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; + break; + + + /*******************************************************************************/ + case RFAL_NFCA_T4T: /* Device supports ISO-DEP */ + + #if RFAL_FEATURE_ISO_DEP_POLL + /* Perform ISO-DEP (ISO14443-4) activation: RATS and PPS if supported */ + rfalIsoDepInitialize(); + EXIT_ON_ERR( err, rfalIsoDepPollAHandleActivation( (rfalIsoDepFSxI)RFAL_ISODEP_FSDI_DEFAULT, RFAL_ISODEP_NO_DID, RFAL_BR_424, &gNfcDev.devList[devIt].proto.isoDep ) ); + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_ISODEP; /* NFC-A T4T device activated */ + #else + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* No ISO-DEP supported activate using RF interface */ + #endif /* RFAL_FEATURE_ISO_DEP_POLL */ + break; + + + + /*******************************************************************************/ + case RFAL_NFCA_T4T_NFCDEP: /* Device supports both T4T and NFC-DEP */ + case RFAL_NFCA_NFCDEP: /* Device supports NFC-DEP */ + + #if RFAL_FEATURE_NFC_DEP + /* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */ + EXIT_ON_ERR( err, rfalNfcNfcDepActivate( &gNfcDev.devList[devIt], RFAL_NFCDEP_COMM_PASSIVE, NULL, 0 ) ); + + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].proto.nfcDep.activation.Target.ATR_RES.NFCID3; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_NFCDEP; /* NFC-A P2P device activated */ + #else + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* No NFC-DEP supported activate using RF interface */ + #endif /* RFAL_FEATURE_NFC_DEP */ + break; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + break; + #endif /* RFAL_FEATURE_NFCA */ + + + /*******************************************************************************/ + /* Passive NFC-B Activation */ + /*******************************************************************************/ + #if RFAL_FEATURE_NFCB + case RFAL_NFC_LISTEN_TYPE_NFCB: + + rfalNfcbPollerInitialize(); + if( gNfcDev.devList[devIt].dev.nfcb.isSleep ) /* Check if desired device is in Sleep */ + { + rfalNfcbSensbRes sensbRes; + uint8_t sensbResLen; + + /* Wake up all cards. SENSB_RES may return collision but the NFCID0 is available to explicitly select NFC-B card via ATTRIB; so error will be ignored here */ + rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_ALLB_REQ, RFAL_NFCB_SLOT_NUM_1, &sensbRes, &sensbResLen ); + } + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfcb.sensbRes.nfcid0; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCB_NFCID0_LEN; + + #if RFAL_FEATURE_ISO_DEP_POLL + /* Check if device supports ISO-DEP (ISO14443-4) */ + if( (gNfcDev.devList[devIt].dev.nfcb.sensbRes.protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK) != 0U ) + { + rfalIsoDepInitialize(); + /* Perform ISO-DEP (ISO14443-4) activation: RATS and PPS if supported */ + EXIT_ON_ERR( err, rfalIsoDepPollBHandleActivation( (rfalIsoDepFSxI)RFAL_ISODEP_FSDI_DEFAULT, RFAL_ISODEP_NO_DID, RFAL_BR_424, 0x00, &gNfcDev.devList[devIt].dev.nfcb, NULL, 0, &gNfcDev.devList[devIt].proto.isoDep ) ); + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_ISODEP; /* NFC-B T4T device activated */ + break; + } + #endif /* RFAL_FEATURE_ISO_DEP_POLL */ + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* NFC-B device activated */ + break; + + #endif /* RFAL_FEATURE_NFCB */ + + + /*******************************************************************************/ + /* Passive NFC-F Activation */ + /*******************************************************************************/ + #if RFAL_FEATURE_NFCF + case RFAL_NFC_LISTEN_TYPE_NFCF: + + rfalNfcfPollerInitialize( gNfcDev.disc.nfcfBR ); + + #if RFAL_FEATURE_NFC_DEP + if( rfalNfcfIsNfcDepSupported( &gNfcDev.devList[devIt].dev.nfcf ) ) + { + /* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */ + EXIT_ON_ERR( err, rfalNfcNfcDepActivate( &gNfcDev.devList[devIt], RFAL_NFCDEP_COMM_PASSIVE, NULL, 0 ) ); + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].proto.nfcDep.activation.Target.ATR_RES.NFCID3; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_NFCDEP; /* NFC-F P2P device activated */ + break; + } + #endif /* RFAL_FEATURE_NFC_DEP */ + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfcf.sensfRes.NFCID2; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCF_NFCID2_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* NFC-F T3T device activated */ + break; + #endif /* RFAL_FEATURE_NFCF */ + + + /*******************************************************************************/ + /* Passive NFC-V Activation */ + /*******************************************************************************/ + #if RFAL_FEATURE_NFCV + case RFAL_NFC_LISTEN_TYPE_NFCV: + + rfalNfcvPollerInitialize(); + + /* No specific activation needed for a T5T */ + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfcv.InvRes.UID; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCV_UID_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* NFC-V T5T device activated */ + break; + #endif /* RFAL_FEATURE_NFCV */ + + + /*******************************************************************************/ + /* Passive ST25TB Activation */ + /*******************************************************************************/ + #if RFAL_FEATURE_ST25TB + case RFAL_NFC_LISTEN_TYPE_ST25TB: + + rfalSt25tbPollerInitialize(); + + /* No specific activation needed for a ST25TB */ + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.st25tb.UID; + gNfcDev.devList[devIt].nfcidLen = RFAL_ST25TB_UID_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* ST25TB device activated */ + break; + #endif /* RFAL_FEATURE_ST25TB */ + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + + gNfcDev.activeDev = &gNfcDev.devList[devIt]; /* Assign active device to be used further on */ + return ERR_NONE; +} + + +/*! + ****************************************************************************** + * \brief Listener Activation + * + * This method handles the listen mode Activation according to the different + * protocols the Reader/Initiator performs + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_PROTO : Unexpected frame received + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +#if RFAL_FEATURE_LISTEN_MODE +static ReturnCode rfalNfcListenActivation( void ) +{ + bool isDataRcvd; + uint8_t hdrLen; + ReturnCode ret; + rfalLmState lmSt; + rfalBitRate bitRate; + + lmSt = rfalListenGetState( &isDataRcvd, &bitRate ); + switch(lmSt) + { + /*******************************************************************************/ + case RFAL_LM_STATE_ACTIVE_A: /* NFC-A CE activation */ + case RFAL_LM_STATE_ACTIVE_Ax: + + if( isDataRcvd ) /* Check if Reader/Initator has sent some data */ + { + /* Set the header length in NFC-A */ + hdrLen = (RFAL_NFCDEP_SB_LEN + RFAL_NFCDEP_LEN_LEN); + + NO_WARNING(hdrLen); /* Supress warning if feature switch is disabled */ + + /* Check if received data is a Sleep request */ + if( rfalNfcaListenerIsSleepReq( gNfcDev.rxBuf.rfBuf, rfalConvBitsToBytes(gNfcDev.rxLen)) ) /* Check if received data is a SLP_REQ */ + { + /* Set the Listen Mode in Sleep state */ + EXIT_ON_ERR( ret, rfalListenSleepStart( RFAL_LM_STATE_SLEEP_A, gNfcDev.rxBuf.rfBuf, sizeof(gNfcDev.rxBuf.rfBuf), &gNfcDev.rxLen ) ); + } + + #if RFAL_FEATURE_ISO_DEP_LISTEN + /* Check if received data is a valid RATS */ + else if( rfalIsoDepIsRats( gNfcDev.rxBuf.rfBuf, (uint8_t)rfalConvBitsToBytes(gNfcDev.rxLen) ) ) + { + rfalIsoDepAtsParam atsParam; + rfalIsoDepListenActvParam rxParam; + + /* Set ATS parameters */ + atsParam.fsci = (uint8_t)RFAL_ISODEP_DEFAULT_FSCI; + atsParam.fwi = RFAL_ISODEP_DEFAULT_FWI; + atsParam.sfgi = RFAL_ISODEP_DEFAULT_SFGI; + atsParam.didSupport = false; + atsParam.ta = RFAL_ISODEP_ATS_TA_SAME_D; + atsParam.hb = NULL; + atsParam.hbLen = 0; + + /* Set Rx parameters */ + rxParam.rxBuf = (rfalIsoDepBufFormat*) &gNfcDev.rxBuf.isoDepBuf; + rxParam.rxLen = &gNfcDev.rxLen; + rxParam.isoDepDev = &gNfcDev.devList->proto.isoDep; + rxParam.isRxChaining = &gNfcDev.isRxChaining; + + rfalListenSetState( RFAL_LM_STATE_CARDEMU_4A ); /* Set next state CE T4T */ + rfalIsoDepInitialize(); /* Initialize ISO-DEP layer to handle ISO14443-a activation / RATS */ + + /* Set ISO-DEP layer to digest RATS and handle activation */ + EXIT_ON_ERR( ret, rfalIsoDepListenStartActivation( &atsParam, NULL, gNfcDev.rxBuf.rfBuf, gNfcDev.rxLen, rxParam ) ); + } + #endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + + #if RFAL_FEATURE_NFC_DEP + /* Check if received data is a valid ATR_REQ */ + else if( rfalNfcDepIsAtrReq( &gNfcDev.rxBuf.rfBuf[hdrLen], (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen), gNfcDev.devList->nfcid ) ) + { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCA; + EXIT_ON_ERR( ret, rfalNfcNfcDepActivate( gNfcDev.devList, RFAL_NFCDEP_COMM_PASSIVE, &gNfcDev.rxBuf.rfBuf[hdrLen], (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen) ) ); + } + #endif /* RFAL_FEATURE_NFC_DEP */ + + else + { + return ERR_PROTO; + } + } + return ERR_BUSY; + + #if RFAL_FEATURE_ISO_DEP_LISTEN + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_4A: /* T4T ISO-DEP activation */ + + ret = rfalIsoDepListenGetActivationStatus(); + if( ret == ERR_NONE ) + { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCA; + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_ISODEP; + gNfcDev.devList->nfcid = NULL; + gNfcDev.devList->nfcidLen = 0; + } + return ret; + #endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_F: /* NFC-F CE activation */ + + if( isDataRcvd ) /* Wait for the first received data */ + { + #if RFAL_FEATURE_NFC_DEP + /* Set the header length in NFC-F */ + hdrLen = RFAL_NFCDEP_LEN_LEN; + + if( rfalNfcDepIsAtrReq( &gNfcDev.rxBuf.rfBuf[hdrLen], (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen), gNfcDev.devList->nfcid ) ) + { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCF; + EXIT_ON_ERR( ret, rfalNfcNfcDepActivate( gNfcDev.devList, RFAL_NFCDEP_COMM_PASSIVE, &gNfcDev.rxBuf.rfBuf[hdrLen], (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen) ) ); + } + else + #endif /* RFAL_FEATURE_NFC_DEP */ + { + rfalListenSetState( RFAL_LM_STATE_CARDEMU_3 ); /* First data already received - set T3T CE */ + } + } + return ERR_BUSY; + + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_3: /* T3T activated */ + + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCF; + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_RF; + gNfcDev.devList->nfcid = NULL; + gNfcDev.devList->nfcidLen = 0; + + return ERR_NONE; + + #if RFAL_FEATURE_NFC_DEP + /*******************************************************************************/ + case RFAL_LM_STATE_TARGET_A: /* NFC-DEP activation */ + case RFAL_LM_STATE_TARGET_F: + + ret = rfalNfcDepListenGetActivationStatus(); + if( ret == ERR_NONE ) + { + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_NFCDEP; + gNfcDev.devList->nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + } + return ret; + #endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + case RFAL_LM_STATE_IDLE: /* AP2P activation */ + if( isDataRcvd ) /* Check if Reader/Initator has sent some data */ + { + + if( (gNfcDev.lmMask & RFAL_LM_MASK_ACTIVE_P2P) != 0U ) /* Check if AP2P is enabled */ + { + + #if RFAL_FEATURE_NFC_DEP + /* Calculate the header length in NFC-A or NFC-F mode*/ + hdrLen = ( (bitRate == RFAL_BR_106) ? (RFAL_NFCDEP_SB_LEN + RFAL_NFCDEP_LEN_LEN) : RFAL_NFCDEP_LEN_LEN ); + + if( rfalNfcDepIsAtrReq( &gNfcDev.rxBuf.rfBuf[hdrLen], (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen), NULL) ) + { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_AP2P; + EXIT_ON_ERR( ret, rfalNfcNfcDepActivate( gNfcDev.devList, RFAL_NFCDEP_COMM_ACTIVE, &gNfcDev.rxBuf.rfBuf[hdrLen], (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen) ) ); + } + else + #endif /* RFAL_FEATURE_NFC_DEP */ + { + return ERR_PROTO; + } + } + } + return ERR_BUSY; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_A: + case RFAL_LM_STATE_READY_Ax: + case RFAL_LM_STATE_SLEEP_A: + case RFAL_LM_STATE_SLEEP_AF: + return ERR_BUSY; + + /*******************************************************************************/ + case RFAL_LM_STATE_POWER_OFF: + return ERR_LINK_LOSS; + + default: /* Wait for activation */ + break; + } + + return ERR_INTERNAL; +} +#endif /* RFAL_FEATURE_LISTEN_MODE */ + + +/*! + ****************************************************************************** + * \brief Poller NFC DEP Activate + * + * This method performs NFC-DEP Activation + * + * \param[in] device : device info + * \param[in] commMode : communication mode (Passive/Active) + * \param[in] atrReq : received ATR_REQ + * \param[in] atrReqLen : received ATR_REQ size + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +#if RFAL_FEATURE_NFC_DEP +static ReturnCode rfalNfcNfcDepActivate( rfalNfcDevice *device, rfalNfcDepCommMode commMode, const uint8_t *atrReq, uint16_t atrReqLen ) +{ + rfalNfcDepAtrParam initParam; + + /* If we are in Poll mode */ + if( rfalNfcIsRemDevListener( device->type ) ) + { + /*******************************************************************************/ + /* If Passive F use the NFCID2 retrieved from SENSF */ + if( device->type == RFAL_NFC_LISTEN_TYPE_NFCF ) + { + initParam.nfcid = device->dev.nfcf.sensfRes.NFCID2; + initParam.nfcidLen = RFAL_NFCF_NFCID2_LEN; + } + else + { + initParam.nfcid = gNfcDev.disc.nfcid3; + initParam.nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + } + + initParam.BS = RFAL_NFCDEP_Bx_NO_HIGH_BR; + initParam.BitRate = RFAL_NFCDEP_Bx_NO_HIGH_BR; + initParam.DID = RFAL_NFCDEP_DID_NO; + initParam.NAD = RFAL_NFCDEP_NAD_NO; + initParam.LR = RFAL_NFCDEP_LR_254; + initParam.GB = gNfcDev.disc.GB; + initParam.GBLen = gNfcDev.disc.GBLen; + initParam.commMode = commMode; + initParam.operParam = (RFAL_NFCDEP_OPER_FULL_MI_EN | RFAL_NFCDEP_OPER_EMPTY_DEP_DIS | RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN); + + rfalNfcDepInitialize(); + /* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */ + return rfalNfcDepInitiatorHandleActivation( &initParam, RFAL_BR_424, &device->proto.nfcDep ); + } + + /* If we are in Listen mode */ +#if RFAL_FEATURE_LISTEN_MODE + else if( rfalNfcIsRemDevPoller( device->type ) ) + { + rfalNfcDepListenActvParam actvParams; + rfalNfcDepTargetParam targetParam; + + ST_MEMCPY(targetParam.nfcid3, (uint8_t*)gNfcDev.disc.nfcid3, RFAL_NFCDEP_NFCID3_LEN); + targetParam.bst = RFAL_NFCDEP_Bx_NO_HIGH_BR; + targetParam.brt = RFAL_NFCDEP_Bx_NO_HIGH_BR; + targetParam.to = RFAL_NFCDEP_WT_TRG_MAX; + targetParam.ppt = rfalNfcDepLR2PP(RFAL_NFCDEP_LR_254); + targetParam.GBtLen = 0; + targetParam.operParam = (RFAL_NFCDEP_OPER_FULL_MI_EN | RFAL_NFCDEP_OPER_EMPTY_DEP_DIS | RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN); + targetParam.commMode = commMode; + + + /* Set activation buffer (including header) for NFC-DEP */ + actvParams.rxBuf = &gNfcDev.rxBuf.nfcDepBuf; + actvParams.rxLen = &gNfcDev.rxLen; + actvParams.isRxChaining = &gNfcDev.isRxChaining; + actvParams.nfcDepDev = &gNfcDev.devList->proto.nfcDep; + + rfalListenSetState( ((device->type == RFAL_NFC_POLL_TYPE_NFCA) ? RFAL_LM_STATE_TARGET_A : RFAL_LM_STATE_TARGET_F) ); + + rfalNfcDepInitialize(); + /* Perform NFC-DEP (P2P) activation: send ATR_RES and handle activation */ + return rfalNfcDepListenStartActivation( &targetParam, atrReq, atrReqLen, actvParams ); + } +#endif /* RFAL_FEATURE_LISTEN_MODE */ + + else + { + return ERR_INTERNAL; + } +} +#endif /* RFAL_FEATURE_NFC_DEP */ + + +/*! + ****************************************************************************** + * \brief Poller NFC Deactivate + * + * This method Deactivates the device if a deactivation procedure exists + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcDeactivation( void ) +{ + /* Check if a device has been activated */ + if( gNfcDev.activeDev != NULL ) + { + switch( gNfcDev.activeDev->rfInterface ) + { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + break; /* No specific deactivation to be performed */ + + /*******************************************************************************/ + #if RFAL_FEATURE_ISO_DEP_POLL + case RFAL_NFC_INTERFACE_ISODEP: + rfalIsoDepDeselect(); /* Send a Deselect to device */ + break; + #endif /* RFAL_FEATURE_ISO_DEP_POLL */ + + /*******************************************************************************/ + #if RFAL_FEATURE_NFC_DEP + case RFAL_NFC_INTERFACE_NFCDEP: + rfalNfcDepRLS(); /* Send a Release to device */ + break; + #endif /* RFAL_FEATURE_NFC_DEP */ + + default: + return ERR_REQUEST; + } + } + + #if RFAL_FEATURE_WAKEUP_MODE + rfalWakeUpModeStop(); + #endif /* RFAL_FEATURE_WAKEUP_MODE */ + + #if RFAL_FEATURE_LISTEN_MODE + rfalListenStop(); + #else + rfalFieldOff(); + #endif + + gNfcDev.activeDev = NULL; + return ERR_NONE; +} diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_nfcDep.c b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcDep.c new file mode 100644 index 0000000..c92c877 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcDep.c @@ -0,0 +1,2530 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: NFCC firmware + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcDep.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-DEP protocol + * + * NFC-DEP is also known as NFCIP - Near Field Communication + * Interface and Protocol + * + * This implementation was based on the following specs: + * - NFC Forum Digital 1.1 + * - ECMA 340 3rd Edition 2013 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_nfcDep.h" +#include "rfal_nfcf.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFC_DEP + #define RFAL_FEATURE_NFC_DEP false /* NFC-DEP module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFC_DEP + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define NFCIP_ATR_RETRY_MAX 2U /*!< Max consecutive retrys of an ATR REQ with transm error*/ + +#define NFCIP_PSLPAY_LEN (2U) /*!< PSL Payload length (BRS + FSL) */ +#define NFCIP_PSLREQ_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< PSL REQ length (incl LEN) */ +#define NFCIP_PSLRES_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< PSL RES length (incl LEN) */ + +#define NFCIP_ATRREQ_BUF_LEN (RFAL_NFCDEP_ATRREQ_MAX_LEN + RFAL_NFCDEP_LEN_LEN) /*!< ATR REQ max length (incl LEN) */ +#define NFCIP_ATRRES_BUF_LEN (RFAL_NFCDEP_ATRRES_MAX_LEN + RFAL_NFCDEP_LEN_LEN) /*!< ATR RES max length (incl LEN) */ + +#define NFCIP_RLSREQ_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< RLS REQ length (incl LEN) */ +#define NFCIP_RLSRES_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< RSL RES length (incl LEN) */ +#define NFCIP_RLSRES_MIN (2U + RFAL_NFCDEP_LEN_LEN) /*!< Minimum length for a RLS RES (incl LEN) */ + +#define NFCIP_DSLREQ_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< DSL REQ length (incl LEN) */ +#define NFCIP_DSLRES_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< DSL RES length (incl LEN) */ +#define NFCIP_DSLRES_MIN (2U + RFAL_NFCDEP_LEN_LEN) /*!< Minimum length for a DSL RES (incl LEN) */ + +#define NFCIP_DSLRES_MAX_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< Maximum length for a DSL RES (incl LEN) */ +#define NFCIP_RLSRES_MAX_LEN (3U + RFAL_NFCDEP_LEN_LEN) /*!< Minimum length for a RLS RES (incl LEN) */ +#define NFCIP_TARGET_RES_MAX ( MAX( NFCIP_RLSRES_MAX_LEN, NFCIP_DSLRES_MAX_LEN) ) /*!< Max target control res length */ + + + +#define NFCIP_NO_FWT RFAL_FWT_NONE /*!< No FWT value - Target Mode */ +#define NFCIP_INIT_MIN_RTOX 1U /*!< Minimum RTOX value Digital 1.0 14.8.4.1 */ +#define NFCIP_INIT_MAX_RTOX 59U /*!< Maximum RTOX value Digital 1.0 14.8.4.1 */ + +#define NFCIP_TARG_MIN_RTOX 1U /*!< Minimum target RTOX value Digital 1.0 14.8.4.1 */ +#define NFCIP_TARG_MAX_RTOX 59U /*!< Maximum target RTOX value Digital 1.0 14.8.4.1 */ + +#define NFCIP_TRECOV 1280U /*!< Digital 1.0 A.10 Trecov */ + +#define NFCIP_TIMEOUT_ADJUSTMENT 512U /*!< Timeout Adjustment to compensate timing from end of Tx to end of frame */ +#define NFCIP_RWT_ACTIVATION (0x1000001U + NFCIP_TIMEOUT_ADJUSTMENT) /*!< Digital 2.0 B.10 RWT ACTIVATION 2^24 + RWT Delta + Adjustment*/ +#define NFCIP_RWT_ACM_ACTIVATION (0x200001U + NFCIP_TIMEOUT_ADJUSTMENT) /*!< Digital 2.0 B.10 RWT ACTIVATION 2^21 + RWT Delta + Adjustment*/ + +#define RFAL_NFCDEP_HEADER_PAD (RFAL_NFCDEP_DEPREQ_HEADER_LEN - RFAL_NFCDEP_LEN_MIN) /*!< Difference between expected rcvd header len and max foreseen */ + + +#define NFCIP_MAX_TX_RETRYS (uint8_t)3U /*!< Number of retransmit retyrs */ +#define NFCIP_MAX_TO_RETRYS (uint8_t)3U /*!< Number of retrys for Timeout */ +#define NFCIP_MAX_RTOX_RETRYS (uint8_t)3U /*!< Number of retrys for RTOX */ +#define NFCIP_MAX_NACK_RETRYS (uint8_t)3U /*!< Number of retrys for NACK */ +#define NFCIP_MAX_ATN_RETRYS (uint8_t)3U /*!< Number of retrys for ATN */ + +#define NFCIP_MIN_TXERROR_LEN 4U /*!< Minimum frame length with error to be ignored Digital 1.0 14.12.5.4 */ + +#define NFCIP_REQ (uint8_t)0xD4U /*!= NFCIP_ST_INIT_IDLE) && ((st) <= NFCIP_ST_INIT_RLS) ) /*!< Checks if module is set as Initiator */ +#define nfcipIsTarget( st ) (!nfcipIsInitiator(st)) /*!< Checks if module is set as Target */ + +#define nfcipIsBRAllowed( br, mBR ) (((1U<<(br)) & (mBR)) != 0U) /*!< Checks bit rate is allowed by given mask */ + +#define nfcipIsEmptyDEPEnabled( op ) (!nfcipIsEmptyDEPDisabled(op)) /*!< Checks if empty payload is allowed by operation config NCI 1.0 Table 81 */ +#define nfcipIsEmptyDEPDisabled( op ) (((op) & RFAL_NFCDEP_OPER_EMPTY_DEP_DIS) != 0U) /*!< Checks if empty payload is not allowed by operation config NCI 1.0 Table 81 */ + +#define nfcipIsRTOXReqEnabled( op ) (!nfcipIsRTOXReqDisabled(op)) /*!< Checks if send a RTOX_REQ is allowed by operation config NCI 1.0 Table 81 */ +#define nfcipIsRTOXReqDisabled( op ) (((op) & RFAL_NFCDEP_OPER_RTOX_REQ_DIS) != 0U) /*!< Checks if send a RTOX_REQ is not allowed by operation config NCI 1.0 Table 81 */ + + +/*! Checks if isDeactivating callback is set and calls it, otherwise returns false */ +#define nfcipIsDeactivationPending() ( (gNfcip.isDeactivating == NULL) ? false : gNfcip.isDeactivating() ) + +/*! Returns the RWT Activation according to the current communication mode */ +#define nfcipRWTActivation() ((gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_ACTIVE) ? NFCIP_RWT_ACM_ACTIVATION : NFCIP_RWT_ACTIVATION) + + +#define nfcipRTOXAdjust( v ) ((v) - ((v)>>3)) /*!< Adjust RTOX timer value to a percentage of the total, current 88% */ + +/*******************************************************************************/ + +// timerPollTimeoutValue is necessary after timerCalculateTimeout so that system will wake up upon timer timeout. +#define nfcipTimerStart( timer, time_ms ) (timer) = platformTimerCreate((uint16_t)(time_ms)) /*!< Configures and starts the RTOX timer */ +#define nfcipTimerisExpired( timer ) platformTimerIsExpired( timer ) /*!< Checks RTOX timer has expired */ + +#define nfcipLogE(...) /*!< Macro for the error log method */ +#define nfcipLogW(...) /*!< Macro for the warning log method */ +#define nfcipLogI(...) /*!< Macro for the info log method */ +#define nfcipLogD(...) /*!< Macro for the debug log method */ + + +/*! Digital 1.1 - 16.12.5.2 The Target SHALL NOT attempt any error recovery and remains in Rx mode upon Transmission or a Protocol Error */ +#define nfcDepReEnableRx( rxB, rxBL, rxL ) rfalTransceiveBlockingTx( NULL, 0, (rxB), (rxBL), (rxL), ( RFAL_TXRX_FLAGS_DEFAULT | (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_ON ), RFAL_FWT_NONE ) + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +/*! Struct that holds all DEP parameters/configs for the following communications */ +typedef struct{ + uint8_t did; /*!< Device ID (DID) to be used */ + + uint8_t* txBuf; /*!< Pointer to the Tx buffer to be sent */ + uint16_t txBufLen; /*!< Length of the data in the txBuf */ + uint8_t txBufPaylPos; /*!< Position inside txBuf where data starts */ + bool txChaining; /*!< Flag indicating chaining on transmission */ + + uint8_t* rxBuf; /*!< Pointer to the Rx buffer for incoming data */ + uint16_t rxBufLen; /*!< Length of the data in the rxBuf */ + uint8_t rxBufPaylPos; /*!< Position inside rxBuf where data is to be placed*/ + + uint32_t fwt; /*!< Frame Waiting Time (FWT) to be used */ + uint32_t dFwt; /*!< Delta Frame Waiting Time (dFWT) to be used */ + uint16_t fsc; /*!< Frame Size (FSC) to be used */ + +} rfalNfcDepDEPParams; + +/*! NFCIP module states */ +typedef enum +{ + NFCIP_ST_IDLE, + NFCIP_ST_INIT_IDLE, + NFCIP_ST_INIT_ATR, + NFCIP_ST_INIT_PSL, + NFCIP_ST_INIT_DEP_IDLE, + NFCIP_ST_INIT_DEP_TX, + NFCIP_ST_INIT_DEP_RX, + NFCIP_ST_INIT_DEP_ATN, + NFCIP_ST_INIT_DSL, + NFCIP_ST_INIT_RLS, + + NFCIP_ST_TARG_WAIT_ATR, + NFCIP_ST_TARG_WAIT_ACTV, + NFCIP_ST_TARG_DEP_IDLE, + NFCIP_ST_TARG_DEP_RX, + NFCIP_ST_TARG_DEP_RTOX, + NFCIP_ST_TARG_DEP_TX, + NFCIP_ST_TARG_DEP_SLEEP +} rfalNfcDepState; + +/*! NFCIP commands (Request, Response) */ +typedef enum{ + NFCIP_CMD_ATR_REQ = 0x00, + NFCIP_CMD_ATR_RES = 0x01, + NFCIP_CMD_WUP_REQ = 0x02, + NFCIP_CMD_WUP_RES = 0x03, + NFCIP_CMD_PSL_REQ = 0x04, + NFCIP_CMD_PSL_RES = 0x05, + NFCIP_CMD_DEP_REQ = 0x06, + NFCIP_CMD_DEP_RES = 0x07, + NFCIP_CMD_DSL_REQ = 0x08, + NFCIP_CMD_DSL_RES = 0x09, + NFCIP_CMD_RLS_REQ = 0x0A, + NFCIP_CMD_RLS_RES = 0x0B +} rfalNfcDepCmd; + + +/*! Struct that holds all NFCIP data */ +typedef struct{ + rfalNfcDepConfigs cfg; /*!< Holds the current configuration to be used */ + + rfalNfcDepState state; /*!< Current state of the NFCIP module */ + uint8_t pni; /*!< Packet Number Information (PNI) counter */ + + uint8_t lastCmd; /*!< Last command sent */ + uint8_t lastPFB; /*!< Last PFB sent */ + uint8_t lastPFBnATN; /*!< Last PFB sent (excluding ATN) */ + uint8_t lastRTOX; /*!< Last RTOX value sent */ + + uint8_t cntTxRetrys; /*!< Retransmissions counter */ + uint8_t cntTORetrys; /*!< Timeouts counter */ + uint8_t cntRTOXRetrys; /*!< RTOX counter */ + uint8_t cntNACKRetrys; /*!< NACK counter */ + uint8_t cntATNRetrys; /*!< Attention (ATN) counter */ + + uint16_t fsc; /*!< Current Frame Size (FSC) to be used */ + bool isTxChaining; /*!< Flag for chaining on Transmission */ + bool isRxChaining; /*!< Flag for chaining on Reception */ + uint8_t* txBuf; /*!< Pointer to the Tx buffer to be sent */ + uint8_t* rxBuf; /*!< Pointer to the Rx buffer for incoming data */ + uint16_t txBufLen; /*!< Length of the data in the txBuf */ + uint16_t rxBufLen; /*!< Length of rxBuf buffer */ + uint16_t* rxRcvdLen; /*!< Length of the data in the rxBuf */ + uint8_t txBufPaylPos; /*!< Position in txBuf where data starts */ + uint8_t rxBufPaylPos; /*!< Position in rxBuf where data is to be placed */ + bool *isChaining; /*!< Flag for chaining on Reception */ + + rfalNfcDepDevice *nfcDepDev; /*!< Pointer to NFC-DEP device info */ + + uint32_t RTOXTimer; /*!< Timer used for RTOX */ + rfalNfcDepDeactCallback isDeactivating; /*!< Deactivating flag check callback */ + + bool isReqPending; /*!< Flag pending REQ from Target activation */ + bool isTxPending; /*!< Flag pending DEP Block while waiting RTOX Ack */ + bool isWait4RTOX; /*!< Flag for waiting RTOX Ack */ +}rfalNfcDep; + + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + +static rfalNfcDep gNfcip; /*!< NFCIP module instance */ + + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + +static ReturnCode nfcipTxRx( rfalNfcDepCmd cmd, uint8_t* txBuf, uint32_t fwt, uint8_t* paylBuf, uint8_t paylBufLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rxActLen ); +static ReturnCode nfcipTx( rfalNfcDepCmd cmd, uint8_t* txBuf, uint8_t *paylBuf, uint16_t paylLen, uint8_t pfbData, uint32_t fwt ); +static ReturnCode nfcipDEPControlMsg( uint8_t pfb, uint8_t RTOX ); +static ReturnCode nfcipInitiatorHandleDEP( ReturnCode rxRes, uint16_t rxLen, uint16_t *outActRxLen, bool *outIsChaining ); +static ReturnCode nfcipTargetHandleRX( ReturnCode rxRes, uint16_t *outActRxLen, bool *outIsChaining ); +static ReturnCode nfcipTargetHandleActivation( rfalNfcDepDevice *nfcDepDev, uint8_t *outBRS ); + + +/*! + ****************************************************************************** + * \brief NFCIP Configure + * + * Configures the nfcip layer with the given configurations + * + * \param[in] cfg : nfcip configuration for following communication + ****************************************************************************** + */ +static void nfcipConfig( const rfalNfcDepConfigs * cfg ); + + +/*! + ****************************************************************************** + * \brief Set DEP parameters + * + * This method sets the parameters/configs for following Data Exchange + * Sets the nfcip module state according to the role it is configured + * + * + * \warning To be used only after proper Initiator/Target activation: + * nfcipTargetHandleActivation() or nfcipInitiatorActivate() has + * returned success + * + * This must be called before nfcipRun() in case of Target to pass + * rxBuffer + * + * Everytime some data needs to be transmitted call this to set it and + * call nfcipRun() until done or error + * + * \param[in] DEPParams : the parameters to be used during Data Exchange + ****************************************************************************** + */ +static void nfcipSetDEPParams( rfalNfcDepDEPParams *DEPParams ); + + +/*! + ****************************************************************************** + * \brief NFCIP run protocol + * + * This method handles all the nfcip protocol during Data Exchange (DEP + * requests and responses). + * + * A data exchange cycle is considered a DEP REQ and a DEP RES. + * + * In case of Tx chaining(MI) must signal it with nfcipSetDEPParams() + * In case of Rx chaining(MI) outIsChaining will be set to true and the + * current data returned + * + * \param[out] outActRxLen : data received length + * \param[out] outIsChaining : true if other peer is performing chaining(MI) + * + * \return ERR_NONE : Data exchange cycle completed successfully + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + * \return ERR_AGAIN : Other peer is doing chaining(MI), current block + * was received successfully call again until complete + * + ****************************************************************************** + */ +static ReturnCode nfcipRun( uint16_t *outActRxLen, bool *outIsChaining ); + + +/*! + ****************************************************************************** + * \brief Transmission method + * + * This method checks if the current communication is Active or Passive + * and performs the necessary procedures for each communication type + * + * Transmits the data hold in txBuf + * + * \param[in] txBuf : buffer to transmit + * \param[in] txBufLen : txBuffer capacity + * \param[in] fwt : fwt for current Tx + * + * \return ERR_NONE : No error + ****************************************************************************** + */ +static ReturnCode nfcipDataTx( uint8_t* txBuf, uint16_t txBufLen, uint32_t fwt ); + + +/*! + ****************************************************************************** + * \brief Reception method + * + * This method checks if the current communication is Active or Passive + * and calls the appropriate reception method + * + * Copies incoming data to rxBuf + * + * \param[in] blocking : reception is to be done blocking or non-blocking + * + * \return ERR_BUSY : Busy + * \return ERR_NONE : No error + ****************************************************************************** + */ +static ReturnCode nfcipDataRx( bool blocking ); + + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ + + +/*******************************************************************************/ +static bool nfcipDxIsSupported( uint8_t Dx, uint8_t BRx, uint8_t BSx ) +{ + uint8_t Bx; + + /* Take the min of the possible bit rates, we'll use one for both directions */ + Bx = MIN(BRx, BSx); + + /* Lower bit rates must be supported for P2P */ + if( (Dx <= (uint8_t)RFAL_NFCDEP_Dx_04_424) ) + { + return true; + } + + if( (Dx == (uint8_t)RFAL_NFCDEP_Dx_08_848) && (Bx >= (uint8_t)RFAL_NFCDEP_Bx_08_848) ) + { + return true; + } + + return false; +} + + +/*******************************************************************************/ +static ReturnCode nfcipTxRx( rfalNfcDepCmd cmd, uint8_t* txBuf, uint32_t fwt, uint8_t* paylBuf, uint8_t paylBufLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rxActLen ) +{ + ReturnCode ret; + + if( (cmd == NFCIP_CMD_DEP_REQ) || (cmd == NFCIP_CMD_DEP_RES) ) /* this method cannot be used for DEPs */ + { + return ERR_PARAM; + } + + /* Assign the global params for this TxRx */ + gNfcip.rxBuf = rxBuf; + gNfcip.rxBufLen = rxBufLen; + gNfcip.rxRcvdLen = rxActLen; + + + /*******************************************************************************/ + /* Transmission */ + /*******************************************************************************/ + if(txBuf != NULL) /* if nothing to Tx, just do Rx */ + { + EXIT_ON_ERR( ret, nfcipTx( cmd, txBuf, paylBuf, paylBufLen, 0, fwt ) ); + } + + /*******************************************************************************/ + /* Reception */ + /*******************************************************************************/ + ret = nfcipDataRx( true ); + if( ret != ERR_NONE ) + { + return ret; + } + + /*******************************************************************************/ + *rxActLen = *rxBuf; /* Use LEN byte instead due to with/without CRC modes */ + return ERR_NONE; /* Tx and Rx completed successfully */ +} + + +/*******************************************************************************/ +static ReturnCode nfcipDEPControlMsg( uint8_t pfb, uint8_t RTOX ) +{ + uint8_t ctrlMsg[20]; + rfalNfcDepCmd depCmd; + uint32_t fwt; + + + /*******************************************************************************/ + /* Calculate Cmd and fwt to be used */ + /*******************************************************************************/ + depCmd = ((gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) ? NFCIP_CMD_DEP_RES : NFCIP_CMD_DEP_REQ); + fwt = ((gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) ? NFCIP_NO_FWT : (nfcip_PFBisSTO( pfb ) ? ( (RTOX*gNfcip.cfg.fwt) + gNfcip.cfg.dFwt) : (gNfcip.cfg.fwt + gNfcip.cfg.dFwt) ) ); + + if( nfcip_PFBisSTO( pfb ) ) + { + ctrlMsg[RFAL_NFCDEP_DEPREQ_HEADER_LEN] = RTOX; + return nfcipTx( depCmd, ctrlMsg, &ctrlMsg[RFAL_NFCDEP_DEPREQ_HEADER_LEN], sizeof(uint8_t), pfb, fwt ); + } + else + { + return nfcipTx( depCmd, ctrlMsg, NULL, 0, pfb, fwt ); + } +} + +/*******************************************************************************/ +static void nfcipClearCounters( void ) +{ + gNfcip.cntATNRetrys = 0; + gNfcip.cntNACKRetrys = 0; + gNfcip.cntTORetrys = 0; + gNfcip.cntTxRetrys = 0; + gNfcip.cntRTOXRetrys = 0; +} + +/*******************************************************************************/ +static ReturnCode nfcipInitiatorHandleDEP( ReturnCode rxRes, uint16_t rxLen, uint16_t *outActRxLen, bool *outIsChaining ) +{ + ReturnCode ret; + uint8_t nfcDepLen; + uint8_t rxMsgIt; + uint8_t rxPFB; + uint8_t rxRTOX; + uint8_t optHdrLen; + + ret = ERR_INTERNAL; + rxMsgIt = 0; + optHdrLen = 0; + + *outActRxLen = 0; + *outIsChaining = false; + + + /*******************************************************************************/ + /* Handle reception errors */ + /*******************************************************************************/ + switch( rxRes ) + { + /*******************************************************************************/ + /* Timeout -> Digital 1.0 14.15.5.6 */ + case ERR_TIMEOUT: + + nfcipLogI( " NFCIP(I) TIMEOUT TORetrys:%d \r\n", gNfcip.cntTORetrys ); + + /* Digital 1.0 14.15.5.6 - If nTO >= Max raise protocol error */ + if( gNfcip.cntTORetrys++ >= NFCIP_MAX_TO_RETRYS ) + { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Upon Timeout error, if Deactivation is pending, no more error recovery + * will be done #54. + * This is used to address the issue some devices that havea big TO. + * Normally LLCP layer has timeout already, and NFCIP layer is still + * running error handling, retrying ATN/NACKs */ + /*******************************************************************************/ + if( nfcipIsDeactivationPending() ) + { + nfcipLogI( " skipping error recovery due deactivation pending \r\n"); + return ERR_TIMEOUT; + } + + /* Digital 1.0 14.15.5.6 1) If last PDU was NACK */ + if( nfcip_PFBisRNACK(gNfcip.lastPFB) ) + { + /* Digital 1.0 14.15.5.6 2) if NACKs failed raise protocol error */ + if( gNfcip.cntNACKRetrys++ >= NFCIP_MAX_NACK_RETRYS ) + { + return ERR_PROTO; + } + + /* Send NACK */ + nfcipLogI( " NFCIP(I) Sending NACK retry: %d \r\n", gNfcip.cntNACKRetrys ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBRPDU_NACK(gNfcip.pni), 0 ) ); + return ERR_BUSY; + } + + nfcipLogI( " NFCIP(I) Checking if to send ATN ATNRetrys: %d \r\n", gNfcip.cntATNRetrys ); + + /* Digital 1.0 14.15.5.6 3) Otherwise send ATN */ + if( gNfcip.cntATNRetrys++ >= NFCIP_MAX_NACK_RETRYS ) + { + return ERR_PROTO; + } + + /* Send ATN */ + nfcipLogI( " NFCIP(I) Sending ATN \r\n" ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBSPDU_ATN(), 0 ) ); + return ERR_BUSY; + + /*******************************************************************************/ + /* Data rcvd with error -> Digital 1.0 14.12.5.4 */ + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + case ERR_RF_COLLISION: + + nfcipLogI( " NFCIP(I) rx Error: %d \r\n", rxRes ); + + /* Digital 1.0 14.12.5.4 Tx Error with data, ignore */ + if( rxLen < NFCIP_MIN_TXERROR_LEN ) + { + nfcipLogI( " NFCIP(I) Transmission error w data \r\n" ); +#if 0 + if(gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_PASSIVE) + { + nfcipLogI( " NFCIP(I) Transmission error w data -> reEnabling Rx \r\n" ); + nfcipReEnableRxTout( NFCIP_TRECOV ); + return ERR_BUSY; + } +#endif /* 0 */ + } + + /* Digital 1.1 16.12.5.4 if NACKs failed raise Transmission error */ + if( gNfcip.cntNACKRetrys++ >= NFCIP_MAX_NACK_RETRYS ) + { + return ERR_FRAMING; + } + + /* Send NACK */ + nfcipLogI( " NFCIP(I) Sending NACK \r\n" ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBRPDU_NACK(gNfcip.pni), 0 ) ); + return ERR_BUSY; + + case ERR_NONE: + break; + + case ERR_BUSY: + return ERR_BUSY; /* Debug purposes */ + + default: + nfcipLogW( " NFCIP(I) Error: %d \r\n", rxRes ); + return rxRes; + } + + /*******************************************************************************/ + /* Rx OK check if valid DEP PDU */ + /*******************************************************************************/ + + /* Due to different modes on ST25R391x (with/without CRC) use NFC-DEP LEN instead of bytes retrieved */ + nfcDepLen = gNfcip.rxBuf[rxMsgIt++]; + + nfcipLogD( " NFCIP(I) rx OK: %d bytes \r\n", nfcDepLen ); + + /* Digital 1.0 14.15.5.5 Protocol Error */ + if( gNfcip.rxBuf[rxMsgIt++] != NFCIP_RES ) + { + nfcipLogW( " NFCIP(I) error %02X instead of %02X \r\n", gNfcip.rxBuf[--rxMsgIt], NFCIP_RES ); + return ERR_PROTO; + } + + /* Digital 1.0 14.15.5.5 Protocol Error */ + if( gNfcip.rxBuf[rxMsgIt++] != (uint8_t)NFCIP_CMD_DEP_RES ) + { + nfcipLogW( " NFCIP(I) error %02X instead of %02X \r\n", gNfcip.rxBuf[--rxMsgIt], NFCIP_CMD_DEP_RES ); + return ERR_PROTO; + } + + rxPFB = gNfcip.rxBuf[rxMsgIt++]; + + /*******************************************************************************/ + /* Check for valid PFB type */ + if( !(nfcip_PFBisSPDU( rxPFB ) || nfcip_PFBisRPDU( rxPFB ) || nfcip_PFBisIPDU( rxPFB )) ) + { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Digital 1.0 14.8.2.1 check if DID is expected and match -> Protocol Error */ + if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) + { + if( (gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || !nfcip_PFBhasDID( rxPFB ) ) + { + return ERR_PROTO; + } + optHdrLen++; /* Inc header optional field cnt*/ + } + else if( nfcip_PFBhasDID( rxPFB ) ) /* DID not expected but rcv */ + { + return ERR_PROTO; + } + else + { + /* MISRA 15.7 - Empty else */ + } + + /*******************************************************************************/ + /* Digital 1.0 14.6.2.8 & 14.6.3.11 NAD must not be used */ + if( gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO ) + { + if( (gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.nad) || !nfcip_PFBhasNAD( rxPFB ) ) + { + return ERR_PROTO; + } + optHdrLen++; /* Inc header optional field cnt*/ + } + else if( nfcip_PFBhasNAD( rxPFB ) ) /* NAD not expected but rcv */ + { + return ERR_PROTO; + } + else + { + /* MISRA 15.7 - Empty else */ + } + + /*******************************************************************************/ + /* Process R-PDU */ + /*******************************************************************************/ + if( nfcip_PFBisRPDU( rxPFB ) ) + { + /*******************************************************************************/ + /* R ACK */ + /*******************************************************************************/ + if( nfcip_PFBisRACK( rxPFB ) ) + { + nfcipLogI( " NFCIP(I) Rcvd ACK \r\n" ); + if( gNfcip.pni == nfcip_PBF_PNI( rxPFB ) ) + { + /* 14.12.3.3 R-ACK with correct PNI -> Increment */ + gNfcip.pni = nfcip_PNIInc( gNfcip.pni ); + + /* R-ACK while not performing chaining -> Protocol error*/ + if( !gNfcip.isTxChaining ) + { + return ERR_PROTO; + } + + nfcipClearCounters(); + gNfcip.state = NFCIP_ST_INIT_DEP_IDLE; + return ERR_NONE; /* This block has been transmitted */ + } + else /* Digital 1.0 14.12.4.5 ACK with wrong PNI Initiator may retransmit */ + { + if( gNfcip.cntTxRetrys++ >= NFCIP_MAX_TX_RETRYS ) + { + return ERR_PROTO; + } + + /* Extended the MAY in Digital 1.0 14.12.4.5 to only reTransmit if the ACK + * is for the previous DEP, otherwise raise Protocol immediately + * If the PNI difference is more than 1 it is worthless to reTransmit 3x + * and after raise the error */ + + if( nfcip_PNIDec( gNfcip.pni ) == nfcip_PBF_PNI( rxPFB ) ) + { + /* ReTransmit */ + nfcipLogI( " NFCIP(I) Rcvd ACK prev PNI -> reTx \r\n" ); + gNfcip.state = NFCIP_ST_INIT_DEP_TX; + return ERR_BUSY; + } + + nfcipLogI( " NFCIP(I) Rcvd ACK unexpected far PNI -> Error \r\n" ); + return ERR_PROTO; + } + } + else /* Digital 1.0 - 14.12.5.2 Target must never send NACK */ + { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Process S-PDU */ + /*******************************************************************************/ + if( nfcip_PFBisSPDU( rxPFB ) ) + { + nfcipLogI( " NFCIP(I) Rcvd S-PDU \r\n" ); + /*******************************************************************************/ + /* S ATN */ + /*******************************************************************************/ + if( nfcip_PFBisSATN( rxPFB ) ) /* If is a S-ATN */ + { + nfcipLogI( " NFCIP(I) Rcvd ATN \r\n" ); + if( nfcip_PFBisSATN( gNfcip.lastPFB ) ) /* Check if is expected */ + { + gNfcip.cntATNRetrys = 0; /* Clear ATN counter */ + + /* Although spec is not clear NFC Forum Digital test is expecting to + * retransmit upon receiving ATN_RES */ + if( nfcip_PFBisSTO( gNfcip.lastPFBnATN ) ) + { + nfcipLogI( " NFCIP(I) Rcvd ATN -> reTx RTOX_RES \r\n" ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBSPDU_TO(), gNfcip.lastRTOX ) ); + } + else + { + /* ReTransmit ? */ + if( gNfcip.cntTxRetrys++ >= NFCIP_MAX_TX_RETRYS ) + { + return ERR_PROTO; + } + + nfcipLogI( " NFCIP(I) Rcvd ATN -> reTx PNI: %d \r\n", gNfcip.pni ); + gNfcip.state = NFCIP_ST_INIT_DEP_TX; + } + + return ERR_BUSY; + } + else /* Digital 1.0 14.12.4.4 & 14.12.4.8 */ + { + return ERR_PROTO; + } + } + /*******************************************************************************/ + /* S TO */ + /*******************************************************************************/ + else if( nfcip_PFBisSTO( rxPFB ) ) /* If is a S-TO (RTOX) */ + { + nfcipLogI( " NFCIP(I) Rcvd TO \r\n" ); + + rxRTOX = gNfcip.rxBuf[rxMsgIt++]; + + /* Digital 1.1 16.12.4.3 - Initiator MAY stop accepting subsequent RTOX Req * + * - RTOX request to an ATN -> Protocol error */ + if( (gNfcip.cntRTOXRetrys++ > NFCIP_MAX_RTOX_RETRYS) || nfcip_PFBisSATN( gNfcip.lastPFB ) ) + { + return ERR_PROTO; + } + + /* Digital 1.1 16.8.4.1 RTOX must be between [1,59] */ + if( (rxRTOX < NFCIP_INIT_MIN_RTOX) || (rxRTOX > NFCIP_INIT_MAX_RTOX) ) + { + return ERR_PROTO; + } + + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBSPDU_TO(), rxRTOX ) ); + gNfcip.lastRTOX = rxRTOX; + + return ERR_BUSY; + } + else + { + /* Unexpected S-PDU */ + return ERR_PROTO; /* PRQA S 2880 # MISRA 2.1 - Guard code to prevent unexpected behavior */ + } + } + + /*******************************************************************************/ + /* Process I-PDU */ + /*******************************************************************************/ + if( nfcip_PFBisIPDU( rxPFB ) ) + { + if( gNfcip.pni != nfcip_PBF_PNI( rxPFB ) ) + { + nfcipLogI( " NFCIP(I) Rcvd IPDU wrong PNI curPNI: %d rxPNI: %d \r\n", gNfcip.pni , nfcip_PBF_PNI( rxPFB ) ); + return ERR_PROTO; + } + + nfcipLogD( " NFCIP(I) Rcvd IPDU OK PNI: %d \r\n", gNfcip.pni ); + + /* 14.12.3.3 I-PDU with correct PNI -> Increment */ + gNfcip.pni = nfcip_PNIInc( gNfcip.pni ); + + + /* Successful data Exchange */ + nfcipClearCounters(); + *outActRxLen = ((uint16_t)nfcDepLen - RFAL_NFCDEP_DEP_HEADER - (uint16_t)optHdrLen); + + if( (&gNfcip.rxBuf[gNfcip.rxBufPaylPos] != &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen]) && (*outActRxLen > 0U) ) + { + ST_MEMMOVE( &gNfcip.rxBuf[gNfcip.rxBufPaylPos], &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen], *outActRxLen ); + } + + /*******************************************************************************/ + /* Check if target is indicating chaining MI */ + /*******************************************************************************/ + if( nfcip_PFBisIMI( rxPFB ) ) + { + gNfcip.isRxChaining = true; + *outIsChaining = true; + + nfcipLogD( " NFCIP(I) Rcvd IPDU OK w MI -> ACK \r\n" ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBRPDU_ACK( gNfcip.pni ), gNfcip.rxBuf[rxMsgIt++] ) ); + + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived*/ + } + else + { + gNfcip.isRxChaining = false; + gNfcip.state = NFCIP_ST_INIT_DEP_IDLE; + + ret = ERR_NONE; /* Data exchange done */ + } + } + return ret; +} + + +/*******************************************************************************/ +static ReturnCode nfcipTargetHandleRX( ReturnCode rxRes, uint16_t *outActRxLen, bool *outIsChaining ) +{ + ReturnCode ret; + uint8_t nfcDepLen; + uint8_t rxMsgIt; + uint8_t rxPFB; + uint8_t optHdrLen; + uint8_t resBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_TARGET_RES_MAX]; + + + ret = ERR_INTERNAL; + rxMsgIt = 0; + optHdrLen = 0; + + *outActRxLen = 0; + *outIsChaining = false; + + + /*******************************************************************************/ + /* Handle reception errors */ + /*******************************************************************************/ + switch( rxRes ) + { + /*******************************************************************************/ + case ERR_NONE: + break; + + case ERR_LINK_LOSS: + nfcipLogW( " NFCIP(T) Error: %d \r\n", rxRes ); + return rxRes; + + case ERR_BUSY: + return ERR_BUSY; /* Debug purposes */ + + case ERR_TIMEOUT: + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + case ERR_PROTO: + default: + /* Digital 1.1 16.12.5.2 The Target MUST NOT attempt any error recovery. * + * The Target MUST always stay in receive mode when a * + * Transmission Error or a Protocol Error occurs. * + * * + * Do not push Transmission/Protocol Errors to upper layer in Listen Mode #766 */ + + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; + } + + /*******************************************************************************/ + /* Rx OK check if valid DEP PDU */ + /*******************************************************************************/ + + /* Due to different modes on ST25R391x (with/without CRC) use NFC-DEP LEN instead of bytes retrieved */ + nfcDepLen = gNfcip.rxBuf[rxMsgIt++]; + + nfcipLogD( " NFCIP(T) rx OK: %d bytes \r\n", nfcDepLen ); + + if( gNfcip.rxBuf[rxMsgIt++] != NFCIP_REQ ) + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore bad request */ + } + + + /*******************************************************************************/ + /* Check whether target rcvd a normal DEP or deactivation request */ + /*******************************************************************************/ + switch( gNfcip.rxBuf[rxMsgIt++] ) + { + /*******************************************************************************/ + case (uint8_t)NFCIP_CMD_DEP_REQ: + break; /* Continue to normal DEP processing */ + + /*******************************************************************************/ + case (uint8_t)NFCIP_CMD_DSL_REQ: + + nfcipLogI( " NFCIP(T) rx DSL \r\n" ); + + /* Digital 1.0 14.9.1.2 If DID is used and incorrect ignore it */ + /* [Digital 1.0, 16.9.1.2]: If DID == 0, Target SHALL ignore DSL_REQ with DID */ + if ( (((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || (nfcDepLen != RFAL_NFCDEP_DSL_RLS_LEN_DID)) && (gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) ) + || ((gNfcip.cfg.did == RFAL_NFCDEP_DID_NO) && (nfcDepLen != RFAL_NFCDEP_DSL_RLS_LEN_NO_DID)) + ) + { + nfcipLogI( " NFCIP(T) DSL wrong DID, ignoring \r\n" ); + return ERR_BUSY; + } + + nfcipTx( NFCIP_CMD_DSL_RES, resBuf, NULL, 0, 0, NFCIP_NO_FWT ); + + gNfcip.state = NFCIP_ST_TARG_DEP_SLEEP; + return ERR_SLEEP_REQ; + + /*******************************************************************************/ + case (uint8_t)NFCIP_CMD_RLS_REQ: + + nfcipLogI( " NFCIP(T) rx RLS \r\n" ); + + /* Digital 1.0 14.10.1.2 If DID is used and incorrect ignore it */ + /* [Digital 1.0, 16.10.2.2]: If DID == 0, Target SHALL ignore DSL_REQ with DID */ + if ( (((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || (nfcDepLen != RFAL_NFCDEP_DSL_RLS_LEN_DID)) && (gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) ) + || ((gNfcip.cfg.did == RFAL_NFCDEP_DID_NO) && (nfcDepLen > RFAL_NFCDEP_DSL_RLS_LEN_NO_DID)) + ) + { + nfcipLogI( " NFCIP(T) RLS wrong DID, ignoring \r\n" ); + return ERR_BUSY; + } + + nfcipTx( NFCIP_CMD_RLS_RES, resBuf, NULL, 0, 0, NFCIP_NO_FWT ); + + gNfcip.state = NFCIP_ST_TARG_DEP_IDLE; + return ERR_RELEASE_REQ; + + /*******************************************************************************/ + /*case NFCIP_CMD_PSL_REQ: PSL must be handled in Activation only */ + /*case NFCIP_CMD_WUP_REQ: WUP not in NFC Forum Digital 1.0 */ + default: + + /* Don't go to NFCIP_ST_TARG_DEP_IDLE state as it needs to ignore this * + * invalid frame, and keep waiting for more frames */ + + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore bad frame */ + } + + /*******************************************************************************/ + + rxPFB = gNfcip.rxBuf[rxMsgIt++]; /* Store rcvd PFB */ + + /*******************************************************************************/ + /* Check for valid PFB type */ + if( !(nfcip_PFBisSPDU( rxPFB ) || nfcip_PFBisRPDU( rxPFB ) || nfcip_PFBisIPDU( rxPFB )) ) + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore invalid PFB */ + } + + /*******************************************************************************/ + if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) + { + if( !nfcip_PFBhasDID( rxPFB ) ) + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore bad/missing DID */ + } + if( gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did ) /* MISRA 13.5 */ + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore bad/missing DID */ + } + optHdrLen++; /* Inc header optional field cnt*/ + } + else if( nfcip_PFBhasDID( rxPFB ) ) /* DID not expected but rcv */ + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected DID */ + } + else + { + /* MISRA 15.7 - Empty else */ + } + + + /*******************************************************************************/ + if( gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO ) + { + if( (gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || !nfcip_PFBhasDID( rxPFB ) ) + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore bad/missing DID */ + } + optHdrLen++; /* Inc header optional field cnt*/ + } + else if( nfcip_PFBhasNAD( rxPFB ) ) /* NAD not expected but rcv */ + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected NAD */ + } + else + { + /* MISRA 15.7 - Empty else */ + } + + + /*******************************************************************************/ + /* Process R-PDU */ + /*******************************************************************************/ + if( nfcip_PFBisRPDU( rxPFB ) ) + { + nfcipLogD( " NFCIP(T) Rcvd R-PDU \r\n" ); + /*******************************************************************************/ + /* R ACK */ + /*******************************************************************************/ + if( nfcip_PFBisRACK( rxPFB ) ) + { + nfcipLogI( " NFCIP(T) Rcvd ACK \r\n" ); + if( gNfcip.pni == nfcip_PBF_PNI( rxPFB ) ) + { + /* R-ACK while not performing chaining -> Protocol error */ + if( !gNfcip.isTxChaining ) + { + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected ACK */ + } + + /* This block has been transmitted and acknowledged, perform RTOX until next data is provided */ + + /* Digital 1.1 16.12.4.7 - If ACK rcvd continue with chaining or an RTOX */ + nfcipTimerStart( gNfcip.RTOXTimer, nfcipRTOXAdjust( nfcipConv1FcToMs( rfalNfcDepWT2RWT( gNfcip.cfg.to ) )) ); + gNfcip.state = NFCIP_ST_TARG_DEP_RTOX; + + return ERR_NONE; /* This block has been transmitted */ + } + + /* Digital 1.0 14.12.3.4 - If last send was ATN and rx PNI is minus 1 */ + else if( nfcip_PFBisSATN( gNfcip.lastPFB ) && (nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI( rxPFB )) ) + { + nfcipLogI( " NFCIP(T) wrong PNI, last was ATN reTx \r\n" ); + /* Spec says to leave current PNI as is, but will be Inc after Tx, remaining the same */ + gNfcip.pni = nfcip_PNIDec( gNfcip.pni ); + + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return ERR_BUSY; + } + else + { + /* MISRA 15.7 - Empty else */ + } + } + /*******************************************************************************/ + /* R NACK */ + /*******************************************************************************/ + /* ISO 18092 12.6.1.3.3 When rcv NACK if PNI = prev PNI sent -> reTx */ + else if( nfcip_PFBisRNACK( rxPFB ) && (nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI( rxPFB ) ) ) + { + nfcipLogI( " NFCIP(T) Rcvd NACK \r\n" ); + + gNfcip.pni = nfcip_PNIDec( gNfcip.pni ); /* Dec so that has the prev PNI */ + + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return ERR_BUSY; + } + else + { + nfcipLogI( " NFCIP(T) Unexpected R-PDU \r\n" ); + + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected R-PDU */ + } + } + + /*******************************************************************************/ + /* Process S-PDU */ + /*******************************************************************************/ + if( nfcip_PFBisSPDU( rxPFB ) ) + { + nfcipLogD( " NFCIP(T) Rcvd S-PDU \r\n" ); + + /*******************************************************************************/ + /* S ATN */ + /*******************************************************************************/ + /* ISO 18092 12.6.3 Attention */ + if( nfcip_PFBisSATN( rxPFB ) ) /* If is a S-ATN */ + { + nfcipLogI( " NFCIP(T) Rcvd ATN curPNI: %d \r\n", gNfcip.pni ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBSPDU_ATN(), 0 ) ); + return ERR_BUSY; + } + + /*******************************************************************************/ + /* S TO */ + /*******************************************************************************/ + else if( nfcip_PFBisSTO( rxPFB ) ) /* If is a S-TO (RTOX) */ + { + if( nfcip_PFBisSTO( gNfcip.lastPFBnATN ) ) + { + nfcipLogI( " NFCIP(T) Rcvd TO \r\n" ); + + /* Digital 1.1 16.8.4.6 RTOX value in RES different that in REQ -> Protocol Error */ + if( gNfcip.lastRTOX != gNfcip.rxBuf[rxMsgIt++] ) + { + nfcipLogI( " NFCIP(T) Mismatched RTOX value \r\n" ); + + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected RTOX value */ + } + + /* Clear waiting for RTOX Ack Flag */ + gNfcip.isWait4RTOX = false; + + /* Check if a Tx is already pending */ + if( gNfcip.isTxPending ) + { + nfcipLogW( " NFCIP(T) Tx pending, go immediately to TX \r\n" ); + + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return ERR_BUSY; + } + + /* Start RTOX timer and change to check state */ + nfcipTimerStart( gNfcip.RTOXTimer, nfcipRTOXAdjust( nfcipConv1FcToMs( gNfcip.lastRTOX * rfalNfcDepWT2RWT(gNfcip.cfg.to ) ) ) ); + gNfcip.state = NFCIP_ST_TARG_DEP_RTOX; + + return ERR_BUSY; + } + } + else + { + /* Unexpected S-PDU */ + nfcipLogI( " NFCIP(T) Unexpected S-PDU \r\n" ); /* PRQA S 2880 # MISRA 2.1 - Guard code to prevent unexpected behavior */ + + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected S-PDU */ + } + } + + /*******************************************************************************/ + /* Process I-PDU */ + /*******************************************************************************/ + if( nfcip_PFBisIPDU( rxPFB ) ) + { + if( gNfcip.pni != nfcip_PBF_PNI( rxPFB ) ) + { + nfcipLogI( " NFCIP(T) Rcvd IPDU wrong PNI curPNI: %d rxPNI: %d \r\n", gNfcip.pni, nfcip_PBF_PNI( rxPFB ) ); + + /* Digital 1.1 16.12.3.4 - If last send was ATN and rx PNI is minus 1 */ + if( nfcip_PFBisSATN(gNfcip.lastPFB ) && (nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI( rxPFB )) ) + { + /* Spec says to leave current PNI as is, but will be Inc after Data Tx, remaining the same */ + gNfcip.pni = nfcip_PNIDec(gNfcip.pni); + + if( nfcip_PFBisIMI( rxPFB ) ) + { + nfcipLogI( " NFCIP(T) PNI = prevPNI && ATN before && chaining -> send ACK \r\n" ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBRPDU_ACK( gNfcip.pni ), gNfcip.rxBuf[rxMsgIt++] ) ); + + /* Digital 1.1 16.12.3.4 (...) leave the current PNI unchanged afterwards */ + gNfcip.pni = nfcip_PNIInc( gNfcip.pni ); + } + else + { + nfcipLogI( " NFCIP(T) PNI = prevPNI && ATN before -> reTx last I-PDU \r\n" ); + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + } + + return ERR_BUSY; + } + + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + return ERR_BUSY; /* ERR_PROTO - Ignore bad PNI value */ + } + + nfcipLogD( " NFCIP(T) Rcvd IPDU OK PNI: %d \r\n", gNfcip.pni ); + + /*******************************************************************************/ + /* Successful data exchange */ + /*******************************************************************************/ + *outActRxLen = ((uint16_t)nfcDepLen - RFAL_NFCDEP_DEP_HEADER - (uint16_t)optHdrLen); + + nfcipClearCounters(); + + if( (&gNfcip.rxBuf[gNfcip.rxBufPaylPos] != &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen]) && (*outActRxLen > 0U) ) + { + ST_MEMMOVE( &gNfcip.rxBuf[gNfcip.rxBufPaylPos], &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen], *outActRxLen ); + } + + + /*******************************************************************************/ + /* Check if Initiator is indicating chaining MI */ + /*******************************************************************************/ + if( nfcip_PFBisIMI( rxPFB ) ) + { + gNfcip.isRxChaining = true; + *outIsChaining = true; + + nfcipLogD( " NFCIP(T) Rcvd IPDU OK w MI -> ACK \r\n" ); + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBRPDU_ACK( gNfcip.pni ), gNfcip.rxBuf[rxMsgIt++] ) ); + + gNfcip.pni = nfcip_PNIInc( gNfcip.pni ); + + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived*/ + } + else + { + if(gNfcip.isRxChaining) + { + nfcipLogI( " NFCIP(T) Rcvd last IPDU chaining finished \r\n" ); + } + + /*******************************************************************************/ + /* Reception done, send to DH and start RTOX timer */ + /*******************************************************************************/ + nfcipTimerStart( gNfcip.RTOXTimer, nfcipRTOXAdjust( nfcipConv1FcToMs( rfalNfcDepWT2RWT( gNfcip.cfg.to ) )) ); + gNfcip.state = NFCIP_ST_TARG_DEP_RTOX; + + gNfcip.isRxChaining = false; + ret = ERR_NONE; /* Data exchange done */ + } + } + return ret; +} + + +/*******************************************************************************/ +static ReturnCode nfcipTx( rfalNfcDepCmd cmd, uint8_t* txBuf, uint8_t *paylBuf, uint16_t paylLen, uint8_t pfbData, uint32_t fwt ) +{ + uint16_t txBufIt; + uint8_t *txBlock; + uint8_t *payloadBuf; + uint8_t pfb; + + + if( txBuf == NULL ) + { + return ERR_PARAM; + } + + + payloadBuf = paylBuf; /* MISRA 17.8: Use intermediate variable */ + + if( (paylLen == 0U) || (payloadBuf == NULL) ) + { + payloadBuf = (uint8_t*) &txBuf[RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /* If not a DEP (no Data) ensure enough space for header */ + } + + + txBufIt = 0; + pfb = pfbData; /* MISRA 17.8: Use intermediate variable */ + + txBlock = payloadBuf; /* Point to beginning of the Data, and go backwards */ + + + gNfcip.lastCmd = (uint8_t)cmd; /* Store last cmd sent */ + gNfcip.lastPFB = NFCIP_PFB_INVALID; /* Reset last pfb sent */ + + /*******************************************************************************/ + /* Compute outgoing NFCIP message */ + /*******************************************************************************/ + switch( cmd ) + { + /*******************************************************************************/ + case NFCIP_CMD_ATR_RES: + case NFCIP_CMD_ATR_REQ: + + rfalNfcDepSetNFCID( payloadBuf, gNfcip.cfg.nfcid, gNfcip.cfg.nfcidLen ); /* NFCID */ + txBufIt += RFAL_NFCDEP_NFCID3_LEN; + + payloadBuf[txBufIt++] = gNfcip.cfg.did; /* DID */ + payloadBuf[txBufIt++] = gNfcip.cfg.bs; /* BS */ + payloadBuf[txBufIt++] = gNfcip.cfg.br; /* BR */ + + if( cmd == NFCIP_CMD_ATR_RES ) + { + payloadBuf[txBufIt++] = gNfcip.cfg.to; /* ATR_RES[ TO ] */ + } + + if( gNfcip.cfg.gbLen > 0U) + { + payloadBuf[txBufIt++] = nfcip_PPwGB( gNfcip.cfg.lr ); /* PP signalling GB */ + ST_MEMCPY( &payloadBuf[txBufIt], gNfcip.cfg.gb, gNfcip.cfg.gbLen ); /* set General Bytes */ + txBufIt += gNfcip.cfg.gbLen; + } + else + { + payloadBuf[txBufIt++] = rfalNfcDepLR2PP( gNfcip.cfg.lr ); /* PP without GB */ + } + + if( (txBufIt + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN) > RFAL_NFCDEP_ATRREQ_MAX_LEN ) /* Check max ATR length (ATR_REQ = ATR_RES)*/ + { + return ERR_PARAM; + } + break; + + /*******************************************************************************/ + case NFCIP_CMD_WUP_REQ: /* ISO 18092 - 12.5.2.1 */ + + rfalNfcDepSetNFCID( (payloadBuf), gNfcip.cfg.nfcid, gNfcip.cfg.nfcidLen ); /* NFCID */ + txBufIt += RFAL_NFCDEP_NFCID3_LEN; + + *(--txBlock) = gNfcip.cfg.did; /* DID */ + break; + + /*******************************************************************************/ + case NFCIP_CMD_WUP_RES: /* ISO 18092 - 12.5.2.2 */ + case NFCIP_CMD_PSL_REQ: + case NFCIP_CMD_PSL_RES: + + *(--txBlock) = gNfcip.cfg.did; /* DID */ + break; + + /*******************************************************************************/ + case NFCIP_CMD_RLS_REQ: + case NFCIP_CMD_RLS_RES: + case NFCIP_CMD_DSL_REQ: + case NFCIP_CMD_DSL_RES: + + /* Digital 1.0 - 14.8.1.1 & 14.9.1.1 & 14.10.1.1 Only add DID if not 0 */ + if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) + { + *(--txBlock) = gNfcip.cfg.did; /* DID */ + } + break; + + /*******************************************************************************/ + case NFCIP_CMD_DEP_REQ: + case NFCIP_CMD_DEP_RES: + + /* Compute optional PFB bits */ + if (gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { pfb |= NFCIP_PFB_DID_BIT; } + if (gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO) { pfb |= NFCIP_PFB_NAD_BIT; } + if ((gNfcip.isTxChaining) && (nfcip_PFBisIPDU(pfb)) ) { pfb |= NFCIP_PFB_MI_BIT; } + + /* Store PFB for future handling */ + gNfcip.lastPFB = pfb; /* store PFB sent */ + + if( !nfcip_PFBisSATN(pfb) ) + { + gNfcip.lastPFBnATN = pfb; /* store last PFB different then ATN */ + } + + + /* Add NAD if it is to be supported */ + if( gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO ) + { + *(--txBlock) = gNfcip.cfg.nad; /* NAD */ + } + + /* Digital 1.0 - 14.8.1.1 & 14.8.1.1 Only add DID if not 0 */ + if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) + { + *(--txBlock) = gNfcip.cfg.did; /* DID */ + } + + *(--txBlock) = pfb; /* PFB */ + + + /* NCI 1.0 - Check if Empty frames are allowed */ + if( (paylLen == 0U) && nfcipIsEmptyDEPDisabled(gNfcip.cfg.oper) && nfcip_PFBisIPDU(pfb) ) + { + return ERR_PARAM; + } + break; + + /*******************************************************************************/ + default: + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Prepend Header */ + /*******************************************************************************/ + *(--txBlock) = (uint8_t)cmd; /* CMD */ + *(--txBlock) = (uint8_t)( nfcipCmdIsReq(cmd) ? NFCIP_REQ : NFCIP_RES ); /* CMDType */ + + + txBufIt += paylLen + (uint16_t)((uint32_t)payloadBuf - (uint32_t)txBlock); /* Calculate overall buffer size */ + + + if( txBufIt > gNfcip.fsc ) /* Check if msg length violates the maximum payload size FSC */ + { + return ERR_NOTSUPP; + } + + /*******************************************************************************/ + return nfcipDataTx( txBlock, txBufIt, fwt ); +} + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +static void nfcipConfig( const rfalNfcDepConfigs * cfg ) +{ + if (cfg == NULL) + { + return; + } + + ST_MEMCPY(&gNfcip.cfg, cfg, sizeof(rfalNfcDepConfigs)); /* Copy given config to local */ + + gNfcip.cfg.to = MIN( RFAL_NFCDEP_WT_TRG_MAX, gNfcip.cfg.to); /* Ensure proper WT value */ + gNfcip.cfg.did = nfcip_DIDMax( gNfcip.cfg.did ); /* Ensure proper DID value */ + gNfcip.fsc = rfalNfcDepLR2FS( gNfcip.cfg.lr ); /* Calculate FSC based on given LR */ + + gNfcip.state = ( ( gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) ? NFCIP_ST_TARG_WAIT_ATR : NFCIP_ST_INIT_IDLE ); +} + + +/*******************************************************************************/ +static ReturnCode nfcipRun( uint16_t *outActRxLen, bool *outIsChaining ) +{ + ReturnCode ret; + + ret = ERR_SYNTAX; + + nfcipLogD( " NFCIP Run() state: %d \r\n", gNfcip.state ); + + switch( gNfcip.state ) + { + /*******************************************************************************/ + case NFCIP_ST_IDLE: + case NFCIP_ST_INIT_DEP_IDLE: + case NFCIP_ST_TARG_DEP_IDLE: + case NFCIP_ST_TARG_DEP_SLEEP: + return ERR_NONE; + + /*******************************************************************************/ + case NFCIP_ST_INIT_DEP_TX: + + nfcipLogD( " NFCIP(I) Tx PNI: %d txLen: %d \r\n", gNfcip.pni, gNfcip.txBufLen ); + ret = nfcipTx( NFCIP_CMD_DEP_REQ, gNfcip.txBuf, &gNfcip.txBuf[gNfcip.txBufPaylPos], gNfcip.txBufLen, nfcip_PFBIPDU( gNfcip.pni ), (gNfcip.cfg.fwt + gNfcip.cfg.dFwt) ); + + switch( ret ) + { + case ERR_PARAM: + default: + gNfcip.state = NFCIP_ST_INIT_DEP_IDLE; + return ret; + + case ERR_NONE: + gNfcip.state = NFCIP_ST_INIT_DEP_RX; + break; + } + /* fall through */ + + /*******************************************************************************/ + case NFCIP_ST_INIT_DEP_RX: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + ret = nfcipDataRx( false ); + + if( ret != ERR_BUSY ) + { + ret = nfcipInitiatorHandleDEP( ret, *gNfcip.rxRcvdLen, outActRxLen, outIsChaining ); + } + + break; + + /*******************************************************************************/ + case NFCIP_ST_TARG_DEP_RTOX: + + if( !nfcipTimerisExpired( gNfcip.RTOXTimer ) ) /* Do nothing until RTOX timer has expired */ + { + return ERR_BUSY; + } + + /* If we cannot send a RTOX raise a Timeout error so that we do not + * hold the field On forever in AP2P */ + if( nfcipIsRTOXReqDisabled(gNfcip.cfg.oper) ) + { + /* We should reEnable Rx, and measure time between our field Off to + * either report link loss or recover #287 */ + nfcipLogI( " NFCIP(T) RTOX not sent due to config, NOT reenabling Rx \r\n" ); + return ERR_TIMEOUT; + } + + if( gNfcip.cntRTOXRetrys++ > NFCIP_MAX_RTOX_RETRYS ) /* Check maximum consecutive RTOX requests */ + { + return ERR_PROTO; + } + + nfcipLogI( " NFCIP(T) RTOX sent \r\n" ); + + gNfcip.lastRTOX = nfcip_RTOXTargMax(gNfcip.cfg.to); /* Calculate requested RTOX value, and send it */ + EXIT_ON_ERR( ret, nfcipDEPControlMsg( nfcip_PFBSPDU_TO(), gNfcip.lastRTOX ) ); + + /* Set waiting for RTOX Ack Flag */ + gNfcip.isWait4RTOX = true; + + gNfcip.state = NFCIP_ST_TARG_DEP_RX; /* Go back to Rx to process RTOX ack */ + return ERR_BUSY; + + /*******************************************************************************/ + case NFCIP_ST_TARG_DEP_TX: + + nfcipLogD( " NFCIP(T) Tx PNI: %d txLen: %d \r\n", gNfcip.pni, gNfcip.txBufLen ); + ret = nfcipTx( NFCIP_CMD_DEP_RES, gNfcip.txBuf, &gNfcip.txBuf[gNfcip.txBufPaylPos], gNfcip.txBufLen, nfcip_PFBIPDU( gNfcip.pni ), NFCIP_NO_FWT ); + + /* Clear flags */ + gNfcip.isTxPending = false; + gNfcip.isWait4RTOX = false; + + /* Digital 1.0 14.12.3.4 Increment the current PNI after Tx */ + gNfcip.pni = nfcip_PNIInc( gNfcip.pni ); + + switch( ret ) + { + case ERR_PARAM: + default: + gNfcip.state = NFCIP_ST_TARG_DEP_IDLE; /* Upon Tx error, goto IDLE state */ + return ret; + + case ERR_NONE: + gNfcip.state = NFCIP_ST_TARG_DEP_RX; /* All OK, goto Rx state */ + break; + } + /* fall through */ + + /*******************************************************************************/ + case NFCIP_ST_TARG_DEP_RX: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + if( gNfcip.isReqPending ) /* if already has Data should be from a DEP from nfcipTargetHandleActivation() */ + { + nfcipLogD( " NFCIP(T) Skipping Rx Using DEP from Activation \r\n" ); + + gNfcip.isReqPending = false; + ret = ERR_NONE; + } + else + { + ret = nfcipDataRx( false ); + } + + if( ret != ERR_BUSY ) + { + ret = nfcipTargetHandleRX( ret, outActRxLen, outIsChaining ); + } + + break; + + /*******************************************************************************/ + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + return ret; +} + + +/*******************************************************************************/ +void rfalNfcDepSetDeactivatingCallback( rfalNfcDepDeactCallback pFunc ) +{ + gNfcip.isDeactivating = pFunc; +} + + +/*******************************************************************************/ +void rfalNfcDepInitialize( void ) +{ + nfcipLogD( " NFCIP Ini() \r\n" ); + + gNfcip.state = NFCIP_ST_IDLE; + gNfcip.isDeactivating = NULL; + + gNfcip.isTxPending = false; + gNfcip.isWait4RTOX = false; + gNfcip.isReqPending = false; + + + gNfcip.cfg.oper = (RFAL_NFCDEP_OPER_FULL_MI_DIS | RFAL_NFCDEP_OPER_EMPTY_DEP_EN | RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN); + + gNfcip.cfg.did = RFAL_NFCDEP_DID_NO; + gNfcip.cfg.nad = RFAL_NFCDEP_NAD_NO; + + gNfcip.cfg.br = RFAL_NFCDEP_Bx_NO_HIGH_BR; + gNfcip.cfg.bs = RFAL_NFCDEP_Bx_NO_HIGH_BR; + + gNfcip.cfg.lr = RFAL_NFCDEP_LR_254; + gNfcip.fsc = rfalNfcDepLR2FS( gNfcip.cfg.lr ); + + gNfcip.cfg.gbLen = 0; + + gNfcip.cfg.fwt = RFAL_NFCDEP_MAX_FWT; + gNfcip.cfg.dFwt = RFAL_NFCDEP_MAX_FWT; + + gNfcip.pni = 0; + gNfcip.RTOXTimer = 0; + + nfcipClearCounters(); +} + + +/*******************************************************************************/ +static void nfcipSetDEPParams( rfalNfcDepDEPParams *DEPParams ) +{ + nfcipLogD( " NFCIP SetDEP() txLen: %d \r\n", DEPParams->txBufLen ); + + gNfcip.isTxChaining = DEPParams->txChaining; + gNfcip.txBuf = DEPParams->txBuf; + gNfcip.rxBuf = DEPParams->rxBuf; + gNfcip.txBufLen = DEPParams->txBufLen; + gNfcip.rxBufLen = DEPParams->rxBufLen; + gNfcip.txBufPaylPos = DEPParams->txBufPaylPos; + gNfcip.rxBufPaylPos = DEPParams->rxBufPaylPos; + + if( DEPParams->did != RFAL_NFCDEP_DID_KEEP ) + { + gNfcip.cfg.did = nfcip_DIDMax( DEPParams->did ); + } + + gNfcip.cfg.fwt = DEPParams->fwt; + gNfcip.cfg.dFwt = DEPParams->dFwt; + gNfcip.fsc = DEPParams->fsc; + + + + if(gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) + { + /* If there's any data to be sent go for Tx */ + if(DEPParams->txBufLen > 0U) + { + /* Ensure that an RTOX Ack is not being expected at moment */ + if( !gNfcip.isWait4RTOX ) + { + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return; + } + else + { + /* If RTOX Ack is expected, signal a pending Tx to be transmitted right after */ + gNfcip.isTxPending = true; + nfcipLogW( " NFCIP(T) Waiting RTOX, queueing outgoing DEP Block \r\n" ); + } + } + + /*Digital 1.0 14.12.4.1 In target mode the first PDU MUST be sent by the Initiator */ + gNfcip.state = NFCIP_ST_TARG_DEP_RX; + return; + } + + /* New data TxRx request clear previous error counters for consecutive TxRx without reseting communication/protocol layer*/ + nfcipClearCounters(); + + gNfcip.state = NFCIP_ST_INIT_DEP_TX; +} + + +/*******************************************************************************/ +bool rfalNfcDepTargetRcvdATR( void ) +{ + return ( (gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) && nfcipIsTarget(gNfcip.state) && (gNfcip.state > NFCIP_ST_TARG_WAIT_ATR) ); +} + + +/*******************************************************************************/ +bool rfalNfcDepIsAtrReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid3 ) +{ + uint8_t msgIt; + + msgIt = 0; + + if ( (bufLen < RFAL_NFCDEP_ATRREQ_MIN_LEN) || (bufLen > RFAL_NFCDEP_ATRREQ_MAX_LEN) ) + { + return false; + } + + if ( buf[msgIt++] != NFCIP_REQ ) + { + return false; + } + + if( buf[msgIt++] != (uint8_t)NFCIP_CMD_ATR_REQ ) + { + return false; + } + + /* Output NFID3 if requested */ + if( nfcid3 != NULL ) + { + ST_MEMCPY( nfcid3, &buf[RFAL_NFCDEP_ATR_REQ_NFCID3_POS], RFAL_NFCDEP_NFCID3_LEN ); + } + + return true; +} + + +/*******************************************************************************/ +static ReturnCode nfcipTargetHandleActivation( rfalNfcDepDevice *nfcDepDev, uint8_t *outBRS ) +{ + ReturnCode ret; + uint8_t msgIt; + uint8_t txBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_PSLRES_LEN]; + + /*******************************************************************************/ + /* Check if we are in correct state */ + /*******************************************************************************/ + if( gNfcip.state != NFCIP_ST_TARG_WAIT_ACTV ) + { + return ERR_WRONG_STATE; + } + + + /*******************************************************************************/ + /* Check required parameters */ + /*******************************************************************************/ + if( outBRS == NULL ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Wait and process incoming cmd (PSL / DEP) */ + /*******************************************************************************/ + ret = nfcipDataRx( false ); + + if( ret != ERR_NONE ) + { + return ret; + } + + msgIt = 0; + *outBRS = RFAL_NFCDEP_BRS_MAINTAIN; /* set out BRS to be maintained */ + + msgIt++; /* Skip LEN byte */ + + if ( gNfcip.rxBuf[msgIt++] != NFCIP_REQ ) + { + return ERR_PROTO; + } + + if( gNfcip.rxBuf[msgIt] == (uint8_t)NFCIP_CMD_PSL_REQ ) + { + msgIt++; + + if( gNfcip.rxBuf[msgIt++] != gNfcip.cfg.did ) /* Checking DID */ + { + return ERR_PROTO; + } + + nfcipLogI( " NFCIP(T) PSL REQ rcvd \r\n" ); + + *outBRS = gNfcip.rxBuf[msgIt++]; /* assign output BRS value */ + + /* Store FSL(LR) and update current config */ + gNfcip.cfg.lr = (gNfcip.rxBuf[msgIt++] & RFAL_NFCDEP_LR_VAL_MASK); + gNfcip.fsc = rfalNfcDepLR2FS( gNfcip.cfg.lr ); + + /*******************************************************************************/ + /* Update NFC-DDE Device info */ + if( nfcDepDev != NULL ) + { + /* Update Bitrate info */ + /* PRQA S 4342 2 # MISRA 10.5 - Layout of enum rfalBitRate and definition of rfalNfcDepBRS2DSI guarantee no invalid enum values to be created */ + nfcDepDev->info.DSI = (rfalBitRate)rfalNfcDepBRS2DSI( *outBRS ); /* DSI codes the bit rate from Initiator to Target */ + nfcDepDev->info.DRI = (rfalBitRate)rfalNfcDepBRS2DRI( *outBRS ); /* DRI codes the bit rate from Target to Initiator */ + + /* Update Length Reduction and Frame Size */ + nfcDepDev->info.LR = gNfcip.cfg.lr; + nfcDepDev->info.FS = gNfcip.fsc; + + /* Update PPi byte */ + nfcDepDev->activation.Initiator.ATR_REQ.PPi &= ~RFAL_NFCDEP_PP_LR_MASK; + nfcDepDev->activation.Initiator.ATR_REQ.PPi |= rfalNfcDepLR2PP( gNfcip.cfg.lr ); + } + + EXIT_ON_ERR( ret, nfcipTx( NFCIP_CMD_PSL_RES, txBuf, NULL, 0, 0, NFCIP_NO_FWT ) ); + } + else + { + if( gNfcip.rxBuf[msgIt] == (uint8_t)NFCIP_CMD_DEP_REQ ) + { + msgIt++; + + /*******************************************************************************/ + /* Digital 1.0 14.12.3.1 PNI must be initialized to 0 */ + if( nfcip_PBF_PNI( gNfcip.rxBuf[msgIt] ) != 0U ) + { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Digital 1.0 14.8.2.1 check if DID is expected and match -> Protocol Error */ + if( nfcip_PFBhasDID( gNfcip.rxBuf[ msgIt] ) ) + { + if( gNfcip.rxBuf[++msgIt] != gNfcip.cfg.did ) + { + return ERR_PROTO; + } + } + else if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) /* DID expected but not rcv */ + { + return ERR_PROTO; + } + else + { + /* MISRA 15.7 - Empty else */ + } + } + + /* Signal Request pending to be digested on normal Handling (DEP_REQ, DSL_REQ, RLS_REQ) */ + gNfcip.isReqPending = true; + } + + gNfcip.state = NFCIP_ST_TARG_DEP_RX; + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepATR( const rfalNfcDepAtrParam* param, rfalNfcDepAtrRes *atrRes, uint8_t* atrResLen ) +{ + ReturnCode ret; + rfalNfcDepConfigs cfg; + uint16_t rxLen; + uint8_t msgIt; + uint8_t txBuf[RFAL_NFCDEP_ATRREQ_MAX_LEN]; + uint8_t rxBuf[NFCIP_ATRRES_BUF_LEN]; + + + if( (param == NULL) || (atrRes == NULL) || (atrResLen == NULL) ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Configure NFC-DEP layer */ + /*******************************************************************************/ + + cfg.did = param->DID; + cfg.nad = param->NAD; + cfg.fwt = RFAL_NFCDEP_MAX_FWT; + cfg.dFwt = RFAL_NFCDEP_MAX_FWT; + cfg.br = param->BR; + cfg.bs = param->BS; + cfg.lr = param->LR; + cfg.to = RFAL_NFCDEP_WT_TRG_MAX; /* Not used in Initiator mode */ + + + cfg.gbLen = param->GBLen; + if( cfg.gbLen > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( cfg.gb, param->GB, cfg.gbLen ); + } + + cfg.nfcidLen = param->nfcidLen; + if( cfg.nfcidLen > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( cfg.nfcid, param->nfcid, cfg.nfcidLen ); + } + + cfg.role = RFAL_NFCDEP_ROLE_INITIATOR; + cfg.oper = param->operParam; + cfg.commMode = param->commMode; + + rfalNfcDepInitialize(); + nfcipConfig( &cfg ); + + /*******************************************************************************/ + /* Send ATR_REQ */ + /*******************************************************************************/ + + EXIT_ON_ERR( ret, nfcipTxRx(NFCIP_CMD_ATR_REQ, txBuf, nfcipRWTActivation(), NULL, 0, rxBuf, NFCIP_ATRRES_BUF_LEN, &rxLen ) ); + + + /*******************************************************************************/ + /* ATR sent, check response */ + /*******************************************************************************/ + msgIt = 0; + rxLen = ((uint16_t)rxBuf[msgIt++] - RFAL_NFCDEP_LEN_LEN); /* use LEN byte */ + + if( (rxLen < RFAL_NFCDEP_ATRRES_MIN_LEN) || (rxLen > RFAL_NFCDEP_ATRRES_MAX_LEN) ) /* Checking length: ATR_RES */ + { + return ERR_PROTO; + } + + if( rxBuf[msgIt++] != NFCIP_RES ) /* Checking if is a response*/ + { + return ERR_PROTO; + } + + if( rxBuf[msgIt++] != (uint8_t)NFCIP_CMD_ATR_RES ) /* Checking if is a ATR RES */ + { + return ERR_PROTO; + } + + ST_MEMCPY( (uint8_t*)atrRes, (rxBuf + RFAL_NFCDEP_LEN_LEN), rxLen ); + *atrResLen = (uint8_t)rxLen; + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepPSL( uint8_t BRS, uint8_t FSL ) +{ + ReturnCode ret; + uint16_t rxLen; + uint8_t msgIt; + uint8_t txBuf[NFCIP_PSLREQ_LEN + NFCIP_PSLPAY_LEN]; + uint8_t rxBuf[NFCIP_PSLRES_LEN]; + + msgIt = NFCIP_PSLREQ_LEN; + + txBuf[msgIt++] = BRS; + txBuf[msgIt++] = FSL; + + /*******************************************************************************/ + /* Send PSL REQ and wait for response */ + /*******************************************************************************/ + EXIT_ON_ERR( ret, nfcipTxRx( NFCIP_CMD_PSL_REQ, txBuf, nfcipRWTActivation(), &txBuf[NFCIP_PSLREQ_LEN], (msgIt - NFCIP_PSLREQ_LEN), rxBuf, NFCIP_PSLRES_LEN, &rxLen ) ); + + + /*******************************************************************************/ + /* PSL sent, check response */ + /*******************************************************************************/ + msgIt = 0; + rxLen = (uint16_t)(rxBuf[msgIt++]); /* use LEN byte */ + + if( rxLen < NFCIP_PSLRES_LEN ) /* Checking length: LEN + RLS_RES */ + { + return ERR_PROTO; + } + + if( rxBuf[msgIt++] != NFCIP_RES ) /* Checking if is a response */ + { + return ERR_PROTO; + } + + if( rxBuf[msgIt++] != (uint8_t)NFCIP_CMD_PSL_RES ) /* Checking if is a PSL RES */ + { + return ERR_PROTO; + } + + if( rxBuf[msgIt++] != gNfcip.cfg.did ) /* Checking DID */ + { + return ERR_PROTO; + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepDSL( void ) +{ + ReturnCode ret; + uint8_t txBuf[ RFAL_NFCDEP_HEADER_PAD + NFCIP_DSLREQ_LEN]; + uint8_t rxBuf[NFCIP_DSLRES_LEN]; + uint8_t rxMsgIt; + uint16_t rxLen = 0; + + if( gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET ) + { + return ERR_NONE; /* Target has no deselect procedure */ + } + + /* Repeating a DSL REQ is optional, not doing it */ + EXIT_ON_ERR( ret, nfcipTxRx( NFCIP_CMD_DSL_REQ, txBuf, nfcipRWTActivation(), NULL, 0, rxBuf, RFAL_NFCDEP_ATRRES_MAX_LEN, &rxLen ) ); + + /*******************************************************************************/ + rxMsgIt = 0; + + if( rxBuf[rxMsgIt++] < NFCIP_DSLRES_MIN ) /* Checking length: LEN + DSL_RES */ + { + return ERR_PROTO; + } + + if( rxBuf[rxMsgIt++] != NFCIP_RES ) /* Checking if is a response */ + { + return ERR_PROTO; + } + + if( rxBuf[rxMsgIt++] != (uint8_t)NFCIP_CMD_DSL_RES ) /* Checking if is DSL RES */ + { + return ERR_PROTO; + } + + if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) + { + if ( rxBuf[rxMsgIt++] != gNfcip.cfg.did ) + { + return ERR_PROTO; + } + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepRLS( void ) +{ + ReturnCode ret; + uint8_t txBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_RLSREQ_LEN]; + uint8_t rxBuf[NFCIP_RLSRES_LEN]; + uint8_t rxMsgIt; + uint16_t rxLen = 0; + + if ( gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET ) /* Target has no release procedure */ + { + return ERR_NONE; + } + + /* Repeating a RLS REQ is optional, not doing it */ + EXIT_ON_ERR( ret, nfcipTxRx( NFCIP_CMD_RLS_REQ, txBuf, nfcipRWTActivation(), NULL, 0, rxBuf, RFAL_NFCDEP_ATRRES_MAX_LEN, &rxLen ) ); + + /*******************************************************************************/ + rxMsgIt = 0; + + if( rxBuf[rxMsgIt++] < NFCIP_RLSRES_MIN ) /* Checking length: LEN + RLS_RES */ + { + return ERR_PROTO; + } + + if( rxBuf[rxMsgIt++] != NFCIP_RES ) /* Checking if is a response */ + { + return ERR_PROTO; + } + + if( rxBuf[rxMsgIt++] != (uint8_t)NFCIP_CMD_RLS_RES ) /* Checking if is RLS RES */ + { + return ERR_PROTO; + } + + if( gNfcip.cfg.did != RFAL_NFCDEP_DID_NO ) + { + if ( rxBuf[rxMsgIt++] != gNfcip.cfg.did ) + { + return ERR_PROTO; + } + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepInitiatorHandleActivation( rfalNfcDepAtrParam* param, rfalBitRate desiredBR, rfalNfcDepDevice* nfcDepDev ) +{ + ReturnCode ret; + uint8_t maxRetyrs; + uint8_t PSL_BRS; + uint8_t PSL_FSL; + bool sendPSL; + + if( (param == NULL) || (nfcDepDev == NULL) ) + { + return ERR_PARAM; + } + + param->NAD = RFAL_NFCDEP_NAD_NO; /* Digital 1.1 16.6.2.9 Initiator SHALL NOT use NAD */ + maxRetyrs = NFCIP_ATR_RETRY_MAX; + + /*******************************************************************************/ + /* Send ATR REQ and wait for response */ + /*******************************************************************************/ + do{ /* Upon transmission error ATR REQ should be retried */ + + ret = rfalNfcDepATR( param, &nfcDepDev->activation.Target.ATR_RES, &nfcDepDev->activation.Target.ATR_RESLen ); + + if( nfcipIsTransmissionError(ret) ) + { + continue; + } + break; + } + while( (maxRetyrs--) != 0U ); + + if( ret != ERR_NONE ) + { + return ret; + } + + /*******************************************************************************/ + /* Compute NFC-DEP device with ATR_RES */ + /*******************************************************************************/ + nfcDepDev->info.GBLen = (nfcDepDev->activation.Target.ATR_RESLen - RFAL_NFCDEP_ATRRES_MIN_LEN); + nfcDepDev->info.DID = nfcDepDev->activation.Target.ATR_RES.DID; + nfcDepDev->info.NAD = RFAL_NFCDEP_NAD_NO; /* Digital 1.1 16.6.3.11 Initiator SHALL ignore b1 of PPt */ + nfcDepDev->info.LR = rfalNfcDepPP2LR( nfcDepDev->activation.Target.ATR_RES.PPt ); + nfcDepDev->info.FS = rfalNfcDepLR2FS( nfcDepDev->info.LR ); + nfcDepDev->info.WT = (nfcDepDev->activation.Target.ATR_RES.TO & RFAL_NFCDEP_WT_MASK); + nfcDepDev->info.FWT = rfalNfcDepCalculateRWT( nfcDepDev->info.WT ); + nfcDepDev->info.dFWT = RFAL_NFCDEP_WT_DELTA; + + rfalGetBitRate( &nfcDepDev->info.DSI, &nfcDepDev->info.DRI ); + + + + /*******************************************************************************/ + /* Check if a PSL needs to be sent */ + /*******************************************************************************/ + sendPSL = false; + PSL_BRS = rfalNfcDepDx2BRS( nfcDepDev->info.DSI ); /* Set current bit rate divisor on both directions */ + PSL_FSL = nfcDepDev->info.LR; /* Set current Frame Size */ + + + + /* Activity 1.0 9.4.4.15 & 9.4.6.3 NFC-DEP Activation PSL + * Activity 2.0 9.4.4.17 & 9.4.6.6 NFC-DEP Activation PSL + * + * PSL_REQ shall only be sent if desired bit rate is different from current (Activity 1.0) + * PSL_REQ shall be sent to update LR or bit rate (Activity 2.0) + * */ + +#if 0 /* PSL due to LR is disabled, can be enabled if desired*/ + /*******************************************************************************/ + /* Check Frame Size */ + /*******************************************************************************/ + if( gNfcip.cfg.lr < nfcDepDev->info.LR ) /* If our Length reduction is smaller */ + { + sendPSL = true; + + nfcDepDev->info.LR = MIN( nfcDepDev->info.LR, gNfcip.cfg.lr ); + + gNfcip.cfg.lr = nfcDepDev->info.LR; /* Update nfcip LR to be used */ + gNfcip.fsc = rfalNfcDepLR2FS( gNfcip.cfg.lr ); /* Update nfcip FSC to be used */ + + PSL_FSL = gNfcip.cfg.lr; /* Set LR to be sent */ + + nfcipLogI( " NFCIP(I) Frame Size differ, PSL new fsc: %d \r\n", gNfcip.fsc ); + } +#endif + + + /*******************************************************************************/ + /* Check Baud rates */ + /*******************************************************************************/ + if( nfcDepDev->info.DSI != desiredBR ) /* if desired BR is different */ + { + /* || (target->brt != RFAL_NFCDEP_Bx_NO_HIGH_BR) || (target->bst != RFAL_NFCDEP_Bx_NO_HIGH_BR) */ /* if target supports higher BR, must send PSL? */ + if( nfcipDxIsSupported( (uint8_t)desiredBR, nfcDepDev->activation.Target.ATR_RES.BRt, nfcDepDev->activation.Target.ATR_RES.BSt ) ) /* if desired BR is supported */ /* MISRA 13.5 */ + { + sendPSL = true; + PSL_BRS = rfalNfcDepDx2BRS( desiredBR ); + + nfcipLogI( " NFCIP(I) BR differ, PSL BR: 0x%02X \r\n", PSL_BRS ); + } + } + + + /*******************************************************************************/ + if( sendPSL ) + { + /*******************************************************************************/ + /* Send PSL REQ and wait for response */ + /*******************************************************************************/ + EXIT_ON_ERR( ret, rfalNfcDepPSL(PSL_BRS, PSL_FSL) ); + + /* Check if bit rate has been changed */ + if( nfcDepDev->info.DSI != desiredBR ) + { + /* Check if device was in Passive NFC-A and went to higher bit rates, use NFC-F */ + if( (nfcDepDev->info.DSI == RFAL_BR_106) && (gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_PASSIVE) ) + { + + #if RFAL_FEATURE_NFCF + /* If Passive initialize NFC-F module */ + rfalNfcfPollerInitialize( desiredBR ); + #else /* RFAL_FEATURE_NFCF */ + return ERR_NOTSUPP; + #endif /* RFAL_FEATURE_NFCF */ + + } + + nfcDepDev->info.DRI = desiredBR; /* DSI Bit Rate coding from Initiator to Target */ + nfcDepDev->info.DSI = desiredBR; /* DRI Bit Rate coding from Target to Initiator */ + + rfalSetBitRate( nfcDepDev->info.DSI, nfcDepDev->info.DRI ); + } + + + return ERR_NONE; /* PSL has been sent */ + } + + return ERR_NONE; /* No PSL has been sent */ +} + + +/*******************************************************************************/ +uint32_t rfalNfcDepCalculateRWT( uint8_t wt ) +{ + /* Digital 1.0 14.6.3.8 & Digital 1.1 16.6.3.9 */ + /* Digital 1.1 16.6.3.9 treat all RFU values as WT=14 */ + uint8_t responseWaitTime = MIN( RFAL_NFCDEP_WT_INI_MAX, wt ); + + return (uint32_t)rfalNfcDepWT2RWT(responseWaitTime); +} + + + +/*******************************************************************************/ +static ReturnCode nfcipDataTx( uint8_t* txBuf, uint16_t txBufLen, uint32_t fwt ) +{ + return rfalTransceiveBlockingTx( txBuf, txBufLen, gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen, (RFAL_TXRX_FLAGS_DEFAULT | (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_ON), ((fwt == NFCIP_NO_FWT) ? RFAL_FWT_NONE : fwt) ); +} + + +/*******************************************************************************/ +static ReturnCode nfcipDataRx( bool blocking ) +{ + ReturnCode ret; + + /* Perform Rx either blocking or non-blocking */ + if( blocking ) + { + ret = rfalTransceiveBlockingRx(); + } + else + { + ret = rfalGetTransceiveStatus(); + } + + if( ret != ERR_BUSY ) + { + if( gNfcip.rxRcvdLen != NULL ) + { + (*gNfcip.rxRcvdLen) = rfalConvBitsToBytes( *gNfcip.rxRcvdLen ); + + if( (ret == ERR_NONE) && (gNfcip.rxBuf != NULL) ) + { + /* Digital 1.1 16.4.1.3 - Length byte LEN SHALL have a value between 3 and 255 -> otherwise treat as Transmission Error * + * - Ensure that actual received and frame length do match, otherwise treat as Transmission error */ + if( (*gNfcip.rxRcvdLen != (uint16_t)*gNfcip.rxBuf) || (*gNfcip.rxRcvdLen < RFAL_NFCDEP_LEN_MIN) || (*gNfcip.rxRcvdLen > RFAL_NFCDEP_LEN_MAX) ) + { + return ERR_FRAMING; + } + } + } + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepListenStartActivation( const rfalNfcDepTargetParam *param, const uint8_t *atrReq, uint16_t atrReqLength, rfalNfcDepListenActvParam rxParam ) +{ + ReturnCode ret; + rfalNfcDepConfigs cfg; + + + if( (param == NULL) || (atrReq == NULL) || (rxParam.rxLen == NULL) ) + { + return ERR_PARAM; + } + + + /*******************************************************************************/ + /* Check whether is a valid ATR_REQ Compute NFC-DEP device */ + if( !rfalNfcDepIsAtrReq( atrReq, atrReqLength, NULL ) ) + { + return ERR_PARAM; + } + + rxParam.nfcDepDev->activation.Initiator.ATR_REQLen = (uint8_t)atrReqLength; /* nfcipIsAtrReq() is already checking Min and Max buffer lengths */ + if( atrReqLength > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( (uint8_t*)&rxParam.nfcDepDev->activation.Initiator.ATR_REQ, atrReq, atrReqLength ); + } + + rxParam.nfcDepDev->info.GBLen = (uint8_t)(atrReqLength - RFAL_NFCDEP_ATRREQ_MIN_LEN); + rxParam.nfcDepDev->info.DID = rxParam.nfcDepDev->activation.Initiator.ATR_REQ.DID; + rxParam.nfcDepDev->info.NAD = RFAL_NFCDEP_NAD_NO; /* Digital 1.1 16.6.2.9 Initiator SHALL NOT use NAD */ + rxParam.nfcDepDev->info.LR = rfalNfcDepPP2LR( rxParam.nfcDepDev->activation.Initiator.ATR_REQ.PPi ); + rxParam.nfcDepDev->info.FS = rfalNfcDepLR2FS( rxParam.nfcDepDev->info.LR ); + rxParam.nfcDepDev->info.WT = 0; + rxParam.nfcDepDev->info.FWT = NFCIP_NO_FWT; + rxParam.nfcDepDev->info.dFWT = NFCIP_NO_FWT; + + rfalGetBitRate( &rxParam.nfcDepDev->info.DSI, &rxParam.nfcDepDev->info.DRI ); + + + /* Store Device Info location, updated upon a PSL */ + gNfcip.nfcDepDev = rxParam.nfcDepDev; + + + /*******************************************************************************/ + cfg.did = rxParam.nfcDepDev->activation.Initiator.ATR_REQ.DID; + cfg.nad = RFAL_NFCDEP_NAD_NO; + + cfg.fwt = RFAL_NFCDEP_MAX_FWT; + cfg.dFwt = RFAL_NFCDEP_MAX_FWT; + + cfg.br = param->brt; + cfg.bs = param->bst; + + cfg.lr = rfalNfcDepPP2LR(param->ppt); + + cfg.gbLen = param->GBtLen; + if( cfg.gbLen > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY(cfg.gb, param->GBt, cfg.gbLen); + } + + cfg.nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + ST_MEMCPY(cfg.nfcid, param->nfcid3, RFAL_NFCDEP_NFCID3_LEN); + + cfg.to = param->to; + + cfg.role = RFAL_NFCDEP_ROLE_TARGET; + cfg.oper = param->operParam; + cfg.commMode = param->commMode; + + rfalNfcDepInitialize(); + nfcipConfig( &cfg ); + + + /*******************************************************************************/ + /* Reply with ATR RES to Initiator */ + /*******************************************************************************/ + gNfcip.rxBuf = (uint8_t*)rxParam.rxBuf; + gNfcip.rxBufLen = sizeof(rfalNfcDepBufFormat); + gNfcip.rxRcvdLen = rxParam.rxLen; + gNfcip.rxBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; + gNfcip.isChaining = rxParam.isRxChaining; + gNfcip.txBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; + + EXIT_ON_ERR( ret, nfcipTx( NFCIP_CMD_ATR_RES, (uint8_t*) gNfcip.rxBuf, NULL, 0, 0, NFCIP_NO_FWT ) ); + + gNfcip.state = NFCIP_ST_TARG_WAIT_ACTV; + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepListenGetActivationStatus( void ) +{ + ReturnCode err; + uint8_t BRS; + + BRS = RFAL_NFCDEP_BRS_MAINTAIN; + + err = nfcipTargetHandleActivation( gNfcip.nfcDepDev, &BRS ); + + switch (err) + { + case ERR_NONE: + + if( BRS != RFAL_NFCDEP_BRS_MAINTAIN ) + { + /* DSI codes the bit rate from Initiator to Target */ + /* DRI codes the bit rate from Target to Initiator */ + + if( gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_ACTIVE ) + { + EXIT_ON_ERR( err, rfalSetMode( RFAL_MODE_LISTEN_ACTIVE_P2P, gNfcip.nfcDepDev->info.DRI, gNfcip.nfcDepDev->info.DSI )); + } + else + { + EXIT_ON_ERR( err, rfalSetMode( ((RFAL_BR_106 == gNfcip.nfcDepDev->info.DRI) ? RFAL_MODE_LISTEN_NFCA : RFAL_MODE_LISTEN_NFCF), gNfcip.nfcDepDev->info.DRI, gNfcip.nfcDepDev->info.DSI )); + } + } + break; + + case ERR_BUSY: + // do nothing + break; + + case ERR_PROTO: + default: + // re-enable receiving of data + nfcDepReEnableRx( gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen ); + break; + } // if (no err) + + return err; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepStartTransceive( rfalNfcDepTxRxParam *param ) +{ + rfalNfcDepDEPParams nfcDepParams; + + nfcDepParams.txBuf = (uint8_t *)param->txBuf; + nfcDepParams.txBufLen = param->txBufLen; + nfcDepParams.txChaining = param->isTxChaining; + nfcDepParams.txBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; /* position in txBuf where actual outgoing data is located */ + nfcDepParams.did = RFAL_NFCDEP_DID_KEEP; + nfcDepParams.rxBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; + nfcDepParams.rxBuf = (uint8_t *)param->rxBuf; + nfcDepParams.rxBufLen = sizeof(rfalNfcDepBufFormat); + nfcDepParams.fsc = param->FSx; + nfcDepParams.fwt = param->FWT; + nfcDepParams.dFwt = param->dFWT; + + gNfcip.rxRcvdLen = param->rxLen; + gNfcip.isChaining = param->isRxChaining; + + nfcipSetDEPParams(&nfcDepParams); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcDepGetTransceiveStatus( void ) +{ + return nfcipRun( gNfcip.rxRcvdLen, gNfcip.isChaining ); +} + +#endif /* RFAL_FEATURE_NFC_DEP */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_nfca.c b/Software/fab-reader2-c/components/rfal/Src/rfal_nfca.c new file mode 100644 index 0000000..03cb2e9 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_nfca.c @@ -0,0 +1,630 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfca.c + * + * \author Gustavo Patricio + * + * \brief Provides several NFC-A convenience methods and definitions + * + * It provides a Poller (ISO14443A PCD) interface and as well as + * some NFC-A Listener (ISO14443A PICC) helpers. + * + * The definitions and helpers methods provided by this module are only + * up to ISO14443-3 layer + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_nfca.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCA + #define RFAL_FEATURE_NFCA false /* NFC-A module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCA + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCA_SLP_FWT rfalConvMsTo1fc(1) /*!< Check 1ms for any modulation ISO14443-3 6.4.3 */ +#define RFAL_NFCA_SLP_CMD 0x50U /*!< SLP cmd (byte1) Digital 1.1 6.9.1 & Table 20 */ +#define RFAL_NFCA_SLP_BYTE2 0x00U /*!< SLP byte2 Digital 1.1 6.9.1 & Table 20 */ +#define RFAL_NFCA_SLP_CMD_POS 0U /*!< SLP cmd position Digital 1.1 6.9.1 & Table 20 */ +#define RFAL_NFCA_SLP_BYTE2_POS 1U /*!< SLP byte2 position Digital 1.1 6.9.1 & Table 20 */ + +#define RFAL_NFCA_SDD_CT 0x88U /*!< Cascade Tag value Digital 1.1 6.7.2 */ +#define RFAL_NFCA_SDD_CT_LEN 1U /*!< Cascade Tag length */ + +#define RFAL_NFCA_SLP_REQ_LEN 2U /*!< SLP_REQ length */ + +#define RFAL_NFCA_SEL_CMD_LEN 1U /*!< SEL_CMD length */ +#define RFAL_NFCA_SEL_PAR_LEN 1U /*!< SEL_PAR length */ +#define RFAL_NFCA_SEL_SELPAR rfalNfcaSelPar(7U, 0U)/*!< SEL_PAR on Select is always with 4 data/nfcid */ +#define RFAL_NFCA_BCC_LEN 1U /*!< BCC length */ + +#define RFAL_NFCA_SDD_REQ_LEN (RFAL_NFCA_SEL_CMD_LEN + RFAL_NFCA_SEL_PAR_LEN) /*!< SDD_REQ length */ +#define RFAL_NFCA_SDD_RES_LEN (RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_BCC_LEN) /*!< SDD_RES length */ + +#define RFAL_NFCA_T_RETRANS 5U /*!< t RETRANSMISSION [3, 33]ms EMVCo 2.6 A.5 */ +#define RFAL_NFCA_N_RETRANS 2U /*!< Number of retries EMVCo 2.6 9.6.1.3 */ + + +/*! SDD_REQ (Select) Cascade Levels */ +enum +{ + RFAL_NFCA_SEL_CASCADE_L1 = 0, /*!< SDD_REQ Cascade Level 1 */ + RFAL_NFCA_SEL_CASCADE_L2 = 1, /*!< SDD_REQ Cascade Level 2 */ + RFAL_NFCA_SEL_CASCADE_L3 = 2 /*!< SDD_REQ Cascade Level 3 */ +}; + +/*! SDD_REQ (Select) request Cascade Level command Digital 1.1 Table 15 */ +enum +{ + RFAL_NFCA_CMD_SEL_CL1 = 0x93, /*!< SDD_REQ command Cascade Level 1 */ + RFAL_NFCA_CMD_SEL_CL2 = 0x95, /*!< SDD_REQ command Cascade Level 2 */ + RFAL_NFCA_CMD_SEL_CL3 = 0x97, /*!< SDD_REQ command Cascade Level 3 */ +}; + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define rfalNfcaSelPar( nBy, nbi ) (uint8_t)((((nBy)<<4U) & 0xF0U) | ((nbi)&0x0FU) ) /*!< Calculates SEL_PAR with the bytes/bits to be sent */ +#define rfalNfcaCLn2SELCMD( cl ) (uint8_t)((uint8_t)(RFAL_NFCA_CMD_SEL_CL1) + (2U*(cl))) /*!< Calculates SEL_CMD with the given cascade level */ +#define rfalNfcaNfcidLen2CL( len ) ((len) / 5U) /*!< Calculates cascade level by the NFCID length */ + +/*! Executes the given Tx method (f) and if a Timeout error is detected it retries (rt) times performing a delay of (dl) in between */ +#define rfalNfcaTxRetry( r, f, rt, dl ) \ + { \ + uint8_t rts = (uint8_t)(rt); \ + do { \ + (r)=(f); \ + if (((rt)!=0U) && ((dl)!=0U)) { \ + platformDelay(dl); \ + } \ + } while( ((rts--) != 0U) && ((r)==ERR_TIMEOUT) ); \ + } + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! SLP_REQ (HLTA) format Digital 1.1 6.9.1 & Table 20 */ +typedef struct +{ + uint8_t frame[RFAL_NFCA_SLP_REQ_LEN]; /*!< SLP: 0x50 0x00 */ +} rfalNfcaSlpReq; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static uint8_t rfalNfcaCalculateBcc( const uint8_t* buf, uint8_t bufLen ); + + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +static uint8_t rfalNfcaCalculateBcc( const uint8_t* buf, uint8_t bufLen ) +{ + uint8_t i; + uint8_t BCC; + + BCC = 0; + + /* BCC is XOR over first 4 bytes of the SDD_RES Digital 1.1 6.7.2 */ + for(i = 0; i < bufLen; i++) + { + BCC ^= buf[i]; + } + + return BCC; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerInitialize( void ) +{ + ReturnCode ret; + + EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCA, RFAL_BR_106, RFAL_BR_106 ) ); + rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); + + rfalSetGT( RFAL_GT_NFCA ); + rfalSetFDTListen( RFAL_FDT_LISTEN_NFCA_POLLER ); + rfalSetFDTPoll( RFAL_FDT_POLL_NFCA_POLLER ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerCheckPresence( rfal14443AShortFrameCmd cmd, rfalNfcaSensRes *sensRes ) +{ + ReturnCode ret; + uint16_t rcvLen; + + /* Digital 1.1 6.10.1.3 For Commands ALL_REQ, SENS_REQ, SDD_REQ, and SEL_REQ, the NFC Forum Device * + * MUST treat receipt of a Listen Frame at a time after FDT(Listen, min) as a Timeour Error */ + + ret = rfalISO14443ATransceiveShortFrame( cmd, (uint8_t*)sensRes, (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), &rcvLen, RFAL_NFCA_FDTMIN ); + if( (ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || (ret == ERR_NOMEM) || (ret == ERR_FRAMING) || (ret == ERR_PAR) ) + { + ret = ERR_NONE; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcaSensRes *sensRes ) +{ + ReturnCode ret; + + EXIT_ON_ERR( ret, rfalNfcaPollerCheckPresence( ((compMode == RFAL_COMPLIANCE_MODE_EMV) ? RFAL_14443A_SHORTFRAME_CMD_WUPA : RFAL_14443A_SHORTFRAME_CMD_REQA), sensRes ) ); + + /* Send SLP_REQ as Activity 1.1 9.2.3.6 and EMVCo 2.6 9.2.1.3 */ + if( compMode != RFAL_COMPLIANCE_MODE_ISO) + { + rfalNfcaPollerSleep(); + } + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len ) +{ + uint8_t i; + ReturnCode ret; + rfalNfcaSelReq selReq; + uint16_t bytesRx; + uint8_t bytesTxRx; + uint8_t bitsTxRx; + bool doBacktrack = false; + uint8_t backtrackCnt = 3; + + /* Check parameters */ + if( (collPending == NULL) || (selRes == NULL) || (nfcId1 == NULL) || (nfcId1Len == NULL) ) + { + return ERR_PARAM; + } + + /* Initialize output parameters */ + *collPending = false; /* Activity 1.1 9.3.4.6 */ + *nfcId1Len = 0; + ST_MEMSET( nfcId1, 0x00, RFAL_NFCA_CASCADE_3_UID_LEN ); + + /*******************************************************************************/ + /* Go through all Cascade Levels Activity 1.1 9.3.4 */ + for( i = (uint8_t)RFAL_NFCA_SEL_CASCADE_L1; i <= (uint8_t)RFAL_NFCA_SEL_CASCADE_L3; i++) + { + /* Initialize the SDD_REQ to send for the new cascade level */ + ST_MEMSET( (uint8_t*)&selReq, 0x00, sizeof(rfalNfcaSelReq) ); + selReq.selCmd = rfalNfcaCLn2SELCMD(i); + + bytesTxRx = RFAL_NFCA_SDD_REQ_LEN; + bitsTxRx = 0; + + /*******************************************************************************/ + /* Go through Collision loop */ + do + { + uint8_t collBit = 1; /* standards mandate or recommend collision bit to be set to One. */ + /* Calculate SEL_PAR with the bytes/bits to be sent */ + selReq.selPar = rfalNfcaSelPar(bytesTxRx, bitsTxRx); + + /* Send SDD_REQ (Anticollision frame) - Retry upon timeout EMVCo 2.6 9.6.1.3 */ + rfalNfcaTxRetry( ret, rfalISO14443ATransceiveAnticollisionFrame( (uint8_t*)&selReq, &bytesTxRx, &bitsTxRx, &bytesRx, RFAL_NFCA_FDTMIN ), ((devLimit==0U)?RFAL_NFCA_N_RETRANS:0U), RFAL_NFCA_T_RETRANS ); + + bytesRx = rfalConvBitsToBytes(bytesRx); + + if ((ret == ERR_TIMEOUT) + && (backtrackCnt != 0U) && !doBacktrack + && !((RFAL_NFCA_SDD_REQ_LEN==bytesTxRx) && (0U==bitsTxRx))) + { + /* In multiple card scenarios it may always happen that some + * collisions of a weaker tag go unnoticed. If then a later + * collision is recognized and the strong tag has a 0 at the + * collision position then no tag will respond. Catch this + * corner case and then try with the bit being sent as zero. */ + rfalNfcaSensRes sensRes; + ret = ERR_RF_COLLISION; + rfalNfcaPollerCheckPresence( RFAL_14443A_SHORTFRAME_CMD_REQA, &sensRes ); + /* Algorithm below does a post-increment, decrement to go back to current position */ + if (0U == bitsTxRx) + { + bitsTxRx = 7; + bytesTxRx--; + } + else + { + bitsTxRx--; + } + collBit = (uint8_t)( ((uint8_t*)&selReq)[bytesTxRx] & (1U << bitsTxRx) ); + collBit = (uint8_t)((0U==collBit)?1U:0U); // invert the collision bit + doBacktrack = true; + backtrackCnt--; + } + else + { + doBacktrack = false; + } + + if( ret == ERR_RF_COLLISION ) + { + /* Check received length */ + if( (bytesTxRx + ((bitsTxRx != 0U) ? 1U : 0U)) > (RFAL_NFCA_SDD_RES_LEN + RFAL_NFCA_SDD_REQ_LEN) ) + { + return ERR_PROTO; + } + + if( ((bytesTxRx + ((bitsTxRx != 0U) ? 1U : 0U)) > (RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN)) && (backtrackCnt != 0U) ) + { /* Collision in BCC: Anticollide only UID part */ + backtrackCnt--; + bytesTxRx = RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN - 1U; + bitsTxRx = 7; + collBit = (uint8_t)( ((uint8_t*)&selReq)[bytesTxRx] & (1U << bitsTxRx) ); /* Not a real collision, extract the actual bit for the subsequent code */ + } + + if( (devLimit == 0U) && !(*collPending) ) + { + /* Activity 1.0 & 1.1 9.3.4.12: If CON_DEVICES_LIMIT has a value of 0, then + * NFC Forum Device is configured to perform collision detection only */ + *collPending = true; + return ERR_IGNORE; + } + + *collPending = true; + + /* Set and select the collision bit, with the number of bytes/bits successfully TxRx */ + if (collBit != 0U) + { + ((uint8_t*)&selReq)[bytesTxRx] = (uint8_t)(((uint8_t*)&selReq)[bytesTxRx] | (1U << bitsTxRx)); /* MISRA 10.3 */ + } + else + { + ((uint8_t*)&selReq)[bytesTxRx] = (uint8_t)(((uint8_t*)&selReq)[bytesTxRx] & ~(1U << bitsTxRx)); /* MISRA 10.3 */ + } + + bitsTxRx++; + + /* Check if number of bits form a byte */ + if( bitsTxRx == RFAL_BITS_IN_BYTE ) + { + bitsTxRx = 0; + bytesTxRx++; + } + } + }while (ret == ERR_RF_COLLISION); + + + /*******************************************************************************/ + /* Check if Collision loop has failed */ + if( ret != ERR_NONE ) + { + return ret; + } + + + /* If collisions are to be reported check whether the response is complete */ + if( (devLimit == 0U) && (bytesRx != sizeof(rfalNfcaSddRes)) ) + { + return ERR_PROTO; + } + + /* Check if the received BCC match */ + if( selReq.bcc != rfalNfcaCalculateBcc( selReq.nfcid1, RFAL_NFCA_CASCADE_1_UID_LEN ) ) + { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Anticollision OK, Select this Cascade Level */ + selReq.selPar = RFAL_NFCA_SEL_SELPAR; + + /* Send SEL_REQ (Select command) - Retry upon timeout EMVCo 2.6 9.6.1.3 */ + rfalNfcaTxRetry( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&selReq, sizeof(rfalNfcaSelReq), (uint8_t*)selRes, sizeof(rfalNfcaSelRes), &bytesRx, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_FDTMIN ), ((devLimit==0U)?RFAL_NFCA_N_RETRANS:0U), RFAL_NFCA_T_RETRANS ); + + if( ret != ERR_NONE ) + { + return ret; + } + + + /* Ensure proper response length */ + if( bytesRx != sizeof(rfalNfcaSelRes) ) + { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Check cascade byte, if cascade tag then go next cascade level */ + if( (ret == ERR_NONE) && (*selReq.nfcid1 == RFAL_NFCA_SDD_CT) ) + { + /* Cascade Tag present, store nfcid1 bytes (excluding cascade tag) and continue for next CL */ + ST_MEMCPY( &nfcId1[*nfcId1Len], &((uint8_t*)&selReq.nfcid1)[RFAL_NFCA_SDD_CT_LEN], (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN) ); + *nfcId1Len += (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN); + } + else + { + /* UID Selection complete, Stop Cascade Level loop */ + ST_MEMCPY( &nfcId1[*nfcId1Len], (uint8_t*)&selReq.nfcid1, RFAL_NFCA_CASCADE_1_UID_LEN ); + *nfcId1Len += RFAL_NFCA_CASCADE_1_UID_LEN; + return ERR_NONE; + } + } + return ERR_INTERNAL; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt ) +{ + ReturnCode ret; + bool collPending; + rfalNfcaSensRes sensRes; + uint16_t rcvLen; + + if( (nfcaDevList == NULL) || (devCnt == NULL) ) + { + return ERR_PARAM; + } + + *devCnt = 0; + ret = ERR_NONE; + + /*******************************************************************************/ + /* Send ALL_REQ before Anticollision if a Sleep was sent before Activity 1.1 9.3.4.1 and EMVco 2.6 9.3.2.1 */ + if( compMode != RFAL_COMPLIANCE_MODE_ISO ) + { + ret = rfalISO14443ATransceiveShortFrame( RFAL_14443A_SHORTFRAME_CMD_WUPA, (uint8_t*)&nfcaDevList->sensRes, (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), &rcvLen, RFAL_NFCA_FDTMIN ); + if(ret != ERR_NONE) + { + if( (compMode == RFAL_COMPLIANCE_MODE_EMV) || ((ret != ERR_RF_COLLISION) && (ret != ERR_CRC) && (ret != ERR_FRAMING) && (ret != ERR_PAR)) ) + { + return ret; + } + } + + /* Check proper SENS_RES/ATQA size */ + if( (ret == ERR_NONE) && (rfalConvBytesToBits(sizeof(rfalNfcaSensRes)) != rcvLen) ) + { + return ERR_PROTO; + } + } + + + #if RFAL_FEATURE_T1T + /*******************************************************************************/ + /* Only check for T1T if previous SENS_RES was received without a transmission * + * error. When collisions occur bits in the SENS_RES may look like a T1T */ + /* If T1T Anticollision is not supported Activity 1.1 9.3.4.3 */ + if( rfalNfcaIsSensResT1T( &nfcaDevList->sensRes ) && (devLimit != 0U) && (ret == ERR_NONE) && (compMode != RFAL_COMPLIANCE_MODE_EMV) ) + { + /* RID_REQ shall be performed with rfalT1TPollerRid() Activity 1.1 9.3.4.24 */ + rfalT1TPollerInitialize(); + EXIT_ON_ERR( ret, rfalT1TPollerRid( &nfcaDevList->ridRes ) ); + + /* T1T doesn't support Anticollision */ + *devCnt = 1; + nfcaDevList->isSleep = false; + nfcaDevList->type = RFAL_NFCA_T1T; + nfcaDevList->nfcId1Len = RFAL_NFCA_CASCADE_1_UID_LEN; + ST_MEMCPY( &nfcaDevList->nfcId1, &nfcaDevList->ridRes.uid, RFAL_NFCA_CASCADE_1_UID_LEN ); + + return ERR_NONE; + } + #endif /* RFAL_FEATURE_T1T */ + + /*******************************************************************************/ + /* Store the SENS_RES from Technology Detection or from WUPA */ + sensRes = nfcaDevList->sensRes; + + if( devLimit > 0U ) /* MISRA 21.18 */ + { + ST_MEMSET( nfcaDevList, 0x00, (sizeof(rfalNfcaListenDevice) * devLimit) ); + } + + /* Restore the prev SENS_RES, assuming that the SENS_RES received is from first device + * When only one device is detected it's not woken up then we'll have no SENS_RES (ATQA) */ + nfcaDevList->sensRes = sensRes; + + + /*******************************************************************************/ + do + { + uint8_t newDeviceType; + + EXIT_ON_ERR( ret, rfalNfcaPollerSingleCollisionResolution( devLimit, &collPending, &nfcaDevList[*devCnt].selRes, (uint8_t*)&nfcaDevList[*devCnt].nfcId1, (uint8_t*)&nfcaDevList[*devCnt].nfcId1Len ) ); + + /* Assign Listen Device */ + newDeviceType = ((uint8_t)nfcaDevList[*devCnt].selRes.sak) & RFAL_NFCA_SEL_RES_CONF_MASK; /* MISRA 10.8 */ + /* PRQA S 4342 1 # MISRA 10.5 - Guaranteed that no invalid enum values are created: see guard_eq_RFAL_NFCA_T2T, .... */ + nfcaDevList[*devCnt].type = (rfalNfcaListenDeviceType) (newDeviceType); + nfcaDevList[*devCnt].isSleep = false; + (*devCnt)++; + + + /* If a collision was detected and device counter is lower than limit Activity 1.1 9.3.4.21 */ + if( (*devCnt < devLimit) && ((collPending) || (compMode != RFAL_COMPLIANCE_MODE_ISO) ) ) + { + /* Put this device to Sleep Activity 1.1 9.3.4.22 */ + rfalNfcaPollerSleep(); + nfcaDevList[(*devCnt - 1U)].isSleep = true; + + + /* Send a new SENS_REQ to check for other cards Activity 1.1 9.3.4.23 */ + ret = rfalNfcaPollerCheckPresence( RFAL_14443A_SHORTFRAME_CMD_REQA, &nfcaDevList[*devCnt].sensRes ); + if( ret == ERR_TIMEOUT ) + { + /* No more devices found, exit */ + collPending = false; + } + else + { + /* Another device found, continue loop */ + collPending = true; + } + } + else + { + /* Exit loop */ + collPending = false; + } + }while( (*devCnt < devLimit) && (collPending) ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerSelect( const uint8_t *nfcid1, uint8_t nfcidLen, rfalNfcaSelRes *selRes ) +{ + uint8_t i; + uint8_t cl; + uint8_t nfcidOffset; + uint16_t rxLen; + ReturnCode ret; + rfalNfcaSelReq selReq; + + if( (nfcid1 == NULL) || (nfcidLen > RFAL_NFCA_CASCADE_3_UID_LEN) || (selRes == NULL) ) + { + return ERR_PARAM; + } + + + /* Calculate Cascate Level */ + cl = rfalNfcaNfcidLen2CL( nfcidLen ); + nfcidOffset = 0; + + /*******************************************************************************/ + /* Go through all Cascade Levels Activity 1.1 9.4.4 */ + for( i = RFAL_NFCA_SEL_CASCADE_L1; i <= cl; i++ ) + { + /* Assign SEL_CMD according to the CLn and SEL_PAR*/ + selReq.selCmd = rfalNfcaCLn2SELCMD(i); + selReq.selPar = RFAL_NFCA_SEL_SELPAR; + + /* Compute NFCID/Data on the SEL_REQ command Digital 1.1 Table 18 */ + if( cl != i ) + { + *selReq.nfcid1 = RFAL_NFCA_SDD_CT; + ST_MEMCPY( &selReq.nfcid1[RFAL_NFCA_SDD_CT_LEN], &nfcid1[nfcidOffset], (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN) ); + nfcidOffset += (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN); + } + else + { + ST_MEMCPY( selReq.nfcid1, &nfcid1[nfcidOffset], RFAL_NFCA_CASCADE_1_UID_LEN ); + } + + /* Calculate nfcid's BCC */ + selReq.bcc = rfalNfcaCalculateBcc( (uint8_t*)&selReq.nfcid1, sizeof(selReq.nfcid1) ); + + /*******************************************************************************/ + /* Send SEL_REQ */ + EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&selReq, sizeof(rfalNfcaSelReq), (uint8_t*)selRes, sizeof(rfalNfcaSelRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_FDTMIN ) ); + + /* Ensure proper response length */ + if( rxLen != sizeof(rfalNfcaSelRes) ) + { + return ERR_PROTO; + } + } + + /* REMARK: Could check if NFCID1 is complete */ + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerSleep( void ) +{ + rfalNfcaSlpReq slpReq; + uint8_t rxBuf; /* dummy buffer, just to perform Rx */ + + slpReq.frame[RFAL_NFCA_SLP_CMD_POS] = RFAL_NFCA_SLP_CMD; + slpReq.frame[RFAL_NFCA_SLP_BYTE2_POS] = RFAL_NFCA_SLP_BYTE2; + + rfalTransceiveBlockingTxRx( (uint8_t*)&slpReq, sizeof(rfalNfcaSlpReq), &rxBuf, sizeof(rxBuf), NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_SLP_FWT ); + + /* ISO14443-3 6.4.3 HLTA - If PICC responds with any modulation during 1 ms this response shall be interpreted as not acknowledge + Digital 2.0 6.9.2.1 & EMVCo 3.0 5.6.2.1 - consider the HLTA command always acknowledged + No check to be compliant with NFC and EMVCo, and to improve interoprability (Kovio RFID Tag) + */ + + return ERR_NONE; +} + + +/*******************************************************************************/ +bool rfalNfcaListenerIsSleepReq( const uint8_t *buf, uint16_t bufLen ) +{ + /* Check if length and payload match */ + if( (bufLen != sizeof(rfalNfcaSlpReq)) || (buf[RFAL_NFCA_SLP_CMD_POS] != RFAL_NFCA_SLP_CMD) || (buf[RFAL_NFCA_SLP_BYTE2_POS] != RFAL_NFCA_SLP_BYTE2) ) + { + return false; + } + + return true; +} + +/* If the guards here don't compile then the code above cannot work anymore. */ +extern uint8_t guard_eq_RFAL_NFCA_T2T[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_T2T) == (uint8_t)RFAL_NFCA_T2T)?1:(-1)]; +extern uint8_t guard_eq_RFAL_NFCA_T4T[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_T4T) == (uint8_t)RFAL_NFCA_T4T)?1:(-1)]; +extern uint8_t guard_eq_RFAL_NFCA_NFCDEP[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_NFCDEP) == (uint8_t)RFAL_NFCA_NFCDEP)?1:(-1)]; +extern uint8_t guard_eq_RFAL_NFCA_T4T_NFCDEP[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_T4T_NFCDEP) == (uint8_t)RFAL_NFCA_T4T_NFCDEP)?1:(-1)]; +#endif /* RFAL_FEATURE_NFCA */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_nfcb.c b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcb.c new file mode 100644 index 0000000..49abebc --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcb.c @@ -0,0 +1,504 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcb.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-B (ISO14443B) helpers + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_nfcb.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCB + #define RFAL_FEATURE_NFCB false /* NFC-B module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCB + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED 0x10U /*!< Bit mask for Extended SensB Response support in SENSB_REQ */ +#define RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */ +#define RFAL_NFCB_SLOT_MARKER_SC_SHIFT 4U /*!< Slot Code position on SLOT_MARKER APn */ + +#define RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN 1U /*!< SLOT_MARKER Slot Code minimum Digital 1.1 Table 37 */ +#define RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX 16U /*!< SLOT_MARKER Slot Code maximum Digital 1.1 Table 37 */ + +#define RFAL_NFCB_ACTIVATION_FWT (RFAL_NFCB_FWTSENSB + RFAL_NFCB_DTPOLL_20) /*!< FWT(SENSB) + dTbPoll Digital 2.0 7.9.1.3 */ + +/*! Advanced and Extended bit mask in Parameter of SENSB_REQ */ +#define RFAL_NFCB_SENSB_REQ_PARAM (RFAL_NFCB_SENSB_REQ_ADV_FEATURE | RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED) + + +/*! NFC-B commands definition */ +enum +{ + RFAL_NFCB_CMD_SENSB_REQ = 0x05, /*!< SENSB_REQ (REQB) & SLOT_MARKER Digital 1.1 Table 24 */ + RFAL_NFCB_CMD_SENSB_RES = 0x50, /*!< SENSB_RES (ATQB) & SLOT_MARKER Digital 1.1 Table 27 */ + RFAL_NFCB_CMD_SLPB_REQ = 0x50, /*!< SLPB_REQ (HLTB command) Digital 1.1 Table 38 */ + RFAL_NFCB_CMD_SLPB_RES = 0x00 /*!< SLPB_RES (HLTB Answer) Digital 1.1 Table 39 */ +}; + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +#define rfalNfcbNI2NumberOfSlots( ni ) (uint8_t)(1U << (ni)) /*!< Converts the Number of slots Identifier to slot number */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! ALLB_REQ (WUPB) and SENSB_REQ (REQB) Command Format Digital 1.1 7.6.1 */ +typedef struct +{ + uint8_t cmd; /*!< xxxxB_REQ: 05h */ + uint8_t AFI; /*!< NFC Identifier */ + uint8_t PARAM; /*!< Application Data */ +} rfalNfcbSensbReq; + +/*! SLOT_MARKER Command format Digital 1.1 7.7.1 */ +typedef struct +{ + uint8_t APn; /*!< Slot number 2..16 | 0101b */ +} rfalNfcbSlotMarker; + +/*! SLPB_REQ (HLTB) Command Format Digital 1.1 7.8.1 */ +typedef struct +{ + uint8_t cmd; /*!< SLPB_REQ: 50h */ + uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/ +} rfalNfcbSlpbReq; + + +/*! SLPB_RES (HLTB) Response Format Digital 1.1 7.8.2 */ +typedef struct +{ + uint8_t cmd; /*!< SLPB_RES: 00h */ +} rfalNfcbSlpbRes; + + +/*! RFAL NFC-B instance */ +typedef struct +{ + uint8_t AFI; /*!< AFI to be used */ + uint8_t PARAM; /*!< PARAM to be used */ +} rfalNfcb; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode rfalNfcbCheckSensbRes( const rfalNfcbSensbRes *sensbRes, uint8_t sensbResLen ); + + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +static rfalNfcb gRfalNfcb; /*!< RFAL NFC-B Instance */ + + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +static ReturnCode rfalNfcbCheckSensbRes( const rfalNfcbSensbRes *sensbRes, uint8_t sensbResLen ) +{ + /* Check response length */ + if( ( (sensbResLen != RFAL_NFCB_SENSB_RES_LEN) && (sensbResLen != RFAL_NFCB_SENSB_RES_EXT_LEN) ) ) + { + return ERR_PROTO; + } + + /* Check SENSB_RES and Protocol Type Digital 1.1 7.6.2.19 */ + if( ((sensbRes->protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU) != 0U) || (sensbRes->cmd != (uint8_t)RFAL_NFCB_CMD_SENSB_RES) ) + { + return ERR_PROTO; + } + return ERR_NONE; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerInitialize( void ) +{ + ReturnCode ret; + + EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCB, RFAL_BR_106, RFAL_BR_106 ) ); + rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); + + rfalSetGT( RFAL_GT_NFCB ); + rfalSetFDTListen( RFAL_FDT_LISTEN_NFCB_POLLER ); + rfalSetFDTPoll( RFAL_FDT_POLL_NFCB_POLLER ); + + gRfalNfcb.AFI = RFAL_NFCB_AFI; + gRfalNfcb.PARAM = RFAL_NFCB_PARAM; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerInitializeWithParams( uint8_t AFI, uint8_t PARAM ) +{ + ReturnCode ret; + + EXIT_ON_ERR( ret, rfalNfcbPollerInitialize() ); + + gRfalNfcb.AFI = AFI; + gRfalNfcb.PARAM = (PARAM & RFAL_NFCB_SENSB_REQ_PARAM); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerCheckPresence( rfalNfcbSensCmd cmd, rfalNfcbSlots slots, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen ) +{ + uint16_t rxLen; + ReturnCode ret; + rfalNfcbSensbReq sensbReq; + + + /* Check if the command requested and given the slot number are valid */ + if( ((RFAL_NFCB_SENS_CMD_SENSB_REQ != cmd) && (RFAL_NFCB_SENS_CMD_ALLB_REQ != cmd)) || + (slots > RFAL_NFCB_SLOT_NUM_16) || (sensbRes == NULL) || (sensbResLen == NULL) ) + { + return ERR_PARAM; + } + + *sensbResLen = 0; + ST_MEMSET(sensbRes, 0x00, sizeof(rfalNfcbSensbRes) ); + + /* Compute SENSB_REQ */ + sensbReq.cmd = RFAL_NFCB_CMD_SENSB_REQ; + sensbReq.AFI = gRfalNfcb.AFI; + sensbReq.PARAM = (((uint8_t)gRfalNfcb.PARAM & RFAL_NFCB_SENSB_REQ_PARAM) | (uint8_t)cmd | (uint8_t)slots); + + /* Send SENSB_REQ and disable AGC to detect collisions */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&sensbReq, sizeof(rfalNfcbSensbReq), (uint8_t*)sensbRes, sizeof(rfalNfcbSensbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_FWTSENSB ); + + *sensbResLen = (uint8_t)rxLen; + + /* Check if a transmission error was detected */ + if( (ret == ERR_CRC) || (ret == ERR_FRAMING) ) + { + /* Invalidate received frame as an error was detected (CollisionResolution checks if valid) */ + *sensbResLen = 0; + return ERR_NONE; + } + + if( ret == ERR_NONE ) + { + return rfalNfcbCheckSensbRes( sensbRes, *sensbResLen ); + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerSleep( const uint8_t* nfcid0 ) +{ + uint16_t rxLen; + ReturnCode ret; + rfalNfcbSlpbReq slpbReq; + rfalNfcbSlpbRes slpbRes; + + if( nfcid0 == NULL ) + { + return ERR_PARAM; + } + + /* Compute SLPB_REQ */ + slpbReq.cmd = RFAL_NFCB_CMD_SLPB_REQ; + ST_MEMCPY( slpbReq.nfcid0, nfcid0, RFAL_NFCB_NFCID0_LEN ); + + EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&slpbReq, sizeof(rfalNfcbSlpbReq), (uint8_t*)&slpbRes, sizeof(rfalNfcbSlpbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_ACTIVATION_FWT )); + + /* Check SLPB_RES */ + if( (rxLen != sizeof(rfalNfcbSlpbRes)) || (slpbRes.cmd != (uint8_t)RFAL_NFCB_CMD_SLPB_RES) ) + { + return ERR_PROTO; + } + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerSlotMarker( uint8_t slotCode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen ) +{ + ReturnCode ret; + rfalNfcbSlotMarker slotMarker; + uint16_t rxLen; + + /* Check parameters */ + if( (sensbRes == NULL) || (sensbResLen == NULL) || + (slotCode < RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN) || + (slotCode > RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX) ) + { + return ERR_PARAM; + } + /* Compose and send SLOT_MARKER with disabled AGC to detect collisions */ + slotMarker.APn = ((slotCode << RFAL_NFCB_SLOT_MARKER_SC_SHIFT) | (uint8_t)RFAL_NFCB_CMD_SENSB_REQ); + + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slotMarker, sizeof(rfalNfcbSlotMarker), (uint8_t*)sensbRes, sizeof(rfalNfcbSensbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_ACTIVATION_FWT ); + + *sensbResLen = (uint8_t)rxLen; + + /* Check if a transmission error was detected */ + if( (ret == ERR_CRC) || (ret == ERR_FRAMING) ) + { + return ERR_RF_COLLISION; + } + + if( ret == ERR_NONE ) + { + return rfalNfcbCheckSensbRes( sensbRes, *sensbResLen ); + } + + return ret; +} + + +ReturnCode rfalNfcbPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen ) +{ + NO_WARNING(compMode); + + return rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_SENSB_REQ, RFAL_NFCB_SLOT_NUM_1, sensbRes, sensbResLen ); +} + + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt ) +{ + bool colPending; /* dummy */ + return rfalNfcbPollerSlottedCollisionResolution( compMode, devLimit, RFAL_NFCB_SLOT_NUM_1, RFAL_NFCB_SLOT_NUM_16, nfcbDevList, devCnt, &colPending ); +} + + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerSlottedCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbSlots initSlots, rfalNfcbSlots endSlots, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt, bool *colPending ) +{ + ReturnCode ret; + uint8_t slotsNum; + uint8_t slotCode; + uint8_t curDevCnt; + + + /* Check parameters. In ISO | Activity 1.0 mode the initial slots must be 1 as continuation of Technology Detection */ + if( (nfcbDevList == NULL) || (devCnt == NULL) || (colPending == NULL) || (initSlots > RFAL_NFCB_SLOT_NUM_16) || + (endSlots > RFAL_NFCB_SLOT_NUM_16) || ((compMode == RFAL_COMPLIANCE_MODE_ISO) && (initSlots != RFAL_NFCB_SLOT_NUM_1)) ) + { + return ERR_PARAM; + } + + /* Initialise as no error in case Activity 1.0 where the previous SENSB_RES from technology detection should be used */ + ret = ERR_NONE; + *devCnt = 0; + curDevCnt = 0; + *colPending = false; + + + /* Send ALLB_REQ Activity 1.1 9.3.5.2 and 9.3.5.3 (Symbol 1 and 2) */ + if( compMode != RFAL_COMPLIANCE_MODE_ISO ) + { + ret = rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_ALLB_REQ, initSlots, &nfcbDevList->sensbRes, &nfcbDevList->sensbResLen ); + if( (ret != ERR_NONE) && (initSlots == RFAL_NFCB_SLOT_NUM_1) ) + { + return ret; + } + } + + + /* Check if there was a transmission error on WUPB EMVCo 2.6 9.3.3.1 */ + if( (compMode == RFAL_COMPLIANCE_MODE_EMV) && (nfcbDevList->sensbResLen == 0U) ) + { + return ERR_FRAMING; + } + + for( slotsNum = (uint8_t)initSlots; slotsNum <= (uint8_t)endSlots; slotsNum++ ) + { + do { + /* Activity 1.1 9.3.5.23 - Symbol 22 */ + if( (compMode == RFAL_COMPLIANCE_MODE_NFC) && (curDevCnt != 0U) ) + { + rfalNfcbPollerSleep( nfcbDevList[(*devCnt-1U)].sensbRes.nfcid0 ); + nfcbDevList[(*devCnt-1U)].isSleep = true; + } + + /* Send SENSB_REQ with number of slots if not the first Activity 1.1 9.3.5.24 - Symbol 23 */ + if( (slotsNum != (uint8_t)initSlots) || *colPending ) + { + /* PRQA S 4342 1 # MISRA 10.5 - Layout of rfalNfcbSlots and above loop guarantee that no invalid enum values are created. */ + ret = rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_SENSB_REQ, (rfalNfcbSlots)slotsNum, &nfcbDevList[*devCnt].sensbRes, &nfcbDevList[*devCnt].sensbResLen ); + } + + /* Activity 1.1 9.3.5.6 - Symbol 5 */ + slotCode = 0; + curDevCnt = 0; + *colPending = false; + + do{ + /* Activity 1.1 9.3.5.26 - Symbol 25 */ + if( slotCode != 0U ) + { + ret = rfalNfcbPollerSlotMarker( slotCode, &nfcbDevList[*devCnt].sensbRes, &nfcbDevList[*devCnt].sensbResLen ); + } + + /* Activity 1.1 9.3.5.7 and 9.3.5.8 - Symbol 6 */ + if( ret != ERR_TIMEOUT ) + { + /* Activity 1.1 9.3.5.8 - Symbol 7 */ + if( (rfalNfcbCheckSensbRes( &nfcbDevList[*devCnt].sensbRes, nfcbDevList[*devCnt].sensbResLen) == ERR_NONE) && (ret == ERR_NONE) ) + { + nfcbDevList[*devCnt].isSleep = false; + + if( compMode == RFAL_COMPLIANCE_MODE_EMV ) + { + (*devCnt)++; + return ret; + } + else if( compMode == RFAL_COMPLIANCE_MODE_ISO ) + { + /* Activity 1.0 9.3.5.8 - Symbol 7 */ + (*devCnt)++; + curDevCnt++; + + /* Activity 1.0 9.3.5.10 - Symbol 9 */ + if( (*devCnt >= devLimit) || (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) ) + { + return ret; + } + + /* Activity 1.0 9.3.5.11 - Symbol 10 */ + rfalNfcbPollerSleep( nfcbDevList[*devCnt-1U].sensbRes.nfcid0 ); + nfcbDevList[*devCnt-1U].isSleep = true; + } + else if( compMode == RFAL_COMPLIANCE_MODE_NFC ) + { + /* Activity 1.1 9.3.5.10 and 9.3.5.11 - Symbol 9 and Symbol 11*/ + if(curDevCnt != 0U) + { + rfalNfcbPollerSleep( nfcbDevList[*devCnt-1U].sensbRes.nfcid0 ); + nfcbDevList[*devCnt-1U].isSleep = true; + } + + /* Activity 1.1 9.3.5.12 - Symbol 11 */ + (*devCnt)++; + curDevCnt++; + + /* Activity 1.1 9.3.5.6 - Symbol 13 */ + if( (*devCnt >= devLimit) || (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) ) + { + return ret; + } + } + else + { + /* MISRA 15.7 - Empty else */ + } + } + else + { + /* If deviceLimit is set to 0 the NFC Forum Device is configured to perform collision detection only Activity 1.0 and 1.1 9.3.5.5 - Symbol 4 */ + if( (devLimit == 0U) && (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) ) + { + return ERR_RF_COLLISION; + } + + /* Activity 1.1 9.3.5.9 - Symbol 8 */ + *colPending = true; + } + } + + /* Activity 1.1 9.3.5.15 - Symbol 14 */ + slotCode++; + } + while( slotCode < rfalNfcbNI2NumberOfSlots(slotsNum) ); + + /* Activity 1.1 9.3.5.17 - Symbol 16 */ + if( !(*colPending) ) + { + return ERR_NONE; + } + + /* Activity 1.1 9.3.5.18 - Symbol 17 */ + } while (curDevCnt != 0U); /* If a collision is detected and card(s) were found on this loop keep the same number of available slots */ + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +uint32_t rfalNfcbTR2ToFDT( uint8_t tr2Code ) +{ + /*******************************************************************************/ + /* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */ + /*! TR2 Table according to Digital 1.1 Table 33 */ + const uint16_t rfalNfcbTr2Table[] = { 1792, 3328, 5376, 9472 }; + /*******************************************************************************/ + + return rfalNfcbTr2Table[ (tr2Code & RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK) ]; +} + +#endif /* RFAL_FEATURE_NFCB */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_nfcf.c b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcf.c new file mode 100644 index 0000000..e3dd112 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcf.c @@ -0,0 +1,546 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcf.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-F Poller (FeliCa PCD) device + * + * The definitions and helpers methods provided by this module are + * aligned with NFC-F (FeliCa - JIS X6319-4) + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_nfcf.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCF + #define RFAL_FEATURE_NFCF false /* NFC-F module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCF + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_NFCF_SENSF_REQ_LEN_MIN 5U /*!< SENSF_RES minimum length */ + +#define RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN 15U /*!< Minimum length for a Check Command T3T 5.4.1 */ +#define RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN 31U /*!< Minimum length for an Update Command T3T 5.5.1 */ + +#define RFAL_NFCF_CHECK_RES_MIN_LEN 11U /*!< CHECK Response minimum length T3T 1.0 Table 8 */ +#define RFAL_NFCF_UPDATE_RES_MIN_LEN 11U /*!< UPDATE Response minimum length T3T 1.0 Table 8 */ + +#define RFAL_NFCF_CHECK_REQ_MAX_LEN 86U /*!< Max length of a Check request T3T 1.0 Table 7 */ +#define RFAL_NFCF_CHECK_REQ_MAX_SERV 15U /*!< Max Services number on Check request T3T 1.0 5.4.1.5 */ +#define RFAL_NFCF_CHECK_REQ_MAX_BLOCK 15U /*!< Max Blocks number on Check request T3T 1.0 5.4.1.10 */ +#define RFAL_NFCF_UPDATE_REQ_MAX_SERV 15U /*!< Max Services number Update request T3T 1.0 5.4.1.5 */ +#define RFAL_NFCF_UPDATE_REQ_MAX_BLOCK 13U /*!< Max Blocks number on Update request T3T 1.0 5.4.1.10 */ + + +/*! MRT Check | Uupdate = (Tt3t x ((A+1) + n (B+1)) x 4^E) + dRWTt3t T3T 5.8 + Max values used: A = 7 ; B = 7 ; E = 3 ; n = 15 (NFC Forum n = 15, JIS n = 32) +*/ +#define RFAL_NFCF_MRT_CHECK_UPDATE ((4096 * (8 + (15 * 8)) * 64 ) + 16) + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ +#define rfalNfcfSlots2CardNum( s ) ((uint8_t)(s)+1U) /*!< Converts Time Slot Number (TSN) into num of slots */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Structure/Buffer to hold the SENSF_RES with LEN byte prepended */ +typedef struct{ + uint8_t LEN; /*!< NFC-F LEN byte */ + rfalNfcfSensfRes SENSF_RES; /*!< SENSF_RES */ +} rfalNfcfSensfResBuf; + + +/*! Greedy collection for NFCF GRE_POLL_F Activity 1.0 Table 10 */ +typedef struct{ + uint8_t pollFound; /*!< Number of devices found by the Poll */ + uint8_t pollCollision; /*!< Number of collisions detected */ + rfalFeliCaPollRes POLL_F[RFAL_NFCF_POLL_MAXCARDS]; /*!< GRE_POLL_F Activity 1.0 Table 10 */ +} rfalNfcfGreedyF; + + +/*! NFC-F SENSF_REQ format Digital 1.1 8.6.1 */ +typedef struct +{ + uint8_t CMD; /*!< Command code: 00h */ + uint8_t SC[RFAL_NFCF_SENSF_SC_LEN]; /*!< System Code */ + uint8_t RC; /*!< Request Code */ + uint8_t TSN; /*!< Time Slot Number */ +} rfalNfcfSensfReq; + + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ +static rfalNfcfGreedyF gRfalNfcfGreedyF; /*!< Activity's NFCF Greedy collection */ + + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static void rfalNfcfComputeValidSENF( rfalNfcfListenDevice *outDevInfo, uint8_t *curDevIdx, uint8_t devLimit, bool overwrite, bool *nfcDepFound ); + + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +/*******************************************************************************/ +static void rfalNfcfComputeValidSENF( rfalNfcfListenDevice *outDevInfo, uint8_t *curDevIdx, uint8_t devLimit, bool overwrite, bool *nfcDepFound ) +{ + uint8_t tmpIdx; + bool duplicate; + rfalNfcfSensfResBuf *sensfBuf; + rfalNfcfSensfResBuf sensfCopy; + + + /*******************************************************************************/ + /* Go through all responses check if valid and duplicates */ + /*******************************************************************************/ + while( (gRfalNfcfGreedyF.pollFound > 0U) && ((*curDevIdx) < devLimit) ) + { + duplicate = false; + gRfalNfcfGreedyF.pollFound--; + + /* MISRA 11.3 - Cannot point directly into different object type, use local copy */ + ST_MEMCPY( (uint8_t*)&sensfCopy, (uint8_t*)&gRfalNfcfGreedyF.POLL_F[gRfalNfcfGreedyF.pollFound], sizeof(rfalNfcfSensfResBuf) ); + + + /* Point to received SENSF_RES */ + sensfBuf = &sensfCopy; + + + /* Check for devices that are already in device list */ + for( tmpIdx = 0; tmpIdx < (*curDevIdx); tmpIdx++ ) + { + if( ST_BYTECMP( sensfBuf->SENSF_RES.NFCID2, outDevInfo[tmpIdx].sensfRes.NFCID2, RFAL_NFCF_NFCID2_LEN ) == 0 ) + { + duplicate = true; + break; + } + } + + /* If is a duplicate skip this (and not to overwrite)*/ + if(duplicate && !overwrite) + { + continue; + } + + /* Check if response length is OK */ + if( (( sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) < RFAL_NFCF_SENSF_RES_LEN_MIN) || ((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) > RFAL_NFCF_SENSF_RES_LEN_MAX) ) + { + continue; + } + + /* Check if the response is a SENSF_RES / Polling response */ + if( sensfBuf->SENSF_RES.CMD != (uint8_t)RFAL_NFCF_CMD_POLLING_RES ) + { + continue; + } + + /* Check if is an overwrite request or new device*/ + if(duplicate && overwrite) + { + /* overwrite deviceInfo/GRE_SENSF_RES with SENSF_RES */ + outDevInfo[tmpIdx].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN); + ST_MEMCPY( &outDevInfo[tmpIdx].sensfRes, &sensfBuf->SENSF_RES, outDevInfo[tmpIdx].sensfResLen ); + continue; + } + else + { + /* fill deviceInfo/GRE_SENSF_RES with new SENSF_RES */ + outDevInfo[(*curDevIdx)].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN); + ST_MEMCPY( &outDevInfo[(*curDevIdx)].sensfRes, &sensfBuf->SENSF_RES, outDevInfo[(*curDevIdx)].sensfResLen ); + } + + /* Check if this device supports NFC-DEP and signal it (ACTIVITY 1.1 9.3.6.63) */ + *nfcDepFound = rfalNfcfIsNfcDepSupported( &outDevInfo[(*curDevIdx)] ); + + (*curDevIdx)++; + } +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerInitialize( rfalBitRate bitRate ) +{ + ReturnCode ret; + + if( (bitRate != RFAL_BR_212) && (bitRate != RFAL_BR_424) ) + { + return ERR_PARAM; + } + + EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCF, bitRate, bitRate ) ); + rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); + + rfalSetGT( RFAL_GT_NFCF ); + rfalSetFDTListen( RFAL_FDT_LISTEN_NFCF_POLLER ); + rfalSetFDTPoll( RFAL_FDT_POLL_NFCF_POLLER ); + + return ERR_NONE; +} + + + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes *cardList, uint8_t *devCnt, uint8_t *collisions ) +{ + return rfalFeliCaPoll( slots, sysCode, reqCode, cardList, rfalNfcfSlots2CardNum(slots), devCnt, collisions ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerCheckPresence( void ) +{ + gRfalNfcfGreedyF.pollFound = 0; + gRfalNfcfGreedyF.pollCollision = 0; + + /* ACTIVITY 1.0 & 1.1 - 9.2.3.17 SENSF_REQ must be with number of slots equal to 4 + * SC must be 0xFFFF + * RC must be 0x00 (No system code info required) */ + return rfalFeliCaPoll( RFAL_FELICA_4_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_NO_REQUEST, gRfalNfcfGreedyF.POLL_F, rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS), &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision ); +} + + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcfListenDevice *nfcfDevList, uint8_t *devCnt ) +{ + ReturnCode ret; + bool nfcDepFound; + + if( (nfcfDevList == NULL) || (devCnt == NULL) ) + { + return ERR_PARAM; + } + + *devCnt = 0; + nfcDepFound = false; + + + /*******************************************************************************************/ + /* ACTIVITY 1.0 - 9.3.6.3 Copy valid SENSF_RES in GRE_POLL_F into GRE_SENSF_RES */ + /* ACTIVITY 1.0 - 9.3.6.6 The NFC Forum Device MUST remove all entries from GRE_SENSF_RES[]*/ + /* ACTIVITY 1.1 - 9.3.63.59 Populate GRE_SENSF_RES with data from GRE_POLL_F */ + /* */ + /* CON_DEVICES_LIMIT = 0 Just check if devices from Tech Detection exceeds -> always true */ + /* Allow the number of slots open on Technology Detection */ + /*******************************************************************************************/ + rfalNfcfComputeValidSENF( nfcfDevList, devCnt, ((devLimit == 0U) ? rfalNfcfSlots2CardNum( RFAL_FELICA_4_SLOTS ) : devLimit), false, &nfcDepFound ); + + + /*******************************************************************************/ + /* ACTIVITY 1.0 - 9.3.6.4 */ + /* ACTIVITY 1.1 - 9.3.63.60 Check if devices found are lower than the limit */ + /* and send a SENSF_REQ if so */ + /*******************************************************************************/ + if( *devCnt < devLimit ) + { + /* ACTIVITY 1.0 - 9.3.6.5 Copy valid SENSF_RES and then to remove it + * ACTIVITY 1.1 - 9.3.6.65 Copy and filter duplicates + * For now, due to some devices keep generating different nfcid2, we use 1.0 + * Phones detected: Samsung Galaxy Nexus,Samsung Galaxy S3,Samsung Nexus S */ + *devCnt = 0; + + ret = rfalNfcfPollerPoll( RFAL_FELICA_16_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_NO_REQUEST, gRfalNfcfGreedyF.POLL_F, &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision ); + if( ret == ERR_NONE ) + { + rfalNfcfComputeValidSENF( nfcfDevList, devCnt, devLimit, false, &nfcDepFound ); + } + + /*******************************************************************************/ + /* ACTIVITY 1.1 - 9.3.6.63 Check if any device supports NFC DEP */ + /*******************************************************************************/ + if( nfcDepFound && (compMode == RFAL_COMPLIANCE_MODE_NFC) ) + { + ret = rfalNfcfPollerPoll( RFAL_FELICA_16_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_SYSTEM_CODE, gRfalNfcfGreedyF.POLL_F, &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision ); + if( ret == ERR_NONE ) + { + rfalNfcfComputeValidSENF( nfcfDevList, devCnt, devLimit, true, &nfcDepFound ); + } + } + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerCheck( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rcvdLen ) +{ + uint8_t txBuf[RFAL_NFCF_CHECK_REQ_MAX_LEN]; + uint8_t msgIt; + uint8_t i; + ReturnCode ret; + uint8_t *checkRes; + + /* Check parameters */ + if( (nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || + (servBlock->numBlock == 0U) || (servBlock->numBlock > RFAL_NFCF_CHECK_REQ_MAX_BLOCK) || + (servBlock->numServ == 0U) || (servBlock->numServ > RFAL_NFCF_CHECK_REQ_MAX_SERV) || + (rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECK_RES_MIN_LEN)) ) + { + return ERR_PARAM; + } + + msgIt = 0; + + /*******************************************************************************/ + /* Compose CHECK command/request */ + + txBuf[msgIt++] = RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION; /* Command Code */ + + ST_MEMCPY( &txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN ); /* NFCID2 */ + msgIt += RFAL_NFCF_NFCID2_LEN; + + txBuf[msgIt++] = servBlock->numServ; /* NoS */ + for( i = 0; i < servBlock->numServ; i++) + { + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */ + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU); + } + + txBuf[msgIt++] = servBlock->numBlock; /* NoB */ + for( i = 0; i < servBlock->numBlock; i++) + { + txBuf[msgIt++] = servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */ + if( (servBlock->blockList[i].conf & 0x80U) != 0U ) /* Check if 2 or 3 byte block list element */ + { + txBuf[msgIt++] = (uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */ + } + else + { + txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */ + txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU); + } + } + + /*******************************************************************************/ + /* Transceive CHECK command/request */ + ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, rxBuf, rxBufLen, rcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCF_MRT_CHECK_UPDATE ); + + if( ret == ERR_NONE ) + { + /* Skip LEN byte */ + checkRes = (rxBuf + RFAL_NFCF_LENGTH_LEN); + + /* Check response length */ + if( *rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS) ) + { + ret = ERR_PROTO; + } + /* Check for a valid response */ + else if( (checkRes[RFAL_NFCF_CMD_POS] != (uint8_t)RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES) || + (checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) || + (checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) ) + { + ret = ERR_REQUEST; + } + /* CHECK succesfull, remove header */ + else + { + (*rcvdLen) -= (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_NOB_POS); + + if( *rcvdLen > 0U ) + { + ST_MEMMOVE( rxBuf, &checkRes[RFAL_NFCF_CHECKUPDATE_RES_NOB_POS], (*rcvdLen) ); + } + } + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerUpdate( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *txBuf, uint16_t txBufLen, const uint8_t *blockData, uint8_t *rxBuf, uint16_t rxBufLen ) +{ + uint8_t i; + uint16_t msgIt; + uint16_t rcvdLen; + uint16_t auxLen; + uint8_t *updateRes; + ReturnCode ret; + + /* Check parameters */ + if( (nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || (txBuf == NULL) || + (servBlock->numBlock == 0U) || (servBlock->numBlock > RFAL_NFCF_UPDATE_REQ_MAX_BLOCK) || + (servBlock->numServ == 0U) || (servBlock->numServ > RFAL_NFCF_UPDATE_REQ_MAX_SERV) || + (rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_UPDATE_RES_MIN_LEN)) ) + { + return ERR_PARAM; + } + + /* Calculate required txBuffer lenth */ + auxLen = (uint16_t)( RFAL_NFCF_CMD_LEN + RFAL_NFCF_NFCID2_LEN + ( servBlock->numServ * sizeof(rfalNfcfServ) ) + + (servBlock->numBlock * sizeof(rfalNfcfBlockListElem)) + (uint16_t)((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN) ); + + /* Check whether the provided buffer is sufficient for this request */ + if( txBufLen < auxLen ) + { + return ERR_PARAM; + } + + msgIt = 0; + + /*******************************************************************************/ + /* Compose UPDATE command/request */ + + txBuf[msgIt++] = RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION; /* Command Code */ + + ST_MEMCPY( &txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN ); /* NFCID2 */ + msgIt += RFAL_NFCF_NFCID2_LEN; + + txBuf[msgIt++] = servBlock->numServ; /* NoS */ + for( i = 0; i < servBlock->numServ; i++) + { + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */ + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU); + } + + txBuf[msgIt++] = servBlock->numBlock; /* NoB */ + for( i = 0; i < servBlock->numBlock; i++) + { + txBuf[msgIt++] = servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */ + if( (servBlock->blockList[i].conf & 0x80U) != 0U ) /* Check if 2 or 3 byte block list element */ + { + txBuf[msgIt++] = (uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */ + } + else + { + txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */ + txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU); + } + } + + auxLen = ((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN); + ST_MEMCPY( &txBuf[msgIt], blockData, auxLen ); /* Block Data */ + msgIt += auxLen; + + + /*******************************************************************************/ + /* Transceive UPDATE command/request */ + ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, rxBuf, rxBufLen, &rcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCF_MRT_CHECK_UPDATE ); + + if( ret == ERR_NONE ) + { + /* Skip LEN byte */ + updateRes = (rxBuf + RFAL_NFCF_LENGTH_LEN); + + /* Check response length */ + if( rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS) ) + { + ret = ERR_PROTO; + } + /* Check for a valid response */ + else if( (updateRes[RFAL_NFCF_CMD_POS] != (uint8_t)RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES) || + (updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) || + (updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) ) + { + ret = ERR_REQUEST; + } + else + { + /* MISRA 15.7 - Empty else */ + } + } + + return ret; +} + + + +/*******************************************************************************/ +bool rfalNfcfListenerIsT3TReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2 ) +{ + /* Check cmd byte */ + switch( *buf ) + { + case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION: + if( bufLen < RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN ) + { + return false; + } + break; + + case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION: + if( bufLen < RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN ) + { + return false; + } + break; + + default: + return false; + } + + /* Output NFID2 if requested */ + if( nfcid2 != NULL ) + { + ST_MEMCPY( nfcid2, &buf[RFAL_NFCF_CMD_LEN], RFAL_NFCF_NFCID2_LEN ); + } + + return true; +} + +#endif /* RFAL_FEATURE_NFCF */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_nfcv.c b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcv.c new file mode 100644 index 0000000..b38c6ba --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_nfcv.c @@ -0,0 +1,874 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcv.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-V Poller (ISO15693) device + * + * The definitions and helpers methods provided by this module are + * aligned with NFC-V (ISO15693) + * + * The definitions and helpers methods provided by this module + * are aligned with NFC-V Digital 2.1 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_nfcv.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCV + #define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCV + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCV_INV_REQ_FLAG 0x06U /*!< INVENTORY_REQ INV_FLAG Digital 2.1 9.6.1 */ +#define RFAL_NFCV_MASKVAL_MAX_LEN 8U /*!< Mask value max length: 64 bits (UID length) */ +#define RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN 64U /*!< Mask value max length in 1 Slot mode in bits Digital 2.1 9.6.1.6 */ +#define RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN 60U /*!< Mask value max length in 16 Slot mode in bits Digital 2.1 9.6.1.6 */ +#define RFAL_NFCV_MAX_SLOTS 16U /*!< NFC-V max number of Slots */ +#define RFAL_NFCV_INV_REQ_HEADER_LEN 3U /*!< INVENTORY_REQ header length (INV_FLAG, CMD, MASK_LEN) */ +#define RFAL_NFCV_INV_RES_LEN 10U /*!< INVENTORY_RES length */ +#define RFAL_NFCV_WR_MUL_REQ_HEADER_LEN 4U /*!< Write Multiple header length (INV_FLAG, CMD, [UID], BNo, Bno) */ + + +#define RFAL_CMD_LEN 1U /*!< Commandbyte length */ +#define RFAL_NFCV_FLAG_POS 0U /*!< Flag byte position */ +#define RFAL_NFCV_FLAG_LEN 1U /*!< Flag byte length */ +#define RFAL_NFCV_DATASTART_POS 1U /*!< Position of start of data */ +#define RFAL_NFCV_DSFI_LEN 1U /*!< DSFID length */ +#define RFAL_NFCV_SLPREQ_REQ_FLAG 0x22U /*!< SLPV_REQ request flags Digital 2.0 (Candidate) 9.7.1.1 */ + +#define RFAL_NFCV_MAX_COLL_SUPPORTED 16U /*!< Maximum number of collisions supported by the Anticollision loop */ + +#define RFAL_FDT_POLL_MAX rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF 20 ms Digital 2.0 B.5 */ + + + +/*! Time from special frame to EOF + * ISO15693 2009 10.4.2 : 20ms + * NFC Forum defines Digital 2.0 9.7.4 : FDTV,EOF = [10 ; 20]ms + */ +#define RFAL_NFCV_FDT_EOF 20U + + + +/*! Time between slots - ISO 15693 defines t3min depending on modulation depth and data rate. + * With only high-bitrate supported, AM modulation and a length of 12 bytes (96bits) for INV_RES we get: + * - ISO t3min = 96/26 ms + 300us = 4 ms + * - NFC Forum defines FDTV,INVENT_NORES = (4394 + 2048)/fc. Digital 2.0 B.5*/ +#define RFAL_NFCV_FDT_V_INVENT_NORES 4U + + + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-V INVENTORY_REQ format Digital 2.0 9.6.1 */ +typedef struct +{ + uint8_t INV_FLAG; /*!< Inventory Flags */ + uint8_t CMD; /*!< Command code: 01h */ + uint8_t MASK_LEN; /*!< Mask Value Length */ + uint8_t MASK_VALUE[RFAL_NFCV_MASKVAL_MAX_LEN]; /*!< Mask Value */ +} rfalNfcvInventoryReq; + + +/*! NFC-V SLP_REQ format Digital 2.0 (Candidate) 9.7.1 */ +typedef struct +{ + uint8_t REQ_FLAG; /*!< Request Flags */ + uint8_t CMD; /*!< Command code: 02h */ + uint8_t UID[RFAL_NFCV_UID_LEN]; /*!< Mask Value */ +} rfalNfcvSlpvReq; + + +/*! Container for a collision found during Anticollision loop */ +typedef struct +{ + uint8_t maskLen; + uint8_t maskVal[RFAL_NFCV_MASKVAL_MAX_LEN]; +}rfalNfcvCollision; + + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode rfalNfcvParseError( uint8_t err ); + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +static ReturnCode rfalNfcvParseError( uint8_t err ) +{ + switch(err) + { + case RFAL_NFCV_ERROR_CMD_NOT_SUPPORTED: + case RFAL_NFCV_ERROR_OPTION_NOT_SUPPORTED: + return ERR_NOTSUPP; + + case RFAL_NFCV_ERROR_CMD_NOT_RECOGNIZED: + return ERR_PROTO; + + case RFAL_NFCV_ERROR_WRITE_FAILED: + return ERR_WRITE; + + default: + return ERR_REQUEST; + } +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerInitialize( void ) +{ + ReturnCode ret; + + EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCV, RFAL_BR_26p48, RFAL_BR_26p48 ) ); + rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); + + rfalSetGT( RFAL_GT_NFCV ); + rfalSetFDTListen( RFAL_FDT_LISTEN_NFCV_POLLER ); + rfalSetFDTPoll( RFAL_FDT_POLL_NFCV_POLLER ); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerCheckPresence( rfalNfcvInventoryRes *invRes ) +{ + ReturnCode ret; + + /* INVENTORY_REQ with 1 slot and no Mask Activity 2.0 (Candidate) 9.2.3.32 */ + ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_1, 0, NULL, invRes, NULL ); + + if( (ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || + (ret == ERR_FRAMING) || (ret == ERR_PROTO) ) + { + ret = ERR_NONE; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerInventory( rfalNfcvNumSlots nSlots, uint8_t maskLen, const uint8_t *maskVal, rfalNfcvInventoryRes *invRes, uint16_t* rcvdLen ) +{ + ReturnCode ret; + rfalNfcvInventoryReq invReq; + uint16_t rxLen; + + if( ((maskVal == NULL) && (maskLen != 0U)) || (invRes == NULL) ) + { + return ERR_PARAM; + } + + invReq.INV_FLAG = (RFAL_NFCV_INV_REQ_FLAG | (uint8_t)nSlots); + invReq.CMD = RFAL_NFCV_CMD_INVENTORY; + invReq.MASK_LEN = (uint8_t)MIN( maskLen, ((nSlots == RFAL_NFCV_NUM_SLOTS_1) ? RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN : RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN) ); /* Digital 2.0 9.6.1.6 */ + + if( rfalConvBitsToBytes(invReq.MASK_LEN) > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( invReq.MASK_VALUE, maskVal, rfalConvBitsToBytes(invReq.MASK_LEN) ); + } + + ret = rfalISO15693TransceiveAnticollisionFrame( (uint8_t*)&invReq, (uint8_t)(RFAL_NFCV_INV_REQ_HEADER_LEN + rfalConvBitsToBytes(invReq.MASK_LEN)), (uint8_t*)invRes, sizeof(rfalNfcvInventoryRes), &rxLen ); + + /* Check for optional output parameter */ + if( rcvdLen != NULL ) + { + *rcvdLen = rxLen; + } + + if( ret == ERR_NONE ) + { + if( rxLen != rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN) ) + { + return ERR_PROTO; + } + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt ) +{ + ReturnCode ret; + uint8_t slotNum; + uint16_t rcvdLen; + uint8_t colIt; + uint8_t colCnt; + uint8_t colPos; + bool colPending; + rfalNfcvCollision colFound[RFAL_NFCV_MAX_COLL_SUPPORTED]; + + + if( (nfcvDevList == NULL) || (devCnt == NULL) ) + { + return ERR_PARAM; + } + + /* Initialize parameters */ + *devCnt = 0; + colIt = 0; + colCnt = 0; + colPending = false; + ST_MEMSET(colFound, 0x00, (sizeof(rfalNfcvCollision)*RFAL_NFCV_MAX_COLL_SUPPORTED) ); + + if( devLimit > 0U ) /* MISRA 21.18 */ + { + ST_MEMSET(nfcvDevList, 0x00, (sizeof(rfalNfcvListenDevice)*devLimit) ); + } + + NO_WARNING(colPending); /* colPending is not exposed externally, in future it might become exposed/ouput parameter */ + + if( compMode == RFAL_COMPLIANCE_MODE_NFC ) + { + /* Send INVENTORY_REQ with one slot Activity 2.0 9.3.7.1 (Symbol 0) */ + ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &nfcvDevList->InvRes, NULL ); + + if( ret == ERR_TIMEOUT ) /* Exit if no device found Activity 2.0 9.3.7.2 (Symbol 1) */ + { + return ERR_NONE; + } + if( ret == ERR_NONE ) /* Device found without transmission error/collision Activity 2.0 9.3.7.3 (Symbol 2) */ + { + (*devCnt)++; + return ERR_NONE; + } + + /* A Collision has been identified Activity 2.0 9.3.7.2 (Symbol 3) */ + colPending = true; + colCnt = 1; + + /* Check if the Collision Resolution is set to perform only Collision detection Activity 2.0 9.3.7.5 (Symbol 4)*/ + if( devLimit == 0U ) + { + return ERR_RF_COLLISION; + } + + platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES); + + /*******************************************************************************/ + /* Collisions pending, Anticollision loop must be executed */ + /*******************************************************************************/ + } + else + { + /* Advance to 16 slots below without mask. Will give a good chance to identify multiple cards */ + colPending = true; + colCnt = 1; + } + + + /* Execute until all collisions are resolved Activity 2.0 9.3.7.16 (Symbol 17) */ + do + { + /* Activity 2.0 9.3.7.5 (Symbol 6) */ + colPending = false; + slotNum = 0; + + do + { + if( slotNum == 0U ) + { + /* Send INVENTORY_REQ with 16 slots Activity 2.0 9.3.7.7 (Symbol 8) */ + ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_16, colFound[colIt].maskLen, colFound[colIt].maskVal, &nfcvDevList[(*devCnt)].InvRes, &rcvdLen ); + } + else + { + ret = rfalISO15693TransceiveEOFAnticollision( (uint8_t*)&nfcvDevList[(*devCnt)].InvRes, sizeof(rfalNfcvInventoryRes), &rcvdLen ); + } + slotNum++; + + /*******************************************************************************/ + if( ret != ERR_TIMEOUT ) + { + if( rcvdLen < rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN) ) + { /* If only a partial frame was received make sure the FDT_V_INVENT_NORES is fulfilled */ + platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES); + } + + if( ret == ERR_NONE ) + { + /* Check if the device found is already on the list and its response is a valid INVENTORY_RES */ + if( rcvdLen == rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN) ) + { + /* Activity 2.0 9.3.7.15 (Symbol 11) */ + (*devCnt)++; + } + } + else /* Treat everything else as collision */ + { + /* Activity 2.0 9.3.7.15 (Symbol 16) */ + colPending = true; + + + /*******************************************************************************/ + /* Ensure that this collision still fits on the container */ + if( colCnt < RFAL_NFCV_MAX_COLL_SUPPORTED ) + { + /* Store this collision on the container to be resolved later */ + /* Activity 2.0 9.3.7.15 (Symbol 16): add the collision information + * (MASK_VAL + SN) to the list containing the collision information */ + ST_MEMCPY(colFound[colCnt].maskVal, colFound[colIt].maskVal, RFAL_NFCV_UID_LEN); + colPos = colFound[colIt].maskLen; + colFound[colCnt].maskVal[(colPos/RFAL_BITS_IN_BYTE)] &= (uint8_t)((1U << (colPos % RFAL_BITS_IN_BYTE)) - 1U); + colFound[colCnt].maskVal[(colPos/RFAL_BITS_IN_BYTE)] |= (uint8_t)((slotNum-1U) << (colPos % RFAL_BITS_IN_BYTE)); + colFound[colCnt].maskVal[((colPos/RFAL_BITS_IN_BYTE)+1U)] = (uint8_t)((slotNum-1U) >> (RFAL_BITS_IN_BYTE - (colPos % RFAL_BITS_IN_BYTE))); + + colFound[colCnt].maskLen = (colFound[colIt].maskLen + 4U); + + colCnt++; + } + } + } + else + { + /* Timeout */ + platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES); + } + + /* Check if devices found have reached device limit Activity 2.0 9.3.7.15 (Symbol 16) */ + if( *devCnt >= devLimit ) + { + return ERR_NONE; + } + } while( slotNum < RFAL_NFCV_MAX_SLOTS ); /* Slot loop */ + colIt++; + } while( colIt < colCnt ); /* Collisions found loop */ + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerSleepCollisionResolution( uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt ) +{ + uint8_t locDevCnt; + ReturnCode ret; + uint8_t i; + + if( (nfcvDevList == NULL) || (devCnt == NULL) ) + { + return ERR_PARAM; + } + + *devCnt = 0; + + do + { + locDevCnt = 0; + ret = rfalNfcvPollerCollisionResolution( RFAL_COMPLIANCE_MODE_ISO, (devLimit - *devCnt), &nfcvDevList[*devCnt], &locDevCnt ); + + for( i = *devCnt; i < (*devCnt + locDevCnt); i++ ) + { + rfalNfcvPollerSleep( 0x00, nfcvDevList[i].InvRes.UID ); + nfcvDevList[i].isSleep = true; + } + *devCnt += locDevCnt; + } + while( (locDevCnt > 0U) && (*devCnt < devLimit) ); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerSleep( uint8_t flags, const uint8_t* uid ) +{ + ReturnCode ret; + rfalNfcvSlpvReq slpReq; + uint8_t rxBuf; /* dummy buffer, just to perform Rx */ + + if( uid == NULL ) + { + return ERR_PARAM; + } + + /* Compute SLPV_REQ */ + slpReq.REQ_FLAG = (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS); /* Should be with UID according Digital 2.0 (Candidate) 9.7.1.1 */ + slpReq.CMD = RFAL_NFCV_CMD_SLPV; + ST_MEMCPY( slpReq.UID, uid, RFAL_NFCV_UID_LEN ); + + /* NFC Forum device SHALL wait at least FDTVpp to consider the SLPV acknowledged (FDTVpp = FDTVpoll) Digital 2.0 (Candidate) 9.7 9.8.2 */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slpReq, sizeof(rfalNfcvSlpvReq), &rxBuf, sizeof(rxBuf), NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_NFCV_POLLER ); + if( ret != ERR_TIMEOUT ) + { + return ret; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerSelect( uint8_t flags, const uint8_t* uid ) +{ + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if( uid == NULL ) + { + return ERR_PARAM; + } + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_SELECT, flags, RFAL_NFCV_PARAM_SKIP, uid, NULL, 0U, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t bn; + + bn = blockNum; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, &bn, sizeof(uint8_t), rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, const uint8_t* wrData, uint8_t blockLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_MAX_BLOCK_LEN)]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + /* Check for valid parameters */ + if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL) ) + { + return ERR_PARAM; + } + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = blockNum; /* Set Block Number (8 bits) */ + ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */ + dataLen += blockLen; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerLockBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum ) +{ + uint16_t rcvLen; + rfalNfcvGenericRes res; + uint8_t bn; + + bn = blockNum; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_LOCK_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, &bn, sizeof(uint8_t), (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = firstBlockNum; /* Set first Block Number */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerWriteMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t *txBuf, uint16_t txBufLen, uint8_t blockLen, const uint8_t* wrData, uint16_t wrDataLen ) +{ + ReturnCode ret; + uint16_t rcvLen; + uint16_t reqLen; + rfalNfcvGenericRes res; + uint16_t msgIt; + + /* Calculate required buffer length */ + reqLen = (uint16_t)((uid != NULL) ? (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen)); + + if( (reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || ((((uint16_t)numOfBlocks) * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) || (wrData == NULL) ) + { + return ERR_PARAM; + } + + msgIt = 0; + + /* Compute Request Command */ + txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS) & ~((uint32_t)RFAL_NFCV_REQ_FLAG_SELECT))); + txBuf[msgIt++] = RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS; + + /* Check if Request is to be sent in Addressed or Selected mode */ + if( uid != NULL ) + { + txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS; + ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN ); + msgIt += (uint8_t)RFAL_NFCV_UID_LEN; + } + else + { + txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_SELECT; + } + + txBuf[msgIt++] = firstBlockNum; + txBuf[msgIt++] = (numOfBlocks - 1U); + + if( wrDataLen > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( &txBuf[msgIt], wrData, wrDataLen ); + msgIt += wrDataLen; + } + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_MAX ); + + if( ret != ERR_NONE ) + { + return ret; + } + + /* Check if the response minimum length has been received */ + if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN ) + { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U ) + { + return rfalNfcvParseError( *res.data ); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_MAX_BLOCK_LEN)]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + /* Check for valid parameters */ + if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) ) + { + return ERR_PARAM; + } + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */ + dataLen += blockLen; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedLockSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum ) +{ + uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedWriteMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t *txBuf, uint16_t txBufLen, uint8_t blockLen, const uint8_t* wrData, uint16_t wrDataLen ) +{ + ReturnCode ret; + uint16_t rcvLen; + uint16_t reqLen; + rfalNfcvGenericRes res; + uint16_t msgIt; + uint16_t nBlocks; + + /* Calculate required buffer length */ + reqLen = ((uid != NULL) ? (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen) ); + + if( (reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (( (uint16_t)numOfBlocks * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) ) + { + return ERR_PARAM; + } + + msgIt = 0; + nBlocks = (numOfBlocks - 1U); + + /* Compute Request Command */ + txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS) & ~((uint32_t)RFAL_NFCV_REQ_FLAG_SELECT))); + txBuf[msgIt++] = RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK; + + /* Check if Request is to be sent in Addressed or Selected mode */ + if( uid != NULL ) + { + txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS; + ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN ); + msgIt += (uint8_t)RFAL_NFCV_UID_LEN; + } + else + { + txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_SELECT; + } + + txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 0) & 0xFFU); + txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 8) & 0xFFU); + txBuf[msgIt++] = (uint8_t)((nBlocks >> 0) & 0xFFU); + txBuf[msgIt++] = (uint8_t)((nBlocks >> 8) & 0xFFU); + + if( wrDataLen > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY( &txBuf[msgIt], wrData, wrDataLen ); + msgIt += wrDataLen; + } + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_MAX ); + + if( ret != ERR_NONE ) + { + return ret; + } + + /* Check if the response minimum length has been received */ + if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN ) + { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U ) + { + return rfalNfcvParseError( *res.data ); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_GET_SYS_INFO, flags, RFAL_NFCV_PARAM_SKIP, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t requestField, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_GET_SYS_INFO, flags, requestField, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerTransceiveReq( uint8_t cmd, uint8_t flags, uint8_t param, const uint8_t* uid, const uint8_t *data, uint16_t dataLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + ReturnCode ret; + rfalNfcvGenericReq req; + uint8_t msgIt; + rfalBitRate rxBR; + bool fastMode; + + msgIt = 0; + fastMode = false; + + /* Check for valid parameters */ + if( (rxBuf == NULL) || (rcvLen == NULL) || ((dataLen > 0U) && (data == NULL)) || + (dataLen > ((uid != NULL) ? RFAL_NFCV_MAX_GEN_DATA_LEN : (RFAL_NFCV_MAX_GEN_DATA_LEN - RFAL_NFCV_UID_LEN))) ) + { + return ERR_PARAM; + } + + + /* Check if the command is an ST's Fast command */ + if( (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION) ) + { + /* Store current Rx bit rate and move to fast mode */ + rfalGetBitRate( NULL, &rxBR ); + rfalSetBitRate( RFAL_BR_KEEP, RFAL_BR_52p97 ); + + fastMode = true; + } + + + /* Compute Request Command */ + req.REQ_FLAG = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS) & ~((uint32_t)RFAL_NFCV_REQ_FLAG_SELECT))); + req.CMD = cmd; + + /* Prepend parameter on ceratin proprietary requests: IC Manuf, Parameters */ + if( param != RFAL_NFCV_PARAM_SKIP ) + { + req.payload.data[msgIt++] = param; + } + + /* Check if request is to be sent in Addressed or Selected mode */ + if( uid != NULL ) + { + req.REQ_FLAG |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS; + ST_MEMCPY( &req.payload.data[msgIt], uid, RFAL_NFCV_UID_LEN ); + msgIt += RFAL_NFCV_UID_LEN; + } + else + { + req.REQ_FLAG |= (uint8_t)RFAL_NFCV_REQ_FLAG_SELECT; + } + + if( dataLen > 0U ) + { + ST_MEMCPY( &req.payload.data[msgIt], data, dataLen); + msgIt += (uint8_t)dataLen; + } + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&req, (RFAL_CMD_LEN + RFAL_NFCV_FLAG_LEN +(uint16_t)msgIt), rxBuf, rxBufLen, rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_MAX ); + + /* If the Option Flag is set in certain commands an EOF needs to be sent after 20ms to retrieve the VICC response ISO15693-3 2009 10.4.2 & 10.4.3 & 10.4.5 */ + if( ((flags & (uint8_t)RFAL_NFCV_REQ_FLAG_OPTION) != 0U) && ((cmd == (uint8_t)RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS) || + (cmd == (uint8_t)RFAL_NFCV_CMD_LOCK_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK)) ) + { + ret = rfalISO15693TransceiveEOF( rxBuf, (uint8_t)rxBufLen, rcvLen ); + } + + /* Restore Rx BitRate */ + if( fastMode ) + { + rfalSetBitRate( RFAL_BR_KEEP, rxBR ); + } + + if( ret != ERR_NONE ) + { + return ret; + } + + /* Check if the response minimum length has been received */ + if( (*rcvLen) < (uint8_t)RFAL_NFCV_FLAG_LEN ) + { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if( (rxBuf[RFAL_NFCV_FLAG_POS] & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U ) + { + return rfalNfcvParseError( rxBuf[RFAL_NFCV_DATASTART_POS] ); + } + + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_NFCV */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_rfst25r3911.c b/Software/fab-reader2-c/components/rfal/Src/rfal_rfst25r3911.c new file mode 100644 index 0000000..c9f9979 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_rfst25r3911.c @@ -0,0 +1,3733 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief RF Abstraction Layer (RFAL) + * + * RFAL implementation for ST25R3911 + */ + + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "rfal_chip.h" +#include "utils.h" +#include "st25r3911.h" +#include "st25r3911_com.h" +#include "st25r3911_interrupt.h" +#include "rfal_analogConfig.h" +#include "rfal_iso15693_2.h" + +/* + ****************************************************************************** + * ENABLE SWITCHS + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_LISTEN_MODE + #error " RFAL: Module configuration missing. Please enable/disable support for Listen Mode: RFAL_FEATURE_LISTEN_MODE " +#endif + +#ifndef RFAL_FEATURE_WAKEUP_MODE + #error " RFAL: Module configuration missing. Please enable/disable support for Wake-Up Mode: RFAL_FEATURE_WAKEUP_MODE " +#endif + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Struct that holds all involved on a Transceive including the context passed by the caller */ +typedef struct{ + rfalTransceiveState state; /*!< Current transceive state */ + rfalTransceiveState lastState; /*!< Last transceive state (debug purposes) */ + ReturnCode status; /*!< Current status/error of the transceive */ + bool rxse; /*!< Flag indicating if RXE was received with RXS */ + + rfalTransceiveContext ctx; /*!< The transceive context given by the caller */ +} rfalTxRx; + + +/*! Struct that holds all context for the Listen Mode */ +typedef struct{ + rfalLmState state; /*!< Current Listen Mode state */ + rfalBitRate brDetected; /*!< Last bit rate detected */ + + uint8_t* rxBuf; /*!< Location to store incoming data in Listen Mode */ + uint16_t rxBufLen; /*!< Length of rxBuf */ + uint16_t* rxLen; /*!< Pointer to write the data length placed into rxBuf */ + bool dataFlag; /*!< Listen Mode current Data Flag */ +} rfalLm; + + +/*! Struct that holds all context for the Wake-Up Mode */ +typedef struct{ + rfalWumState state; /*!< Current Wake-Up Mode state */ + rfalWakeUpConfig cfg; /*!< Current Wake-Up Mode context */ +} rfalWum; + + +/*! Struct that holds the timings GT and FDTs */ +typedef struct{ + uint32_t GT; /*!< GT in 1/fc */ + uint32_t FDTListen; /*!< FDTListen in 1/fc */ + uint32_t FDTPoll; /*!< FDTPoll in 1/fc */ +} rfalTimings; + + +/*! Struct that holds the software timers */ +typedef struct{ + uint32_t GT; /*!< RFAL's GT timer */ + uint32_t FWT; /*!< FWT/RWT timer for Active P2P*/ + uint32_t RXE; /*!< Timer between RXS and RXE */ +} rfalTimers; + + +/*! Struct that holds the RFAL's callbacks */ +typedef struct{ + rfalPreTxRxCallback preTxRx; /*!< RFAL's Pre TxRx callback */ + rfalPostTxRxCallback postTxRx; /*!< RFAL's Post TxRx callback */ +} rfalCallbacks; + + +/*! Struct that holds counters to control the FIFO on Tx and Rx */ +typedef struct{ + uint16_t expWL; /*!< The amount of bytes expected to be Tx when a WL interrupt occours */ + uint16_t bytesTotal; /*!< Total bytes to be transmitted OR the total bytes received */ + uint16_t bytesWritten;/*!< Amount of bytes already written on FIFO (Tx) OR read (RX) from FIFO and written on rxBuffer*/ + uint8_t status[ST25R3911_FIFO_STATUS_LEN]; /*!< FIFO Status Registers */ +} rfalFIFO; + + +/*! Struct that holds RFAL's configuration settings */ +typedef struct{ + uint8_t obsvModeTx; /*!< RFAL's config of the ST25R3911's observation mode while Tx */ + uint8_t obsvModeRx; /*!< RFAL's config of the ST25R3911's observation mode while Rx */ + rfalEHandling eHandling; /*!< RFAL's error handling config/mode */ +} rfalConfigs; + + +/*! Struct that holds NFC-F data - Used only inside rfalFelicaPoll() (static to avoid adding it into stack) */ +typedef struct{ + rfalFeliCaPollRes pollResponses[RFAL_FELICA_POLL_MAX_SLOTS]; /* FeliCa Poll response container for 16 slots */ +} rfalNfcfWorkingData; + + +/*! Struct that holds NFC-V current context + * + * 96 bytes is FIFO size of ST25R3911, codingBuffer has to be big enough for coping with maximum response size (Manchester coded) + * - current implementation expects it be written in one bulk into FIFO + * - needs to be above FIFO water level of ST25R3911 (64) + * - 65 is actually 1 byte too much, but ~75us in 1of256 another byte is already gone + * + * - inventory requests responses: 14 bytes + * - Max read single block responses: 32 bytes + * - Read multiple block responses: variable + * + * ISO15693 frame: SOF + Flags + Data + CRC + EOF + */ +typedef struct{ + uint8_t codingBuffer[((2 + 255 + 3)*2)];/*!< Coding buffer, length MUST be above 64: [65; ...] */ + uint16_t nfcvOffset; /*!< Offset needed for ISO15693 coding function */ + rfalTransceiveContext origCtx; /*!< Context provided by user */ + uint16_t ignoreBits; /*!< Number of bits at the beginning of a frame to be ignored when decoding*/ +} rfalNfcvWorkingData; + + +/*! RFAL instance */ +typedef struct{ + rfalState state; /*!< RFAL's current state */ + rfalMode mode; /*!< RFAL's current mode */ + rfalBitRate txBR; /*!< RFAL's current Tx Bit Rate */ + rfalBitRate rxBR; /*!< RFAL's current Rx Bit Rate */ + bool field; /*!< Current field state (On / Off) */ + + rfalConfigs conf; /*!< RFAL's configuration settings */ + rfalTimings timings; /*!< RFAL's timing setting */ + rfalTxRx TxRx; /*!< RFAL's transceive management */ + rfalFIFO fifo; /*!< RFAL's FIFO management */ + rfalTimers tmr; /*!< RFAL's Software timers */ + rfalCallbacks callbacks; /*!< RFAL's callbacks */ + +#if RFAL_FEATURE_LISTEN_MODE + rfalLm Lm; /*!< RFAL's listen mode management */ +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +#if RFAL_FEATURE_WAKEUP_MODE + rfalWum wum; /*!< RFAL's Wake-up mode management */ +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +#if RFAL_FEATURE_NFCF + rfalNfcfWorkingData nfcfData; /*!< RFAL's working data when supporting NFC-F */ +#endif /* RFAL_FEATURE_NFCF */ + +#if RFAL_FEATURE_NFCV + rfalNfcvWorkingData nfcvData; /*!< RFAL's working data when supporting NFC-V */ +#endif /* RFAL_FEATURE_NFCV */ + +} rfal; + + + +/*! Felica's command set */ +typedef enum +{ + FELICA_CMD_POLLING = 0x00, /*!< Felica Poll/REQC command (aka SENSF_REQ) to identify a card */ + FELICA_CMD_POLLING_RES = 0x01, /*!< Felica Poll/REQC command (aka SENSF_RES) response */ + FELICA_CMD_REQUEST_SERVICE = 0x02, /*!< verify the existence of Area and Service */ + FELICA_CMD_REQUEST_RESPONSE = 0x04, /*!< verify the existence of a card */ + FELICA_CMD_READ_WITHOUT_ENCRYPTION = 0x06, /*!< read Block Data from a Service that requires no authentication */ + FELICA_CMD_WRITE_WITHOUT_ENCRYPTION = 0x08, /*!< write Block Data to a Service that requires no authentication */ + FELICA_CMD_REQUEST_SYSTEM_CODE = 0x0c, /*!< acquire the System Code registered to a card */ + FELICA_CMD_AUTHENTICATION1 = 0x10, /*!< authenticate a card */ + FELICA_CMD_AUTHENTICATION2 = 0x12, /*!< allow a card to authenticate a Reader/Writer */ + FELICA_CMD_READ = 0x14, /*!< read Block Data from a Service that requires authentication */ + FELICA_CMD_WRITE = 0x16, /*!< write Block Data to a Service that requires authentication */ +}t_rfalFeliCaCmd; + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define RFAL_FIFO_IN_LT_32 32U /*!< Number of bytes in the FIFO when WL interrupt occurs while Tx ( fifo_lt: 0 ) */ +#define RFAL_FIFO_IN_LT_16 16U /*!< Number of bytes in the FIFO when WL interrupt occurs while Tx ( fifo_lt: 1 ) */ + +#define RFAL_FIFO_OUT_LT_32 (ST25R3911_FIFO_DEPTH - RFAL_FIFO_IN_LT_32) /*!< Number of bytes sent/out of the FIFO when WL interrupt occurs while Tx ( fifo_lt: 0 ) */ +#define RFAL_FIFO_OUT_LT_16 (ST25R3911_FIFO_DEPTH - RFAL_FIFO_IN_LT_16) /*!< Number of bytes sent/out of the FIFO when WL interrupt occurs while Tx ( fifo_lt: 1 ) */ + +#define RFAL_FIFO_STATUS_REG1 0U /*!< Location of FIFO status register 1 in local copy */ +#define RFAL_FIFO_STATUS_REG2 1U /*!< Location of FIFO status register 2 in local copy */ +#define RFAL_FIFO_STATUS_INVALID 0xFFU /*!< Value indicating that the local FIFO status in invalid|cleared */ + +#define RFAL_ST25R3911_GPT_MAX_1FC rfalConv8fcTo1fc( 0xFFFFU ) /*!< Max GPT steps in 1fc (0xFFFF steps of 8/fc => 0xFFFF * 590ns = 38,7ms) */ +#define RFAL_ST25R3911_NRT_MAX_1FC rfalConv4096fcTo1fc( 0xFFFFU ) /*!< Max NRT steps in 1fc (0xFFFF steps of 4096/fc => 0xFFFF * 302us = 19.8s ) */ +#define RFAL_ST25R3911_NRT_DISABLED 0U /*!< NRT Disabled: All 0 No-response timer is not started, wait forever */ +#define RFAL_ST25R3911_MRT_MAX_1FC rfalConv64fcTo1fc( 0x00FFU ) /*!< Max MRT steps in 1fc (0x00FF steps of 64/fc => 0x00FF * 4.72us = 1.2ms ) */ +#define RFAL_ST25R3911_MRT_MIN_1FC rfalConv64fcTo1fc( 0x0004U ) /*!< Min MRT steps in 1fc ( 0<=mrt<=4 ; 4 (64/fc) => 0x0004 * 4.72us = 18.88us ) */ +#define RFAL_ST25R3911_GT_MAX_1FC rfalConvMsTo1fc( 5000U ) /*!< Max GT value allowed in 1/fc */ +#define RFAL_ST25R3911_GT_MIN_1FC rfalConvMsTo1fc(RFAL_ST25R3911_SW_TMR_MIN_1MS) /*!< Min GT value allowed in 1/fc */ +#define RFAL_ST25R3911_SW_TMR_MIN_1MS 1U /*!< Min value of a SW timer in ms */ + +#define RFAL_OBSMODE_DISABLE 0x00U /*!< Observation Mode disabled */ + +#define RFAL_NFC_RX_INCOMPLETE_LEN (uint8_t)1U /*!< Threshold value where incoming rx may be considered as incomplete in NFC */ +#define RFAL_EMVCO_RX_MAXLEN (uint8_t)4U /*!< Maximum value where EMVCo to apply special error handling */ +#define RFAL_EMVCO_RX_MINLEN (uint8_t)2U /*!< Minimum value where EMVCo to apply special error handling */ + +#define RFAL_NORXE_TOUT 10U /*!< Timeout to be used on a potential missing RXE - Silicon ST25R3911B Errata #1.1 */ + +#define RFAL_ISO14443A_SDD_RES_LEN 5U /*!< SDD_RES | Anticollision (UID CLn) length - rfalNfcaSddRes */ + +#define RFAL_FELICA_POLL_DELAY_TIME 512U /*!< FeliCa Poll Processing time is 2.417 ms ~512*64/fc Digital 1.1 A4 */ +#define RFAL_FELICA_POLL_SLOT_TIME 256U /*!< FeliCa Poll Time Slot duration is 1.208 ms ~256*64/fc Digital 1.1 A4 */ + +#define RFAL_ISO15693_IGNORE_BITS rfalConvBytesToBits(2U) /*!< Ignore collisions before the UID (RES_FLAG + DSFID) */ + + +/*******************************************************************************/ + +#define RFAL_LM_GT rfalConvUsTo1fc(100U) /*!< Listen Mode Guard Time enforced (GT - Passive; TIRFG - Active) */ +#define RFAL_FDT_POLL_ADJUSTMENT rfalConvUsTo1fc(80U) /*!< FDT Poll adjustment: Time between the expiration of GPT to the actual Tx */ +#define RFAL_FDT_LISTEN_MRT_ADJUSTMENT 64U /*!< MRT jitter adjustment: timeout will be between [ tout ; tout + 64 cycles ] */ +#define RFAL_AP2P_FIELDOFF_TRFW rfalConv8fcTo1fc(64U) /*!< Time after TXE and Field Off in AP2P Trfw: 37.76us -> 64 (8/fc) */ + + +/*! FWT adjustment: + * 64 : NRT jitter between TXE and NRT start */ +#define RFAL_FWT_ADJUSTMENT 64U + +/*! FWT ISO14443A adjustment: + * 512 : Initial 4bit length */ +#define RFAL_FWT_A_ADJUSTMENT 512U + +/*! FWT ISO14443B adjustment: + * 2784 : Adjustment for the SOF and initial byte */ +#define RFAL_FWT_B_ADJUSTMENT 2784U + + +/*! FWT FeliCa 212 adjustment: + * 1024 : Length of the two Sync bytes at 212kbps */ +#define RFAL_FWT_F_212_ADJUSTMENT 1024U + +/*! FWT FeliCa 424 adjustment: + * 512 : Length of the two Sync bytes at 424kbps */ +#define RFAL_FWT_F_424_ADJUSTMENT 512U + + +/*! Time between our field Off and other peer field On : Tadt + (n x Trfw) + * Ecma 340 11.1.2 - Tadt: [56.64 , 188.72] us ; n: [0 , 3] ; Trfw = 37.76 us + * Should be: 189 + (3*38) = 303us ; we'll use a more relaxed setting: 605 us */ +#define RFAL_AP2P_FIELDON_TADTTRFW rfalConvUsTo1fc(605U) + + +/*! FDT Listen adjustment for ISO14443A EMVCo 2.6 4.8.1.3 ; Digital 1.1 6.10 + * + * 276: Time from the rising pulse of the pause of the logic '1' (i.e. the time point to measure the deaftime from), + * to the actual end of the EOF sequence (the point where the MRT starts). Please note that the ST25R391x uses the + * ISO14443-2 definition where the EOF consists of logic '0' followed by sequence Y. + */ +#define RFAL_FDT_LISTEN_A_ADJUSTMENT 276U + + +/*! FDT Listen adjustment for ISO14443B EMVCo 2.6 4.8.1.6 ; Digital 1.1 7.9 + * + * 340: Time from the rising edge of the EoS to the starting point of the MRT timer (sometime after the final high + * part of the EoS is completed). + * + * -64: Adjustment for the TR1PUTMIN. + * The TR1PUTMIN of the ST25R3911 is 1152/fc (72/fs). The EMVCo test case TB0000 measures the TR1PUTMIN. + * It takes the default value of TR1PUTMIN (79/fs) and reduces it by 128/fc in every iteration. + * This results in a TR1PUTMIN of 1136/fc (71/fs) for the second iteration. The ST25R3911 sends a NAK because + * the TR1PUTMIN of the ST25R3911 (72/fs) is higher than 71/fs. + * Therefore the test suite assumes TR1PUTMIN of 1264/fc (79/fs). + * The test cases TB340.0 and TB435.0 uses the TR1PUTMIN to send frames too early. In order to correctly + * recognise these frames as being sent too early (starting inside reader deaf time), the MRT has to be + * increased by at least 64/fc (8/fs). + */ +#define RFAL_FDT_LISTEN_B_ADJUSTMENT (340U - 64U) + + +/*! FDT Listen adjustment for ISO15693 + * ISO15693 2000 8.4 t1 MIN = 4192/fc + * ISO15693 2009 9.1 t1 MIN = 4320/fc + * Digital 2.1 B.5 FDTV,LISTEN,MIN = 4310/fc + * Set FDT Listen one step earlier than on the more recent spec versions for greater interoprability + */ +#define RFAL_FDT_LISTEN_V_ADJUSTMENT 128U + + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +#define rfalCalcNumBytes( nBits ) (((uint32_t)(nBits) + 7U) / 8U) /*!< Returns the number of bytes required to fit given the number of bits */ + +#define rfalTimerStart( timer, time_ms ) (timer) = platformTimerCreate((uint16_t)(time_ms)) /*!< Configures and starts the RTOX timer */ +#define rfalTimerisExpired( timer ) platformTimerIsExpired( timer ) /*!< Checks if timer has expired */ + +#define rfalST25R3911ObsModeDisable() st25r3911WriteTestRegister(0x01U, 0x00U) /*!< Disable ST25R3911 Observation mode */ +#define rfalST25R3911ObsModeTx() st25r3911WriteTestRegister(0x01U, gRFAL.conf.obsvModeTx) /*!< Enable Observation mode 0x0A CSI: Digital TX modulation signal CSO: none */ +#define rfalST25R3911ObsModeRx() st25r3911WriteTestRegister(0x01U, gRFAL.conf.obsvModeRx) /*!< Enable Observation mode 0x04 CSI: Digital output of AM channel CSO: Digital output of PM channel */ + + +#define rfalCheckDisableObsMode() if(gRFAL.conf.obsvModeRx != 0U){ rfalST25R3911ObsModeDisable(); } /*!< Checks if the observation mode is enabled, and applies on ST25R3911 */ +#define rfalCheckEnableObsModeTx() if(gRFAL.conf.obsvModeTx != 0U){ rfalST25R3911ObsModeTx(); } /*!< Checks if the observation mode is enabled, and applies on ST25R3911 */ +#define rfalCheckEnableObsModeRx() if(gRFAL.conf.obsvModeRx != 0U){ rfalST25R3911ObsModeRx(); } /*!< Checks if the observation mode is enabled, and applies on ST25R3911 */ + + +#define rfalGetIncmplBits( FIFOStatus2 ) (( (FIFOStatus2) >> 1) & 0x07U) /*!< Returns the number of bits from fifo status */ +#define rfalIsIncompleteByteError( error ) (((error) >= ERR_INCOMPLETE_BYTE) && ((error) <= ERR_INCOMPLETE_BYTE_07)) /*!< Checks if given error is a Incomplete error */ + +#define rfalAdjACBR( b ) (((uint16_t)(b) >= (uint16_t)RFAL_BR_52p97) ? (uint16_t)(b) : ((uint16_t)(b)+1U)) /*!< Adjusts ST25R391x Bit rate to Analog Configuration */ +#define rfalConvBR2ACBR( b ) (((rfalAdjACBR((b)))<din; + streamConf.dout = isoStreamConfig->dout; + streamConf.report_period_length = isoStreamConfig->report_period_length; + streamConf.useBPSK = isoStreamConfig->useBPSK; + st25r3911StreamConfigure(&streamConf); + } + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON) ); + rfalSetAnalogConfig( (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX ) ); + rfalSetAnalogConfig( (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX ) ); + break; + + #endif /* RFAL_FEATURE_NFCV */ + + + /*******************************************************************************/ + case RFAL_MODE_POLL_ACTIVE_P2P: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON) ); + rfalSetAnalogConfig( (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX ) ); + rfalSetAnalogConfig( (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX ) ); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_ACTIVE_P2P: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON) ); + rfalSetAnalogConfig( (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX ) ); + rfalSetAnalogConfig( (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX ) ); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCA: + case RFAL_MODE_LISTEN_NFCB: + case RFAL_MODE_LISTEN_NFCF: + case RFAL_MODE_NONE: + return ERR_WRONG_STATE; + + /*******************************************************************************/ + default: + return ERR_NOT_IMPLEMENTED; + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalGetBitRate( rfalBitRate *txBR, rfalBitRate *rxBR ) +{ + if( (gRFAL.state == RFAL_STATE_IDLE) || (gRFAL.mode == RFAL_MODE_NONE) ) + { + return ERR_WRONG_STATE; + } + + if( txBR != NULL ) + { + *txBR = gRFAL.txBR; + } + + if( rxBR != NULL ) + { + *rxBR = gRFAL.rxBR; + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +void rfalSetErrorHandling( rfalEHandling eHandling ) +{ + gRFAL.conf.eHandling = eHandling; +} + + +/*******************************************************************************/ +rfalEHandling rfalGetErrorHandling( void ) +{ + return gRFAL.conf.eHandling; +} + + +/*******************************************************************************/ +void rfalSetFDTPoll( uint32_t FDTPoll ) +{ + gRFAL.timings.FDTPoll = MIN( FDTPoll, RFAL_ST25R3911_GPT_MAX_1FC ); +} + + +/*******************************************************************************/ +uint32_t rfalGetFDTPoll( void ) +{ + return gRFAL.timings.FDTPoll; +} + + +/*******************************************************************************/ +void rfalSetFDTListen( uint32_t FDTListen ) +{ + gRFAL.timings.FDTListen = MIN( FDTListen, RFAL_ST25R3911_MRT_MAX_1FC); +} + +/*******************************************************************************/ +uint32_t rfalGetFDTListen( void ) +{ + return gRFAL.timings.FDTListen; +} + +void rfalSetGT( uint32_t GT ) +{ + gRFAL.timings.GT = MIN( GT, RFAL_ST25R3911_GT_MAX_1FC ); +} + +/*******************************************************************************/ +uint32_t rfalGetGT( void ) +{ + return gRFAL.timings.GT; +} + +/*******************************************************************************/ +bool rfalIsGTExpired( void ) +{ + if( gRFAL.tmr.GT != RFAL_TIMING_NONE ) + { + if( !rfalTimerisExpired( gRFAL.tmr.GT ) ) + { + return false; + } + } + return true; +} + +/*******************************************************************************/ +ReturnCode rfalFieldOnAndStartGT( void ) +{ + ReturnCode ret; + + /* Check if RFAL has been initialized (Oscillator should be running) and also + * if a direct register access has been performed and left the Oscillator Off */ + if( !st25r3911IsOscOn() || (gRFAL.state < RFAL_STATE_INIT) ) + { + return ERR_WRONG_STATE; + } + + ret = ERR_NONE; + + /* Set Analog configurations for Field On event */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_FIELD_ON) ); + + /*******************************************************************************/ + /* Perform collision avoidance and turn field On if not already On */ + if( !st25r3911IsTxEnabled() || !gRFAL.field ) + { + /* Use Thresholds set by AnalogConfig */ + ret = st25r3911PerformCollisionAvoidance( ST25R3911_CMD_RESPONSE_RF_COLLISION_0, ST25R3911_THRESHOLD_DO_NOT_SET, ST25R3911_THRESHOLD_DO_NOT_SET, 0 ); + + gRFAL.field = st25r3911IsTxEnabled(); + + /* Only turn on Receiver and Transmitter if field was successfully turned On */ + if(gRFAL.field) + { + st25r3911TxRxOn(); /* Enable Tx and Rx (Tx is already On) */ + } + } + + /*******************************************************************************/ + /* Start GT timer in case the GT value is set */ + if( (gRFAL.timings.GT != RFAL_TIMING_NONE) ) + { + /* Ensure that a SW timer doesn't have a lower value then the minimum */ + rfalTimerStart( gRFAL.tmr.GT, rfalConv1fcToMs( MAX( (gRFAL.timings.GT), RFAL_ST25R3911_GT_MIN_1FC) ) ); + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalFieldOff( void ) +{ + /* Check whether a TxRx is not yet finished */ + if( gRFAL.TxRx.state != RFAL_TXRX_STATE_IDLE ) + { + rfalCleanupTransceive(); + } + + /* Disable Tx and Rx */ + st25r3911TxRxOff(); + + /* Set Analog configurations for Field Off event */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_FIELD_OFF) ); + gRFAL.field = false; + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalStartTransceive( const rfalTransceiveContext *ctx ) +{ + uint32_t FxTAdj; /* FWT or FDT adjustment calculation */ + + /* Check for valid parameters */ + if( ctx == NULL ) + { + return ERR_PARAM; + } + + /* Ensure that RFAL is already Initialized and the mode has been set */ + if( (gRFAL.state >= RFAL_STATE_MODE_SET) /*&& (gRFAL.TxRx.state == RFAL_TXRX_STATE_INIT )*/ ) + { + /*******************************************************************************/ + /* Check whether the field is already On, otherwise no TXE will be received */ + if( !st25r3911IsTxEnabled() && (!rfalIsModePassiveListen( gRFAL.mode ) && (ctx->txBuf != NULL)) ) + { + return ERR_WRONG_STATE; + } + + gRFAL.TxRx.ctx = *ctx; + + /*******************************************************************************/ + if( gRFAL.timings.FDTListen != RFAL_TIMING_NONE ) + { + /* Calculate MRT adjustment accordingly to the current mode */ + FxTAdj = RFAL_FDT_LISTEN_MRT_ADJUSTMENT; + if(gRFAL.mode == RFAL_MODE_POLL_NFCA) { FxTAdj += (uint32_t)RFAL_FDT_LISTEN_A_ADJUSTMENT; } + if(gRFAL.mode == RFAL_MODE_POLL_NFCA_T1T) { FxTAdj += (uint32_t)RFAL_FDT_LISTEN_A_ADJUSTMENT; } + if(gRFAL.mode == RFAL_MODE_POLL_NFCB) { FxTAdj += (uint32_t)RFAL_FDT_LISTEN_B_ADJUSTMENT; } + if(gRFAL.mode == RFAL_MODE_POLL_NFCV) { FxTAdj += (uint32_t)RFAL_FDT_LISTEN_V_ADJUSTMENT; } + + + /* Set Minimum FDT(Listen) in which PICC is not allowed to send a response */ + st25r3911WriteRegister( ST25R3911_REG_MASK_RX_TIMER, (uint8_t)rfalConv1fcTo64fc( (FxTAdj > gRFAL.timings.FDTListen) ? RFAL_ST25R3911_MRT_MIN_1FC : (gRFAL.timings.FDTListen - FxTAdj) ) ); + } + + /*******************************************************************************/ + /* FDT Poll will be loaded in rfalPrepareTransceive() once the previous was expired */ + + /*******************************************************************************/ + if( rfalIsModePassiveComm( gRFAL.mode ) ) /* Passive Comms */ + { + if( (gRFAL.TxRx.ctx.fwt != RFAL_FWT_NONE) && (gRFAL.TxRx.ctx.fwt != 0U) ) + { + /* Ensure proper timing configuration */ + if( gRFAL.timings.FDTListen >= gRFAL.TxRx.ctx.fwt ) + { + return ERR_PARAM; + } + + FxTAdj = RFAL_FWT_ADJUSTMENT; + if(gRFAL.mode == RFAL_MODE_POLL_NFCA) { FxTAdj += (uint32_t)RFAL_FWT_A_ADJUSTMENT; } + if(gRFAL.mode == RFAL_MODE_POLL_NFCA_T1T) { FxTAdj += (uint32_t)RFAL_FWT_A_ADJUSTMENT; } + if(gRFAL.mode == RFAL_MODE_POLL_NFCB) { FxTAdj += (uint32_t)RFAL_FWT_B_ADJUSTMENT; } + if(gRFAL.mode == RFAL_MODE_POLL_NFCF) + { + FxTAdj += (uint32_t)((gRFAL.txBR == RFAL_BR_212) ? RFAL_FWT_F_212_ADJUSTMENT : RFAL_FWT_F_424_ADJUSTMENT ); + } + + /* Ensure that the given FWT doesn't exceed NRT maximum */ + gRFAL.TxRx.ctx.fwt = MIN( (gRFAL.TxRx.ctx.fwt + FxTAdj), RFAL_ST25R3911_NRT_MAX_1FC ); + + /* Set FWT in the NRT */ + st25r3911SetNoResponseTime_64fcs( rfalConv1fcTo64fc( gRFAL.TxRx.ctx.fwt ) ); + } + else + { + /* Disable NRT, no NRE will be triggered, therefore wait endlessly for Rx */ + st25r3911SetNoResponseTime_64fcs( RFAL_ST25R3911_NRT_DISABLED ); + } + } + else /* Active Comms */ + { + /* Setup NRT timer for rf response RF collision timeout. */ + st25r3911SetNoResponseTime_64fcs( rfalConv1fcTo64fc(RFAL_AP2P_FIELDON_TADTTRFW) ); + + /* In Active Mode No Response Timer cannot be used to measure FWT a SW timer is used instead */ + } + + gRFAL.state = RFAL_STATE_TXRX; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_IDLE; + gRFAL.TxRx.status = ERR_BUSY; + gRFAL.TxRx.rxse = false; + + #if RFAL_FEATURE_NFCV + /*******************************************************************************/ + if( (RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode) ) + { /* Exchange receive buffer with internal buffer */ + gRFAL.nfcvData.origCtx = gRFAL.TxRx.ctx; + + gRFAL.TxRx.ctx.rxBuf = ((gRFAL.nfcvData.origCtx.rxBuf != NULL) ? gRFAL.nfcvData.codingBuffer : NULL); + gRFAL.TxRx.ctx.rxBufLen = (uint16_t)rfalConvBytesToBits(sizeof(gRFAL.nfcvData.codingBuffer)); + gRFAL.TxRx.ctx.flags = (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL + | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP + | (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF + | (uint32_t)(gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_AGC_OFF) + | (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP + | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE; + + /* In NFCV a TxRx with a valid txBuf and txBufSize==0 indicates to send an EOF */ + /* Skip logic below that would go directly into receive */ + if ( gRFAL.TxRx.ctx.txBuf != NULL ) + { + return ERR_NONE; + } + } + #endif /* RFAL_FEATURE_NFCV */ + + + /*******************************************************************************/ + /* Check if the Transceive start performing Tx or goes directly to Rx */ + if( (gRFAL.TxRx.ctx.txBuf == NULL) || (gRFAL.TxRx.ctx.txBufLen == 0U) ) + { + /* Clear FIFO, Clear and Enable the Interrupts */ + rfalPrepareTransceive( ); + + /* Disable our field upon a Rx reEnable on AP2P */ + if( rfalIsModeActiveComm(gRFAL.mode) ) + { + st25r3911TxOff(); + } + + /* No Tx done, enable the Receiver */ + st25r3911ExecuteCommand( ST25R3911_CMD_UNMASK_RECEIVE_DATA ); + + /* Start NRT manually, if FWT = 0 (wait endlessly for Rx) chip will ignore anyhow */ + st25r3911ExecuteCommand( ST25R3911_CMD_START_NO_RESPONSE_TIMER ); + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + } + + return ERR_NONE; + } + + return ERR_WRONG_STATE; +} + + +/*******************************************************************************/ +bool rfalIsTransceiveInTx( void ) +{ + return ( (gRFAL.TxRx.state >= RFAL_TXRX_STATE_TX_IDLE) && (gRFAL.TxRx.state < RFAL_TXRX_STATE_RX_IDLE) ); +} + + +/*******************************************************************************/ +bool rfalIsTransceiveInRx( void ) +{ + return (gRFAL.TxRx.state >= RFAL_TXRX_STATE_RX_IDLE); +} + + +/*******************************************************************************/ +ReturnCode rfalTransceiveBlockingTx( uint8_t* txBuf, uint16_t txBufLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* actLen, uint32_t flags, uint32_t fwt ) +{ + ReturnCode ret; + rfalTransceiveContext ctx; + + rfalCreateByteFlagsTxRxContext( ctx, txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt ); + EXIT_ON_ERR( ret, rfalStartTransceive( &ctx ) ); + + return rfalTransceiveRunBlockingTx(); +} + + +/*******************************************************************************/ +static ReturnCode rfalTransceiveRunBlockingTx( void ) +{ + ReturnCode ret; + + do{ + rfalWorker(); + ret = rfalGetTransceiveStatus(); + } + while( rfalIsTransceiveInTx() && (ret == ERR_BUSY) ); + + if( rfalIsTransceiveInRx() ) + { + return ERR_NONE; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalTransceiveBlockingRx( void ) +{ + ReturnCode ret; + + do{ + rfalWorker(); + ret = rfalGetTransceiveStatus(); + } + while( rfalIsTransceiveInRx() && (ret == ERR_BUSY) ); + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalTransceiveBlockingTxRx( uint8_t* txBuf, uint16_t txBufLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* actLen, uint32_t flags, uint32_t fwt ) +{ + ReturnCode ret; + + EXIT_ON_ERR( ret, rfalTransceiveBlockingTx( txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt ) ); + ret = rfalTransceiveBlockingRx(); + + /* Convert received bits to bytes */ + if( actLen != NULL ) + { + *actLen = rfalConvBitsToBytes(*actLen); + } + + return ret; +} + + +/*******************************************************************************/ +static ReturnCode rfalRunTransceiveWorker( void ) +{ + if( gRFAL.state == RFAL_STATE_TXRX ) + { + /* Run Tx or Rx state machines */ + if( rfalIsTransceiveInTx() ) + { + rfalTransceiveTx(); + return rfalGetTransceiveStatus(); + } + + if( rfalIsTransceiveInRx() ) + { + rfalTransceiveRx(); + return rfalGetTransceiveStatus(); + } + } + return ERR_WRONG_STATE; +} + +/*******************************************************************************/ +rfalTransceiveState rfalGetTransceiveState( void ) +{ + return gRFAL.TxRx.state; +} + +ReturnCode rfalGetTransceiveStatus( void ) +{ + return ((gRFAL.TxRx.state == RFAL_TXRX_STATE_IDLE) ? gRFAL.TxRx.status : ERR_BUSY); +} + + +/*******************************************************************************/ +ReturnCode rfalGetTransceiveRSSI( uint16_t *rssi ) +{ + uint16_t amRSSI; + uint16_t pmRSSI; + + if( rssi == NULL ) + { + return ERR_PARAM; + } + + /* Check if Manual channel is enabled */ + if( st25r3911CheckReg( ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_rx_man, ST25R3911_REG_OP_CONTROL_rx_man ) ) + { + st25r3911GetRSSI( &amRSSI, &pmRSSI ); + + /* Check which channel is selected */ + *rssi = ( st25r3911CheckReg( ST25R3911_REG_RX_CONF1, ST25R3911_REG_RX_CONF1_ch_sel, ST25R3911_REG_RX_CONF1_ch_sel ) ? pmRSSI : amRSSI ); + return ERR_NONE; + } + + *rssi = 0; + return ERR_NOTSUPP; +} + + +/*******************************************************************************/ +void rfalWorker( void ) +{ + platformProtectWorker(); /* Protect RFAL Worker/Task/Process */ + + switch( gRFAL.state ) + { + case RFAL_STATE_TXRX: + rfalRunTransceiveWorker(); + break; + + #if RFAL_FEATURE_LISTEN_MODE + case RFAL_STATE_LM: + rfalRunListenModeWorker(); + break; + #endif /* RFAL_FEATURE_LISTEN_MODE */ + + #if RFAL_FEATURE_WAKEUP_MODE + case RFAL_STATE_WUM: + rfalRunWakeUpModeWorker(); + break; + #endif /* RFAL_FEATURE_WAKEUP_MODE */ + + /* Nothing to be done */ + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + + platformUnprotectWorker(); /* Unprotect RFAL Worker/Task/Process */ +} + + +/*******************************************************************************/ +static void rfalErrorHandling( void ) +{ + bool rxHasIncParError; + uint8_t fifoBytesToRead; + uint8_t reEnRx[] = { ST25R3911_CMD_CLEAR_FIFO, ST25R3911_CMD_UNMASK_RECEIVE_DATA }; + + + fifoBytesToRead = rfalFIFOStatusGetNumBytes(); + + + /*******************************************************************************/ + /* EMVCo */ + /*******************************************************************************/ + if( gRFAL.conf.eHandling == RFAL_ERRORHANDLING_EMVCO ) + { + /*******************************************************************************/ + /* EMD Handling - NFC Forum Digital 1.1 4.1.1.1 ; EMVCo 2.6 4.9.2 */ + /* ReEnable the receiver on frames with a length < 4 bytes, upon: */ + /* - Collision or Framing error detected */ + /* - Residual bits are detected (hard framing error) */ + /* - Parity error */ + /* - CRC error */ + /*******************************************************************************/ + + /* Check if reception has incompete bytes or parity error */ + rxHasIncParError = ( rfalFIFOStatusIsIncompleteByte() ? true : rfalFIFOStatusIsMissingPar() ); /* MISRA 13.5 */ + + /* In case there are residual bits decrement FIFO bytes */ + if( (fifoBytesToRead > 0U) && rxHasIncParError) + { + fifoBytesToRead--; + } + + if( ( (gRFAL.fifo.bytesTotal + fifoBytesToRead) < RFAL_EMVCO_RX_MAXLEN ) && + ( (gRFAL.TxRx.status == ERR_RF_COLLISION) || (gRFAL.TxRx.status == ERR_FRAMING) || + (gRFAL.TxRx.status == ERR_PAR) || (gRFAL.TxRx.status == ERR_CRC) || + rxHasIncParError ) ) + { + /* Ignore this reception, ReEnable receiver */ + st25r3911ExecuteCommands( reEnRx, sizeof(reEnRx) ); + + rfalFIFOStatusClear(); + gRFAL.fifo.bytesTotal = 0; + gRFAL.TxRx.status = ERR_BUSY; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXS; + } + return; + } + + /*******************************************************************************/ + /* ISO14443A Mode */ + /*******************************************************************************/ + if( gRFAL.mode == RFAL_MODE_POLL_NFCA ) + { + + /*******************************************************************************/ + /* If we received one incomplete byte (not a block and a incomplete byte at * + * the end) we will raise a specific error ( support for T2T 4 bit ACK / NAK ) * + * Otherwise just leave it as an CRC/FRAMING/PAR error */ + /*******************************************************************************/ + if( (gRFAL.TxRx.status == ERR_PAR) || (gRFAL.TxRx.status == ERR_CRC) ) + { + if( rfalFIFOStatusIsIncompleteByte() && (fifoBytesToRead == RFAL_NFC_RX_INCOMPLETE_LEN) ) + { + st25r3911ReadFifo( (uint8_t*)(gRFAL.TxRx.ctx.rxBuf), fifoBytesToRead ); + if( (gRFAL.TxRx.ctx.rxRcvdLen) != NULL ) + { + *gRFAL.TxRx.ctx.rxRcvdLen = rfalFIFOGetNumIncompleteBits(); + } + + gRFAL.TxRx.status = ERR_INCOMPLETE_BYTE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + } + } + +} + + +/*******************************************************************************/ +static void rfalCleanupTransceive( void ) +{ + /*******************************************************************************/ + /* Transceive flags */ + /*******************************************************************************/ + + /* Restore default settings on NFCIP1 mode, Receiving parity + CRC bits and manual Tx Parity*/ + st25r3911ClrRegisterBits( ST25R3911_REG_ISO14443A_NFC, (ST25R3911_REG_ISO14443A_NFC_no_tx_par | ST25R3911_REG_ISO14443A_NFC_no_rx_par | ST25R3911_REG_ISO14443A_NFC_nfc_f0) ); + + /* Restore AGC enabled */ + st25r3911SetRegisterBits( ST25R3911_REG_RX_CONF2, ST25R3911_REG_RX_CONF2_agc_en ); + + /*******************************************************************************/ + + + + /*******************************************************************************/ + /* Execute Post Transceive Callback */ + /*******************************************************************************/ + if( gRFAL.callbacks.postTxRx != NULL ) + { + gRFAL.callbacks.postTxRx(); + } + /*******************************************************************************/ + +} + + +/*******************************************************************************/ +static void rfalPrepareTransceive( void ) +{ + uint32_t maskInterrupts; + uint8_t reg; + + /*******************************************************************************/ + /* In the EMVCo mode the NRT will continue to run. * + * For the clear to stop it, the EMV mode has to be disabled before */ + st25r3911ClrRegisterBits( ST25R3911_REG_GPT_CONTROL, ST25R3911_REG_GPT_CONTROL_nrt_emv ); + + /* Reset receive logic */ + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_FIFO ); + + /* Reset Rx Gain */ + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_SQUELCH ); + + + /*******************************************************************************/ + /* FDT Poll */ + /*******************************************************************************/ + if( rfalIsModePassiveComm( gRFAL.mode ) ) /* Passive Comms */ + { + /* In Passive communications General Purpose Timer is used to measure FDT Poll */ + if( gRFAL.timings.FDTPoll != RFAL_TIMING_NONE ) + { + /* Configure GPT to start at RX end */ + st25r3911StartGPTimer_8fcs( (uint16_t)rfalConv1fcTo8fc( MIN( gRFAL.timings.FDTPoll, (gRFAL.timings.FDTPoll - RFAL_FDT_POLL_ADJUSTMENT) ) ), ST25R3911_REG_GPT_CONTROL_gptc_erx ); + } + } + + + /*******************************************************************************/ + /* Execute Pre Transceive Callback */ + /*******************************************************************************/ + if( gRFAL.callbacks.preTxRx != NULL ) + { + gRFAL.callbacks.preTxRx(); + } + /*******************************************************************************/ + + maskInterrupts = ( ST25R3911_IRQ_MASK_FWL | ST25R3911_IRQ_MASK_TXE | + ST25R3911_IRQ_MASK_RXS | ST25R3911_IRQ_MASK_RXE | + ST25R3911_IRQ_MASK_FWL | ST25R3911_IRQ_MASK_NRE | + ST25R3911_IRQ_MASK_PAR | ST25R3911_IRQ_MASK_CRC | + ST25R3911_IRQ_MASK_ERR1 | ST25R3911_IRQ_MASK_ERR2 ); + + + /*******************************************************************************/ + /* Transceive flags */ + /*******************************************************************************/ + + reg = (ST25R3911_REG_ISO14443A_NFC_no_tx_par_off | ST25R3911_REG_ISO14443A_NFC_no_rx_par_off | ST25R3911_REG_ISO14443A_NFC_nfc_f0_off); + + /* Check if NFCIP1 mode is to be enabled */ + if( (gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_NFCIP1_ON) != 0U ) + { + reg |= ST25R3911_REG_ISO14443A_NFC_nfc_f0; + } + + /* Check if Parity check is to be skipped and to keep the parity + CRC bits in FIFO */ + if( (gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP) != 0U ) + { + reg |= ST25R3911_REG_ISO14443A_NFC_no_rx_par; + } + + /* Check if automatic Parity bits is to be disabled */ + if( (gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_PAR_TX_NONE) != 0U ) + { + reg |= ST25R3911_REG_ISO14443A_NFC_no_tx_par; + } + + /* Apply current TxRx flags on ISO14443A and NFC 106kb/s Settings Register */ + st25r3911ChangeRegisterBits( ST25R3911_REG_ISO14443A_NFC, (ST25R3911_REG_ISO14443A_NFC_no_tx_par | ST25R3911_REG_ISO14443A_NFC_no_rx_par | ST25R3911_REG_ISO14443A_NFC_nfc_f0), reg ); + + + /* Check if AGC is to be disabled */ + if( (gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_AGC_OFF) != 0U ) + { + st25r3911ClrRegisterBits( ST25R3911_REG_RX_CONF2, ST25R3911_REG_RX_CONF2_agc_en ); + } + else + { + st25r3911SetRegisterBits( ST25R3911_REG_RX_CONF2, ST25R3911_REG_RX_CONF2_agc_en ); + } + /*******************************************************************************/ + + + + /*******************************************************************************/ + /* EMVCo NRT mode */ + /*******************************************************************************/ + if( gRFAL.conf.eHandling == RFAL_ERRORHANDLING_EMVCO ) + { + st25r3911SetRegisterBits( ST25R3911_REG_GPT_CONTROL, ST25R3911_REG_GPT_CONTROL_nrt_emv ); + } + else + { + st25r3911ClrRegisterBits( ST25R3911_REG_GPT_CONTROL, ST25R3911_REG_GPT_CONTROL_nrt_emv ); + } + /*******************************************************************************/ + + + + /* In Active comms enable also External Field interrupts */ + if( rfalIsModeActiveComm( gRFAL.mode ) ) + { + maskInterrupts |= ( ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_EON | ST25R3911_IRQ_MASK_CAT | ST25R3911_IRQ_MASK_CAC ); + } + + + /*******************************************************************************/ + /* clear and enable these interrupts */ + st25r3911GetInterrupt( maskInterrupts ); + st25r3911EnableInterrupts( maskInterrupts ); + + /* Clear FIFO status local copy */ + rfalFIFOStatusClear(); +} + +/*******************************************************************************/ +static void rfalTransceiveTx( void ) +{ + volatile uint32_t irqs; + uint16_t tmp; + ReturnCode ret; + + /* Supress warning in case NFC-V feature is disabled */ + ret = ERR_NONE; + NO_WARNING(ret); + + + irqs = ST25R3911_IRQ_MASK_NONE; + + if( gRFAL.TxRx.state != gRFAL.TxRx.lastState ) + { + /* rfalLogD( "RFAL: lastSt: %d curSt: %d \r\n", gRFAL.TxRx.lastState, gRFAL.TxRx.state ); */ + gRFAL.TxRx.lastState = gRFAL.TxRx.state; + } + + switch( gRFAL.TxRx.state ) + { + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_IDLE: + + /* Nothing to do */ + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_WAIT_GT ; + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_GT: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + if( !rfalIsGTExpired() ) + { + break; + } + + gRFAL.tmr.GT = RFAL_TIMING_NONE; + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_WAIT_FDT; + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_FDT: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Only in Passive communications GPT is used to measure FDT Poll */ + if( rfalIsModePassiveComm( gRFAL.mode ) ) + { + if( st25r3911IsGPTRunning() ) + { + break; + } + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_TRANSMIT; + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_TRANSMIT: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Clear FIFO, Clear and Enable the Interrupts */ + rfalPrepareTransceive( ); + + /* Calculate when Water Level Interrupt will be triggered */ + gRFAL.fifo.expWL = (uint16_t)( st25r3911CheckReg( ST25R3911_REG_IO_CONF1, ST25R3911_REG_IO_CONF1_fifo_lt, ST25R3911_REG_IO_CONF1_fifo_lt_16bytes) ? RFAL_FIFO_OUT_LT_16 : RFAL_FIFO_OUT_LT_32 ); + + #if RFAL_FEATURE_NFCV + /*******************************************************************************/ + /* In NFC-V streaming mode, the FIFO needs to be loaded with the coded bits */ + if( (RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode) ) + { + #if 0 + /* Debugging code: output the payload bits by writing into the FIFO and subsequent clearing */ + st25r3911WriteFifo(gRFAL.TxRx.ctx.txBuf, rfalConvBitsToBytes(gRFAL.TxRx.ctx.txBufLen)); + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_FIFO ); + #endif + /* Calculate the bytes needed to be Written into FIFO (a incomplete byte will be added as 1byte) */ + gRFAL.nfcvData.nfcvOffset = 0; + ret = iso15693VCDCode(gRFAL.TxRx.ctx.txBuf, rfalConvBitsToBytes(gRFAL.TxRx.ctx.txBufLen), (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL) != 0U)?false:true),(((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL) != 0U)?false:true), (RFAL_MODE_POLL_PICOPASS == gRFAL.mode), + &gRFAL.fifo.bytesTotal, &gRFAL.nfcvData.nfcvOffset, gRFAL.nfcvData.codingBuffer, MIN( (uint16_t)ST25R3911_FIFO_DEPTH, (uint16_t)sizeof(gRFAL.nfcvData.codingBuffer) ), &gRFAL.fifo.bytesWritten); + + if( (ret != ERR_NONE) && (ret != ERR_AGAIN) ) + { + gRFAL.TxRx.status = ret; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + /* Set the number of full bytes and bits to be transmitted */ + st25r3911SetNumTxBits( rfalConvBytesToBits(gRFAL.fifo.bytesTotal) ); + + /* Load FIFO with coded bytes */ + /* TODO: check bytesWritten does not exceed 255 */ + st25r3911WriteFifo( gRFAL.nfcvData.codingBuffer, (uint8_t)gRFAL.fifo.bytesWritten ); + + } + /*******************************************************************************/ + else + #endif /* RFAL_FEATURE_NFCV */ + { + /* Calculate the bytes needed to be Written into FIFO (a incomplete byte will be added as 1byte) */ + gRFAL.fifo.bytesTotal = (uint16_t)rfalCalcNumBytes(gRFAL.TxRx.ctx.txBufLen); + + /* Set the number of full bytes and bits to be transmitted */ + st25r3911SetNumTxBits( gRFAL.TxRx.ctx.txBufLen ); + + /* Load FIFO with total length or FIFO's maximum */ + gRFAL.fifo.bytesWritten = MIN( gRFAL.fifo.bytesTotal, ST25R3911_FIFO_DEPTH ); + st25r3911WriteFifo( gRFAL.TxRx.ctx.txBuf, (uint8_t)gRFAL.fifo.bytesWritten ); + } + + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeTx(); + + /*******************************************************************************/ + /* Trigger/Start transmission */ + if( (gRFAL.TxRx.ctx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL) != 0U ) + { + st25r3911ExecuteCommand( ST25R3911_CMD_TRANSMIT_WITHOUT_CRC ); + } + else + { + st25r3911ExecuteCommand( ST25R3911_CMD_TRANSMIT_WITH_CRC ); + } + + /* Check if a WL level is expected or TXE should come */ + gRFAL.TxRx.state = (( gRFAL.fifo.bytesWritten < gRFAL.fifo.bytesTotal ) ? RFAL_TXRX_STATE_TX_WAIT_WL : RFAL_TXRX_STATE_TX_WAIT_TXE); + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_WL: + + irqs = st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_FWL | ST25R3911_IRQ_MASK_TXE) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + if( ((irqs & ST25R3911_IRQ_MASK_FWL) != 0U) && ((irqs & ST25R3911_IRQ_MASK_TXE) == 0U) ) + { + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_RELOAD_FIFO; + } + else + { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_RELOAD_FIFO: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + #if RFAL_FEATURE_NFCV + /*******************************************************************************/ + /* In NFC-V streaming mode, the FIFO needs to be loaded with the coded bits */ + if( (RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode) ) + { + uint16_t maxLen; + + /* Load FIFO with the remaining length or maximum available (which fit on the coding buffer) */ + maxLen = (uint16_t)MIN( (gRFAL.fifo.bytesTotal - gRFAL.fifo.bytesWritten), gRFAL.fifo.expWL); + maxLen = (uint16_t)MIN( maxLen, sizeof(gRFAL.nfcvData.codingBuffer) ); + tmp = 0; + + /* Calculate the bytes needed to be Written into FIFO (a incomplete byte will be added as 1byte) */ + ret = iso15693VCDCode(gRFAL.TxRx.ctx.txBuf, rfalConvBitsToBytes(gRFAL.TxRx.ctx.txBufLen), (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL) != 0U)?false:true), (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL) != 0U)?false:true), (RFAL_MODE_POLL_PICOPASS == gRFAL.mode), + &gRFAL.fifo.bytesTotal, &gRFAL.nfcvData.nfcvOffset, gRFAL.nfcvData.codingBuffer, maxLen, &tmp); + + if( (ret != ERR_NONE) && (ret != ERR_AGAIN) ) + { + gRFAL.TxRx.status = ret; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + + /* Load FIFO with coded bytes */ + /* TODO: check tmp does not exceed 255 */ + st25r3911WriteFifo( gRFAL.nfcvData.codingBuffer, (uint8_t)tmp ); + } + /*******************************************************************************/ + else + #endif /* RFAL_FEATURE_NFCV */ + { + /* Load FIFO with the remaining length or maximum available */ + tmp = MIN( (gRFAL.fifo.bytesTotal - gRFAL.fifo.bytesWritten), gRFAL.fifo.expWL); /* tmp holds the number of bytes written on this iteration */ + /* TODO: check tmp does not exceed 255 */ + st25r3911WriteFifo( &gRFAL.TxRx.ctx.txBuf[gRFAL.fifo.bytesWritten], (uint8_t)tmp ); + } + + /* Update total written bytes to FIFO */ + gRFAL.fifo.bytesWritten += tmp; + + /* Check if a WL level is expected or TXE should come */ + gRFAL.TxRx.state = (( gRFAL.fifo.bytesWritten < gRFAL.fifo.bytesTotal ) ? RFAL_TXRX_STATE_TX_WAIT_WL : RFAL_TXRX_STATE_TX_WAIT_TXE); + break; + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_TXE: + + irqs = st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_FWL | ST25R3911_IRQ_MASK_TXE) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + + if( (irqs & ST25R3911_IRQ_MASK_TXE) != 0U ) + { + /* In Active comm start SW timer to measure FWT */ + if( rfalIsModeActiveComm( gRFAL.mode) && (gRFAL.TxRx.ctx.fwt != RFAL_FWT_NONE) && (gRFAL.TxRx.ctx.fwt != 0U) ) + { + rfalTimerStart( gRFAL.tmr.FWT, rfalConv1fcToMs( gRFAL.TxRx.ctx.fwt ) ); + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_DONE; + } + else if( (irqs & ST25R3911_IRQ_MASK_FWL) != 0U ) + { + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata #TBD */ + /* ST25R3911 may send a WL even when all bytes have been written to FIFO */ + /*******************************************************************************/ + break; /* Ignore ST25R3911 FIFO WL if total TxLen is already on the FIFO */ + } + else + { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_DONE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* If no rxBuf is provided do not wait/expect Rx */ + if( gRFAL.TxRx.ctx.rxBuf == NULL ) + { + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + gRFAL.TxRx.status = ERR_NONE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + } + + rfalCheckEnableObsModeRx(); + + /* Goto Rx */ + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_FAIL: + + /* Error should be assigned by previous state */ + if( gRFAL.TxRx.status == ERR_BUSY ) + { + gRFAL.TxRx.status = ERR_SYSTEM; + } + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + + /*******************************************************************************/ + default: + gRFAL.TxRx.status = ERR_SYSTEM; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } +} + + +/*******************************************************************************/ +static void rfalTransceiveRx( void ) +{ + volatile uint32_t irqs; + uint8_t tmp; + uint8_t aux; + + irqs = ST25R3911_IRQ_MASK_NONE; + + if( gRFAL.TxRx.state != gRFAL.TxRx.lastState ) + { + /* rfalLogD( "RFAL: lastSt: %d curSt: %d \r\n", gRFAL.TxRx.lastState, gRFAL.TxRx.state ); */ + gRFAL.TxRx.lastState = gRFAL.TxRx.state; + } + + switch( gRFAL.TxRx.state ) + { + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_IDLE: + + /* Clear rx counters */ + gRFAL.fifo.bytesWritten = 0; // Total bytes written on RxBuffer + gRFAL.fifo.bytesTotal = 0; // Total bytes in FIFO will now be from Rx + if( gRFAL.TxRx.ctx.rxRcvdLen != NULL ) + { + *gRFAL.TxRx.ctx.rxRcvdLen = 0; + } + + gRFAL.TxRx.state = ( rfalIsModeActiveComm( gRFAL.mode ) ? RFAL_TXRX_STATE_RX_WAIT_EON : RFAL_TXRX_STATE_RX_WAIT_RXS ); + break; + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_RXS: + + /*******************************************************************************/ + /* If in Active comm, Check if FWT SW timer has expired */ + if( rfalIsModeActiveComm( gRFAL.mode ) && (gRFAL.TxRx.ctx.fwt != RFAL_FWT_NONE) && (gRFAL.TxRx.ctx.fwt != 0U) ) + { + if( rfalTimerisExpired( gRFAL.tmr.FWT ) ) + { + gRFAL.TxRx.status = ERR_TIMEOUT; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + } + + /*******************************************************************************/ + irqs = st25r3911GetInterrupt( ( ST25R3911_IRQ_MASK_RXS | ST25R3911_IRQ_MASK_NRE | ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_RXE) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata #1.7 */ + /* NRE interrupt may be triggered twice */ + /* Ignore NRE if is detected together with no Rx Start */ + /*******************************************************************************/ + + /* Only raise Timeout if NRE is detected with no Rx Start (NRT EMV mode) */ + if( ((irqs & ST25R3911_IRQ_MASK_NRE) != 0U) && ((irqs & ST25R3911_IRQ_MASK_RXS) == 0U) ) + { + gRFAL.TxRx.status = ERR_TIMEOUT; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* Only raise Link Loss if EOF is detected with no Rx Start */ + if( ((irqs & ST25R3911_IRQ_MASK_EOF) != 0U) && ((irqs & ST25R3911_IRQ_MASK_RXS) == 0U) ) + { + /* In AP2P a Field On has already occurred - treat this as timeout | mute */ + gRFAL.TxRx.status = ( rfalIsModeActiveComm( gRFAL.mode ) ? ERR_TIMEOUT : ERR_LINK_LOSS ); + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + if( (irqs & ST25R3911_IRQ_MASK_RXS) != 0U ) + { + /* If we got RXS + RXE together, jump directly into RFAL_TXRX_STATE_RX_ERR_CHECK */ + if( (irqs & ST25R3911_IRQ_MASK_RXE) != 0U ) + { + gRFAL.TxRx.rxse = true; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_ERR_CHECK; + break; + } + else + { + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata #1.1 */ + /* Rarely on corrupted frames I_rxs gets signaled but I_rxe is not signaled */ + /* Use a SW timer to handle an eventual missing RXE */ + rfalTimerStart( gRFAL.tmr.RXE, RFAL_NORXE_TOUT ); + /*******************************************************************************/ + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXE; + } + } + else if( (irqs & ST25R3911_IRQ_MASK_RXE) != 0U ) + { + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata #1.9 */ + /* ST25R3911 may indicate RXE without RXS previously, this happens upon some */ + /* noise or incomplete byte frames with less than 4 bits */ + /*******************************************************************************/ + + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + + rfalErrorHandling(); + break; + } + else + { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_RXE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + irqs = st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_RXE | ST25R3911_IRQ_MASK_FWL | ST25R3911_IRQ_MASK_EOF) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911B Errata #1.1 */ + /* ST25R3911 may indicate RXS without RXE afterwards, this happens rarely on */ + /* corrupted frames. */ + /* SW timer is used to timeout upon a missing RXE */ + if( rfalTimerisExpired( gRFAL.tmr.RXE ) ) + { + gRFAL.TxRx.status = ERR_FRAMING; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + /*******************************************************************************/ + + break; /* No interrupt to process */ + } + + if( ((irqs & ST25R3911_IRQ_MASK_FWL) != 0U) && ((irqs & ST25R3911_IRQ_MASK_RXE) == 0U) ) + { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_FIFO; + break; + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_ERR_CHECK; + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_ERR_CHECK: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Retrieve and check for any error irqs */ + irqs |= st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_CRC | ST25R3911_IRQ_MASK_PAR | ST25R3911_IRQ_MASK_ERR1 | ST25R3911_IRQ_MASK_ERR2 | ST25R3911_IRQ_MASK_COL) ); + + if( (irqs & ST25R3911_IRQ_MASK_ERR1) != 0U ) + { + gRFAL.TxRx.status = ERR_FRAMING; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } + /* Discard Soft Framing errors if not in EMVCo error handling */ + else if( ((irqs & ST25R3911_IRQ_MASK_ERR2) != 0U) && (gRFAL.conf.eHandling == RFAL_ERRORHANDLING_EMVCO) ) + { + gRFAL.TxRx.status = ERR_FRAMING; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } + else if( (irqs & ST25R3911_IRQ_MASK_PAR) != 0U ) + { + gRFAL.TxRx.status = ERR_PAR; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } + else if( (irqs & ST25R3911_IRQ_MASK_CRC) != 0U ) + { + gRFAL.TxRx.status = ERR_CRC; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } + else if( (irqs & ST25R3911_IRQ_MASK_COL) != 0U ) + { + gRFAL.TxRx.status = ERR_RF_COLLISION; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } + else if( ((irqs & ST25R3911_IRQ_MASK_EOF) != 0U) && ((irqs & ST25R3911_IRQ_MASK_RXE) == 0U) ) + { + gRFAL.TxRx.status = ERR_LINK_LOSS; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + else if( ((irqs & ST25R3911_IRQ_MASK_RXE) != 0U) || (gRFAL.TxRx.rxse) ) + { + /* Reception ended without any error indication, * + * check FIFO status for malformed or incomplete frames */ + + /* Check if the reception ends with an incomplete byte (residual bits) */ + if( rfalFIFOStatusIsIncompleteByte() ) + { + gRFAL.TxRx.status = ERR_INCOMPLETE_BYTE; + } + /* Check if the reception ends with missing parity bit */ + else if( rfalFIFOStatusIsMissingPar() ) + { + gRFAL.TxRx.status = ERR_FRAMING; + } + else + { + /* MISRA 15.7 - Empty else */ + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + } + else + { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_READ_DATA: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + tmp = rfalFIFOStatusGetNumBytes(); + + /*******************************************************************************/ + /* Check if CRC should not be placed in rxBuf */ + if( ((gRFAL.TxRx.ctx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP) == 0U) ) + { + /* Check if CRC is being placed into the FIFO and if received frame was bigger than CRC */ + if( st25r3911IsCRCinFIFO() && ((gRFAL.fifo.bytesTotal + tmp) > 0U) ) + { + /* By default CRC will not be placed into the rxBuffer */ + if( ( tmp > (uint8_t)RFAL_CRC_LEN) ) + { + tmp -= (uint8_t)RFAL_CRC_LEN; + } + /* If the CRC was already placed into rxBuffer (due to WL interrupt where CRC was already in FIFO Read) + * cannot remove it from rxBuf. Can only remove it from rxBufLen not indicate the presence of CRC */ + else if(gRFAL.fifo.bytesTotal > (uint16_t)RFAL_CRC_LEN) + { + gRFAL.fifo.bytesTotal -= (uint16_t)RFAL_CRC_LEN; + } + else + { + /* MISRA 15.7 - Empty else */ + } + } + } + + gRFAL.fifo.bytesTotal += tmp; /* add to total bytes counter */ + + /*******************************************************************************/ + /* Check if remaining bytes fit on the rxBuf available */ + if( gRFAL.fifo.bytesTotal > rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen) ) + { + tmp = (uint8_t)( rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen) - gRFAL.fifo.bytesWritten); + + gRFAL.TxRx.status = ERR_NOMEM; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + + /*******************************************************************************/ + /* Retrieve remaining bytes from FIFO to rxBuf, and assign total length rcvd */ + st25r3911ReadFifo( &gRFAL.TxRx.ctx.rxBuf[gRFAL.fifo.bytesWritten], tmp); + if( (gRFAL.TxRx.ctx.rxRcvdLen != NULL) ) + { + (*gRFAL.TxRx.ctx.rxRcvdLen) = (uint16_t)rfalConvBytesToBits( gRFAL.fifo.bytesTotal ); + if( rfalFIFOStatusIsIncompleteByte() ) + { + (*gRFAL.TxRx.ctx.rxRcvdLen) -= (RFAL_BITS_IN_BYTE - rfalFIFOGetNumIncompleteBits()); + } + } + + #if RFAL_FEATURE_NFCV + /*******************************************************************************/ + /* Decode sub bit stream into payload bits for NFCV, if no error found so far */ + if( ((RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode)) && (gRFAL.TxRx.status == ERR_BUSY) ) + { + ReturnCode ret; + uint16_t offset = 0; + + ret = iso15693VICCDecode(gRFAL.TxRx.ctx.rxBuf, gRFAL.fifo.bytesTotal, + gRFAL.nfcvData.origCtx.rxBuf, rfalConvBitsToBytes(gRFAL.nfcvData.origCtx.rxBufLen), &offset, gRFAL.nfcvData.origCtx.rxRcvdLen, gRFAL.nfcvData.ignoreBits, (RFAL_MODE_POLL_PICOPASS == gRFAL.mode) ); + + if( ((ERR_NONE == ret) || (ERR_CRC == ret)) + && (((uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP & gRFAL.nfcvData.origCtx.flags) == 0U) + && ((*gRFAL.nfcvData.origCtx.rxRcvdLen % RFAL_BITS_IN_BYTE) == 0U) + && (*gRFAL.nfcvData.origCtx.rxRcvdLen >= rfalConvBytesToBits(RFAL_CRC_LEN) ) + ) + { + *gRFAL.nfcvData.origCtx.rxRcvdLen -= (uint16_t)rfalConvBytesToBits(RFAL_CRC_LEN); /* Remove CRC */ + } + + /* Restore original ctx */ + gRFAL.TxRx.ctx = gRFAL.nfcvData.origCtx; + gRFAL.TxRx.status = ((ret != ERR_NONE) ? ret : ERR_BUSY); + } + #endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + /* If an error as been marked/detected don't fall into to RX_DONE */ + if( gRFAL.TxRx.status != ERR_BUSY ) + { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + if( rfalIsModeActiveComm( gRFAL.mode ) ) + { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_EOF; + break; + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_DONE; + /* fall through */ + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_DONE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + + gRFAL.TxRx.status = ERR_NONE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_READ_FIFO: + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911B Errata #1.1 */ + /* ST25R3911 may indicate RXS without RXE afterwards, this happens rarely on */ + /* corrupted frames. */ + /* Re-Start SW timer to handle an eventual missing RXE */ + rfalTimerStart( gRFAL.tmr.RXE, RFAL_NORXE_TOUT ); + /*******************************************************************************/ + + + tmp = rfalFIFOStatusGetNumBytes(); + gRFAL.fifo.bytesTotal += tmp; + + /*******************************************************************************/ + /* Calculate the amount of bytes that still fits in rxBuf */ + aux = (uint8_t)(( gRFAL.fifo.bytesTotal > rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen) ) ? (rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen) - gRFAL.fifo.bytesWritten) : tmp); + + /*******************************************************************************/ + /* Retrieve incoming bytes from FIFO to rxBuf, and store already read amount */ + st25r3911ReadFifo( &gRFAL.TxRx.ctx.rxBuf[gRFAL.fifo.bytesWritten], aux); + gRFAL.fifo.bytesWritten += aux; + + /*******************************************************************************/ + /* If the bytes already read were not the full FIFO WL, dump the remaining * + * FIFO so that ST25R391x can continue with reception */ + if( aux < tmp ) + { + st25r3911ReadFifo( NULL, (tmp - aux) ); + } + + rfalFIFOStatusClear(); + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXE; + break; + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_FAIL: + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + /* Error should be assigned by previous state */ + if( gRFAL.TxRx.status == ERR_BUSY ) + { + gRFAL.TxRx.status = ERR_SYSTEM; + } + + /*rfalLogD( "RFAL: curSt: %d Error: %d \r\n", gRFAL.TxRx.state, gRFAL.TxRx.status );*/ + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_EON: + + irqs = st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_EON | ST25R3911_IRQ_MASK_NRE) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + if( (irqs & ST25R3911_IRQ_MASK_EON) != 0U ) + { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXS; + } + + if( (irqs & ST25R3911_IRQ_MASK_NRE) != 0U ) + { + /* ST25R3911 uses the NRT to measure other device's Field On max time: Tadt + (n x Trfw) */ + gRFAL.TxRx.status = ERR_LINK_LOSS; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + break; + + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_EOF: + + irqs = st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_CAT | ST25R3911_IRQ_MASK_CAC) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + if( (irqs & ST25R3911_IRQ_MASK_CAT) != 0U ) + { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_DONE; + } + else if( (irqs & ST25R3911_IRQ_MASK_CAC) != 0U ) + { + gRFAL.TxRx.status = ERR_RF_COLLISION; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + else + { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + break; + + + /*******************************************************************************/ + default: + gRFAL.TxRx.status = ERR_SYSTEM; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } +} + +/*******************************************************************************/ +static void rfalFIFOStatusUpdate( void ) +{ + if(gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] == RFAL_FIFO_STATUS_INVALID) + { + st25r3911ReadMultipleRegisters( ST25R3911_REG_FIFO_RX_STATUS1, gRFAL.fifo.status, ST25R3911_FIFO_STATUS_LEN ); + } +} + + +/*******************************************************************************/ +static void rfalFIFOStatusClear( void ) +{ + gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] = RFAL_FIFO_STATUS_INVALID; +} + + +/*******************************************************************************/ +static uint8_t rfalFIFOStatusGetNumBytes( void ) +{ + rfalFIFOStatusUpdate(); + + return gRFAL.fifo.status[RFAL_FIFO_STATUS_REG1]; + +} + + +/*******************************************************************************/ +static bool rfalFIFOStatusIsIncompleteByte( void ) +{ + rfalFIFOStatusUpdate(); + return ((gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & (ST25R3911_REG_FIFO_RX_STATUS2_mask_fifo_lb | ST25R3911_REG_FIFO_RX_STATUS2_fifo_ncp)) != 0U); +} + + +/*******************************************************************************/ +static bool rfalFIFOStatusIsMissingPar( void ) +{ + rfalFIFOStatusUpdate(); + return ((gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & ST25R3911_REG_FIFO_RX_STATUS2_np_lb) != 0U); +} + + +/*******************************************************************************/ +static uint8_t rfalFIFOGetNumIncompleteBits( void ) +{ + rfalFIFOStatusUpdate(); + return ((gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & ST25R3911_REG_FIFO_RX_STATUS2_mask_fifo_lb) >> ST25R3911_REG_FIFO_RX_STATUS2_shift_fifo_lb); +} + + +#if RFAL_FEATURE_NFCA + +/*******************************************************************************/ +ReturnCode rfalISO14443ATransceiveShortFrame( rfal14443AShortFrameCmd txCmd, uint8_t* rxBuf, uint8_t rxBufLen, uint16_t* rxRcvdLen, uint32_t fwt ) +{ + ReturnCode ret; + uint8_t directCmd; + + /* Check if RFAL is properly initialized */ + if( !st25r3911IsTxEnabled() || (gRFAL.state < RFAL_STATE_MODE_SET) || (( gRFAL.mode != RFAL_MODE_POLL_NFCA ) && ( gRFAL.mode != RFAL_MODE_POLL_NFCA_T1T )) ) + { + return ERR_WRONG_STATE; + } + + /* Check for valid parameters */ + if( (rxBuf == NULL) || (rxRcvdLen == NULL) || (fwt == RFAL_FWT_NONE) ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Select the Direct Command to be performed */ + switch (txCmd) + { + case RFAL_14443A_SHORTFRAME_CMD_WUPA: + directCmd = ST25R3911_CMD_TRANSMIT_WUPA; + break; + + case RFAL_14443A_SHORTFRAME_CMD_REQA: + directCmd = ST25R3911_CMD_TRANSMIT_REQA; + break; + + default: + return ERR_PARAM; + } + + + /*******************************************************************************/ + /* Enable anti collision to recognise collision in first byte of SENS_REQ */ + st25r3911SetRegisterBits( ST25R3911_REG_ISO14443A_NFC, ST25R3911_REG_ISO14443A_NFC_antcl); + + /* Disable CRC while receiving since ATQA has no CRC included */ + st25r3911SetRegisterBits( ST25R3911_REG_AUX, ST25R3911_REG_AUX_no_crc_rx ); + + + /*******************************************************************************/ + /* Wait for GT and FDT */ + while( !rfalIsGTExpired() ) { /* MISRA 15.6: mandatory brackets */ }; + while( st25r3911IsGPTRunning() ) { /* MISRA 15.6: mandatory brackets */ }; + + gRFAL.tmr.GT = RFAL_TIMING_NONE; + + + /*******************************************************************************/ + /* Prepare for Transceive, Receive only (bypass Tx states) */ + gRFAL.TxRx.ctx.flags = ((uint32_t) RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP ); + gRFAL.TxRx.ctx.rxBuf = rxBuf; + gRFAL.TxRx.ctx.rxBufLen = rxBufLen; + gRFAL.TxRx.ctx.rxRcvdLen = rxRcvdLen; + + /*******************************************************************************/ + /* Load NRT with FWT */ + st25r3911SetNoResponseTime_64fcs( rfalConv1fcTo64fc( MIN( (fwt + RFAL_FWT_ADJUSTMENT + RFAL_FWT_A_ADJUSTMENT), RFAL_ST25R3911_NRT_MAX_1FC ) ) ); + + if( gRFAL.timings.FDTListen != RFAL_TIMING_NONE ) + { + /* Set Minimum FDT(Listen) in which PICC is not allowed to send a response */ + st25r3911WriteRegister( ST25R3911_REG_MASK_RX_TIMER, (uint8_t)rfalConv1fcTo64fc( ((RFAL_FDT_LISTEN_MRT_ADJUSTMENT + RFAL_FDT_LISTEN_A_ADJUSTMENT) > gRFAL.timings.FDTListen) ? RFAL_ST25R3911_MRT_MIN_1FC : (gRFAL.timings.FDTListen - (RFAL_FDT_LISTEN_MRT_ADJUSTMENT + RFAL_FDT_LISTEN_A_ADJUSTMENT)) ) ); + } + + /* In Passive communications General Purpose Timer is used to measure FDT Poll */ + if( gRFAL.timings.FDTPoll != RFAL_TIMING_NONE ) + { + /* Configure GPT to start at RX end */ + st25r3911StartGPTimer_8fcs( (uint16_t)rfalConv1fcTo8fc( MIN( gRFAL.timings.FDTPoll, (gRFAL.timings.FDTPoll - RFAL_FDT_POLL_ADJUSTMENT) ) ), ST25R3911_REG_GPT_CONTROL_gptc_erx ); + } + + /*******************************************************************************/ + rfalPrepareTransceive(); + + /* Also enable bit collision interrupt */ + st25r3911GetInterrupt( ST25R3911_IRQ_MASK_COL ); + st25r3911EnableInterrupts( ST25R3911_IRQ_MASK_COL ); + + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeTx(); + + /*******************************************************************************/ + /* Chip bug: Clear nbtx bits before sending WUPA/REQA - otherwise ST25R3911 will report parity error */ + st25r3911WriteRegister( ST25R3911_REG_NUM_TX_BYTES2, 0); + + /* Send either WUPA or REQA. All affected tags will backscatter ATQA and change to READY state */ + st25r3911ExecuteCommand( directCmd ); + + /* Wait for TXE */ + if( st25r3911WaitForInterruptsTimed( ST25R3911_IRQ_MASK_TXE, (uint16_t)MAX( rfalConv1fcToMs( fwt ), RFAL_ST25R3911_SW_TMR_MIN_1MS ) ) == 0U) + { + ret = ERR_IO; + } + else + { + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeRx(); + + /* Jump into a transceive Rx state for reception (bypass Tx states) */ + gRFAL.state = RFAL_STATE_TXRX; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + gRFAL.TxRx.status = ERR_BUSY; + + /* Execute Transceive Rx blocking */ + ret = rfalTransceiveBlockingRx(); + } + + + /* Disable Collision interrupt */ + st25r3911DisableInterrupts( (ST25R3911_IRQ_MASK_COL) ); + + /* Disable anti collision again */ + st25r3911ClrRegisterBits( ST25R3911_REG_ISO14443A_NFC, ST25R3911_REG_ISO14443A_NFC_antcl ); + + /* ReEnable CRC on Rx */ + st25r3911ClrRegisterBits(ST25R3911_REG_AUX, ST25R3911_REG_AUX_no_crc_rx ); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalISO14443ATransceiveAnticollisionFrame( uint8_t *buf, uint8_t *bytesToSend, uint8_t *bitsToSend, uint16_t *rxLength, uint32_t fwt ) +{ + ReturnCode ret; + rfalTransceiveContext ctx; + uint8_t collByte; + uint8_t collData; + + /* Check if RFAL is properly initialized */ + if( (gRFAL.state < RFAL_STATE_MODE_SET) || ( gRFAL.mode != RFAL_MODE_POLL_NFCA ) ) + { + return ERR_WRONG_STATE; + } + + /* Check for valid parameters */ + if( (buf == NULL) || (bytesToSend == NULL) || (bitsToSend == NULL) || (rxLength == NULL) ) + { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Set speficic Analog Config for Anticolission if needed */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL) ); + + + /*******************************************************************************/ + /* Enable anti collision to recognise collision in first byte of SENS_REQ */ + st25r3911SetRegisterBits( ST25R3911_REG_ISO14443A_NFC, ST25R3911_REG_ISO14443A_NFC_antcl ); + + /* Disable CRC while receiving */ + st25r3911SetRegisterBits( ST25R3911_REG_AUX, ST25R3911_REG_AUX_no_crc_rx ); + + + + /*******************************************************************************/ + /* Prepare for Transceive */ + ctx.flags = ( (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_AGC_OFF ); /* Disable Automatic Gain Control (AGC) for better detection of collision */ + ctx.txBuf = buf; + ctx.txBufLen = (uint16_t)(rfalConvBytesToBits( *bytesToSend ) + *bitsToSend ); + ctx.rxBuf = &buf[*bytesToSend]; + ctx.rxBufLen = (uint16_t)rfalConvBytesToBits( RFAL_ISO14443A_SDD_RES_LEN ); + ctx.rxRcvdLen = rxLength; + ctx.fwt = fwt; + + rfalStartTransceive( &ctx ); + + /* Additionally enable bit collision interrupt */ + st25r3911GetInterrupt( ST25R3911_IRQ_MASK_COL ); + st25r3911EnableInterrupts( ST25R3911_IRQ_MASK_COL ); + + /*******************************************************************************/ + collByte = 0; + + /* save the collision byte */ + if ((*bitsToSend) > 0U) + { + buf[(*bytesToSend)] <<= (RFAL_BITS_IN_BYTE - (*bitsToSend)); + buf[(*bytesToSend)] >>= (RFAL_BITS_IN_BYTE - (*bitsToSend)); + collByte = buf[(*bytesToSend)]; + } + + + /*******************************************************************************/ + /* Run Transceive blocking */ + ret = rfalTransceiveRunBlockingTx(); + if( ret == ERR_NONE) + { + ret = rfalTransceiveBlockingRx(); + + /*******************************************************************************/ + if ((*bitsToSend) > 0U) + { + buf[(*bytesToSend)] >>= (*bitsToSend); + buf[(*bytesToSend)] <<= (*bitsToSend); + buf[(*bytesToSend)] |= collByte; + } + + if( (ERR_RF_COLLISION == ret) ) + { + /* read out collision register */ + st25r3911ReadRegister( ST25R3911_REG_COLLISION_STATUS, &collData); + + (*bytesToSend) = ((collData >> ST25R3911_REG_COLLISION_STATUS_shift_c_byte) & 0x0FU); // 4-bits Byte information + (*bitsToSend) = ((collData >> ST25R3911_REG_COLLISION_STATUS_shift_c_bit) & 0x07U); // 3-bits bit information + + } + } + + + /*******************************************************************************/ + /* Disable Collision interrupt */ + st25r3911DisableInterrupts( (ST25R3911_IRQ_MASK_COL) ); + + /* Disable anti collision again */ + st25r3911ClrRegisterBits( ST25R3911_REG_ISO14443A_NFC, ST25R3911_REG_ISO14443A_NFC_antcl ); + + /* ReEnable CRC on Rx */ + st25r3911ClrRegisterBits( ST25R3911_REG_AUX, ST25R3911_REG_AUX_no_crc_rx ); + /*******************************************************************************/ + + + /* Restore common Analog configurations for this mode */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX) ); + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX) ); + + return ret; +} + +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCV + +/*******************************************************************************/ +ReturnCode rfalISO15693TransceiveAnticollisionFrame( uint8_t *txBuf, uint8_t txBufLen, uint8_t *rxBuf, uint8_t rxBufLen, uint16_t *actLen ) +{ + ReturnCode ret; + rfalTransceiveContext ctx; + + /* Check if RFAL is properly initialized */ + if( (gRFAL.state < RFAL_STATE_MODE_SET) || ( gRFAL.mode != RFAL_MODE_POLL_NFCV ) ) + { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Set speficic Analog Config for Anticolission if needed */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL) ); + + + /* Ignoring collisions before the UID (RES_FLAG + DSFID) */ + gRFAL.nfcvData.ignoreBits = (uint16_t)RFAL_ISO15693_IGNORE_BITS; + + /*******************************************************************************/ + /* Prepare for Transceive */ + ctx.flags = ((txBufLen==0U)?(uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL:(uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO) | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_AGC_OFF | ((txBufLen==0U)?(uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL:(uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO); /* Disable Automatic Gain Control (AGC) for better detection of collision */ + ctx.txBuf = txBuf; + ctx.txBufLen = (uint16_t)rfalConvBytesToBits(txBufLen); + ctx.rxBuf = rxBuf; + ctx.rxBufLen = (uint16_t)rfalConvBytesToBits(rxBufLen); + ctx.rxRcvdLen = actLen; + ctx.fwt = rfalConv64fcTo1fc(ISO15693_FWT); + + rfalStartTransceive( &ctx ); + + /*******************************************************************************/ + /* Run Transceive blocking */ + ret = rfalTransceiveRunBlockingTx(); + if( ret == ERR_NONE) + { + ret = rfalTransceiveBlockingRx(); + } + + /* Restore common Analog configurations for this mode */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX) ); + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX) ); + + gRFAL.nfcvData.ignoreBits = 0; + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalISO15693TransceiveEOFAnticollision( uint8_t *rxBuf, uint8_t rxBufLen, uint16_t *actLen ) +{ + uint8_t dummy; + + return rfalISO15693TransceiveAnticollisionFrame( &dummy, 0, rxBuf, rxBufLen, actLen ); +} + +/*******************************************************************************/ +ReturnCode rfalISO15693TransceiveEOF( uint8_t *rxBuf, uint8_t rxBufLen, uint16_t *actLen ) +{ + ReturnCode ret; + uint8_t dummy; + + /* Check if RFAL is properly initialized */ + if( ( gRFAL.state < RFAL_STATE_MODE_SET ) || ( gRFAL.mode != RFAL_MODE_POLL_NFCV ) ) + { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Run Transceive blocking */ + ret = rfalTransceiveBlockingTxRx( &dummy, + 0, + rxBuf, + rxBufLen, + actLen, + ( (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP |(uint32_t)RFAL_TXRX_FLAGS_AGC_ON ), + rfalConv64fcTo1fc(ISO15693_FWT) ); + return ret; +} + +#endif /* RFAL_FEATURE_NFCV */ + +#if RFAL_FEATURE_NFCF + +/*******************************************************************************/ +ReturnCode rfalFeliCaPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes* pollResList, uint8_t pollResListSize, uint8_t *devicesDetected, uint8_t *collisionsDetected ) +{ + ReturnCode ret; + uint8_t frame[RFAL_FELICA_POLL_REQ_LEN - RFAL_FELICA_LEN_LEN]; // LEN is added by ST25R3911 automatically + uint16_t actLen; + uint8_t frameIdx; + uint8_t devDetected; + uint8_t colDetected; + rfalEHandling curHandling; + uint8_t nbSlots; + + /* Check if RFAL is properly initialized */ + if( (gRFAL.state < RFAL_STATE_MODE_SET) || ( gRFAL.mode != RFAL_MODE_POLL_NFCF ) ) + { + return ERR_WRONG_STATE; + } + + frameIdx = 0; + colDetected = 0; + devDetected = 0; + nbSlots = (uint8_t)slots; + + /*******************************************************************************/ + /* Compute SENSF_REQ frame */ + frame[frameIdx++] = (uint8_t)FELICA_CMD_POLLING; /* CMD: SENF_REQ */ + frame[frameIdx++] = (uint8_t)(sysCode >> 8); /* System Code (SC) */ + frame[frameIdx++] = (uint8_t)(sysCode & 0xFFU); /* System Code (SC) */ + frame[frameIdx++] = reqCode; /* Communication Parameter Request (RC)*/ + frame[frameIdx++] = nbSlots; /* TimeSlot (TSN) */ + + + /*******************************************************************************/ + /* NRT should not stop on reception - Use EMVCo mode to run NRT in nrt_emv * + * ERRORHANDLING_EMVCO has no special handling for NFC-F mode */ + curHandling = gRFAL.conf.eHandling; + rfalSetErrorHandling( RFAL_ERRORHANDLING_EMVCO ); + + /*******************************************************************************/ + /* Run transceive blocking, + * Calculate Total Response Time in(64/fc): + * 512 PICC process time + (n * 256 Time Slot duration) */ + ret = rfalTransceiveBlockingTx( frame, + (uint16_t)frameIdx, + (uint8_t*)gRFAL.nfcfData.pollResponses, + RFAL_FELICA_POLL_RES_LEN, + &actLen, + (RFAL_TXRX_FLAGS_DEFAULT), + rfalConv64fcTo1fc( RFAL_FELICA_POLL_DELAY_TIME + (RFAL_FELICA_POLL_SLOT_TIME * ((uint32_t)nbSlots + 1U)) ) ); + + /*******************************************************************************/ + /* If Tx OK, Wait for all responses, store them as soon as they appear */ + if( ret == ERR_NONE ) + { + bool timeout; + + do + { + ret = rfalTransceiveBlockingRx(); + if( ret == ERR_TIMEOUT ) + { + /* Upon timeout the full Poll Delay + (Slot time)*(nbSlots) has expired */ + timeout = true; + } + else + { + /* Reception done, reEnabled Rx for following Slot */ + st25r3911ExecuteCommand( ST25R3911_CMD_UNMASK_RECEIVE_DATA ); + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_SQUELCH ); + + /* If the reception was OK, new device found */ + if( ret == ERR_NONE ) + { + devDetected++; + + /* Overwrite the Transceive context for the next reception */ + gRFAL.TxRx.ctx.rxBuf = (uint8_t*)gRFAL.nfcfData.pollResponses[devDetected]; + } + /* If the reception was not OK, mark as collision */ + else + { + colDetected++; + } + + /* Check whether NRT has expired meanwhile */ + timeout = st25r3911CheckReg( ST25R3911_REG_REGULATOR_RESULT, ST25R3911_REG_REGULATOR_RESULT_nrt_on, 0x00 ); + if( !timeout ) + { + /* Jump again into transceive Rx state for the following reception */ + gRFAL.TxRx.status = ERR_BUSY; + gRFAL.state = RFAL_STATE_TXRX; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + } + } + }while( ((nbSlots--) != 0U) && !timeout ); + } + + /*******************************************************************************/ + /* Restore NRT to normal mode - back to previous error handling */ + rfalSetErrorHandling( curHandling ); + + /*******************************************************************************/ + /* Assign output parameters if requested */ + + if( (pollResList != NULL) && (pollResListSize > 0U) && (devDetected > 0U) ) + { + ST_MEMCPY( pollResList, gRFAL.nfcfData.pollResponses, (RFAL_FELICA_POLL_RES_LEN * (uint32_t)MIN(pollResListSize, devDetected) ) ); + } + + if( devicesDetected != NULL ) + { + *devicesDetected = devDetected; + } + + if( collisionsDetected != NULL ) + { + *collisionsDetected = colDetected; + } + + return (( (colDetected != 0U) || (devDetected != 0U)) ? ERR_NONE : ret); +} + +#endif /* RFAL_FEATURE_NFCF */ + + +/***************************************************************************** + * Listen Mode * + *****************************************************************************/ + + + +/*******************************************************************************/ +bool rfalIsExtFieldOn( void ) +{ + return st25r3911IsExtFieldOn(); +} + +#if RFAL_FEATURE_LISTEN_MODE + +/*******************************************************************************/ +ReturnCode rfalListenStart( uint32_t lmMask, const rfalLmConfPA *confA, const rfalLmConfPB *confB, const rfalLmConfPF *confF, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rxLen ) +{ + NO_WARNING(confA); + NO_WARNING(confB); + NO_WARNING(confF); + + + gRFAL.Lm.state = RFAL_LM_STATE_NOT_INIT; + + + /*******************************************************************************/ + if( ((lmMask & RFAL_LM_MASK_NFCA) != 0U) || ((lmMask & RFAL_LM_MASK_NFCB) != 0U) || ((lmMask & RFAL_LM_MASK_NFCF) != 0U) ) + { + return ERR_NOTSUPP; + } + + + /*******************************************************************************/ + if( (lmMask & RFAL_LM_MASK_ACTIVE_P2P) != 0U ) + { + gRFAL.state = RFAL_STATE_LM; + + gRFAL.Lm.rxBuf = rxBuf; + gRFAL.Lm.rxBufLen = rxBufLen; + gRFAL.Lm.rxLen = rxLen; + *gRFAL.Lm.rxLen = 0; + gRFAL.Lm.dataFlag = false; + + /* Disable GPT trigger source */ + st25r3911ChangeRegisterBits( ST25R3911_REG_GPT_CONTROL, ST25R3911_REG_GPT_CONTROL_gptc_mask, ST25R3911_REG_GPT_CONTROL_gptc_no_trigger ); + + /* On Bit Rate Detection Mode ST25R391x will filter incoming frames during MRT time starting on External Field On event, use 512/fc steps */ + st25r3911WriteRegister( ST25R3911_REG_MASK_RX_TIMER, (uint8_t)rfalConv1fcTo512fc( RFAL_LM_GT ) ); + + /* Restore default settings on NFCIP1 mode, Receiving parity + CRC bits and manual Tx Parity*/ + st25r3911ClrRegisterBits( ST25R3911_REG_ISO14443A_NFC, (ST25R3911_REG_ISO14443A_NFC_no_tx_par | ST25R3911_REG_ISO14443A_NFC_no_rx_par | ST25R3911_REG_ISO14443A_NFC_nfc_f0) ); + + /* Enable External Field Detector */ + st25r3911SetRegisterBits( ST25R3911_REG_AUX, ST25R3911_REG_AUX_en_fd ); + + /* Enable Receiver */ + st25r3911ChangeRegisterBits( ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_rx_en, ST25R3911_REG_OP_CONTROL_rx_en ); + + /* Set Analog configurations for generic Listen mode */ + /* Not on SetState(POWER OFF) as otherwise would be applied on every Field Event */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON) ); + + /* Initialize as POWER_OFF and set proper mode in RF Chip */ + rfalListenSetState( RFAL_LM_STATE_POWER_OFF ); + } + else + { + return ERR_REQUEST; /* Listen Start called but no mode was enabled */ + } + + return ERR_NONE; +} + + + +/*******************************************************************************/ +static ReturnCode rfalRunListenModeWorker( void ) +{ + volatile uint32_t irqs; + uint8_t tmp; + + if( gRFAL.state != RFAL_STATE_LM ) + { + return ERR_WRONG_STATE; + } + + switch( gRFAL.Lm.state ) + { + /*******************************************************************************/ + case RFAL_LM_STATE_POWER_OFF: + + irqs = st25r3911GetInterrupt( ( ST25R3911_IRQ_MASK_EON ) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + if( (irqs & ST25R3911_IRQ_MASK_EON) != 0U ) + { + rfalListenSetState( RFAL_LM_STATE_IDLE ); + } + else + { + break; + } + /* fall through */ + + + /*******************************************************************************/ + case RFAL_LM_STATE_IDLE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + irqs = st25r3911GetInterrupt( ( ST25R3911_IRQ_MASK_NFCT | ST25R3911_IRQ_MASK_RXE | ST25R3911_IRQ_MASK_EOF ) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + if( (irqs & ST25R3911_IRQ_MASK_NFCT) != 0U ) + { + /* Retrieve detected bitrate */ + uint8_t newBr; + st25r3911ReadRegister( ST25R3911_REG_NFCIP1_BIT_RATE, &newBr ); + newBr >>= ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate_shift; + + if (newBr > ST25R3911_REG_BIT_RATE_rxrate_424) + { + newBr = ST25R3911_REG_BIT_RATE_rxrate_424; + } + + gRFAL.Lm.brDetected = (rfalBitRate)(newBr); /* PRQA S 4342 # MISRA 10.5 - Guaranteed that no invalid enum values may be created. See also equalityGuard_RFAL_BR_106 ff.*/ + } + if( ((irqs & ST25R3911_IRQ_MASK_RXE) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP) ) + { + irqs = st25r3911GetInterrupt( ( ST25R3911_IRQ_MASK_RXE | ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_CRC | ST25R3911_IRQ_MASK_PAR | ST25R3911_IRQ_MASK_ERR2 | ST25R3911_IRQ_MASK_ERR1 ) ); + + if( ((irqs & ST25R3911_IRQ_MASK_CRC) != 0U) || ((irqs & ST25R3911_IRQ_MASK_PAR) != 0U) || ((irqs & ST25R3911_IRQ_MASK_ERR1) != 0U) ) + { + /* nfc_ar may have triggered RF Collision Avoidance, disable it before executing Clear (Stop All activities) */ + st25r3911ClrRegisterBits( ST25R3911_REG_MODE, ST25R3911_REG_MODE_nfc_ar ); + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_FIFO ); + st25r3911ExecuteCommand( ST25R3911_CMD_UNMASK_RECEIVE_DATA ); + st25r3911SetRegisterBits( ST25R3911_REG_MODE, ST25R3911_REG_MODE_nfc_ar ); + st25r3911TxOff(); + break; /* A bad reception occurred, remain in same state */ + } + + /* Retrieve received data */ + st25r3911ReadRegister(ST25R3911_REG_FIFO_RX_STATUS1, &tmp); + *gRFAL.Lm.rxLen = tmp; + + st25r3911ReadFifo( gRFAL.Lm.rxBuf, (uint8_t)MIN( *gRFAL.Lm.rxLen, rfalConvBitsToBytes(gRFAL.Lm.rxBufLen) ) ); + + /* Check if the data we got has at least the CRC and remove it, otherwise leave at 0 */ + *gRFAL.Lm.rxLen -= ((*gRFAL.Lm.rxLen > RFAL_CRC_LEN) ? RFAL_CRC_LEN : *gRFAL.Lm.rxLen); + *gRFAL.Lm.rxLen = (uint16_t)rfalConvBytesToBits( *gRFAL.Lm.rxLen ); + gRFAL.Lm.dataFlag = true; + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + } + else if( ((irqs & ST25R3911_IRQ_MASK_EOF) != 0U) && (!gRFAL.Lm.dataFlag) ) + { + rfalListenSetState( RFAL_LM_STATE_POWER_OFF ); + } + else + { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_F: + case RFAL_LM_STATE_READY_A: + case RFAL_LM_STATE_ACTIVE_A: + case RFAL_LM_STATE_ACTIVE_Ax: + case RFAL_LM_STATE_SLEEP_A: + case RFAL_LM_STATE_SLEEP_B: + case RFAL_LM_STATE_SLEEP_AF: + case RFAL_LM_STATE_READY_Ax: + case RFAL_LM_STATE_CARDEMU_4A: + case RFAL_LM_STATE_CARDEMU_4B: + case RFAL_LM_STATE_CARDEMU_3: + return ERR_INTERNAL; + + case RFAL_LM_STATE_TARGET_F: + case RFAL_LM_STATE_TARGET_A: + break; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalListenStop( void ) +{ + gRFAL.Lm.state = RFAL_LM_STATE_NOT_INIT; + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Disable Receiver and Transmitter */ + rfalFieldOff(); + + /* As there's no Off mode, set default value: ISO14443A with automatic RF Collision Avoidance Off */ + st25r3911WriteRegister( ST25R3911_REG_MODE, (ST25R3911_REG_MODE_om_iso14443a | ST25R3911_REG_MODE_nfc_ar_off) ); + + /* Set Analog configurations for Listen Off event */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_OFF) ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +/* PRQA S 3673 1 # MISRA 8.13 - ST25R3911B does not support Listen mode. Implementation for other chips will modify rxBuf and rxLen */ +ReturnCode rfalListenSleepStart( rfalLmState sleepSt, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rxLen ) +{ + NO_WARNING(sleepSt); + NO_WARNING(rxBuf); + NO_WARNING(rxBufLen); + NO_WARNING(rxLen); + + return ERR_NOTSUPP; +} + + +/*******************************************************************************/ +rfalLmState rfalListenGetState( bool *dataFlag, rfalBitRate *lastBR ) +{ + /* Allow state retrieval even if gRFAL.state != RFAL_STATE_LM so * + * that this Lm state can be used by caller after activation */ + + if( lastBR != NULL ) + { + *lastBR = gRFAL.Lm.brDetected; + } + + if( dataFlag != NULL ) + { + *dataFlag = gRFAL.Lm.dataFlag; + } + + return gRFAL.Lm.state; +} + + +/*******************************************************************************/ +ReturnCode rfalListenSetState( rfalLmState newSt ) +{ + ReturnCode ret; + uint8_t tmp; + rfalLmState newState; + bool reSetState; + + /*rfalLogD( "RFAL: curState: %02X newState: %02X \r\n", gRFAL.Lm.state, newSt );*/ + + /* SetState clears the Data flag */ + gRFAL.Lm.dataFlag = false; + newState = newSt; + ret = ERR_NONE; + + do{ + reSetState = false; + + /*******************************************************************************/ + switch( newState ) + { + /*******************************************************************************/ + case RFAL_LM_STATE_POWER_OFF: + + /*******************************************************************************/ + /* Disable nfc_ar as RF Collision Avoidance timer may have already started */ + st25r3911ClrRegisterBits( ST25R3911_REG_MODE, ST25R3911_REG_MODE_nfc_ar ); + + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_FIFO ); + + /* Ensure that our field is Off, as automatic response RF Collision Avoidance may have been triggered */ + st25r3911TxOff(); + + /*******************************************************************************/ + /* Ensure that the NFCIP1 mode is disabled */ + st25r3911ClrRegisterBits( ST25R3911_REG_ISO14443A_NFC, ST25R3911_REG_ISO14443A_NFC_nfc_f0 ); + + + /*******************************************************************************/ + /* Clear and enable required IRQs */ + st25r3911DisableInterrupts( ST25R3911_IRQ_MASK_ALL ); + + + st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_NFCT | ST25R3911_IRQ_MASK_RXS | ST25R3911_IRQ_MASK_CRC | ST25R3911_IRQ_MASK_ERR1 | + ST25R3911_IRQ_MASK_ERR2 | ST25R3911_IRQ_MASK_PAR | ST25R3911_IRQ_MASK_EON | ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_RXE ) ); + + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata TDB */ + /* RXS and NFCT are triggered very close (specially in higher bitrates). * + * If the interrupt status register is being read when NFCT is trigerred, the * + * IRQ line might go low and NFCT is not signalled on the status register. * + * For initial bitrate detection, mask RXS, only wait for NFCT and RXE. */ + /*******************************************************************************/ + + st25r3911EnableInterrupts( (ST25R3911_IRQ_MASK_NFCT | ST25R3911_IRQ_MASK_CRC | ST25R3911_IRQ_MASK_ERR1 | + ST25R3911_IRQ_MASK_ERR2 | ST25R3911_IRQ_MASK_PAR | ST25R3911_IRQ_MASK_EON | ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_RXE ) ); + + /*******************************************************************************/ + /* Clear the bitRate previously detected */ + gRFAL.Lm.brDetected = RFAL_BR_KEEP; + + + /*******************************************************************************/ + /* Apply the BitRate detection mode mode */ + st25r3911WriteRegister( ST25R3911_REG_MODE, (ST25R3911_REG_MODE_targ_targ | ST25R3911_REG_MODE_om_bit_rate_detection | ST25R3911_REG_MODE_nfc_ar_on) ); + + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata #1.3 */ + /* Even though bitrate is going to be detected the bitrate must be set to * + * 106kbps to get correct 106kbps parity */ + st25r3911WriteRegister( ST25R3911_REG_BIT_RATE, (ST25R3911_REG_BIT_RATE_txrate_106 | ST25R3911_REG_BIT_RATE_rxrate_106) ); + /*******************************************************************************/ + + + /*******************************************************************************/ + /* Check if external Field is already On */ + if( rfalIsExtFieldOn() ) + { + reSetState = true; + newState = RFAL_LM_STATE_IDLE; /* Set IDLE state */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_IDLE: + + /*******************************************************************************/ + /* In Active P2P the Initiator may: Turn its field On; LM goes into IDLE state; + * Initiator sends an unexpected frame raising a Protocol error; Initiator + * turns its field Off and ST25R3911 performs the automatic RF Collision + * Avoidance keeping our field On; upon a Protocol error upper layer sets + * again the state to IDLE to clear dataFlag and wait for next data. + * + * Ensure that when upper layer calls SetState(IDLE), it restores initial + * configuration and that check whether an external Field is still present */ + + /* nfc_ar may have triggered RF Collision Avoidance, disable it before executing Clear (Stop All activities) */ + st25r3911ClrRegisterBits( ST25R3911_REG_MODE, ST25R3911_REG_MODE_nfc_ar ); + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_FIFO ); + st25r3911SetRegisterBits( ST25R3911_REG_MODE, ST25R3911_REG_MODE_nfc_ar ); + + /* Ensure that our field is Off, as automatic response RF Collision Avoidance may have been triggered */ + st25r3911TxOff(); + + + /* Load 2nd/3rd stage gain setting from registers into the receiver */ + st25r3911ExecuteCommand( ST25R3911_CMD_CLEAR_SQUELCH ); + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3911 Errata #1.4 */ + /* Enable; disable; enable mixer to make sure the digital decoder is in * + * high state. This also switches the demodulator to mixer mode. */ + st25r3911ReadRegister( ST25R3911_REG_RX_CONF1, &tmp ); + st25r3911WriteRegister( ST25R3911_REG_RX_CONF1, (tmp | ST25R3911_REG_RX_CONF1_amd_sel) ); + st25r3911WriteRegister( ST25R3911_REG_RX_CONF1, (uint8_t)(tmp & ~ST25R3911_REG_RX_CONF1_amd_sel) ); + st25r3911WriteRegister( ST25R3911_REG_RX_CONF1, (tmp | ST25R3911_REG_RX_CONF1_amd_sel) ); + /*******************************************************************************/ + + /* ReEnable the receiver */ + st25r3911ExecuteCommand( ST25R3911_CMD_UNMASK_RECEIVE_DATA ); + + + /* If external Field is no longer detected go back to POWER_OFF */ + if( !st25r3911IsExtFieldOn() ) + { + reSetState = true; + newState = RFAL_LM_STATE_POWER_OFF; /* Set POWER_OFF state */ + } + + /*******************************************************************************/ + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeRx(); + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_TARGET_A: + case RFAL_LM_STATE_TARGET_F: + /* States not handled by the LM, just keep state context */ + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_F: + case RFAL_LM_STATE_CARDEMU_3: + case RFAL_LM_STATE_READY_Ax: + case RFAL_LM_STATE_READY_A: + case RFAL_LM_STATE_ACTIVE_Ax: + case RFAL_LM_STATE_ACTIVE_A: + case RFAL_LM_STATE_SLEEP_A: + case RFAL_LM_STATE_SLEEP_B: + case RFAL_LM_STATE_SLEEP_AF: + case RFAL_LM_STATE_CARDEMU_4A: + case RFAL_LM_STATE_CARDEMU_4B: + return ERR_NOTSUPP; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + } + while( reSetState ); + + gRFAL.Lm.state = newState; + + return ret; +} + +#endif /* RFAL_FEATURE_LISTEN_MODE */ + + +/******************************************************************************* + * Wake-Up Mode * + *******************************************************************************/ + +#if RFAL_FEATURE_WAKEUP_MODE + +/*******************************************************************************/ +ReturnCode rfalWakeUpModeStart( const rfalWakeUpConfig *config ) +{ + uint8_t aux; + uint8_t reg; + uint32_t irqs; + + /* The Wake-Up procedure is explained in detail in Application Note: AN4985 */ + + if( config == NULL ) + { + gRFAL.wum.cfg.period = RFAL_WUM_PERIOD_500MS; + gRFAL.wum.cfg.irqTout = false; + gRFAL.wum.cfg.swTagDetect = false; + + gRFAL.wum.cfg.indAmp.enabled = true; + gRFAL.wum.cfg.indPha.enabled = true; + gRFAL.wum.cfg.cap.enabled = false; + gRFAL.wum.cfg.indAmp.delta = 2U; + gRFAL.wum.cfg.indAmp.reference = RFAL_WUM_REFERENCE_AUTO; + gRFAL.wum.cfg.indAmp.autoAvg = false; + gRFAL.wum.cfg.indPha.delta = 2U; + gRFAL.wum.cfg.indPha.reference = RFAL_WUM_REFERENCE_AUTO; + gRFAL.wum.cfg.indPha.autoAvg = false; + } + else + { + gRFAL.wum.cfg = *config; + } + + + /* Check for valid configuration */ + if( (gRFAL.wum.cfg.cap.enabled && (gRFAL.wum.cfg.indAmp.enabled || gRFAL.wum.cfg.indPha.enabled)) || + (!gRFAL.wum.cfg.cap.enabled && !gRFAL.wum.cfg.indAmp.enabled && !gRFAL.wum.cfg.indPha.enabled) || + gRFAL.wum.cfg.swTagDetect ) + { + return ERR_PARAM; + } + + irqs = ST25R3911_IRQ_MASK_NONE; + + + /* Disable Tx, Rx, External Field Detector and set default ISO14443A mode */ + st25r3911TxRxOff(); + st25r3911ClrRegisterBits( ST25R3911_REG_AUX, ST25R3911_REG_AUX_en_fd ); + st25r3911ChangeRegisterBits(ST25R3911_REG_MODE, (ST25R3911_REG_MODE_targ | ST25R3911_REG_MODE_mask_om), (ST25R3911_REG_MODE_targ_init | ST25R3911_REG_MODE_om_iso14443a) ); + + /* Set Analog configurations for Wake-up On event */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_WAKEUP_ON) ); + + /*******************************************************************************/ + /* Prepare Wake-Up Timer Control Register */ + reg = (uint8_t)(((uint8_t)gRFAL.wum.cfg.period & 0x0FU) << ST25R3911_REG_WUP_TIMER_CONTROL_shift_wut); + reg |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.period < (uint8_t)RFAL_WUM_PERIOD_100MS) ? ST25R3911_REG_WUP_TIMER_CONTROL_wur : 0x00U); + + if(gRFAL.wum.cfg.irqTout) + { + reg |= ST25R3911_REG_WUP_TIMER_CONTROL_wto; + irqs |= ST25R3911_IRQ_MASK_WT; + } + + /*******************************************************************************/ + /* Check if Inductive Amplitude is to be performed */ + if( gRFAL.wum.cfg.indAmp.enabled ) + { + aux = (uint8_t)((gRFAL.wum.cfg.indAmp.delta) << ST25R3911_REG_AMPLITUDE_MEASURE_CONF_shift_am_d); + aux |= (uint8_t)(gRFAL.wum.cfg.indAmp.aaInclMeas ? ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_aam : 0x00U); + aux |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.indAmp.aaWeight << ST25R3911_REG_AMPLITUDE_MEASURE_CONF_shift_am_aew) & ST25R3911_REG_AMPLITUDE_MEASURE_CONF_mask_am_aew); + aux |= (uint8_t)(gRFAL.wum.cfg.indAmp.autoAvg ? ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_ae : 0x00U); + + st25r3911WriteRegister( ST25R3911_REG_AMPLITUDE_MEASURE_CONF, aux ); + + /* Only need to set the reference if not using Auto Average */ + if( !gRFAL.wum.cfg.indAmp.autoAvg ) + { + if( gRFAL.wum.cfg.indAmp.reference == RFAL_WUM_REFERENCE_AUTO ) + { + st25r3911MeasureAmplitude( &gRFAL.wum.cfg.indAmp.reference ); + } + st25r3911WriteRegister( ST25R3911_REG_AMPLITUDE_MEASURE_REF, gRFAL.wum.cfg.indAmp.reference ); + } + + reg |= ST25R3911_REG_WUP_TIMER_CONTROL_wam; + irqs |= ST25R3911_IRQ_MASK_WAM; + } + + /*******************************************************************************/ + /* Check if Inductive Phase is to be performed */ + if( gRFAL.wum.cfg.indPha.enabled ) + { + aux = (uint8_t)((gRFAL.wum.cfg.indPha.delta) << ST25R3911_REG_PHASE_MEASURE_CONF_shift_pm_d); + aux |= (uint8_t)(gRFAL.wum.cfg.indPha.aaInclMeas ? ST25R3911_REG_PHASE_MEASURE_CONF_pm_aam : 0x00U); + aux |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.indPha.aaWeight << ST25R3911_REG_PHASE_MEASURE_CONF_shift_pm_aew) & ST25R3911_REG_PHASE_MEASURE_CONF_mask_pm_aew); + aux |= (uint8_t)(gRFAL.wum.cfg.indPha.autoAvg ? ST25R3911_REG_PHASE_MEASURE_CONF_pm_ae : 0x00U); + + st25r3911WriteRegister( ST25R3911_REG_PHASE_MEASURE_CONF, aux ); + + /* Only need to set the reference if not using Auto Average */ + if( !gRFAL.wum.cfg.indPha.autoAvg ) + { + if( gRFAL.wum.cfg.indPha.reference == RFAL_WUM_REFERENCE_AUTO ) + { + st25r3911MeasurePhase( &gRFAL.wum.cfg.indPha.reference ); + } + st25r3911WriteRegister( ST25R3911_REG_PHASE_MEASURE_REF, gRFAL.wum.cfg.indPha.reference ); + } + + reg |= ST25R3911_REG_WUP_TIMER_CONTROL_wph; + irqs |= ST25R3911_IRQ_MASK_WPH; + } + + /*******************************************************************************/ + /* Check if Capacitive is to be performed */ + if( gRFAL.wum.cfg.cap.enabled ) + { + /*******************************************************************************/ + /* Perform Capacitive sensor calibration */ + + /* Disable Oscillator and Field */ + st25r3911ClrRegisterBits( ST25R3911_REG_OP_CONTROL, (ST25R3911_REG_OP_CONTROL_en | ST25R3911_REG_OP_CONTROL_tx_en) ); + + /* Sensor gain should be configured on Analog Config */ + + /* Perform calibration procedure */ + st25r3911CalibrateCapacitiveSensor( NULL ); + + + /*******************************************************************************/ + aux = (uint8_t)((gRFAL.wum.cfg.cap.delta) << ST25R3911_REG_CAPACITANCE_MEASURE_CONF_shift_cm_d); + aux |= (uint8_t)(gRFAL.wum.cfg.cap.aaInclMeas ? ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_aam : 0x00U); + aux |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.cap.aaWeight << ST25R3911_REG_CAPACITANCE_MEASURE_CONF_shift_cm_aew) & ST25R3911_REG_CAPACITANCE_MEASURE_CONF_mask_cm_aew); + aux |= (uint8_t)(gRFAL.wum.cfg.cap.autoAvg ? ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_ae : 0x00U); + + st25r3911WriteRegister( ST25R3911_REG_CAPACITANCE_MEASURE_CONF, aux ); + + /* Only need to set the reference if not using Auto Average */ + if( !gRFAL.wum.cfg.cap.autoAvg ) + { + if( gRFAL.wum.cfg.indPha.reference == RFAL_WUM_REFERENCE_AUTO ) + { + st25r3911MeasureCapacitance( &gRFAL.wum.cfg.cap.reference ); + } + st25r3911WriteRegister( ST25R3911_REG_CAPACITANCE_MEASURE_REF, gRFAL.wum.cfg.cap.reference ); + } + + reg |= ST25R3911_REG_WUP_TIMER_CONTROL_wcap; + irqs |= ST25R3911_IRQ_MASK_WCAP; + } + + /* Disable and clear all interrupts except Wake-Up IRQs */ + st25r3911DisableInterrupts( ST25R3911_IRQ_MASK_ALL ); + st25r3911GetInterrupt( irqs ); + st25r3911EnableInterrupts( irqs ); + + /* Enable Low Power Wake-Up Mode */ + st25r3911WriteRegister( ST25R3911_REG_WUP_TIMER_CONTROL, reg ); + st25r3911ChangeRegisterBits( ST25R3911_REG_OP_CONTROL, (ST25R3911_REG_OP_CONTROL_en | ST25R3911_REG_OP_CONTROL_wu), ST25R3911_REG_OP_CONTROL_wu ); + + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED; + gRFAL.state = RFAL_STATE_WUM; + + return ERR_NONE; +} + + +/*******************************************************************************/ +bool rfalWakeUpModeHasWoke( void ) +{ + return (gRFAL.wum.state >= RFAL_WUM_STATE_ENABLED_WOKE); +} + + +/*******************************************************************************/ +static void rfalRunWakeUpModeWorker( void ) +{ + uint32_t irqs; + + if( gRFAL.state != RFAL_STATE_WUM ) + { + return; + } + + switch( gRFAL.wum.state ) + { + case RFAL_WUM_STATE_ENABLED: + case RFAL_WUM_STATE_ENABLED_WOKE: + + irqs = st25r3911GetInterrupt( ( ST25R3911_IRQ_MASK_WT | ST25R3911_IRQ_MASK_WAM | ST25R3911_IRQ_MASK_WPH | ST25R3911_IRQ_MASK_WCAP ) ); + if( irqs == ST25R3911_IRQ_MASK_NONE ) + { + break; /* No interrupt to process */ + } + + /*******************************************************************************/ + /* Check and mark which measurement(s) cause interrupt */ + if((irqs & ST25R3911_IRQ_MASK_WAM) != 0U) + { + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + } + + if((irqs & ST25R3911_IRQ_MASK_WPH) != 0U) + { + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + } + + if((irqs & ST25R3911_IRQ_MASK_WCAP) != 0U) + { + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + } + break; + + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } +} + + +/*******************************************************************************/ +ReturnCode rfalWakeUpModeStop( void ) +{ + if( gRFAL.wum.state == RFAL_WUM_STATE_NOT_INIT ) + { + return ERR_WRONG_STATE; + } + + gRFAL.wum.state = RFAL_WUM_STATE_NOT_INIT; + + /* Re-Enable External Field Detector */ + st25r3911SetRegisterBits( ST25R3911_REG_AUX, ST25R3911_REG_AUX_en_fd ); + + /* Disable Wake-Up Mode */ + st25r3911ClrRegisterBits( ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_wu ); + st25r3911DisableInterrupts( (ST25R3911_IRQ_MASK_WT | ST25R3911_IRQ_MASK_WAM | ST25R3911_IRQ_MASK_WPH | ST25R3911_IRQ_MASK_WCAP) ); + + /* Re-Enable the Oscillator */ + st25r3911OscOn(); + + /* Set Analog configurations for Wake-up Off event */ + rfalSetAnalogConfig( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_WAKEUP_OFF) ); + + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + + +/******************************************************************************* + * RF Chip * + *******************************************************************************/ + +/*******************************************************************************/ +ReturnCode rfalChipWriteReg( uint16_t reg, const uint8_t* values, uint8_t len ) +{ + if( !st25r3911IsRegValid( (uint8_t)reg) ) + { + return ERR_PARAM; + } + + st25r3911WriteMultipleRegisters( (uint8_t)reg, values, len ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipReadReg( uint16_t reg, uint8_t* values, uint8_t len ) +{ + if( !st25r3911IsRegValid( (uint8_t)reg) ) + { + return ERR_PARAM; + } + + st25r3911ReadMultipleRegisters( (uint8_t)reg, values, len ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipExecCmd( uint16_t cmd ) +{ + if( !st25r3911IsCmdValid( (uint8_t)cmd) ) + { + return ERR_PARAM; + } + + st25r3911ExecuteCommand( (uint8_t) cmd ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipWriteTestReg( uint16_t reg, uint8_t value ) +{ + st25r3911WriteTestRegister( (uint8_t)reg, value ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipReadTestReg( uint16_t reg, uint8_t* value ) +{ + st25r3911ReadTestRegister( (uint8_t)reg, value ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipChangeRegBits( uint16_t reg, uint8_t valueMask, uint8_t value ) +{ + st25r3911ChangeRegisterBits( (uint8_t)reg, valueMask, value ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipChangeTestRegBits( uint16_t reg, uint8_t valueMask, uint8_t value ) +{ + st25r3911ChangeTestRegisterBits( (uint8_t)reg, valueMask, value ); + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipSetRFO( uint8_t rfo ) +{ + st25r3911WriteRegister( ST25R3911_REG_RFO_AM_OFF_LEVEL, rfo ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipGetRFO( uint8_t* result ) +{ + st25r3911ReadRegister(ST25R3911_REG_RFO_AM_ON_LEVEL, result); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipMeasureAmplitude( uint8_t* result ) +{ + st25r3911MeasureAmplitude( result ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipMeasurePhase( uint8_t* result ) +{ + st25r3911MeasurePhase( result ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipMeasureCapacitance( uint8_t* result ) +{ + st25r3911MeasureCapacitance( result ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalChipMeasurePowerSupply( uint8_t param, uint8_t* result ) +{ + *result = st25r3911MeasurePowerSupply( param ); + + return ERR_NONE; +} + + + +/*******************************************************************************/ + +/* All bitrates defined in ST25R3911B registers are nibbles. This rfal code + * up there only works if equality to values of enum rfalBitrate is guaranteed: */ +extern uint8_t equalityGuard_RFAL_BR_106[(ST25R3911_REG_BIT_RATE_rxrate_106==(uint8_t)RFAL_BR_106)?1:(-1)]; +extern uint8_t equalityGuard_RFAL_BR_212[(ST25R3911_REG_BIT_RATE_rxrate_212==(uint8_t)RFAL_BR_212)?1:(-1)]; +extern uint8_t equalityGuard_RFAL_BR_424[(ST25R3911_REG_BIT_RATE_rxrate_424==(uint8_t)RFAL_BR_424)?1:(-1)]; +extern uint8_t equalityGuard_RFAL_BR_848[(ST25R3911_REG_BIT_RATE_rxrate_848==(uint8_t)RFAL_BR_848)?1:(-1)]; +extern uint8_t equalityGuard_RFAL_BR_1695[(ST25R3911_REG_BIT_RATE_rxrate_1695==(uint8_t)RFAL_BR_1695)?1:(-1)]; +extern uint8_t equalityGuard_RFAL_BR_3390[(ST25R3911_REG_BIT_RATE_rxrate_3390==(uint8_t)RFAL_BR_3390)?1:(-1)]; +extern uint8_t equalityGuard_RFAL_BR_6780[(ST25R3911_REG_BIT_RATE_rxrate_6780==(uint8_t)RFAL_BR_6780)?1:(-1)]; diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_st25tb.c b/Software/fab-reader2-c/components/rfal/Src/rfal_st25tb.c new file mode 100644 index 0000000..41c9430 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_st25tb.c @@ -0,0 +1,551 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25tb.c + * + * \author Gustavo Patricio + * + * \brief Implementation of ST25TB interface + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_st25tb.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ +#ifndef RFAL_FEATURE_ST25TB + #define RFAL_FEATURE_ST25TB false /* ST25TB module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_ST25TB + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_ST25TB_CMD_LEN 1U /*!< ST25TB length of a command */ +#define RFAL_ST25TB_SLOTS 16U /*!< ST25TB number of slots */ +#define RFAL_ST25TB_SLOTNUM_MASK 0x0FU /*!< ST25TB Slot Number bit mask on SlotMarker */ +#define RFAL_ST25TB_SLOTNUM_SHIFT 4U /*!< ST25TB Slot Number shift on SlotMarker */ + +#define RFAL_ST25TB_INITIATE_CMD1 0x06U /*!< ST25TB Initiate command byte1 */ +#define RFAL_ST25TB_INITIATE_CMD2 0x00U /*!< ST25TB Initiate command byte2 */ +#define RFAL_ST25TB_PCALL_CMD1 0x06U /*!< ST25TB Pcall16 command byte1 */ +#define RFAL_ST25TB_PCALL_CMD2 0x04U /*!< ST25TB Pcall16 command byte2 */ +#define RFAL_ST25TB_SELECT_CMD 0x0EU /*!< ST25TB Select command */ +#define RFAL_ST25TB_GET_UID_CMD 0x0BU /*!< ST25TB Get UID command */ +#define RFAL_ST25TB_COMPLETION_CMD 0x0FU /*!< ST25TB Completion command */ +#define RFAL_ST25TB_RESET_INV_CMD 0x0CU /*!< ST25TB Reset to Inventory command */ +#define RFAL_ST25TB_READ_BLOCK_CMD 0x08U /*!< ST25TB Read Block command */ +#define RFAL_ST25TB_WRITE_BLOCK_CMD 0x09U /*!< ST25TB Write Block command */ + + +#define RFAL_ST25TB_T0 2157U /*!< ST25TB t0 159 us ST25TB RF characteristics */ +#define RFAL_ST25TB_T1 2048U /*!< ST25TB t1 151 us ST25TB RF characteristics */ + +#define RFAL_ST25TB_FWT (RFAL_ST25TB_T0 + RFAL_ST25TB_T1) /*!< ST25TB FWT = T0 + T1 */ +#define RFAL_ST25TB_TW rfalConvMsTo1fc(7U) /*!< ST25TB TW : Programming time for write max 7ms */ + + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Initiate Request */ +typedef struct +{ + uint8_t cmd1; /*!< Initiate Request cmd1: 0x06 */ + uint8_t cmd2; /*!< Initiate Request cmd2: 0x00 */ +} rfalSt25tbInitiateReq; + +/*! Pcall16 Request */ +typedef struct +{ + uint8_t cmd1; /*!< Pcal16 Request cmd1: 0x06 */ + uint8_t cmd2; /*!< Pcal16 Request cmd2: 0x04 */ +} rfalSt25tbPcallReq; + + +/*! Select Request */ +typedef struct +{ + uint8_t cmd; /*!< Select Request cmd: 0x0E */ + uint8_t chipId; /*!< Chip ID */ +} rfalSt25tbSelectReq; + +/*! Read Block Request */ +typedef struct +{ + uint8_t cmd; /*!< Select Request cmd: 0x08 */ + uint8_t address; /*!< Block address */ +} rfalSt25tbReadBlockReq; + +/*! Write Block Request */ +typedef struct +{ + uint8_t cmd; /*!< Select Request cmd: 0x09 */ + uint8_t address; /*!< Block address */ + rfalSt25tbBlock data; /*!< Block Data */ +} rfalSt25tbWriteBlockReq; + + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief ST25TB Poller Do Collision Resolution + * + * This method performs ST25TB Collision resolution loop for each slot + * + * \param[in] devLimit : device limit value, and size st25tbDevList + * \param[out] st25tbDevList : ST35TB listener device info + * \param[out] devCnt : Devices found counter + * + * \return colPending : true if a collision was detected + ***************************************************************************** + */ +static bool rfalSt25tbPollerDoCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt ); + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + + +static bool rfalSt25tbPollerDoCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt ) +{ + uint8_t i; + uint8_t chipId; + ReturnCode ret; + bool col; + + col = false; + + for(i = 0; i < RFAL_ST25TB_SLOTS; i++) + { + platformDelay(1); /* Wait t2: Answer to new request delay */ + + if( i==0U ) + { + /* Step 2: Send Pcall16 */ + ret = rfalSt25tbPollerPcall( &chipId ); + } + else + { + /* Step 3-17: Send Pcall16 */ + ret = rfalSt25tbPollerSlotMarker( i, &chipId ); + } + + if( ret == ERR_NONE ) + { + /* Found another device */ + st25tbDevList[*devCnt].chipID = chipId; + st25tbDevList[*devCnt].isDeselected = false; + + /* Select Device, retrieve its UID */ + ret = rfalSt25tbPollerSelect( chipId ); + + /* By Selecting this device, the previous gets Deselected */ + if( (*devCnt) > 0U ) + { + st25tbDevList[(*devCnt)-1U].isDeselected = true; + } + + if( ERR_NONE == ret ) + { + rfalSt25tbPollerGetUID( &st25tbDevList[*devCnt].UID ); + } + + if( ERR_NONE == ret ) + { + (*devCnt)++; + } + } + else if( (ret == ERR_CRC) || (ret == ERR_FRAMING) ) + { + col = true; + } + else + { + /* MISRA 15.7 - Empty else */ + } + + if( *devCnt >= devLimit ) + { + break; + } + } + return col; +} + + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerInitialize( void ) +{ + return rfalNfcbPollerInitialize(); +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerCheckPresence( uint8_t *chipId ) +{ + ReturnCode ret; + uint8_t chipIdRes; + + chipIdRes = 0x00; + + /* Send Initiate Request */ + ret = rfalSt25tbPollerInitiate( &chipIdRes ); + + /* Check if a transmission error was detected */ + if( (ret == ERR_CRC) || (ret == ERR_FRAMING) ) + { + return ERR_NONE; + } + + /* Copy chip ID if requested */ + if( chipId != NULL ) + { + *chipId = chipIdRes; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerInitiate( uint8_t *chipId ) +{ + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbInitiateReq initiateReq; + uint8_t rxBuf[RFAL_ST25TB_CHIP_ID_LEN + RFAL_ST25TB_CRC_LEN]; /* In case we receive less data that CRC, RF layer will not remove the CRC from buffer */ + + /* Compute Initiate Request */ + initiateReq.cmd1 = RFAL_ST25TB_INITIATE_CMD1; + initiateReq.cmd2 = RFAL_ST25TB_INITIATE_CMD2; + + /* Send Initiate Request */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&initiateReq, sizeof(rfalSt25tbInitiateReq), (uint8_t*)rxBuf, sizeof(rxBuf), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); + + /* Check for valid Select Response */ + if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN) ) + { + return ERR_PROTO; + } + + /* Copy chip ID if requested */ + if( chipId != NULL ) + { + *chipId = *rxBuf; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerPcall( uint8_t *chipId ) +{ + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbPcallReq pcallReq; + + /* Compute Pcal16 Request */ + pcallReq.cmd1 = RFAL_ST25TB_PCALL_CMD1; + pcallReq.cmd2 = RFAL_ST25TB_PCALL_CMD2; + + /* Send Pcal16 Request */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&pcallReq, sizeof(rfalSt25tbPcallReq), (uint8_t*)chipId, RFAL_ST25TB_CHIP_ID_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); + + /* Check for valid Select Response */ + if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN) ) + { + return ERR_PROTO; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerSlotMarker( uint8_t slotNum, uint8_t *chipIdRes ) +{ + ReturnCode ret; + uint16_t rxLen; + uint8_t slotMarker; + + if( (slotNum == 0U) || (slotNum > 15U) ) + { + return ERR_PARAM; + } + + /* Compute SlotMarker */ + slotMarker = ( ((slotNum & RFAL_ST25TB_SLOTNUM_MASK) << RFAL_ST25TB_SLOTNUM_SHIFT) | RFAL_ST25TB_PCALL_CMD1 ); + + + /* Send SlotMarker */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slotMarker, RFAL_ST25TB_CMD_LEN, (uint8_t*)chipIdRes, RFAL_ST25TB_CHIP_ID_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); + + /* Check for valid ChipID Response */ + if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN) ) + { + return ERR_PROTO; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerSelect( uint8_t chipId ) +{ + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbSelectReq selectReq; + uint8_t chipIdRes; + + /* Compute Select Request */ + selectReq.cmd = RFAL_ST25TB_SELECT_CMD; + selectReq.chipId = chipId; + + /* Send Select Request */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&selectReq, sizeof(rfalSt25tbSelectReq), (uint8_t*)&chipIdRes, RFAL_ST25TB_CHIP_ID_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); + + /* Check for valid Select Response */ + if( (ret == ERR_NONE) && ((rxLen != RFAL_ST25TB_CHIP_ID_LEN) || (chipIdRes != chipId)) ) + { + return ERR_PROTO; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerGetUID( rfalSt25tbUID *UID ) +{ + ReturnCode ret; + uint16_t rxLen; + uint8_t getUidReq; + + + /* Compute Get UID Request */ + getUidReq = RFAL_ST25TB_GET_UID_CMD; + + /* Send Select Request */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&getUidReq, RFAL_ST25TB_CMD_LEN, (uint8_t*)UID, sizeof(rfalSt25tbUID), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); + + /* Check for valid UID Response */ + if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_UID_LEN) ) + { + return ERR_PROTO; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt ) +{ + + uint8_t chipId; + ReturnCode ret; + bool detected; /* collision or device was detected */ + + if( (st25tbDevList == NULL) || (devCnt == NULL) || (devLimit == 0U) ) + { + return ERR_PARAM; + } + + *devCnt = 0; + + /* Step 1: Send Initiate */ + ret = rfalSt25tbPollerInitiate( &chipId ); + if( ret == ERR_NONE ) + { + /* If only 1 answer is detected */ + st25tbDevList[*devCnt].chipID = chipId; + st25tbDevList[*devCnt].isDeselected = false; + + /* Retrieve its UID and keep it Selected*/ + ret = rfalSt25tbPollerSelect( chipId ); + + if( ERR_NONE == ret ) + { + ret = rfalSt25tbPollerGetUID( &st25tbDevList[*devCnt].UID ); + } + + if( ERR_NONE == ret ) + { + (*devCnt)++; + } + } + /* Always proceed to Pcall16 anticollision as phase differences of tags can lead to no tag recognized, even if there is one */ + if( *devCnt < devLimit ) + { + /* Multiple device responses */ + do + { + detected = rfalSt25tbPollerDoCollisionResolution( devLimit, st25tbDevList, devCnt ); + } + while( (detected == true) && (*devCnt < devLimit) ); + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerReadBlock( uint8_t blockAddress, rfalSt25tbBlock *blockData ) +{ + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbReadBlockReq readBlockReq; + + + /* Compute Read Block Request */ + readBlockReq.cmd = RFAL_ST25TB_READ_BLOCK_CMD; + readBlockReq.address = blockAddress; + + /* Send Read Block Request */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&readBlockReq, sizeof(rfalSt25tbReadBlockReq), (uint8_t*)blockData, sizeof(rfalSt25tbBlock), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); + + /* Check for valid UID Response */ + if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_BLOCK_LEN) ) + { + return ERR_PROTO; + } + + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerWriteBlock( uint8_t blockAddress, const rfalSt25tbBlock *blockData ) +{ + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbWriteBlockReq writeBlockReq; + rfalSt25tbBlock tmpBlockData; + + + /* Compute Write Block Request */ + writeBlockReq.cmd = RFAL_ST25TB_WRITE_BLOCK_CMD; + writeBlockReq.address = blockAddress; + ST_MEMCPY( &writeBlockReq.data, blockData, RFAL_ST25TB_BLOCK_LEN ); + + /* Send Write Block Request */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&writeBlockReq, sizeof(rfalSt25tbWriteBlockReq), tmpBlockData, RFAL_ST25TB_BLOCK_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, (RFAL_ST25TB_FWT + RFAL_ST25TB_TW) ); + + /* Check if an unexpected answer was received */ + if( ret == ERR_NONE ) + { + return ERR_PROTO; + } + /* Check there was any error besides Timeout*/ + if( ret != ERR_TIMEOUT ) + { + return ret; + } + + ret = rfalSt25tbPollerReadBlock(blockAddress, &tmpBlockData); + if( ret == ERR_NONE ) + { + if( ST_BYTECMP( &tmpBlockData, blockData, RFAL_ST25TB_BLOCK_LEN ) == 0 ) + { + return ERR_NONE; + } + return ERR_PROTO; + } + return ret; +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerCompletion( void ) +{ + uint8_t completionReq; + + /* Compute Completion Request */ + completionReq = RFAL_ST25TB_COMPLETION_CMD; + + /* Send Completion Request, no response is expected */ + return rfalTransceiveBlockingTxRx( (uint8_t*)&completionReq, RFAL_ST25TB_CMD_LEN, NULL, 0, NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); +} + + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerResetToInventory( void ) +{ + uint8_t resetInvReq; + + /* Compute Completion Request */ + resetInvReq = RFAL_ST25TB_RESET_INV_CMD; + + /* Send Completion Request, no response is expected */ + return rfalTransceiveBlockingTxRx( (uint8_t*)&resetInvReq, RFAL_ST25TB_CMD_LEN, NULL, 0, NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT ); +} + +#endif /* RFAL_FEATURE_ST25TB */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_st25xv.c b/Software/fab-reader2-c/components/rfal/Src/rfal_st25xv.c new file mode 100644 index 0000000..c835004 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_st25xv.c @@ -0,0 +1,528 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25xv.c + * + * \author Gustavo Patricio + * + * \brief NFC-V ST25 NFC-V Tag specific features + * + * This module provides support for ST's specific features available on + * NFC-V (ISO15693) tag families: ST25D, ST25TV, M24LR + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_st25xv.h" +#include "rfal_nfcv.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_ST25xV + #define RFAL_FEATURE_ST25xV false /* ST25xV module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_ST25xV + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_ST25xV_READ_CONFIG_LEN 2U /*!< READ CONFIGURATION length */ +#define RFAL_ST25xV_READ_MSG_LEN_LEN 2U /*!< READ MESSAGE LENGTH length */ +#define RFAL_ST25xV_CONF_POINTER_LEN 1U /*!< READ/WRITE CONFIGURATION Pointer length */ +#define RFAL_ST25xV_CONF_REGISTER_LEN 1U /*!< READ/WRITE CONFIGURATION Register length */ +#define RFAL_ST25xV_PWDNUM_LEN 1U /*!< Password Number length */ +#define RFAL_ST25xV_PWD_LEN 8U /*!< Password length */ +#define RFAL_ST25xV_MBPOINTER_LEN 1U /*!< Read Message MBPointer length */ +#define RFAL_ST25xV_NUMBYTES_LEN 1U /*!< Read Message Number of Bytes length */ + +#define RFAL_ST25TV02K_TBOOT_RF 1U /*!< RF Boot time (Minimum time from carrier generation to first data) */ +#define RFAL_ST25TV02K_TRF_OFF 2U /*!< RF OFF time */ + +#define RFAL_FDT_POLL_MAX rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF 20 ms Digital 2.0 B.5 */ +#define RFAL_NFCV_FLAG_POS 0U /*!< Flag byte position */ +#define RFAL_NFCV_FLAG_LEN 1U /*!< Flag byte length */ + + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +static ReturnCode rfalST25xVPollerGenericReadConfiguration(uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ); +static ReturnCode rfalST25xVPollerGenericWriteConfiguration( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ); +static ReturnCode rfalST25xVPollerGenericReadMessageLength( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t* msgLen ); +static ReturnCode rfalST25xVPollerGenericReadMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ); +static ReturnCode rfalST25xVPollerGenericWriteMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen ); +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericReadConfiguration(uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ) +{ + ReturnCode ret; + uint8_t p; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if( regValue == NULL ) + { + return ERR_PARAM; + } + + p = pointer; + + ret = rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, &p, sizeof(uint8_t), (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); + if( ret == ERR_NONE ) + { + if( rcvLen < RFAL_ST25xV_READ_CONFIG_LEN ) + { + ret = ERR_PROTO; + } + else + { + *regValue = res.data[0]; + } + } + return ret; +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericWriteConfiguration( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ) +{ + uint8_t data[RFAL_ST25xV_CONF_POINTER_LEN + RFAL_ST25xV_CONF_REGISTER_LEN]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + dataLen = 0U; + + data[dataLen++] = pointer; + data[dataLen++] = regValue; + + return rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); + +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericReadMessageLength( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t* msgLen ) +{ + ReturnCode ret; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if( msgLen == NULL ) + { + return ERR_PARAM; + } + + ret = rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, NULL, 0, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); + if( ret == ERR_NONE ) + { + if( rcvLen < RFAL_ST25xV_READ_MSG_LEN_LEN ) + { + ret = ERR_PROTO; + } + else + { + *msgLen = res.data[0]; + } + } + return ret; +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericReadMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[RFAL_ST25xV_MBPOINTER_LEN + RFAL_ST25xV_NUMBYTES_LEN]; + uint8_t dataLen; + + dataLen = 0; + + /* Compute Request Data */ + data[dataLen++] = mbPointer; + data[dataLen++] = numBytes; + + return rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericWriteMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen ) +{ + ReturnCode ret; + uint8_t reqFlag; + uint16_t msgIt; + rfalBitRate rxBR; + bool fastMode; + rfalNfcvGenericRes res; + uint16_t rcvLen; + + /* Calculate required Tx buf length: Mfg Code UID MSGLen MSGLen+1 */ + msgIt = (uint16_t)( msgLen + sizeof(flags) + sizeof(cmd) + 1U + ((uid != NULL) ? RFAL_NFCV_UID_LEN : 0U) + 1U + 1U ); + + /* Check for valid parameters */ + if( (txBuf == NULL) || (msgData == NULL) || (msgLen == 0U) || (msgLen == 0xFFU) || (txBufLen < msgIt) ) + { + return ERR_PARAM; + } + + msgIt = 0; + fastMode = false; + + /* Check if the command is an ST's Fast command */ + if( cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE ) + { + /* Store current Rx bit rate and move to fast mode */ + rfalGetBitRate( NULL, &rxBR ); + rfalSetBitRate( RFAL_BR_KEEP, RFAL_BR_52p97 ); + + fastMode = true; + } + + /* Compute Request Command */ + reqFlag = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS) & ~((uint32_t)RFAL_NFCV_REQ_FLAG_SELECT))); + reqFlag |= (( uid != NULL ) ? (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS : (uint8_t)RFAL_NFCV_REQ_FLAG_SELECT); + + txBuf[msgIt++] = reqFlag; + txBuf[msgIt++] = cmd; + txBuf[msgIt++] = RFAL_NFCV_ST_IC_MFG_CODE; + + if( uid != NULL ) + { + ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN ); + msgIt += RFAL_NFCV_UID_LEN; + } + txBuf[msgIt++] = msgLen; + ST_MEMCPY( &txBuf[msgIt], msgData, (uint8_t)(msgLen + 1U) ); /* Message Data contains (MSGLength + 1) bytes */ + msgIt += (uint8_t)(msgLen + 1U); + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_MAX ); + + + /* Restore Rx BitRate */ + if( fastMode ) + { + rfalSetBitRate( RFAL_BR_KEEP, rxBR ); + } + + if( ret != ERR_NONE ) + { + return ret; + } + + /* Check if the response minimum length has been received */ + if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN ) + { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U ) + { + return ERR_PROTO; + } + + return ERR_NONE; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[RFAL_NFCV_BLOCKNUM_M24LR_LEN]; + uint8_t dataLen; + + dataLen = 0; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_SINGLE_BLOCK, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_MAX_BLOCK_LEN)]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + /* Check for valid parameters */ + if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL) ) + { + return ERR_PARAM; + } + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */ + dataLen += blockLen; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_BLOCKNUM_M24LR_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)firstBlockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(firstBlockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t bn; + + bn = blockNum; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, &bn, sizeof(uint8_t), rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[RFAL_NFCV_BLOCKNUM_M24LR_LEN]; + uint8_t dataLen; + + dataLen = 0; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_BLOCKNUM_M24LR_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)firstBlockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(firstBlockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = firstBlockNum; /* Set first Block Number */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastExtReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ) +{ + return rfalST25xVPollerGenericReadConfiguration(RFAL_NFCV_CMD_READ_CONFIGURATION, flags, uid, pointer, regValue ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerWriteConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ) +{ + return rfalST25xVPollerGenericWriteConfiguration( RFAL_NFCV_CMD_WRITE_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ) +{ + return rfalST25xVPollerGenericReadConfiguration(RFAL_NFCV_CMD_READ_DYN_CONFIGURATION, flags, uid, pointer, regValue ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ) +{ + return rfalST25xVPollerGenericWriteConfiguration( RFAL_NFCV_CMD_WRITE_DYN_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue ) +{ + return rfalST25xVPollerGenericReadConfiguration(RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION, flags, uid, pointer, regValue ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue ) +{ + return rfalST25xVPollerGenericWriteConfiguration( RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerPresentPassword( uint8_t flags, const uint8_t* uid, uint8_t pwdNum, const uint8_t *pwd, uint8_t pwdLen) +{ + uint8_t data[RFAL_ST25xV_PWDNUM_LEN + RFAL_ST25xV_PWD_LEN]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if( (pwdLen > RFAL_ST25xV_PWD_LEN) || (pwd == NULL) ) + { + return ERR_PARAM; + } + + dataLen = 0U; + data[dataLen++] = pwdNum;; + if( pwdLen > 0U ) + { + ST_MEMCPY(&data[dataLen], pwd, pwdLen); + } + dataLen += pwdLen; + + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_PRESENT_PASSWORD, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen ); + +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerGetRandomNumber( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + rfalFieldOff(); + platformDelay(RFAL_ST25TV02K_TRF_OFF); + rfalNfcvPollerInitialize(); + rfalFieldOnAndStartGT(); + platformDelay(RFAL_ST25TV02K_TBOOT_RF); + return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_GET_RANDOM_NUMBER, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen ) +{ + return rfalST25xVPollerGenericWriteMessage( RFAL_NFCV_CMD_WRITE_MESSAGE, flags, uid, msgLen, msgData, txBuf, txBufLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen ) +{ + return rfalST25xVPollerGenericWriteMessage( RFAL_NFCV_CMD_FAST_WRITE_MESSAGE, flags, uid, msgLen, msgData, txBuf, txBufLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadMessageLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen ) +{ + return rfalST25xVPollerGenericReadMessageLength(RFAL_NFCV_CMD_READ_MESSAGE_LENGTH, flags, uid, msgLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadMsgLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen ) +{ + return rfalST25xVPollerGenericReadMessageLength(RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH, flags, uid, msgLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + return rfalST25xVPollerGenericReadMessage(RFAL_NFCV_CMD_READ_MESSAGE, flags, uid, mbPointer, numBytes, rxBuf, rxBufLen, rcvLen ); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) +{ + return rfalST25xVPollerGenericReadMessage(RFAL_NFCV_CMD_FAST_READ_MESSAGE, flags, uid, mbPointer, numBytes, rxBuf, rxBufLen, rcvLen ); +} + +#endif /* RFAL_FEATURE_ST25xV */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_t1t.c b/Software/fab-reader2-c/components/rfal/Src/rfal_t1t.c new file mode 100644 index 0000000..995899c --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_t1t.c @@ -0,0 +1,220 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t1t.c + * + * \author Gustavo Patricio + * + * \brief Provides NFC-A T1T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 1 Tag T1T (Topaz) + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "rfal_t1t.h" +#include "utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_T1T + #define RFAL_FEATURE_T1T false /* T1T module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_T1T + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_T1T_DRD_READ (1236U*2U) /*!< DRD for Reads with n=9 => 1236/fc ~= 91 us T1T 1.2 4.4.2 */ +#define RFAL_T1T_DRD_WRITE 36052U /*!< DRD for Write with n=281 => 36052/fc ~= 2659 us T1T 1.2 4.4.2 */ +#define RFAL_T1T_DRD_WRITE_E 70996U /*!< DRD for Write/Erase with n=554 => 70996/fc ~= 5236 us T1T 1.2 4.4.2 */ + +#define RFAL_T1T_RID_RES_HR0_VAL 0x10U /*!< HR0 indicating NDEF support Digital 2.0 (Candidate) 11.6.2.1 */ +#define RFAL_T1T_RID_RES_HR0_MASK 0xF0U /*!< HR0 most significant nibble mask */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A T1T (Topaz) RID_REQ Digital 1.1 10.6.1 & Table 49 */ +typedef struct +{ + uint8_t cmd; /*!< T1T cmd: RID */ + uint8_t add; /*!< ADD: undefined value */ + uint8_t data; /*!< DATA: undefined value */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID-echo: undefined value */ +} rfalT1TRidReq; + + +/*! NFC-A T1T (Topaz) RALL_REQ T1T 1.2 Table 4 */ +typedef struct +{ + uint8_t cmd; /*!< T1T cmd: RALL */ + uint8_t add1; /*!< ADD: 0x00 */ + uint8_t add0; /*!< ADD: 0x00 */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID */ +} rfalT1TRallReq; + + +/*! NFC-A T1T (Topaz) WRITE_REQ T1T 1.2 Table 4 */ +typedef struct +{ + uint8_t cmd; /*!< T1T cmd: RALL */ + uint8_t add; /*!< ADD */ + uint8_t data; /*!< DAT */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID */ +} rfalT1TWriteReq; + + +/*! NFC-A T1T (Topaz) WRITE_RES T1T 1.2 Table 4 */ +typedef struct +{ + uint8_t add; /*!< ADD */ + uint8_t data; /*!< DAT */ +} rfalT1TWriteRes; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +ReturnCode rfalT1TPollerInitialize( void ) +{ + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalSetMode( RFAL_MODE_POLL_NFCA_T1T, RFAL_BR_106, RFAL_BR_106 ) ); + rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC ); + + rfalSetGT( RFAL_GT_NONE ); /* T1T should only be initialized after NFC-A mode, therefore the GT has been fulfilled */ + rfalSetFDTListen( RFAL_FDT_LISTEN_NFCA_POLLER ); /* T1T uses NFC-A FDT Listen with n=9 Digital 1.1 10.7.2 */ + rfalSetFDTPoll( RFAL_FDT_POLL_NFCA_T1T_POLLER ); + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalT1TPollerRid( rfalT1TRidRes *ridRes ) +{ + ReturnCode ret; + rfalT1TRidReq ridReq; + uint16_t rcvdLen; + + if( ridRes == NULL ) + { + return ERR_PARAM; + } + + /* Compute RID command and set Undefined Values to 0x00 Digital 1.1 10.6.1 */ + ST_MEMSET( &ridReq, 0x00, sizeof(rfalT1TRidReq) ); + ridReq.cmd = (uint8_t)RFAL_T1T_CMD_RID; + + EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&ridReq, sizeof(rfalT1TRidReq), (uint8_t*)ridRes, sizeof(rfalT1TRidRes), &rcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_T1T_DRD_READ ) ); + + /* Check expected RID response length and the HR0 Digital 2.0 (Candidate) 11.6.2.1 */ + if( (rcvdLen != sizeof(rfalT1TRidRes)) || ((ridRes->hr0 & RFAL_T1T_RID_RES_HR0_MASK) != RFAL_T1T_RID_RES_HR0_VAL) ) + { + return ERR_PROTO; + } + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalT1TPollerRall( const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rxRcvdLen ) +{ + rfalT1TRallReq rallReq; + + if( (rxBuf == NULL) || (uid == NULL) || (rxRcvdLen == NULL) ) + { + return ERR_PARAM; + } + + /* Compute RALL command and set Add to 0x00 */ + ST_MEMSET( &rallReq, 0x00, sizeof(rfalT1TRallReq) ); + rallReq.cmd = (uint8_t)RFAL_T1T_CMD_RALL; + ST_MEMCPY(rallReq.uid, uid, RFAL_T1T_UID_LEN); + + return rfalTransceiveBlockingTxRx( (uint8_t*)&rallReq, sizeof(rfalT1TRallReq), (uint8_t*)rxBuf, rxBufLen, rxRcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_T1T_DRD_READ ); +} + + +/*******************************************************************************/ +ReturnCode rfalT1TPollerWrite( const uint8_t* uid, uint8_t address, uint8_t data ) +{ + rfalT1TWriteReq writeReq; + rfalT1TWriteRes writeRes; + uint16_t rxRcvdLen; + ReturnCode err; + + if( uid == NULL ) + { + return ERR_PARAM; + } + + writeReq.cmd = (uint8_t)RFAL_T1T_CMD_WRITE_E; + writeReq.add = address; + writeReq.data = data; + ST_MEMCPY(writeReq.uid, uid, RFAL_T1T_UID_LEN); + + err = rfalTransceiveBlockingTxRx( (uint8_t*)&writeReq, sizeof(rfalT1TWriteReq), (uint8_t*)&writeRes, sizeof(rfalT1TWriteRes), &rxRcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_T1T_DRD_WRITE_E ); + + if( err == ERR_NONE ) + { + if( (writeReq.add != writeRes.add) || (writeReq.data != writeRes.data) || (rxRcvdLen != sizeof(rfalT1TWriteRes)) ) + { + return ERR_PROTO; + } + } + return err; +} + +#endif /* RFAL_FEATURE_T1T */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_t2t.c b/Software/fab-reader2-c/components/rfal/Src/rfal_t2t.c new file mode 100644 index 0000000..de80a81 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_t2t.c @@ -0,0 +1,242 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2018 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t2t.c + * + * \author + * + * \brief Provides NFC-A T2T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 2 Tag T2T + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ + #include "rfal_t2t.h" + #include "utils.h" + + /* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_T2T + #define RFAL_FEATURE_T2T false /* T2T module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_T2T + + /* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + #define RFAL_FDT_POLL_READ_MAX rfalConvMsTo1fc(5U) /*!< Maximum Wait time for Read command as defined in TS T2T 1.0 table 18 */ + #define RFAL_FDT_POLL_WRITE_MAX rfalConvMsTo1fc(10U) /*!< Maximum Wait time for Write command as defined in TS T2T 1.0 table 18 */ + #define RFAL_FDT_POLL_SL_MAX rfalConvMsTo1fc(1U) /*!< Maximum Wait time for Sector Select as defined in TS T2T 1.0 table 18 */ + #define RFAL_T2T_ACK_NACK_LEN 1U /*!< Len of NACK in bytes (4 bits) */ + #define RFAL_T2T_ACK 0x0AU /*!< ACK value */ + #define RFAL_T2T_ACK_MASK 0x0FU /*!< ACK value */ + + + #define RFAL_T2T_SECTOR_SELECT_P1_BYTE2 0xFFU /*!< Sector Select Packet 1 byte 2 */ + #define RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN 3U /*!< Sector Select RFU length */ + + + + /* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A T2T command set T2T 1.0 5.1 */ +typedef enum +{ + RFAL_T2T_CMD_READ = 0x30, /*!< T2T Read */ + RFAL_T2T_CMD_WRITE = 0xA2, /*!< T2T Write */ + RFAL_T2T_CMD_SECTOR_SELECT = 0xC2 /*!< T2T Sector Select */ +} rfalT2Tcmds; + + + /*! NFC-A T2T READ T2T 1.0 5.2 and table 11 */ +typedef struct +{ + uint8_t code; /*!< Command code */ + uint8_t blNo; /*!< Block number */ +} rfalT2TReadReq; + + + /*! NFC-A T2T WRITE T2T 1.0 5.3 and table 12 */ +typedef struct +{ + uint8_t code; /*!< Command code */ + uint8_t blNo; /*!< Block number */ + uint8_t data[RFAL_T2T_WRITE_DATA_LEN]; /*!< Data */ +} rfalT2TWriteReq; + + +/*! NFC-A T2T SECTOR SELECT Packet 1 T2T 1.0 5.4 and table 13 */ +typedef struct +{ + uint8_t code; /*!< Command code */ + uint8_t byte2; /*!< Sector Select Packet 1 byte 2 */ +} rfalT2TSectorSelectP1Req; + + +/*! NFC-A T2T SECTOR SELECT Packet 2 T2T 1.0 5.4 and table 13 */ +typedef struct +{ + uint8_t secNo; /*!< Block number */ + uint8_t rfu[RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN]; /*!< Sector Select Packet RFU */ +} rfalT2TSectorSelectP2Req; + + + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + + ReturnCode rfalT2TPollerRead( uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen ) + { + ReturnCode ret; + rfalT2TReadReq req; + + if( (rxBuf == NULL) || (rcvLen == NULL) ) + { + return ERR_PARAM; + } + + req.code = (uint8_t)RFAL_T2T_CMD_READ; + req.blNo = blockNum; + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&req, sizeof(rfalT2TReadReq), rxBuf, rxBufLen, rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_READ_MAX ); + + /* T2T 1.0 5.2.1.7 The Reader/Writer SHALL treat a NACK in response to a READ Command as a Protocol Error */ + if( (ret == ERR_INCOMPLETE_BYTE) && (*rcvLen == RFAL_T2T_ACK_NACK_LEN) && ((*rxBuf & RFAL_T2T_ACK_MASK) != RFAL_T2T_ACK) ) + { + return ERR_PROTO; + } + return ret; + } + + + /*******************************************************************************/ + ReturnCode rfalT2TPollerWrite( uint8_t blockNum, const uint8_t* wrData ) + { + ReturnCode ret; + rfalT2TWriteReq req; + uint8_t res; + uint16_t rxLen; + + req.code = (uint8_t)RFAL_T2T_CMD_WRITE; + req.blNo = blockNum; + ST_MEMCPY(req.data, wrData, RFAL_T2T_WRITE_DATA_LEN); + + + /* Transceive WRITE Command */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&req, sizeof(rfalT2TWriteReq), &res, sizeof(uint8_t), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_READ_MAX ); + + /* Check for a valid ACK */ + if( (ret == ERR_INCOMPLETE_BYTE) || (ret == ERR_NONE) ) + { + ret = ERR_PROTO; + + if( (rxLen == RFAL_T2T_ACK_NACK_LEN) && ((res & RFAL_T2T_ACK_MASK) == RFAL_T2T_ACK) ) + { + ret = ERR_NONE; + } + } + + return ret; + } + + + /*******************************************************************************/ + ReturnCode rfalT2TPollerSectorSelect( uint8_t sectorNum ) + { + rfalT2TSectorSelectP1Req p1Req; + rfalT2TSectorSelectP2Req p2Req; + ReturnCode ret; + uint8_t res; + uint16_t rxLen; + + + /* Compute SECTOR SELECT Packet 1 */ + p1Req.code = (uint8_t)RFAL_T2T_CMD_SECTOR_SELECT; + p1Req.byte2 = RFAL_T2T_SECTOR_SELECT_P1_BYTE2; + + /* Transceive SECTOR SELECT Packet 1 */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&p1Req, sizeof(rfalT2TSectorSelectP1Req), &res, sizeof(uint8_t), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_SL_MAX ); + + /* Check and report any transmission error */ + if( (ret != ERR_INCOMPLETE_BYTE) && (ret != ERR_NONE) ) + { + return ret; + } + + /* Ensure that an ACK was received */ + if( (ret != ERR_INCOMPLETE_BYTE) || (rxLen != RFAL_T2T_ACK_NACK_LEN) || ((res & RFAL_T2T_ACK_MASK) != RFAL_T2T_ACK) ) + { + return ERR_PROTO; + } + + + /* Compute SECTOR SELECT Packet 2 */ + p2Req.secNo = sectorNum; + ST_MEMSET( &p2Req.rfu, 0x00, RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN ); + + + /* Transceive SECTOR SELECT Packet 2 */ + ret = rfalTransceiveBlockingTxRx( (uint8_t*)&p2Req, sizeof(rfalT2TSectorSelectP2Req), &res, sizeof(uint8_t), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_SL_MAX ); + + /* T2T 1.0 5.4.1.14 The Reader/Writer SHALL treat any response received before the end of PATT2T,SL,MAX as a Protocol Error */ + if( (ret == ERR_NONE) || (ret == ERR_INCOMPLETE_BYTE) ) + { + return ERR_PROTO; + } + + /* T2T 1.0 5.4.1.13 The Reader/Writer SHALL treat the transmission of the SECTOR SELECT Command Packet 2 as being successful when it receives no response until PATT2T,SL,MAX. */ + if( ret == ERR_TIMEOUT ) + { + return ERR_NONE; + } + + return ret; + } + +#endif /* RFAL_FEATURE_T2T */ diff --git a/Software/fab-reader2-c/components/rfal/Src/rfal_t4t.c b/Software/fab-reader2-c/components/rfal/Src/rfal_t4t.c new file mode 100644 index 0000000..3353f91 --- /dev/null +++ b/Software/fab-reader2-c/components/rfal/Src/rfal_t4t.c @@ -0,0 +1,398 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2018 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t4t.h + * + * \author Gustavo Patricio + * + * \brief Provides convenience methods and definitions for T4T (ISO7816-4) + * + * This module provides an interface to exchange T4T APDUs according to + * NFC Forum T4T and ISO7816-4 + * + * This implementation was based on the following specs: + * - ISO/IEC 7816-4 3rd Edition 2013-04-15 + * - NFC Forum T4T Technical Specification 1.0 2017-08-28 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ + #include "rfal_t4t.h" + #include "utils.h" + + /* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_T4T + #define RFAL_FEATURE_T4T false /* T4T module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_T4T + + /* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_T4T_OFFSET_DO 0x54U /*!< Tag value for offset BER-TLV data object */ +#define RFAL_T4T_LENGTH_DO 0x03U /*!< Len value for offset BER-TLV data object */ +#define RFAL_T4T_DATA_DO 0x53U /*!< Tag value for data BER-TLV data object */ + +#define RFAL_T4T_MAX_LC 255U /*!< Maximum Lc value for short Lc coding */ + /* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeCAPDU( rfalT4tCApduParam *apduParam ) +{ + uint8_t hdrLen; + uint16_t msgIt; + + if( (apduParam == NULL) || (apduParam->cApduBuf == NULL) || (apduParam->cApduLen == NULL) ) + { + return ERR_PARAM; + } + + msgIt = 0; + *(apduParam->cApduLen) = 0; + + /*******************************************************************************/ + /* Compute Command-APDU according to the format T4T 1.0 5.1.2 & ISO7816-4 2013 Table 1 */ + + /* Check if Data is present */ + if( apduParam->LcFlag ) + { + if( apduParam->Lc == 0U ) + { + /* Extented field coding not supported */ + return ERR_PARAM; + } + + /* Check whether requested Lc fits */ + if( (uint16_t)apduParam->Lc > (uint16_t)(RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN - RFAL_T4T_LE_LEN) ) + { + return ERR_PARAM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ + } + + /* Calculate the header length a place the data/body where it should be */ + hdrLen = RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN + RFAL_T4T_LC_LEN; + + /* make sure not to exceed buffer size */ + if( ((uint16_t)hdrLen + (uint16_t)apduParam->Lc + (apduParam->LeFlag ? RFAL_T4T_LC_LEN : 0U)) > RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN ) + { + return ERR_NOMEM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ + } + ST_MEMMOVE( &apduParam->cApduBuf->apdu[hdrLen], apduParam->cApduBuf->apdu, apduParam->Lc ); + } + + /* Prepend the ADPDU's header */ + apduParam->cApduBuf->apdu[msgIt++] = apduParam->CLA; + apduParam->cApduBuf->apdu[msgIt++] = apduParam->INS; + apduParam->cApduBuf->apdu[msgIt++] = apduParam->P1; + apduParam->cApduBuf->apdu[msgIt++] = apduParam->P2; + + + /* Check if Data field length is to be added */ + if( apduParam->LcFlag ) + { + apduParam->cApduBuf->apdu[msgIt++] = apduParam->Lc; + msgIt += apduParam->Lc; + } + + /* Check if Expected Response Length is to be added */ + if( apduParam->LeFlag ) + { + apduParam->cApduBuf->apdu[msgIt++] = apduParam->Le; + } + + *(apduParam->cApduLen) = msgIt; + + return ERR_NONE; +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerParseRAPDU( rfalT4tRApduParam *apduParam ) +{ + if( (apduParam == NULL) || (apduParam->rApduBuf == NULL) ) + { + return ERR_PARAM; + } + + if( apduParam->rcvdLen < RFAL_T4T_MAX_RAPDU_SW1SW2_LEN ) + { + return ERR_PROTO; + } + + apduParam->rApduBodyLen = (apduParam->rcvdLen - (uint16_t)RFAL_T4T_MAX_RAPDU_SW1SW2_LEN); + apduParam->statusWord = GETU16( &apduParam->rApduBuf->apdu[ apduParam->rApduBodyLen ] ); + + /* Check SW1 SW2 T4T 1.0 5.1.3 NOTE */ + if( apduParam->statusWord == RFAL_T4T_ISO7816_STATUS_COMPLETE ) + { + return ERR_NONE; + } + + return ERR_REQUEST; +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeSelectAppl( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* aid, uint8_t aidLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h A4h 00h 00h 07h AID 00h */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT; + cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME; + cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE; + cAPDU.Lc = aidLen; + cAPDU.Le = 0x00; + cAPDU.LcFlag = true; + cAPDU.LeFlag = true; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if( aidLen > 0U ) + { + ST_MEMCPY( cAPDU.cApduBuf->apdu, aid, aidLen ); + } + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeSelectFile( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h A4h 00h 0Ch 02h FID - */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT; + cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID; + cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA; + cAPDU.Lc = fidLen; + cAPDU.Le = 0x00; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if( fidLen > 0U ) + { + ST_MEMCPY( cAPDU.cApduBuf->apdu, fid, fidLen ); + } + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeSelectFileV1Mapping( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h A4h 00h 00h 02h FID - */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT; + cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID; + cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE; + cAPDU.Lc = fidLen; + cAPDU.Le = 0x00; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if( fidLen > 0U ) + { + ST_MEMCPY( cAPDU.cApduBuf->apdu, fid, fidLen ); + } + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeReadData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, uint8_t expLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h B0h [Offset] - - len */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY; + cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU); + cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU); + cAPDU.Le = expLen; + cAPDU.LcFlag = false; + cAPDU.LeFlag = true; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeReadDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, uint8_t expLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + uint8_t dataIt; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h B1h 00h 00h Lc 54 03 xxyyzz len */ + /* [Offset] */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY_ODO; + cAPDU.P1 = 0x00U; + cAPDU.P2 = 0x00U; + cAPDU.Le = expLen; + cAPDU.LcFlag = true; + cAPDU.LeFlag = true; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + dataIt = 0U; + cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO; + cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO; + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset); + cAPDU.Lc = dataIt; + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeWriteData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h D6h [Offset] len Data - */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY; + cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU); + cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU); + cAPDU.Lc = dataLen; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if( dataLen > 0U ) + { + ST_MEMCPY( cAPDU.cApduBuf->apdu, data, dataLen ); + } + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeWriteDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen ) +{ + rfalT4tCApduParam cAPDU; + uint8_t dataIt; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h D7h 00h 00h len 54 03 xxyyzz 53 Ld data - */ + /* [offset] [data] */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY_ODO; + cAPDU.P1 = 0x00U; + cAPDU.P2 = 0x00U; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + dataIt = 0U; + cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO; + cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO; + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset); + cApduBuf->apdu[dataIt++] = RFAL_T4T_DATA_DO; + cApduBuf->apdu[dataIt++] = dataLen; + + if( (((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_T4T_MAX_LC) || (((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN) ) + { + return (ERR_NOMEM); + } + + if( dataLen > 0U ) + { + ST_MEMCPY( &cAPDU.cApduBuf->apdu[dataIt], data, dataLen ); + } + dataIt += dataLen; + cAPDU.Lc = dataIt; + + return rfalT4TPollerComposeCAPDU( &cAPDU ); +} + + +#endif /* RFAL_FEATURE_T4T */ diff --git a/Software/fab-reader2-c/components/st25r3911/CMakeLists.txt b/Software/fab-reader2-c/components/st25r3911/CMakeLists.txt new file mode 100644 index 0000000..66900f1 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "st25r3911.c" "st25r3911_com.c" "st25r3911_interrupt.c" "timer.c" "st25r3911_spi.c" "utils.c" + INCLUDE_DIRS "." REQUIRES driver) diff --git a/Software/fab-reader2-c/components/st25r3911/Release_Notes.html b/Software/fab-reader2-c/components/st25r3911/Release_Notes.html new file mode 100644 index 0000000..cefbfb6 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/Release_Notes.html @@ -0,0 +1,177 @@ + + + + + + + + + + + + + Release Notes for ST25R3911 Driver + + + + + + + + + +
+


+

+
+ + + + + + +
+ + + + + + + + + +
+

Back to Release page

+
+

Release +Notes for ST25R3911 driver

+

Copyright +2017 STMicroelectronics

+

+
+

 

+ + + + + + +
+

Update +History

+ + +

V1.0.0 +/ 15-March-2017

+

Main +Changes

+ + +
    +
  • First +official release.
  • +
+ +

License
+

+
Redistribution +and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met:
+
+
    +
  1. Redistributions +of source code must retain the above copyright notice, this list of +conditions and the following disclaimer.
  2. +
  3. Redistributions +in binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution.
  4. +
  5. Neither the +name of STMicroelectronics nor the names of its contributors may be +used to endorse or promote products derived
    +
  6. +
+        +from this software without specific prior written permission.
+
+ THIS +SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE.
+

+ +
+
+

For +complete documentation on STM32 Microcontrollers +visit www.st.com/STM32

+
+

+
+
+

 

+
+ + \ No newline at end of file diff --git a/Software/fab-reader2-c/components/st25r3911/platform.h b/Software/fab-reader2-c/components/st25r3911/platform.h new file mode 100644 index 0000000..c61c170 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/platform.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ +/*! \file + * + * \author + * + * \brief Platform header file. Defining platform independent functionality. + * + */ + + +/* + * PROJECT: + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file platform.h + * + * \author Gustavo Patricio + * + * \brief Platform specific definition layer + * + * This should contain all platform and hardware specifics such as + * GPIO assignment, system resources, locks, IRQs, etc + * + * Each distinct platform/system/board must provide this definitions + * for all SW layers to use + * + */ + +#ifndef PLATFORM_H +#define PLATFORM_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include + +#include + +#include +#include +#include +#include + +#include "st25r3911_spi.h" +#include "timer.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define ST25R391X_SS_PIN 4 /*!< GPIO pin used for ST25R3911 SPI SS */ +#define ST25R391X_SS_PORT /*!< GPIO port used for ST25R3911 SPI SS port */ + +#define ST25R391X_INT_PIN 15 /*!< GPIO pin used for ST25R3911 External Interrupt */ +#define ST25R391X_INT_PORT /*!< GPIO port used for ST25R3911 External Interrupt */ + +#ifdef LED_FIELD_Pin +#define PLATFORM_LED_FIELD_PIN LED_FIELD_Pin /*!< GPIO pin used as field LED */ +#endif + +#ifdef LED_FIELD_GPIO_Port +#define PLATFORM_LED_FIELD_PORT LED_FIELD_GPIO_Port /*!< GPIO port used as field LED */ +#endif + + +#define PLATFORM_LED_A_PIN LED_A_Pin /*!< GPIO pin used for LED A */ +#define PLATFORM_LED_A_PORT LED_A_GPIO_Port /*!< GPIO port used for LED A */ +#define PLATFORM_LED_B_PIN LED_B_Pin /*!< GPIO pin used for LED B */ +#define PLATFORM_LED_B_PORT LED_B_GPIO_Port /*!< GPIO port used for LED B */ +#define PLATFORM_LED_F_PIN LED_F_Pin /*!< GPIO pin used for LED F */ +#define PLATFORM_LED_F_PORT LED_F_GPIO_Port /*!< GPIO port used for LED F */ +#define PLATFORM_LED_V_PIN LED_V_Pin /*!< GPIO pin used for LED V */ +#define PLATFORM_LED_V_PORT LED_V_GPIO_Port /*!< GPIO port used for LED V */ +#define PLATFORM_LED_AP2P_PIN LED_AP2P_Pin /*!< GPIO pin used for LED AP2P */ +#define PLATFORM_LED_AP2P_PORT LED_AP2P_GPIO_Port /*!< GPIO port used for LED AP2P*/ + +#define PLATFORM_USER_BUTTON_PIN 12 /*!< GPIO pin user button */ +#define PLATFORM_USER_BUTTON_PORT B1_GPIO_Port /*!< GPIO port user button */ + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define platformProtectST25R391xComm() taskENTER_CRITICAL(&CommProtectLock) /*!< Protect unique access to ST25R391x communication channel - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */ +#define platformUnprotectST25R391xComm() taskEXIT_CRITICAL(&CommProtectLock) /*!< Unprotect unique access to ST25R391x communication channel - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */ + +#define platformProtectST25R391xIrqStatus() platformProtectST25R391xComm() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */ +#define platformUnprotectST25R391xIrqStatus() platformUnprotectST25R391xComm() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */ + +#define platformProtectWorker() /* Protect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */ +#define platformUnprotectWorker() /* Unprotect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */ + + +#define platformIrqST25R3911SetCallback( cb ) +#define platformIrqST25R3911PinInitialize() + +#define platformIrqST25R3916SetCallback( cb ) +#define platformIrqST25R3916PinInitialize() + + +#define platformLedsInitialize() /*!< Initializes the pins used as LEDs to outputs*/ + +#define platformLedOff( port, pin ) platformGpioClear((port), (pin)) /*!< Turns the given LED Off */ +#define platformLedOn( port, pin ) platformGpioSet((port), (pin)) /*!< Turns the given LED On */ +#define platformLedToogle( port, pin ) platformGpioToogle((port), (pin)) /*!< Toogle the given LED */ + +#define platformGpioSet( port, pin ) ESP_ERROR_CHECK(gpio_set_level(pin, 1)) /*!< Turns the given GPIO High */ +#define platformGpioClear( port, pin ) ESP_ERROR_CHECK(gpio_set_level(pin, 0)) /*!< Turns the given GPIO Low */ +#define platformGpioToogle( port, pin ) ESP_ERROR_CHECK(gpio_set_level(pin, !gpio_get_level(pin))) /*!< Toogles the given GPIO */ +#define platformGpioIsHigh( port, pin ) (gpio_get_level(pin)) /*!< Checks if the given LED is High */ +#define platformGpioIsLow( port, pin ) (!platformGpioIsHigh(port, pin)) /*!< Checks if the given LED is Low */ + +#define platformTimerCreate( t ) timerCalculateTimer(t) /*!< Create a timer with the given time (ms) */ +#define platformTimerIsExpired( timer ) timerIsExpired(timer) /*!< Checks if the given timer is expired */ +#define platformDelay( t ) vTaskDelay(pdMS_TO_TICKS(t)) /*!< Performs a delay for the given time (ms) */ + +#define platformGetSysTick() pdTICKS_TO_MS(xTaskGetTickCount()) /*!< Get System Tick ( 1 tick = 1 ms) */ + +#define platformSpiSelect() platformGpioClear( ST25R391X_SS_PORT, ST25R391X_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Select */ +#define platformSpiDeselect() platformGpioSet( ST25R391X_SS_PORT, ST25R391X_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Deselect */ +#define platformSpiTxRx( txBuf, rxBuf, len ) st25r3911_spiTxRx( (txBuf), (rxBuf), (len) ) /*!< SPI transceive */ + + +#define platformI2CTx( txBuf, len ) /*!< I2C Transmit */ +#define platformI2CRx( txBuf, len ) /*!< I2C Receive */ +#define platformI2CStart() /*!< I2C Start condition */ +#define platformI2CStop() /*!< I2C Stop condition */ +#define platformI2CRepeatStart() /*!< I2C Repeat Start */ +#define platformI2CSlaveAddrWR(add) /*!< I2C Slave address for Write operation */ +#define platformI2CSlaveAddrRD(add) /*!< I2C Slave address for Read operation */ + +#define platformLog(...) ESP_LOGI("RFAL",__VA_ARGS__) /*!< Log method */ + +/* +****************************************************************************** +* GLOBAL VARIABLES +****************************************************************************** +*/ +extern portMUX_TYPE CommProtectLock; /* Global Protection Counter provided per platform - instantiated in main.c */ + +/* +****************************************************************************** +* RFAL FEATURES CONFIGURATION +****************************************************************************** +*/ + +#define RFAL_FEATURE_LISTEN_MODE false /*!< Enable/Disable RFAL support for Listen Mode */ +#define RFAL_FEATURE_WAKEUP_MODE true /*!< Enable/Disable RFAL support for the Wake-Up mode */ +#define RFAL_FEATURE_NFCA true /*!< Enable/Disable RFAL support for NFC-A (ISO14443A) */ +#define RFAL_FEATURE_NFCB true /*!< Enable/Disable RFAL support for NFC-B (ISO14443B) */ +#define RFAL_FEATURE_NFCF false /*!< Enable/Disable RFAL support for NFC-F (FeliCa) */ +#define RFAL_FEATURE_NFCV false /*!< Enable/Disable RFAL support for NFC-V (ISO15693) */ +#define RFAL_FEATURE_T1T false /*!< Enable/Disable RFAL support for T1T (Topaz) */ +#define RFAL_FEATURE_T2T true /*!< Enable/Disable RFAL support for T2T */ +#define RFAL_FEATURE_T4T true /*!< Enable/Disable RFAL support for T4T */ +#define RFAL_FEATURE_ST25TB false /*!< Enable/Disable RFAL support for ST25TB */ +#define RFAL_FEATURE_ST25xV false /*!< Enable/Disable RFAL support for ST25TV/ST25DV */ +#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG false /*!< Enable/Disable Analog Configs to be dynamically updated (RAM) */ +#define RFAL_FEATURE_DYNAMIC_POWER false /*!< Enable/Disable RFAL dynamic power support */ +#define RFAL_FEATURE_ISO_DEP true /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4) */ +#define RFAL_FEATURE_ISO_DEP_POLL true /*!< Enable/Disable RFAL support for Poller mode (PCD) ISO-DEP (ISO14443-4) */ +#define RFAL_FEATURE_ISO_DEP_LISTEN false /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP (ISO14443-4) */ +#define RFAL_FEATURE_NFC_DEP false /*!< Enable/Disable RFAL support for NFC-DEP (NFCIP1/P2P) */ + + +#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN 256U /*!< ISO-DEP I-Block max length. Please use values as defined by rfalIsoDepFSx */ +#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN 1024U /*!< ISO-DEP APDU max length. Please use multiples of I-Block max length */ + +#endif /* PLATFORM_H */ + + diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911.c b/Software/fab-reader2-c/components/st25r3911/st25r3911.c new file mode 100644 index 0000000..20410a6 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911.c @@ -0,0 +1,656 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief ST25R3911 high level interface + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "st25r3911.h" +#include "st25r3911_com.h" +#include "st25r3911_interrupt.h" +#include "utils.h" + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ + +#define ST25R3911_OSC_STABLE_TIMEOUT 10U /*!< Timeout for Oscillator to get stable, datasheet: 700us, take 5 ms */ +#define ST25R3911_CA_TIMEOUT 10U /*!< Timeout for Collision Avoidance command */ +#define ST25R3911_TOUT_CALIBRATE_CAP_SENSOR 4U /*!< Max duration Calibrate Capacitive Sensor command Datasheet: 3ms */ + +/* +****************************************************************************** +* LOCAL CONSTANTS +****************************************************************************** +*/ + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ +static uint32_t st25r3911NoResponseTime_64fcs; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode st25r3911ExecuteCommandAndGetResult(uint8_t cmd, uint8_t resreg, uint8_t sleeptime, uint8_t* result); + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +void st25r3911TxRxOn( void ) +{ + st25r3911SetRegisterBits(ST25R3911_REG_OP_CONTROL, (ST25R3911_REG_OP_CONTROL_rx_en | ST25R3911_REG_OP_CONTROL_tx_en) ); +} + +void st25r3911TxRxOff( void ) +{ + st25r3911ClrRegisterBits(ST25R3911_REG_OP_CONTROL, (ST25R3911_REG_OP_CONTROL_rx_en | ST25R3911_REG_OP_CONTROL_tx_en) ); +} + + +void st25r3911OscOn( void ) +{ + /* Check if oscillator is already turned on and stable */ + /* Use ST25R3911_REG_OP_CONTROL_en instead of ST25R3911_REG_AUX_DISPLAY_osc_ok to be on the safe side */ + if( !st25r3911CheckReg( ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_en, ST25R3911_REG_OP_CONTROL_en ) ) + { + /* Clear any eventual previous oscillator IRQ */ + st25r3911GetInterrupt( ST25R3911_IRQ_MASK_OSC ); + + /* enable oscillator frequency stable interrupt */ + st25r3911EnableInterrupts(ST25R3911_IRQ_MASK_OSC); + + /* enable oscillator and regulator output */ + st25r3911ModifyRegister(ST25R3911_REG_OP_CONTROL, 0x00, ST25R3911_REG_OP_CONTROL_en); + + /* wait for the oscillator interrupt */ + st25r3911WaitForInterruptsTimed(ST25R3911_IRQ_MASK_OSC, ST25R3911_OSC_STABLE_TIMEOUT); + st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_OSC); + } + +} + + +void st25r3911Initialize(void) +{ + uint16_t vdd_mV; + + /* first, reset the st25r3911 */ + st25r3911ExecuteCommand(ST25R3911_CMD_SET_DEFAULT); + + /* Set Operation Control Register to default value */ + st25r3911WriteRegister(ST25R3911_REG_OP_CONTROL, 0x00); + + /* enable pull downs on miso line */ + st25r3911ModifyRegister(ST25R3911_REG_IO_CONF2, 0, + ST25R3911_REG_IO_CONF2_miso_pd1 | + ST25R3911_REG_IO_CONF2_miso_pd2); + + /* after reset all interrupts are enabled. so disable them at first */ + st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_ALL); + /* and clear them, just to be sure... */ + st25r3911ClearInterrupts(); + + st25r3911OscOn(); + + /* Measure vdd and set sup3V bit accordingly */ + vdd_mV = st25r3911MeasureVoltage(ST25R3911_REG_REGULATOR_CONTROL_mpsv_vdd); + + st25r3911ModifyRegister(ST25R3911_REG_IO_CONF2, + ST25R3911_REG_IO_CONF2_sup3V, + (uint8_t)((vdd_mV < 3600U)?ST25R3911_REG_IO_CONF2_sup3V:0U)); + + /* Make sure Transmitter and Receiver are disabled */ + st25r3911TxRxOff(); + + return; +} + +void st25r3911Deinitialize(void) +{ + st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_ALL); + + /* Disabe Tx and Rx, Keep OSC */ + st25r3911TxRxOff(); + + return; +} + +ReturnCode st25r3911AdjustRegulators(uint16_t* result_mV) +{ + uint8_t result; + uint8_t io_conf2; + ReturnCode err = ERR_NONE; + + /* Reset logic and set regulated voltages to be defined by result of Adjust Regulators command */ + st25r3911SetRegisterBits( ST25R3911_REG_REGULATOR_CONTROL, ST25R3911_REG_REGULATOR_CONTROL_reg_s ); + st25r3911ClrRegisterBits( ST25R3911_REG_REGULATOR_CONTROL, ST25R3911_REG_REGULATOR_CONTROL_reg_s ); + + st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_ADJUST_REGULATORS, + ST25R3911_REG_REGULATOR_RESULT, + 5, + &result); + + st25r3911ReadRegister(ST25R3911_REG_IO_CONF2, &io_conf2); + + result >>= ST25R3911_REG_REGULATOR_RESULT_shift_reg; + result -= 5U; + if (result_mV != NULL) + { + if((io_conf2 & ST25R3911_REG_IO_CONF2_sup3V) != 0U) + { + *result_mV = 2400; + *result_mV += (uint16_t)result * 100U; + } + else + { + *result_mV = 3900; + *result_mV += (uint16_t)result * 120U; + } + } + return err; +} + +void st25r3911MeasureAmplitude(uint8_t* result) +{ + st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_MEASURE_AMPLITUDE, + ST25R3911_REG_AD_RESULT, + 10, + result); +} + +void st25r3911MeasurePhase(uint8_t* result) +{ + st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_MEASURE_PHASE, + ST25R3911_REG_AD_RESULT, + 10, + result); +} + +void st25r3911MeasureCapacitance(uint8_t* result) +{ + st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_MEASURE_CAPACITANCE, + ST25R3911_REG_AD_RESULT, + 10, + result); +} + +void st25r3911CalibrateAntenna(uint8_t* result) +{ + st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_CALIBRATE_ANTENNA, + ST25R3911_REG_ANT_CAL_RESULT, + 10, + result); +} + +void st25r3911CalibrateModulationDepth(uint8_t* result) +{ + st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_CALIBRATE_MODULATION, + ST25R3911_REG_AM_MOD_DEPTH_RESULT, + 10, + result); +} + + +ReturnCode st25r3911CalibrateCapacitiveSensor(uint8_t* result) +{ + ReturnCode ret; + uint8_t res; + + /* Clear Manual calibration values to enable automatic calibration mode */ + st25r3911ClrRegisterBits( ST25R3911_REG_CAP_SENSOR_CONTROL, ST25R3916_REG_CAP_SENSOR_CONTROL_mask_cs_mcal ); + + /* Execute automatic calibration */ + ret = st25r3911ExecuteCommandAndGetResult( ST25R3911_CMD_CALIBRATE_C_SENSOR, ST25R3911_REG_CAP_SENSOR_RESULT, ST25R3911_TOUT_CALIBRATE_CAP_SENSOR, &res ); + + /* Check wether the calibration was successull */ + if( ((res & ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_end) != ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_end) || + ((res & ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_err) == ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_err) || (ret != ERR_NONE) ) + { + return ERR_IO; + } + + if( result != NULL ) + { + (*result) = (uint8_t)(res >> ST25R3911_REG_CAP_SENSOR_CONTROL_shift_cs_mcal); + } + + return ERR_NONE; +} + + +ReturnCode st25r3911SetBitrate(uint8_t txRate, uint8_t rxRate) +{ + uint8_t reg; + + st25r3911ReadRegister(ST25R3911_REG_BIT_RATE, ®); + if (rxRate != ST25R3911_BR_DO_NOT_SET) + { + if(rxRate > ST25R3911_BR_3390) + { + return ERR_PARAM; + } + else + { + reg = (uint8_t)(reg & ~ST25R3911_REG_BIT_RATE_mask_rxrate); /* MISRA 10.3 */ + reg |= rxRate << ST25R3911_REG_BIT_RATE_shift_rxrate; + } + } + if (txRate != ST25R3911_BR_DO_NOT_SET) + { + if(txRate > ST25R3911_BR_6780) + { + return ERR_PARAM; + } + else + { + reg = (uint8_t)(reg & ~ST25R3911_REG_BIT_RATE_mask_txrate); /* MISRA 10.3 */ + reg |= txRate<> ST25R3911_REG_FIFO_RX_STATUS2_shift_fifo_lb); +} + +uint32_t st25r3911GetNoResponseTime_64fcs(void) +{ + return st25r3911NoResponseTime_64fcs; +} + +void st25r3911StartGPTimer_8fcs(uint16_t gpt_8fcs, uint8_t trigger_source) +{ + st25r3911SetGPTime_8fcs(gpt_8fcs); + + st25r3911ModifyRegister(ST25R3911_REG_GPT_CONTROL, + ST25R3911_REG_GPT_CONTROL_gptc_mask, + trigger_source); + if (trigger_source == 0U) + { + st25r3911ExecuteCommand(ST25R3911_CMD_START_GP_TIMER); + } + + return; +} + +void st25r3911SetGPTime_8fcs(uint16_t gpt_8fcs) +{ + st25r3911WriteRegister(ST25R3911_REG_GPT1, (uint8_t)(gpt_8fcs >> 8)); + st25r3911WriteRegister(ST25R3911_REG_GPT2, (uint8_t)(gpt_8fcs & 0xffU)); + + return; +} + +bool st25r3911CheckReg( uint8_t reg, uint8_t mask, uint8_t value ) +{ + uint8_t regVal; + + regVal = 0; + st25r3911ReadRegister( reg, ®Val ); + + return ((regVal & mask) == value ); +} + + +bool st25r3911CheckChipID( uint8_t *rev ) +{ + uint8_t ID; + + ID = 0; + st25r3911ReadRegister( ST25R3911_REG_IC_IDENTITY, &ID ); + + platformLog("Chip ID: 0x%02x", ID); + /* Check if IC Identity Register contains ST25R3911's IC type code */ + if( (ID & ST25R3911_REG_IC_IDENTITY_mask_ic_type) != ST25R3911_REG_IC_IDENTITY_ic_type ) + { + return false; + } + + if(rev != NULL) + { + *rev = (ID & ST25R3911_REG_IC_IDENTITY_mask_ic_rev); + } + + return true; +} + +ReturnCode st25r3911SetNoResponseTime_64fcs(uint32_t nrt_64fcs) +{ + ReturnCode err = ERR_NONE; + uint8_t nrt_step = 0; + uint32_t noResponseTime_64fcs = nrt_64fcs; /* MISRA 17.8: Use intermediate variable */ + + st25r3911NoResponseTime_64fcs = noResponseTime_64fcs; + if (noResponseTime_64fcs > (uint32_t)0xFFFFU) + { + nrt_step = ST25R3911_REG_GPT_CONTROL_nrt_step; + noResponseTime_64fcs = (noResponseTime_64fcs + 63U) / 64U; + if (noResponseTime_64fcs > (uint32_t)0xFFFFU) + { + noResponseTime_64fcs = 0xFFFFU; + err = ERR_PARAM; + } + st25r3911NoResponseTime_64fcs = 64U * noResponseTime_64fcs; + } + + st25r3911ModifyRegister(ST25R3911_REG_GPT_CONTROL, ST25R3911_REG_GPT_CONTROL_nrt_step, nrt_step); + st25r3911WriteRegister(ST25R3911_REG_NO_RESPONSE_TIMER1, (uint8_t)(noResponseTime_64fcs >> 8)); + st25r3911WriteRegister(ST25R3911_REG_NO_RESPONSE_TIMER2, (uint8_t)(noResponseTime_64fcs & 0xffU)); + + return err; +} + +ReturnCode st25r3911SetStartNoResponseTime_64fcs(uint32_t nrt_64fcs) +{ + ReturnCode err; + + err = st25r3911SetNoResponseTime_64fcs( nrt_64fcs ); + if(err == ERR_NONE) + { + st25r3911ExecuteCommand(ST25R3911_CMD_START_NO_RESPONSE_TIMER); + } + + return err; +} + +ReturnCode st25r3911PerformCollisionAvoidance( uint8_t FieldONCmd, uint8_t pdThreshold, uint8_t caThreshold, uint8_t nTRFW ) +{ + uint8_t treMask; + uint32_t irqs; + + if( (FieldONCmd != ST25R3911_CMD_INITIAL_RF_COLLISION) && + (FieldONCmd != ST25R3911_CMD_RESPONSE_RF_COLLISION_0) && + (FieldONCmd != ST25R3911_CMD_RESPONSE_RF_COLLISION_N) ) + { + return ERR_PARAM; + } + + /* Check if new thresholds are to be applied */ + if( (pdThreshold != ST25R3911_THRESHOLD_DO_NOT_SET) || (caThreshold != ST25R3911_THRESHOLD_DO_NOT_SET) ) + { + treMask = 0; + + if(pdThreshold != ST25R3911_THRESHOLD_DO_NOT_SET) + { + treMask |= ST25R3911_REG_FIELD_THRESHOLD_mask_trg; + } + + if(caThreshold != ST25R3911_THRESHOLD_DO_NOT_SET) + { + treMask |= ST25R3911_REG_FIELD_THRESHOLD_mask_rfe; + } + + /* Set Detection Threshold and|or Collision Avoidance Threshold */ + st25r3911ChangeRegisterBits( ST25R3911_REG_FIELD_THRESHOLD, treMask, (pdThreshold & ST25R3911_REG_FIELD_THRESHOLD_mask_trg) | (caThreshold & ST25R3911_REG_FIELD_THRESHOLD_mask_rfe ) ); + } + + /* Set n x TRFW */ + st25r3911ModifyRegister(ST25R3911_REG_AUX, ST25R3911_REG_AUX_mask_nfc_n, (nTRFW & ST25R3911_REG_AUX_mask_nfc_n) ); + + /* Enable and clear CA specific interrupts and execute command */ + st25r3911EnableInterrupts( (ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT) ); + st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT) ); + + st25r3911ExecuteCommand(FieldONCmd); + + irqs = st25r3911WaitForInterruptsTimed(ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT, ST25R3911_CA_TIMEOUT ); + + /* Clear any previous External Field events and disable CA specific interrupts */ + st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_EON) ); + st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT); + + + if((ST25R3911_IRQ_MASK_CAC & irqs) != 0U) /* Collision occurred */ + { + return ERR_RF_COLLISION; + } + + if((ST25R3911_IRQ_MASK_CAT & irqs) != 0U) /* No Collision detected, Field On */ + { + return ERR_NONE; + } + + /* No interrupt detected */ + return ERR_INTERNAL; +} + +ReturnCode st25r3911GetRegsDump(uint8_t* resRegDump, uint8_t* sizeRegDump) +{ + uint8_t regIt; + uint8_t regDump[ST25R3911_REG_IC_IDENTITY+1U]; + + if(!sizeRegDump || !resRegDump) + { + return ERR_PARAM; + } + + for( regIt = ST25R3911_REG_IO_CONF1; regIt < SIZEOF_ARRAY(regDump); regIt++ ) + { + st25r3911ReadRegister(regIt, ®Dump[regIt] ); + } + + *sizeRegDump = MIN(*sizeRegDump, regIt); + if( *sizeRegDump > 0U ) /* MISRA 21.18 */ + { + ST_MEMCPY(resRegDump, regDump, *sizeRegDump ); + } + + return ERR_NONE; +} + + +void st25r3911SetNumTxBits( uint32_t nBits ) +{ + st25r3911WriteRegister(ST25R3911_REG_NUM_TX_BYTES2, (uint8_t)((nBits >> 0) & 0xffU)); + st25r3911WriteRegister(ST25R3911_REG_NUM_TX_BYTES1, (uint8_t)((nBits >> 8) & 0xffU)); +} + + +bool st25r3911IsCmdValid( uint8_t cmd ) +{ + if( !((cmd >= ST25R3911_CMD_SET_DEFAULT) && (cmd <= ST25R3911_CMD_ANALOG_PRESET)) && + !((cmd >= ST25R3911_CMD_MASK_RECEIVE_DATA) && (cmd <= ST25R3911_CMD_CLEAR_RSSI)) && + !((cmd >= ST25R3911_CMD_TRANSPARENT_MODE) && (cmd <= ST25R3911_CMD_START_NO_RESPONSE_TIMER)) && + !((cmd >= ST25R3911_CMD_TEST_CLEARA) && (cmd <= ST25R3911_CMD_FUSE_PPROM)) ) + { + return false; + } + return true; +} + +ReturnCode st25r3911StreamConfigure(const struct st25r3911StreamConfig *config) +{ + uint8_t smd = 0; + uint8_t mode; + + if (config->useBPSK != 0U) + { + mode = ST25R3911_REG_MODE_om_bpsk_stream; + if ((config->din<2U) || (config->din>4U)) /* not in fc/4 .. fc/16 */ + { + return ERR_PARAM; + } + smd |= (4U - config->din) << ST25R3911_REG_STREAM_MODE_shift_scf; + + } + else + { + mode = ST25R3911_REG_MODE_om_subcarrier_stream; + if ((config->din<3U) || (config->din>6U)) /* not in fc/8 .. fc/64 */ + { + return ERR_PARAM; + } + smd |= (6U - config->din) << ST25R3911_REG_STREAM_MODE_shift_scf; + if (config->report_period_length == 0U) + { + return ERR_PARAM; + } + } + + if ((config->dout<1U) || (config->dout>7U)) /* not in fc/2 .. fc/128 */ + { + return ERR_PARAM; + } + smd |= (7U - config->dout) << ST25R3911_REG_STREAM_MODE_shift_stx; + + if (config->report_period_length > 3U) + { + return ERR_PARAM; + } + smd |= config->report_period_length << ST25R3911_REG_STREAM_MODE_shift_scp; + + st25r3911WriteRegister(ST25R3911_REG_STREAM_MODE, smd); + st25r3911ChangeRegisterBits(ST25R3911_REG_MODE, ST25R3911_REG_MODE_mask_om, mode); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3911GetRSSI( uint16_t *amRssi, uint16_t *pmRssi ) +{ + /*******************************************************************************/ + /* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */ + /*< ST25R3911 RSSI Display Reg values:0 1 2 3 4 5 6 7 8 9 a b c d e f */ + const uint16_t st25r3911Rssi2mV[] = { 0 ,20 ,27 ,37 ,52 ,72 ,99 ,136 ,190 ,262 ,357 ,500 ,686 ,950, 0, 0 }; + + /* ST25R3911 2/3 stage gain reduction [dB] 0 0 0 0 0 3 6 9 12 15 18 na na na na na */ + const uint16_t st25r3911Gain2Percent[] = { 100, 100, 100, 100, 100, 141, 200, 281, 398, 562, 794, 1, 1, 1, 1, 1 }; + /*******************************************************************************/ + + uint8_t rssi; + uint8_t gainRed; + + st25r3911ReadRegister( ST25R3911_REG_RSSI_RESULT, &rssi ); + st25r3911ReadRegister( ST25R3911_REG_GAIN_RED_STATE, &gainRed ); + + if( amRssi != NULL ) + { + *amRssi = (uint16_t) ( ( (uint32_t)st25r3911Rssi2mV[ (rssi >> ST25R3911_REG_RSSI_RESULT_shift_rssi_am) ] * (uint32_t)st25r3911Gain2Percent[ (gainRed >> ST25R3911_REG_GAIN_RED_STATE_shift_gs_am) ] ) / 100U ); + } + + if( pmRssi != NULL ) + { + *pmRssi = (uint16_t) ( ( (uint32_t)st25r3911Rssi2mV[ (rssi & ST25R3911_REG_RSSI_RESULT_mask_rssi_pm) ] * (uint32_t)st25r3911Gain2Percent[ (gainRed & ST25R3911_REG_GAIN_RED_STATE_mask_gs_pm) ] ) / 100U ); + } + + return ERR_NONE; +} + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Executes a direct command and returns the result + * + * This function executes the direct command given by \a cmd waits for + * \a sleeptime for I_dct and returns the result read from register \a resreg. + * No checking of the validity of the cmd is performed. + * + * \param[in] cmd: direct command to execute. + * \param[in] resreg: Address of the register containing the result. + * \param[in] sleeptime: time in milliseconds to wait before reading the result. + * \param[out] result: 8 bit long result + * + ***************************************************************************** + */ +static ReturnCode st25r3911ExecuteCommandAndGetResult(uint8_t cmd, uint8_t resreg, uint8_t sleeptime, uint8_t* result) +{ + + st25r3911EnableInterrupts(ST25R3911_IRQ_MASK_DCT); + st25r3911GetInterrupt(ST25R3911_IRQ_MASK_DCT); + st25r3911ExecuteCommand(cmd); + st25r3911WaitForInterruptsTimed(ST25R3911_IRQ_MASK_DCT, sleeptime); + st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_DCT); + + /* read out the result if the pointer is not NULL */ + if (result != NULL) + { + st25r3911ReadRegister(resreg, result); + } + + return ERR_NONE; +} diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911.h b/Software/fab-reader2-c/components/st25r3911/st25r3911.h new file mode 100644 index 0000000..3a81b34 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911.h @@ -0,0 +1,601 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief ST25R3911 declaration file + * + * API: + * - Initialize ST25R3911 driver: #st25r3911Initialize + * - Deinitialize ST25R3911 driver: #st25r3911Deinitialize + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3911 + * \brief RFAL ST25R3911 Driver + * @{ + * + * \addtogroup ST25R3911_Driver + * \brief RFAL ST25R3911 Driver + * @{ + * + */ + +#ifndef ST25R3911_H +#define ST25R3911_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" +#include "st_errno.h" + +/* +****************************************************************************** +* GLOBAL DATATYPES +****************************************************************************** +*/ + +/*! Parameters how the stream mode should work */ +struct st25r3911StreamConfig { + uint8_t useBPSK; /*!< 0: subcarrier, 1:BPSK */ + uint8_t din; /*!< the divider for the in subcarrier frequency: fc/2^din */ + uint8_t dout; /*!< the divider for the in subcarrier frequency fc/2^dout */ + uint8_t report_period_length; /*!< the length of the reporting period 2^report_period_length */ +}; + + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define ST25R3911_FDT_NONE 0x00U /*!< Value indicating not to perform FDT */ + +#define MS_TO_64FCS(A) ((A) * 212U) /*!< Converts from ms to 64/fc steps */ +#define MS_FROM_64FCS(A) ((A) / 212U) /*!< Converts from 64/fc steps to ms */ + +/* ST25R3911 direct commands */ +#define ST25R3911_CMD_SET_DEFAULT 0xC1U /*!< Puts the chip in default state (same as after power-up) */ +#define ST25R3911_CMD_CLEAR_FIFO 0xC2U /*!< Stops all activities and clears FIFO */ +#define ST25R3911_CMD_TRANSMIT_WITH_CRC 0xC4U /*!< Transmit with CRC */ +#define ST25R3911_CMD_TRANSMIT_WITHOUT_CRC 0xC5U /*!< Transmit without CRC */ +#define ST25R3911_CMD_TRANSMIT_REQA 0xC6U /*!< Transmit REQA */ +#define ST25R3911_CMD_TRANSMIT_WUPA 0xC7U /*!< Transmit WUPA */ +#define ST25R3911_CMD_INITIAL_RF_COLLISION 0xC8U /*!< NFC transmit with Initial RF Collision Avoidance */ +#define ST25R3911_CMD_RESPONSE_RF_COLLISION_N 0xC9U /*!< NFC transmit with Response RF Collision Avoidance */ +#define ST25R3911_CMD_RESPONSE_RF_COLLISION_0 0xCAU /*!< NFC transmit with Response RF Collision Avoidance with n=0 */ +#define ST25R3911_CMD_NORMAL_NFC_MODE 0xCBU /*!< NFC switch to normal NFC mode */ +#define ST25R3911_CMD_ANALOG_PRESET 0xCCU /*!< Analog Preset */ +#define ST25R3911_CMD_MASK_RECEIVE_DATA 0xD0U /*!< Mask recive data */ +#define ST25R3911_CMD_UNMASK_RECEIVE_DATA 0xD1U /*!< Unmask recive data */ +#define ST25R3911_CMD_MEASURE_AMPLITUDE 0xD3U /*!< Measure singal amplitude on RFI inputs */ +#define ST25R3911_CMD_SQUELCH 0xD4U /*!< Squelch */ +#define ST25R3911_CMD_CLEAR_SQUELCH 0xD5U /*!< Clear Squelch */ +#define ST25R3911_CMD_ADJUST_REGULATORS 0xD6U /*!< Adjust regulators */ +#define ST25R3911_CMD_CALIBRATE_MODULATION 0xD7U /*!< Calibrate modulation depth */ +#define ST25R3911_CMD_CALIBRATE_ANTENNA 0xD8U /*!< Calibrate antenna */ +#define ST25R3911_CMD_MEASURE_PHASE 0xD9U /*!< Measure phase between RFO and RFI signal */ +#define ST25R3911_CMD_CLEAR_RSSI 0xDAU /*!< clear RSSI bits and restart the measurement */ +#define ST25R3911_CMD_TRANSPARENT_MODE 0xDCU /*!< Transparent mode */ +#define ST25R3911_CMD_CALIBRATE_C_SENSOR 0xDDU /*!< Calibrate the capacitive sensor */ +#define ST25R3911_CMD_MEASURE_CAPACITANCE 0xDEU /*!< Measure capacitance */ +#define ST25R3911_CMD_MEASURE_VDD 0xDFU /*!< Measure power supply voltage */ +#define ST25R3911_CMD_START_GP_TIMER 0xE0U /*!< Start the general purpose timer */ +#define ST25R3911_CMD_START_WUP_TIMER 0xE1U /*!< Start the wake-up timer */ +#define ST25R3911_CMD_START_MASK_RECEIVE_TIMER 0xE2U /*!< Start the mask-receive timer */ +#define ST25R3911_CMD_START_NO_RESPONSE_TIMER 0xE3U /*!< Start the no-repsonse timer */ +#define ST25R3911_CMD_TEST_CLEARA 0xFAU /*!< Clear Test register */ +#define ST25R3911_CMD_TEST_CLEARB 0xFBU /*!< Clear Test register */ +#define ST25R3911_CMD_TEST_ACCESS 0xFCU /*!< Enable R/W access to the test registers */ +#define ST25R3911_CMD_LOAD_PPROM 0xFDU /*!< Load data from the poly fuses to RAM */ +#define ST25R3911_CMD_FUSE_PPROM 0xFEU /*!< Fuse poly fuses with data from the RAM */ + + +#define ST25R3911_FIFO_DEPTH 96U /*!< Depth of FIFO */ + +#define ST25R3911_THRESHOLD_DO_NOT_SET 0xFFU /*!< Indicates not to change this Threshold */ + +#define ST25R3911_BR_DO_NOT_SET 0xFFU /*!< Indicates not to change this Bit Rate */ +#define ST25R3911_BR_106 0x00U /*!< ST25R3911 Bit Rate 106 kbit/s (fc/128) */ +#define ST25R3911_BR_212 0x01U /*!< ST25R3911 Bit Rate 212 kbit/s (fc/64) */ +#define ST25R3911_BR_424 0x02U /*!< ST25R3911 Bit Rate 424 kbit/s (fc/32) */ +#define ST25R3911_BR_848 0x03U /*!< ST25R3911 Bit Rate 848 kbit/s (fc/16) */ +#define ST25R3911_BR_1695 0x04U /*!< ST25R3911 Bit Rate 1696 kbit/s (fc/8) */ +#define ST25R3911_BR_3390 0x05U /*!< ST25R3911 Bit Rate 3390 kbit/s (fc/4) */ +#define ST25R3911_BR_6780 0x06U /*!< ST25R3911 Bit Rate 6780 kbit/s (fc/2) */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Checks if General Purpose Timer is still running by reading gpt_on flag */ +#define st25r3911IsGPTRunning( ) ( st25r3911CheckReg(ST25R3911_REG_REGULATOR_RESULT, ST25R3911_REG_REGULATOR_RESULT_gpt_on, ST25R3911_REG_REGULATOR_RESULT_gpt_on) ) + +/*! Checks if CRC is configured to be in FIFO */ +#define st25r3911IsCRCinFIFO( ) ( st25r3911CheckReg(ST25R3911_REG_AUX, ST25R3911_REG_AUX_crc_2_fifo, ST25R3911_REG_AUX_crc_2_fifo) ) + +/*! Checks if External Filed is detected by reading ST25R3911 External Field + * Detector output */ +#define st25r3911IsExtFieldOn() ( st25r3911CheckReg(ST25R3911_REG_AUX_DISPLAY, ST25R3911_REG_AUX_DISPLAY_efd_o, ST25R3911_REG_AUX_DISPLAY_efd_o ) ) + +/*! Checks if Transmitter is enabled (Field On) */ +#define st25r3911IsTxEnabled() ( st25r3911CheckReg(ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_tx_en, ST25R3911_REG_OP_CONTROL_tx_en ) ) + +/*! Turn Off Tx (Field Off) */ +#define st25r3911TxOff() st25r3911ClrRegisterBits(ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_tx_en ); + +/*! Checks if last FIFO byte is complete */ +#define st25r3911IsLastFIFOComplete() st25r3911CheckReg( ST25R3911_REG_FIFO_RX_STATUS2, ST25R3911_REG_FIFO_RX_STATUS2_mask_fifo_lb, 0 ) + +/*! Checks if the Oscillator is enabled */ +#define st25r3911IsOscOn() st25r3911CheckReg( ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_en, ST25R3911_REG_OP_CONTROL_en ) + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Turn on Oscillator and Regulator + * + * This function turn on oscillator and regulator and wait for the oscillator to + * become stable. + * + ***************************************************************************** + */ +extern void st25r3911OscOn( void ); + +/*! + ***************************************************************************** + * \brief Turn On Tx and Rx + * + * This function turns On Tx and Rx (Field On) + * + ***************************************************************************** + */ +extern void st25r3911TxRxOn( void ); + +/*! + ***************************************************************************** + * \brief Turn Off Tx and Rx + * + * This function turns Off Tx and Rx (Field Off) + * + ***************************************************************************** + */ +extern void st25r3911TxRxOff( void ); + +/*! + ***************************************************************************** + * \brief Initialise ST25R3911 driver + * + * This function initialises the ST25R3911 driver. + * + ***************************************************************************** + */ +extern void st25r3911Initialize( void ); + +/*! + ***************************************************************************** + * \brief Deinitialize ST25R3911 driver + * + * Calling this function deinitializes the ST25R3911 driver. + * + ***************************************************************************** + */ +extern void st25r3911Deinitialize( void ); + + +/*! + ***************************************************************************** + * \brief Sets the bitrate registers + * + * This function sets the bitrate register for rx and tx + * + * \param txRate : speed is 2^txrate * 106 kb/s + * 0xff : don't set txrate + * \param rxRate : speed is 2^rxrate * 106 kb/s + * 0xff : don't set rxrate + * + * \return ERR_NONE : No error, both bit rates were set + * \return ERR_PARAM: At least one bit rate was invalid + * + ***************************************************************************** + */ +extern ReturnCode st25r3911SetBitrate( uint8_t txRate, uint8_t rxRate ); + +/*! + ***************************************************************************** + * \brief Adjusts supply regulators according to the current supply voltage + * + * On this function the power level is measured in maximum load conditions and + * the regulated voltage reference is set to 250mV below this level. + * Execution of this function lasts arround 5ms. + * + * The regulated voltages will be set to the result of Adjust Regulators + * + * \param [out] result_mV : Result of calibration in milliVolts. + * + * \return ERR_IO : Error during communication with ST25R3911. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode st25r3911AdjustRegulators( uint16_t* result_mV ); + +/*! + ***************************************************************************** + * \brief Measure Amplitude + * + * This function measured the amplitude on the RFI inputs and stores the + * result in parameter \a result. + * + * \param[out] result: 8 bit long result of RF measurement. + * + ***************************************************************************** + */ +extern void st25r3911MeasureAmplitude( uint8_t* result ); + +/*! + ***************************************************************************** + * \brief Measure Capacitance + * + * This function performs the capacitance measurement and stores the + * result in parameter \a result. + * + * \param[out] result: 8 bit long result of RF measurement. + * + ***************************************************************************** + */ +extern void st25r3911MeasureCapacitance( uint8_t* result ); + +/*! + ***************************************************************************** + * \brief Measure Voltage + * + * This function measures the voltage on one of VDD and VSP_* + * result in parameter \a result. + * + * \param[in] mpsv : one of ST25R3911_REG_REGULATOR_CONTROL_mpsv_vdd + * ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_rf + * ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_a + * or ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_d + * + * \return the measured voltage raw values + * + ***************************************************************************** + */ +extern uint8_t st25r3911MeasurePowerSupply( uint8_t mpsv ); + +/*! + ***************************************************************************** + * \brief Measure Voltage + * + * This function measures the voltage on one of VDD and VSP_* + * result in parameter \a result. + * + * \param[in] mpsv : one of ST25R3911_REG_REGULATOR_CONTROL_mpsv_vdd + * ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_rf + * ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_a + * or ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_d + * + * \return the measured voltage in mV + * + ***************************************************************************** + */ +extern uint16_t st25r3911MeasureVoltage( uint8_t mpsv ); + +/*! + ***************************************************************************** + * \brief Calibrate antenna + * + * This function is used to calibrate the antenna using a special sequence. + * The result is stored in the \a result parameter. + * + * \param[out] result: 8 bit long result of antenna calibration algorithm. + * + ***************************************************************************** + */ +extern void st25r3911CalibrateAntenna( uint8_t* result ); + +/*! + ***************************************************************************** + * \brief Measure Phase + * + * This function performs a Phase measurement. + * The result is stored in the \a result parameter. + * + * \param[out] result: 8 bit long result of the measurement. + * + ***************************************************************************** + */ +extern void st25r3911MeasurePhase( uint8_t* result ); + +/*! + ***************************************************************************** + * \brief Calibrate modulation depth + * + * This function is used to calibrate the modulation depth using a special sequence. + * The result is stored in the \a result parameter. + * + * \param[out] result: 8 bit long result of antenna calibration algorithm. + * + ***************************************************************************** + */ +extern void st25r3911CalibrateModulationDepth( uint8_t* result ); + + +/*! + ***************************************************************************** + * \brief Calibrate Capacitive Sensor + * + * This function performs automatic calibration of the capacitive sensor + * and stores the result in parameter \a result. + * + * \warning To avoid interference with Xtal oscillator and reader magnetic + * field, it is strongly recommended to perform calibration + * in Power-down mode only. + * This method does not modify the Oscillator nor transmitter state, + * these should be configured before by user. + * + * \param[out] result: 5 bit long result of the calibration. + * Binary weighted, step 0.1 pF, max 3.1 pF + * + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_IO : The calibration was not successful + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +extern ReturnCode st25r3911CalibrateCapacitiveSensor( uint8_t* result ); + +/*! + ***************************************************************************** + * \brief set no response time + * + * This function executes sets the no response time to the defines value + * + * \param nrt_64fcs : no response time in 64/fc = 4.72us + * completion interrupt + * + * \return ERR_PARAM : if time is too large + */ +extern ReturnCode st25r3911SetNoResponseTime_64fcs( uint32_t nrt_64fcs ); + +/*! + ***************************************************************************** + * \brief set no response time + * + * This function executes sets and immediately start the no response timer + * to the defines value + * This is used when needs to add more time before timeout whitout Tx + * + * \param nrt_64fcs : no response time in 64/fc = 4.72us + * completion interrupt + * + * \return ERR_PARAM : if time is too large + */ +extern ReturnCode st25r3911SetStartNoResponseTime_64fcs( uint32_t nrt_64fcs ); + +/*! + ***************************************************************************** + * \brief Perform Collision Avoidance + * + * Performs Collision Avoidance with the given threshold and with the + * n number of TRFW + * + * \param[in] FieldONCmd : Field ON command to be executed ST25R3911_CMD_INITIAL_RF_COLLISION + * or ST25R3911_CMD_RESPONSE_RF_COLLISION_0/N + * \param[in] pdThreshold : Peer Detection Threshold (ST25R3916_REG_FIELD_THRESHOLD_trg_xx) + * 0xff : don't set Threshold (ST25R3916_THRESHOLD_DO_NOT_SET) + * \param[in] caThreshold : Collision Avoidance Threshold (ST25R3916_REG_FIELD_THRESHOLD_rfe_xx) + * 0xff : don't set Threshold (ST25R3916_THRESHOLD_DO_NOT_SET) + * \param[in] nTRFW : Number of TRFW + * + * \return ERR_NONE : no collision detected + * \return ERR_RF_COLLISION : collision detected + */ +extern ReturnCode st25r3911PerformCollisionAvoidance( uint8_t FieldONCmd, uint8_t pdThreshold, uint8_t caThreshold, uint8_t nTRFW ); + + +/*! + ***************************************************************************** + * \brief Get amount of bits of the last FIFO byte if incomplete + * + * Gets the number of bits of the last FIFO byte if incomplete + * + * \return the number of bits of the last FIFO byte if incomplete, 0 if + * the last byte is complete + * + ***************************************************************************** + */ +extern uint8_t st25r3911GetNumFIFOLastBits( void ); + +/*! + ***************************************************************************** + * \brief Get NRT time + * + * This returns the last value set on the NRT + * + * \warning it does not reads chip register, just the sw var that contains the + * last value set before + * + * \return the value of the NRT + */ +extern uint32_t st25r3911GetNoResponseTime_64fcs( void ); + +/*! + ***************************************************************************** + * \brief set general purpose timer timeout + * + * This function sets the proper registers but does not start the timer actually + * + * \param gpt_8fcs : general purpose timer timeout in 8/fc = 590ns + * + */ +extern void st25r3911SetGPTime_8fcs( uint16_t gpt_8fcs ); +/*! + ***************************************************************************** + * \brief Starts GPT with given timeout + * + * This function starts the general purpose timer with the given timeout + * + * \param gpt_8fcs : general purpose timer timeout in 8/fc = 590ns + * \param trigger_source : no trigger, start of Rx, end of Rx, end of Tx in NFC mode + */ +extern void st25r3911StartGPTimer_8fcs( uint16_t gpt_8fcs, uint8_t trigger_source ); + +/*! + ***************************************************************************** + * \brief Checks if register contains a expected value + * + * This function checks if the given reg contains a value that once masked + * equals the expected value + * + * \param reg : the register to check the value + * \param mask : the mask apply on register value + * \param value : expected value to be compared to + * + * \return true when reg contains the expected value | false otherwise + */ +bool st25r3911CheckReg( uint8_t reg, uint8_t mask, uint8_t value ); + +/*! + ***************************************************************************** + * \brief Sets the number Tx Bits + * + * Sets ST25R3911 internal registers with correct number of complete bytes and + * bits to be sent + * + * \param nBits : the number bits to be transmitted + ***************************************************************************** + */ +void st25r3911SetNumTxBits( uint32_t nBits ); + +/*! + ***************************************************************************** + * \brief Check Identity + * + * Checks if the chip ID is as expected. + * + * 5 bit IC type code for ST25R3911: 00001 + * The 3 lsb contain the IC revision code + * + * + * \param[out] rev : the IC revision code + * + * \return true when IC type is as expected + * + ***************************************************************************** + */ +bool st25r3911CheckChipID( uint8_t *rev ); + +/*! + ***************************************************************************** + * \brief Check if command is valid + * + * Checks if the given command is a valid ST25R3911 command + * + * \param[in] cmd: Command to check + * + * \return true if is a valid command + * \return false otherwise + * + ***************************************************************************** + */ +bool st25r3911IsCmdValid( uint8_t cmd ); + +/*! + ***************************************************************************** + * \brief Configure the stream mode of ST25R3911 + * + * This function initializes the stream with the given parameters + * + * \param[in] config : all settings for bitrates, type, etc. + + * \return ERR_NONE : No error, stream mode driver initialized. + * + ***************************************************************************** + */ +extern ReturnCode st25r3911StreamConfigure( const struct st25r3911StreamConfig *config ); + +/*! + ***************************************************************************** + * \brief Retrieves all internal registers from st25r3911 + */ +extern ReturnCode st25r3911GetRegsDump( uint8_t* resRegDump, uint8_t* sizeRegDump ); + + +/*! + ***************************************************************************** + * \brief Gets the RSSI values + * + * This function gets the RSSI value of the previous reception taking into + * account the gain reductions that were used. + * RSSI value for both AM and PM channel can be retrieved. + * + * \param[out] amRssi: the RSSI on the AM channel expressed in mV + * \param[out] pmRssi: the RSSI on the PM channel expressed in mV + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3911GetRSSI( uint16_t *amRssi, uint16_t *pmRssi ); + + +#endif /* ST25R3911_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ + diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911_com.c b/Software/fab-reader2-c/components/st25r3911/st25r3911_com.c new file mode 100644 index 0000000..4ee4ac7 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911_com.c @@ -0,0 +1,457 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief Implementation of ST25R3911 communication. + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "st25r3911_com.h" +#include "st25r3911.h" +#include "utils.h" + + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ + +#define ST25R3911_WRITE_MODE (0U) /*!< ST25R3911 SPI Operation Mode: Write */ +#define ST25R3911_READ_MODE (1U << 6) /*!< ST25R3911 SPI Operation Mode: Read */ +#define ST25R3911_FIFO_LOAD (2U << 6) /*!< ST25R3911 SPI Operation Mode: FIFO Load */ +#define ST25R3911_FIFO_READ (0xBFU) /*!< ST25R3911 SPI Operation Mode: FIFO Read */ +#define ST25R3911_CMD_MODE (3U << 6) /*!< ST25R3911 SPI Operation Mode: Direct Command */ + +#define ST25R3911_CMD_LEN (1U) /*!< ST25R3911 CMD length */ +#define ST25R3911_BUF_LEN (ST25R3911_CMD_LEN+ST25R3911_FIFO_DEPTH) /*!< ST25R3911 communication buffer: CMD + FIFO length */ + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +#ifdef ST25R391X_COM_SINGLETXRX +static uint8_t comBuf[ST25R3911_BUF_LEN]; /*!< ST25R3911 communication buffer */ +#endif /* ST25R391X_COM_SINGLETXRX */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +static inline void st25r3911CheckFieldSetLED(uint8_t value) +{ + if ((ST25R3911_REG_OP_CONTROL_tx_en & value) != 0U) + { +#ifdef PLATFORM_LED_FIELD_PIN + platformLedOn( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN ); + } + else + { + platformLedOff( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN ); +#endif /* PLATFORM_LED_FIELD_PIN */ + } +} + + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +void st25r3911ReadRegister(uint8_t reg, uint8_t* value) +{ +#ifdef ST25R391X_COM_SINGLETXRX + uint8_t* buf = comBuf; +#else /* ST25R391X_COM_SINGLETXRX */ + uint8_t buf[2]; +#endif /* ST25R391X_COM_SINGLETXRX */ + + platformProtectST25R391xComm(); + platformSpiSelect(); + + buf[0] = (reg | ST25R3911_READ_MODE); + buf[1] = 0; + + platformSpiTxRx(buf, buf, 2); + + if(value != NULL) + { + *value = buf[1]; + } + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + + return; +} + + +void st25r3911ReadMultipleRegisters(uint8_t reg, uint8_t* values, uint8_t length) +{ +#if !defined(ST25R391X_COM_SINGLETXRX) + uint8_t cmd = (reg | ST25R3911_READ_MODE); +#endif /* !ST25R391X_COM_SINGLETXRX */ + + if (length > 0U) + { + platformProtectST25R391xComm(); + platformSpiSelect(); + +#ifdef ST25R391X_COM_SINGLETXRX + + ST_MEMSET( comBuf, 0x00, MIN( (ST25R3911_CMD_LEN + (uint32_t)length), ST25R3911_BUF_LEN ) ); + comBuf[0] = (reg | ST25R3911_READ_MODE); + + platformSpiTxRx(comBuf, comBuf, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) ); /* Transceive as a single SPI call */ + ST_MEMCPY( values, &comBuf[ST25R3911_CMD_LEN], MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) ); /* Copy from local buf to output buffer and skip cmd byte */ + +#else /* ST25R391X_COM_SINGLETXRX */ + + /* Since the result comes one byte later, let's first transmit the adddress with discarding the result */ + platformSpiTxRx(&cmd, NULL, ST25R3911_CMD_LEN); + platformSpiTxRx(NULL, values, length); + +#endif /* ST25R391X_COM_SINGLETXRX */ + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + } + + return; +} + +void st25r3911ReadTestRegister(uint8_t reg, uint8_t* value) +{ + +#ifdef ST25R391X_COM_SINGLETXRX + uint8_t* buf = comBuf; +#else /* ST25R391X_COM_SINGLETXRX */ + uint8_t buf[3]; +#endif /* ST25R391X_COM_SINGLETXRX */ + + platformProtectST25R391xComm(); + platformSpiSelect(); + + buf[0] = ST25R3911_CMD_TEST_ACCESS; + buf[1] = (reg | ST25R3911_READ_MODE); + buf[2] = 0x00; + + platformSpiTxRx(buf, buf, 3); + + if(value != NULL) + { + *value = buf[2]; + } + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + + return; +} + +void st25r3911WriteTestRegister(uint8_t reg, uint8_t value) +{ +#ifdef ST25R391X_COM_SINGLETXRX + uint8_t* buf = comBuf; +#else /* ST25R391X_COM_SINGLETXRX */ + uint8_t buf[3]; +#endif /* ST25R391X_COM_SINGLETXRX */ + + platformProtectST25R391xComm(); + platformSpiSelect(); + + buf[0] = ST25R3911_CMD_TEST_ACCESS; + buf[1] = (reg | ST25R3911_WRITE_MODE); + buf[2] = value; + + platformSpiTxRx(buf, NULL, 3); + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + + return; +} + +void st25r3911WriteRegister(uint8_t reg, uint8_t value) +{ +#ifdef ST25R391X_COM_SINGLETXRX + uint8_t* buf = comBuf; +#else /* ST25R391X_COM_SINGLETXRX */ + uint8_t buf[2]; +#endif /* ST25R391X_COM_SINGLETXRX */ + + if (ST25R3911_REG_OP_CONTROL == reg) + { + st25r3911CheckFieldSetLED(value); + } + + platformProtectST25R391xComm(); + platformSpiSelect(); + + buf[0] = reg | ST25R3911_WRITE_MODE; + buf[1] = value; + + platformSpiTxRx(buf, NULL, 2); + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + + return; +} + +void st25r3911ClrRegisterBits( uint8_t reg, uint8_t clr_mask ) +{ + uint8_t tmp; + + st25r3911ReadRegister(reg, &tmp); + tmp &= ~clr_mask; + st25r3911WriteRegister(reg, tmp); + + return; +} + + +void st25r3911SetRegisterBits( uint8_t reg, uint8_t set_mask ) +{ + uint8_t tmp; + + st25r3911ReadRegister(reg, &tmp); + tmp |= set_mask; + st25r3911WriteRegister(reg, tmp); + + return; +} + +void st25r3911ChangeRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value) +{ + st25r3911ModifyRegister(reg, valueMask, (valueMask & value) ); +} + +void st25r3911ModifyRegister(uint8_t reg, uint8_t clr_mask, uint8_t set_mask) +{ + uint8_t tmp; + + st25r3911ReadRegister(reg, &tmp); + + /* mask out the bits we don't want to change */ + tmp &= ~clr_mask; + /* set the new value */ + tmp |= set_mask; + st25r3911WriteRegister(reg, tmp); + + return; +} + +void st25r3911ChangeTestRegisterBits( uint8_t reg, uint8_t valueMask, uint8_t value ) +{ + uint8_t rdVal; + uint8_t wrVal; + + /* Read current reg value */ + st25r3911ReadTestRegister(reg, &rdVal); + + /* Compute new value */ + wrVal = (rdVal & ~valueMask); + wrVal |= (value & valueMask); + + /* Write new reg value */ + st25r3911WriteTestRegister(reg, wrVal ); + + return; +} + +void st25r3911WriteMultipleRegisters(uint8_t reg, const uint8_t* values, uint8_t length) +{ +#if !defined(ST25R391X_COM_SINGLETXRX) + uint8_t cmd = (reg | ST25R3911_WRITE_MODE); +#endif /* !ST25R391X_COM_SINGLETXRX */ + + if ((reg <= ST25R3911_REG_OP_CONTROL) && ((reg+length) >= ST25R3911_REG_OP_CONTROL)) + { + st25r3911CheckFieldSetLED(values[ST25R3911_REG_OP_CONTROL-reg]); + } + + if (length > 0U) + { + /* make this operation atomic */ + platformProtectST25R391xComm(); + platformSpiSelect(); + +#ifdef ST25R391X_COM_SINGLETXRX + + comBuf[0] = (reg | ST25R3911_WRITE_MODE); + ST_MEMCPY( &comBuf[ST25R3911_CMD_LEN], values, MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) ); + + platformSpiTxRx( comBuf, NULL, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) ); + +#else /*ST25R391X_COM_SINGLETXRX*/ + + platformSpiTxRx( &cmd, NULL, ST25R3911_CMD_LEN ); + platformSpiTxRx( values, NULL, length ); + +#endif /*ST25R391X_COM_SINGLETXRX*/ + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + } + + return; +} + + +void st25r3911WriteFifo(const uint8_t* values, uint8_t length) +{ +#if !defined(ST25R391X_COM_SINGLETXRX) + uint8_t cmd = ST25R3911_FIFO_LOAD; +#endif /* !ST25R391X_COM_SINGLETXRX */ + + if (length > 0U) + { + platformProtectST25R391xComm(); + platformSpiSelect(); + +#ifdef ST25R391X_COM_SINGLETXRX + + comBuf[0] = ST25R3911_FIFO_LOAD; + ST_MEMCPY( &comBuf[ST25R3911_CMD_LEN], values, MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) ); + + platformSpiTxRx( comBuf, NULL, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) ); + +#else /*ST25R391X_COM_SINGLETXRX*/ + + platformSpiTxRx( &cmd, NULL, ST25R3911_CMD_LEN ); + platformSpiTxRx( values, NULL, length ); + +#endif /*ST25R391X_COM_SINGLETXRX*/ + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + } + + return; +} + +void st25r3911ReadFifo(uint8_t* buf, uint8_t length) +{ +#if !defined(ST25R391X_COM_SINGLETXRX) + uint8_t cmd = ST25R3911_FIFO_READ; +#endif /* !ST25R391X_COM_SINGLETXRX */ + + if(length > 0U) + { + platformProtectST25R391xComm(); + platformSpiSelect(); + +#ifdef ST25R391X_COM_SINGLETXRX + + ST_MEMSET( comBuf, 0x00, MIN( (ST25R3911_CMD_LEN + (uint32_t)length), ST25R3911_BUF_LEN ) ); + comBuf[0] = ST25R3911_FIFO_READ; + + platformSpiTxRx( comBuf, comBuf, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) ); /* Transceive as a single SPI call */ + ST_MEMCPY( buf, &comBuf[ST25R3911_CMD_LEN], MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) ); /* Copy from local buf to output buffer and skip cmd byte */ + +#else /*ST25R391X_COM_SINGLETXRX*/ + + platformSpiTxRx( &cmd, NULL, ST25R3911_CMD_LEN ); + platformSpiTxRx( NULL, buf, length ); + +#endif /*ST25R391X_COM_SINGLETXRX*/ + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + } + + return; +} + +void st25r3911ExecuteCommand( uint8_t cmd ) +{ + uint8_t tmpCmd; /* MISRA 17.8 */ + +#ifdef PLATFORM_LED_FIELD_PIN + if ( (cmd >= ST25R3911_CMD_TRANSMIT_WITH_CRC) && (cmd <= ST25R3911_CMD_RESPONSE_RF_COLLISION_0)) + { + platformLedOff(PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN); + } +#endif /* PLATFORM_LED_FIELD_PIN */ + + tmpCmd = (cmd | ST25R3911_CMD_MODE); + + platformProtectST25R391xComm(); + platformSpiSelect(); + + platformSpiTxRx( &tmpCmd, NULL, ST25R3911_CMD_LEN ); + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + + return; +} + + +void st25r3911ExecuteCommands(const uint8_t *cmds, uint8_t length) +{ + platformProtectST25R391xComm(); + platformSpiSelect(); + + platformSpiTxRx(cmds, NULL, length); + + platformSpiDeselect(); + platformUnprotectST25R391xComm(); + + return; +} + +bool st25r3911IsRegValid( uint8_t reg ) +{ + if( !(( (int16_t)reg >= (int16_t)ST25R3911_REG_IO_CONF1) && (reg <= ST25R3911_REG_CAPACITANCE_MEASURE_RESULT)) && (reg != ST25R3911_REG_IC_IDENTITY) ) + { + return false; + } + return true; +} + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911_com.h b/Software/fab-reader2-c/components/st25r3911/st25r3911_com.h new file mode 100644 index 0000000..c5f540f --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911_com.h @@ -0,0 +1,816 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief ST25R3911 communication declaration file + * + */ +/*! + * This driver provides basic abstraction for communication with the ST25R3911. + * It uses the SPI driver for interfacing with the ST25R3911. + * + * API: + * - Read Register: #st25r3911ReadRegister + * - Modify Register: #st25r3911ModifyRegister + * - Write Register: #st25r3911WriteRegister + * - Write Multiple Registers: #st25r3911WriteMultipleRegisters + * - Load ST25R3911 FIFO with data: #st25r3911WriteFifo + * - Read from ST25R3911 FIFO: #st25r3911ReadFifo + * - Execute direct command: #st25r3911ExecuteCommand + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3911 + * \brief RFAL ST25R3911 Driver + * @{ + * + * \addtogroup ST25R3911_Com + * \brief RFAL ST25R3911 Communication + * @{ + * + */ + +#ifndef ST25R3911_COM_H +#define ST25R3911_COM_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" +#include "st_errno.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define ST25R3911_FIFO_STATUS_LEN 2 /*!< Number of FIFO Status Register */ + + + + +#define ST25R3911_REG_IO_CONF1 0x00U /*!< RW IO Configuration Register 1 */ +#define ST25R3911_REG_IO_CONF2 0x01U /*!< RW IO Configuration Register 2 */ + +#define ST25R3911_REG_OP_CONTROL 0x02U /*!< RW Operation Control Register */ +#define ST25R3911_REG_MODE 0x03U /*!< RW Mode Definition Register */ +#define ST25R3911_REG_BIT_RATE 0x04U /*!< RW Bit Rate Definition Register */ + +#define ST25R3911_REG_ISO14443A_NFC 0x05U /*!< RW ISO14443A and NFC 106 kBit/s Settings Register */ +#define ST25R3911_REG_ISO14443B_1 0x06U /*!< RW ISO14443B Settings Register 1 */ +#define ST25R3911_REG_ISO14443B_2 0x07U /*!< RW ISO14443B Settings Register 2 */ +#define ST25R3911_REG_STREAM_MODE 0x08U /*!< RW Stream Mode Definition Register */ +#define ST25R3911_REG_AUX 0x09U /*!< RW Auxiliary Definition Register */ +#define ST25R3911_REG_RX_CONF1 0x0AU /*!< RW Receiver Configuration Register 1 */ +#define ST25R3911_REG_RX_CONF2 0x0BU /*!< RW Receiver Configuration Register 2 */ +#define ST25R3911_REG_RX_CONF3 0x0CU /*!< RW Receiver Configuration Register 3 */ +#define ST25R3911_REG_RX_CONF4 0x0DU /*!< RW Receiver Configuration Register 4 */ + +#define ST25R3911_REG_MASK_RX_TIMER 0x0EU /*!< RW Mask Receive Timer Register */ +#define ST25R3911_REG_NO_RESPONSE_TIMER1 0x0FU /*!< RW No-response Timer Register 1 */ +#define ST25R3911_REG_NO_RESPONSE_TIMER2 0x10U /*!< RW No-response Timer Register 2 */ +#define ST25R3911_REG_GPT_CONTROL 0x11U /*!< RW General Purpose Timer Control Register */ +#define ST25R3911_REG_GPT1 0x12U /*!< RW General Purpose Timer Register 1 */ +#define ST25R3911_REG_GPT2 0x13U /*!< RW General Purpose Timer Register 2 */ + +#define ST25R3911_REG_IRQ_MASK_MAIN 0x14U /*!< RW Mask Main Interrupt Register */ +#define ST25R3911_REG_IRQ_MASK_TIMER_NFC 0x15U /*!< RW Mask Timer and NFC Interrupt Register */ +#define ST25R3911_REG_IRQ_MASK_ERROR_WUP 0x16U /*!< RW Mask Error and Wake-up Interrupt Register */ +#define ST25R3911_REG_IRQ_MAIN 0x17U /*!< R Main Interrupt Register */ +#define ST25R3911_REG_IRQ_TIMER_NFC 0x18U /*!< R Timer and NFC Interrupt Register */ +#define ST25R3911_REG_IRQ_ERROR_WUP 0x19U /*!< R Error and Wake-up Interrupt Register */ +#define ST25R3911_REG_FIFO_RX_STATUS1 0x1AU /*!< R FIFO RX Status Register 1 */ +#define ST25R3911_REG_FIFO_RX_STATUS2 0x1BU /*!< R FIFO RX Status Register 2 */ +#define ST25R3911_REG_COLLISION_STATUS 0x1CU /*!< R Collision Display Register */ + +#define ST25R3911_REG_NUM_TX_BYTES1 0x1DU /*!< RW Number of Transmitted Bytes Register 1 */ +#define ST25R3911_REG_NUM_TX_BYTES2 0x1EU /*!< RW Number of Transmitted Bytes Register 2 */ + +#define ST25R3911_REG_NFCIP1_BIT_RATE 0x1FU /*!< R NFCIP Bit Rate Detection Display Register */ + +#define ST25R3911_REG_AD_RESULT 0x20U /*!< R A/D Converter Output Register */ + +#define ST25R3911_REG_ANT_CAL_CONTROL 0x21U /*!< RW Antenna Calibration Control Register */ +#define ST25R3911_REG_ANT_CAL_TARGET 0x22U /*!< RW Antenna Calibration Target Register */ +#define ST25R3911_REG_ANT_CAL_RESULT 0x23U /*!< R Antenna Calibration Display Register */ + +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL 0x24U /*!< RW AM Modulation Depth Control Register */ +#define ST25R3911_REG_AM_MOD_DEPTH_RESULT 0x25U /*!< R AM Modulation Depth Display Register */ +#define ST25R3911_REG_RFO_AM_ON_LEVEL 0x26U /*!< RW RFO AM Modulation (On) Level Definition Register */ +#define ST25R3911_REG_RFO_AM_OFF_LEVEL 0x27U /*!< RW RFO Normal (AM Off) Level Definition Register */ + +#define ST25R3911_REG_FIELD_THRESHOLD 0x29U /*!< RW External Field Detector Threshold Register */ + +#define ST25R3911_REG_REGULATOR_CONTROL 0x2AU /*!< RW Regulated Voltage Control Register */ +#define ST25R3911_REG_REGULATOR_RESULT 0x2BU /*!< R Regulator Display Register */ + +#define ST25R3911_REG_RSSI_RESULT 0x2CU /*!< R RSSI Display Register*/ +#define ST25R3911_REG_GAIN_RED_STATE 0x2DU /*!< R Gain Reduction State Register*/ + +#define ST25R3911_REG_CAP_SENSOR_CONTROL 0x2EU /*!< RW Capacitive Sensor Control Register */ +#define ST25R3911_REG_CAP_SENSOR_RESULT 0x2FU /*!< R Capacitive Sensor Display Register */ + +#define ST25R3911_REG_AUX_DISPLAY 0x30U /*!< R Auxiliary Display Register */ + +#define ST25R3911_REG_WUP_TIMER_CONTROL 0x31U /*!< RW Wake-up Timer Control Register */ +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF 0x32U /*!< RW Amplitude Measurement Configuration Register */ +#define ST25R3911_REG_AMPLITUDE_MEASURE_REF 0x33U /*!< RW Amplitude Measurement Reference Register */ +#define ST25R3911_REG_AMPLITUDE_MEASURE_AA_RESULT 0x34U /*!< R Amplitude Measurement Auto Averaging Display Register */ +#define ST25R3911_REG_AMPLITUDE_MEASURE_RESULT 0x35U /*!< R Amplitude Measurement Display Register */ +#define ST25R3911_REG_PHASE_MEASURE_CONF 0x36U /*!< RW Phase Measurement Configuration Register */ +#define ST25R3911_REG_PHASE_MEASURE_REF 0x37U /*!< RW Phase Measurement Reference Register */ +#define ST25R3911_REG_PHASE_MEASURE_AA_RESULT 0x38U /*!< R Phase Measurement Auto Averaging Display Register */ +#define ST25R3911_REG_PHASE_MEASURE_RESULT 0x39U /*!< R Phase Measurement Display Register */ +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF 0x3AU /*!< RW Capacitance Measurement Configuration Register */ +#define ST25R3911_REG_CAPACITANCE_MEASURE_REF 0x3BU /*!< RW Capacitance Measurement Reference Register */ +#define ST25R3911_REG_CAPACITANCE_MEASURE_AA_RESULT 0x3CU /*!< R Capacitance Measurement Auto Averaging Display Register */ +#define ST25R3911_REG_CAPACITANCE_MEASURE_RESULT 0x3DU /*!< R Capacitance Measurement Display Register */ + +#define ST25R3911_REG_IC_IDENTITY 0x3FU /*!< R Chip Id: 0 for old silicon, v2 silicon: 0x09 */ + + +/*! Register bit definitions \cond DOXYGEN_SUPRESS */ + +#define ST25R3911_REG_IO_CONF1_lf_clk_off (1U<<0) +#define ST25R3911_REG_IO_CONF1_out_cl0 (1U<<1) +#define ST25R3911_REG_IO_CONF1_out_cl1 (1U<<2) +#define ST25R3911_REG_IO_CONF1_mask_out_cl (3U<<1) +#define ST25R3911_REG_IO_CONF1_osc (1U<<3) +#define ST25R3911_REG_IO_CONF1_fifo_lt (1U<<4) +#define ST25R3911_REG_IO_CONF1_fifo_lt_32bytes (0U<<4) +#define ST25R3911_REG_IO_CONF1_fifo_lt_16bytes (1U<<4) +#define ST25R3911_REG_IO_CONF1_fifo_lr (1U<<5) +#define ST25R3911_REG_IO_CONF1_fifo_lr_64bytes (0U<<5) +#define ST25R3911_REG_IO_CONF1_fifo_lr_80bytes (1U<<5) +#define ST25R3911_REG_IO_CONF1_rfo2 (1U<<6) +#define ST25R3911_REG_IO_CONF1_single (1U<<7) +#define ST25R3911_REG_IO_CONF2_slow_up (1U<<0) +#define ST25R3911_REG_IO_CONF2_io_18 (1U<<2) +#define ST25R3911_REG_IO_CONF2_miso_pd1 (1U<<3) +#define ST25R3911_REG_IO_CONF2_miso_pd2 (1U<<4) +#define ST25R3911_REG_IO_CONF2_vspd_off (1U<<6) +#define ST25R3911_REG_IO_CONF2_sup3V (1U<<7) +#define ST25R3911_REG_OP_CONTROL_wu (1U<<2) +#define ST25R3911_REG_OP_CONTROL_tx_en (1U<<3) +#define ST25R3911_REG_OP_CONTROL_rx_man (1U<<4) +#define ST25R3911_REG_OP_CONTROL_rx_chn (1U<<5) +#define ST25R3911_REG_OP_CONTROL_rx_en (1U<<6) +#define ST25R3911_REG_OP_CONTROL_en (1U<<7) +#define ST25R3911_REG_MODE_nfc_ar (1U<<0) +#define ST25R3911_REG_MODE_nfc_ar_on (1U<<0) +#define ST25R3911_REG_MODE_nfc_ar_off (0U<<0) +#define ST25R3911_REG_MODE_mask_om (0xfU<<3) +#define ST25R3911_REG_MODE_om_nfc (0x0U<<3) +#define ST25R3911_REG_MODE_om_iso14443a (0x1U<<3) +#define ST25R3911_REG_MODE_om_iso14443b (0x2U<<3) +#define ST25R3911_REG_MODE_om_felica (0x3U<<3) +#define ST25R3911_REG_MODE_om_topaz (0x4U<<3) +#define ST25R3911_REG_MODE_om_subcarrier_stream (0xeU<<3) +#define ST25R3911_REG_MODE_om_bpsk_stream (0xfU<<3) +#define ST25R3911_REG_MODE_om_bit_rate_detection (0x0U<<3) +#define ST25R3911_REG_MODE_om_nfcip1_normal_mode (0x1U<<3) +#define ST25R3911_REG_MODE_targ (1U<<7) +#define ST25R3911_REG_MODE_targ_targ (1U<<7) +#define ST25R3911_REG_MODE_targ_init (0U<<7) +#define ST25R3911_REG_BIT_RATE_mask_txrate (0xfU<<4) +#define ST25R3911_REG_BIT_RATE_shift_txrate (4U) +#define ST25R3911_REG_BIT_RATE_txrate_106 (0x0U<<4) +#define ST25R3911_REG_BIT_RATE_txrate_212 (0x1U<<4) +#define ST25R3911_REG_BIT_RATE_txrate_424 (0x2U<<4) +#define ST25R3911_REG_BIT_RATE_txrate_848 (0x3U<<4) +#define ST25R3911_REG_BIT_RATE_txrate_1695 (0x4U<<4) +#define ST25R3911_REG_BIT_RATE_txrate_3390 (0x5U<<4) +#define ST25R3911_REG_BIT_RATE_txrate_6780 (0x6U<<4) +#define ST25R3911_REG_BIT_RATE_mask_rxrate (0xfU<<0) +#define ST25R3911_REG_BIT_RATE_shift_rxrate (0U) +#define ST25R3911_REG_BIT_RATE_rxrate_106 (0x0U<<0) +#define ST25R3911_REG_BIT_RATE_rxrate_212 (0x1U<<0) +#define ST25R3911_REG_BIT_RATE_rxrate_424 (0x2U<<0) +#define ST25R3911_REG_BIT_RATE_rxrate_848 (0x3U<<0) +#define ST25R3911_REG_BIT_RATE_rxrate_1695 (0x4U<<0) +#define ST25R3911_REG_BIT_RATE_rxrate_3390 (0x5U<<0) +#define ST25R3911_REG_BIT_RATE_rxrate_6780 (0x6U<<0) +#define ST25R3911_REG_ISO14443A_NFC_antcl (1U<<0) +#define ST25R3911_REG_ISO14443A_NFC_mask_p_len (0xfU<<1) +#define ST25R3911_REG_ISO14443A_NFC_shift_p_len (1U) +#define ST25R3911_REG_ISO14443A_NFC_nfc_f0 (1U<<5) +#define ST25R3911_REG_ISO14443A_NFC_nfc_f0_off (0U<<5) +#define ST25R3911_REG_ISO14443A_NFC_no_rx_par (1U<<6) +#define ST25R3911_REG_ISO14443A_NFC_no_rx_par_off (0U<<6) +#define ST25R3911_REG_ISO14443A_NFC_no_tx_par (1U<<7) +#define ST25R3911_REG_ISO14443A_NFC_no_tx_par_off (0U<<7) +#define ST25R3911_REG_ISO14443B_1_mask_eof (1U<<2) +#define ST25R3911_REG_ISO14443B_1_eof_10etu (0U<<2) +#define ST25R3911_REG_ISO14443B_1_eof_11etu (1U<<2) +#define ST25R3911_REG_ISO14443B_1_mask_sof (3U<<3) +#define ST25R3911_REG_ISO14443B_1_mask_sof_0 (1U<<4) +#define ST25R3911_REG_ISO14443B_1_sof_0_10etu (0U<<4) +#define ST25R3911_REG_ISO14443B_1_sof_0_11etu (1U<<4) +#define ST25R3911_REG_ISO14443B_1_mask_sof_1 (1U<<3) +#define ST25R3911_REG_ISO14443B_1_sof_1_2etu (0U<<3) +#define ST25R3911_REG_ISO14443B_1_sof_2_3etu (1U<<3) +#define ST25R3911_REG_ISO14443B_1_mask_egt (7U<<5) +#define ST25R3911_REG_ISO14443B_1_shift_egt (5U) +#define ST25R3911_REG_ISO14443B_2_eof_12 (1U<<3) +#define ST25R3911_REG_ISO14443B_2_eof_12_10to11etu (0U<<3) +#define ST25R3911_REG_ISO14443B_2_eof_12_10to12etu (1U<<3) +#define ST25R3911_REG_ISO14443B_2_no_eof (1U<<4) +#define ST25R3911_REG_ISO14443B_2_no_sof (1U<<5) +#define ST25R3911_REG_ISO14443B_2_mask_tr1 (3U<<6) +#define ST25R3911_REG_ISO14443B_2_shift_tr1 (6U) +#define ST25R3911_REG_ISO14443B_2_tr1_0 (1U<<6) +#define ST25R3911_REG_ISO14443B_2_tr1_1 (1U<<7) +#define ST25R3911_REG_ISO14443B_2_tr1_80fs80fs (0U<<6) +#define ST25R3911_REG_ISO14443B_2_tr1_64fs32fs (1U<<6) +#define ST25R3911_REG_STREAM_MODE_mask_stx (7U<<0) +#define ST25R3911_REG_STREAM_MODE_shift_stx (0U) +#define ST25R3911_REG_STREAM_MODE_stx_106 (0U<<0) +#define ST25R3911_REG_STREAM_MODE_stx_212 (1U<<0) +#define ST25R3911_REG_STREAM_MODE_stx_424 (2U<<0) +#define ST25R3911_REG_STREAM_MODE_stx_848 (3U<<0) +#define ST25R3911_REG_STREAM_MODE_stx_1695 (4U<<0) +#define ST25R3911_REG_STREAM_MODE_stx_3390 (5U<<0) +#define ST25R3911_REG_STREAM_MODE_stx_6780 (6U<<0) +#define ST25R3911_REG_STREAM_MODE_mask_scp (3U<<3) +#define ST25R3911_REG_STREAM_MODE_shift_scp (3U) +#define ST25R3911_REG_STREAM_MODE_scp_1pulse (0U<<3) +#define ST25R3911_REG_STREAM_MODE_scp_2pulses (1U<<3) +#define ST25R3911_REG_STREAM_MODE_scp_4pulses (2U<<3) +#define ST25R3911_REG_STREAM_MODE_scp_8pulses (3U<<3) +#define ST25R3911_REG_STREAM_MODE_mask_scf (3U<<5) +#define ST25R3911_REG_STREAM_MODE_shift_scf (5U) +#define ST25R3911_REG_STREAM_MODE_scf_bpsk848 (0U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_bpsk1695 (1U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_bpsk3390 (2U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_bpsk106 (3U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_sc212 (0U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_sc424 (1U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_sc848 (2U<<5) +#define ST25R3911_REG_STREAM_MODE_scf_sc1695 (3U<<5) +#define ST25R3911_REG_AUX_mask_nfc_n (3U<<0) +#define ST25R3911_REG_AUX_nfc_n0 (1U<<0) +#define ST25R3911_REG_AUX_nfc_n1 (1U<<1) +#define ST25R3911_REG_AUX_rx_tol (1U<<2) +#define ST25R3911_REG_AUX_ook_hr (1U<<3) +#define ST25R3911_REG_AUX_en_fd (1U<<4) +#define ST25R3911_REG_AUX_tr_am (1U<<5) +#define ST25R3911_REG_AUX_crc_2_fifo (1U<<6) +#define ST25R3911_REG_AUX_no_crc_rx (1U<<7) +#define ST25R3911_REG_RX_CONF1_z12k (1U<<0) +#define ST25R3911_REG_RX_CONF1_h80 (1U<<1) +#define ST25R3911_REG_RX_CONF1_h200 (1U<<2) +#define ST25R3911_REG_RX_CONF1_mask_lp (7U<<3) +#define ST25R3911_REG_RX_CONF1_lp_1200khz (0U<<3) +#define ST25R3911_REG_RX_CONF1_lp_600khz (1U<<3) +#define ST25R3911_REG_RX_CONF1_lp_300khz (2U<<3) +#define ST25R3911_REG_RX_CONF1_lp_2000khz (4U<<3) +#define ST25R3911_REG_RX_CONF1_lp_7000khz (5U<<3) +#define ST25R3911_REG_RX_CONF1_amd_sel (1U<<6) +#define ST25R3911_REG_RX_CONF1_ch_sel (1U<<7) +#define ST25R3911_REG_RX_CONF2_sqm_dyn (1U<<1) +#define ST25R3911_REG_RX_CONF2_agc_alg (1U<<2) +#define ST25R3911_REG_RX_CONF2_agc_m (1U<<3) +#define ST25R3911_REG_RX_CONF2_agc_en (1U<<4) +#define ST25R3911_REG_RX_CONF2_lf_en (1U<<5) +#define ST25R3911_REG_RX_CONF2_lf_op (1U<<6) +#define ST25R3911_REG_RX_CONF2_rx_lp (1U<<7) +#define ST25R3911_REG_RX_CONF3_rg_nfc (1U<<0) +#define ST25R3911_REG_RX_CONF3_lim (1U<<1) +#define ST25R3911_REG_RX_CONF3_shift_rg1_pm (2U) +#define ST25R3911_REG_RX_CONF3_mask_rg1_pm (0x7U<<2) +#define ST25R3911_REG_RX_CONF3_rg1_pm0 (1U<<2) +#define ST25R3911_REG_RX_CONF3_rg1_pm1 (1U<<3) +#define ST25R3911_REG_RX_CONF3_rg1_pm2 (1U<<4) +#define ST25R3911_REG_RX_CONF3_shift_rg1_am (5U) +#define ST25R3911_REG_RX_CONF3_mask_rg1_am (0x7U<<5) +#define ST25R3911_REG_RX_CONF3_rg1_am0 (1U<<5) +#define ST25R3911_REG_RX_CONF3_rg1_am1 (1U<<6) +#define ST25R3911_REG_RX_CONF3_rg1_am2 (1U<<7) +#define ST25R3911_REG_RX_CONF4_shift_rg2_pm (0U) +#define ST25R3911_REG_RX_CONF4_mask_rg2_pm (0xfU<<0) +#define ST25R3911_REG_RX_CONF4_rg2_pm0 (1U<<0) +#define ST25R3911_REG_RX_CONF4_rg2_pm1 (1U<<1) +#define ST25R3911_REG_RX_CONF4_rg2_pm2 (1U<<2) +#define ST25R3911_REG_RX_CONF4_rg2_pm3 (1U<<3) +#define ST25R3911_REG_RX_CONF4_shift_rg2_am (4U) +#define ST25R3911_REG_RX_CONF4_mask_rg2_am (0xfU<<4) +#define ST25R3911_REG_RX_CONF4_rg2_am0 (1U<<4) +#define ST25R3911_REG_RX_CONF4_rg2_am1 (1U<<5) +#define ST25R3911_REG_RX_CONF4_rg2_am2 (1U<<6) +#define ST25R3911_REG_RX_CONF4_rg2_am3 (1U<<7) +#define ST25R3911_REG_GPT_CONTROL_nrt_step (1U<<0) +#define ST25R3911_REG_GPT_CONTROL_nrt_emv (1U<<1) +#define ST25R3911_REG_GPT_CONTROL_gptc0 (1U<<5) +#define ST25R3911_REG_GPT_CONTROL_gptc1 (1U<<6) +#define ST25R3911_REG_GPT_CONTROL_gptc2 (1U<<7) +#define ST25R3911_REG_GPT_CONTROL_gptc_mask (0x7U<<5) +#define ST25R3911_REG_GPT_CONTROL_gptc_no_trigger (0x0U<<5) +#define ST25R3911_REG_GPT_CONTROL_gptc_erx (0x1U<<5) +#define ST25R3911_REG_GPT_CONTROL_gptc_srx (0x2U<<5) +#define ST25R3911_REG_GPT_CONTROL_gptc_etx_nfc (0x3U<<5) +#define ST25R3911_REG_FIFO_RX_STATUS2_np_lb (1U<<0) +#define ST25R3911_REG_FIFO_RX_STATUS2_mask_fifo_lb (7U<<1) +#define ST25R3911_REG_FIFO_RX_STATUS2_shift_fifo_lb (1U) +#define ST25R3911_REG_FIFO_RX_STATUS2_fifo_lb0 (1U<<1) +#define ST25R3911_REG_FIFO_RX_STATUS2_fifo_lb1 (1U<<2) +#define ST25R3911_REG_FIFO_RX_STATUS2_fifo_lb2 (1U<<3) +#define ST25R3911_REG_FIFO_RX_STATUS2_fifo_ncp (1U<<4) +#define ST25R3911_REG_FIFO_RX_STATUS2_fifo_ovr (1U<<5) +#define ST25R3911_REG_FIFO_RX_STATUS2_fifo_unf (1U<<6) +#define ST25R3911_REG_COLLISION_STATUS_c_pb (1U<<0) +#define ST25R3911_REG_COLLISION_STATUS_mask_c_bit (3U<<1) +#define ST25R3911_REG_COLLISION_STATUS_shift_c_bit (1U) +#define ST25R3911_REG_COLLISION_STATUS_mask_c_byte (0xfU<<4) +#define ST25R3911_REG_COLLISION_STATUS_shift_c_byte (4U) +#define ST25R3911_ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate0 (1U<<4) +#define ST25R3911_ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate1 (1U<<5) +#define ST25R3911_ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate2 (1U<<6) +#define ST25R3911_ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate3 (1U<<7) +#define ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate_mask (0xfU<<4) +#define ST25R3911_REG_NFCIP1_BIT_RATE_nfc_rate_shift (4U) +#define ST25R3911_REG_ANT_CAL_CONTROL_mask_tre (0xfU<<3) +#define ST25R3911_REG_ANT_CAL_CONTROL_shift_tre (3U) +#define ST25R3911_REG_ANT_CAL_CONTROL_tre_0 (1U<<3) +#define ST25R3911_REG_ANT_CAL_CONTROL_tre_1 (1U<<4) +#define ST25R3911_REG_ANT_CAL_CONTROL_tre_2 (1U<<5) +#define ST25R3911_REG_ANT_CAL_CONTROL_tre_3 (1U<<6) +#define ST25R3911_REG_ANT_CAL_CONTROL_trim_s (1U<<7) +#define ST25R3911_REG_ANT_CAL_RESULT_tri_err (1U<<3) +#define ST25R3911_REG_ANT_CAL_RESULT_tri_0 (1U<<4) +#define ST25R3911_REG_ANT_CAL_RESULT_tri_1 (1U<<5) +#define ST25R3911_REG_ANT_CAL_RESULT_tri_2 (1U<<6) +#define ST25R3911_REG_ANT_CAL_RESULT_tri_3 (1U<<7) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mask_mod (0x3fU<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_shift_mod (1U) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_8percent (0xbU<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_10percent (0xeU<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_14percent (0x14U<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_20percent (0x20U<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_25percent (0x2aU<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_30percent (0x37U<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_mod_33percent (0x3fU<<1) +#define ST25R3911_REG_AM_MOD_DEPTH_CONTROL_am_s (1U<<7) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram0 (1U<<0) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram1 (1U<<1) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram2 (1U<<2) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram3 (1U<<3) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram4 (1U<<4) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram5 (1U<<5) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram6 (1U<<6) +#define ST25R3911_REG_RFO_AM_MOD_LEVEL_dram7 (1U<<7) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_t0 (1U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_t1 (1U<<1) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_t2 (1U<<2) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_t3 (1U<<3) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_l0 (1U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_l1 (1U<<5) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_l2 (1U<<6) +#define ST25R3911_REG_FIELD_THRESHOLD_mask_trg (0x07U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_75mV (0x00U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_105mV (0x01U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_150mV (0x02U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_205mV (0x03U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_290mV (0x04U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_400mV (0x05U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_560mV (0x06U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_trg_800mV (0x07U<<4) +#define ST25R3911_REG_FIELD_THRESHOLD_mask_rfe (0x0FU<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_75mV (0x00U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_105mV (0x01U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_150mV (0x02U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_205mV (0x03U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_290mV (0x04U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_400mV (0x05U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_560mV (0x06U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_800mV (0x07U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_25mV (0x08U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_33mV (0x09U<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_47mV (0x0AU<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_64mV (0x0BU<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_90mV (0x0CU<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_125mV (0x0DU<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_175mV (0x0EU<<0) +#define ST25R3911_REG_FIELD_THRESHOLD_rfe_250mV (0x0FU<<0) +#define ST25R3911_REG_REGULATOR_CONTROL_shift_mpsv (1U) +#define ST25R3911_REG_REGULATOR_CONTROL_mask_mpsv (3U<<1) +#define ST25R3911_REG_REGULATOR_CONTROL_mpsv_vdd (0U<<1) +#define ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_a (1U<<1) +#define ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_d (2U<<1) +#define ST25R3911_REG_REGULATOR_CONTROL_mpsv_vsp_rf (3U<<1) +#define ST25R3911_REG_REGULATOR_CONTROL_mask_rege (0xfU<<3) +#define ST25R3911_REG_REGULATOR_CONTROL_shift_rege (3U) +#define ST25R3911_REG_REGULATOR_CONTROL_reg_s (1U<<7) +#define ST25R3911_REG_REGULATOR_RESULT_mrt_on (1U<<0) +#define ST25R3911_REG_REGULATOR_RESULT_nrt_on (1U<<1) +#define ST25R3911_REG_REGULATOR_RESULT_gpt_on (1U<<2) +#define ST25R3911_REG_REGULATOR_RESULT_mask_reg (0xfU<<4) +#define ST25R3911_REG_REGULATOR_RESULT_shift_reg (4U) +#define ST25R3911_REG_REGULATOR_RESULT_reg_0 (1U<<4) +#define ST25R3911_REG_REGULATOR_RESULT_reg_1 (1U<<5) +#define ST25R3911_REG_REGULATOR_RESULT_reg_2 (1U<<6) +#define ST25R3911_REG_REGULATOR_RESULT_reg_3 (1U<<7) +#define ST25R3911_REG_RSSI_RESULT_mask_rssi_pm (0xfU) +#define ST25R3911_REG_RSSI_RESULT_shift_rssi_pm (0U) +#define ST25R3911_REG_RSSI_RESULT_rssi_pm0 (1U<<0) +#define ST25R3911_REG_RSSI_RESULT_rssi_pm1 (1U<<1) +#define ST25R3911_REG_RSSI_RESULT_rssi_pm2 (1U<<2) +#define ST25R3911_REG_RSSI_RESULT_rssi_pm3 (1U<<3) +#define ST25R3911_REG_RSSI_RESULT_mask_rssi_am (0xfU<<4) +#define ST25R3911_REG_RSSI_RESULT_shift_rssi_am (4U) +#define ST25R3911_REG_RSSI_RESULT_rssi_am_0 (1U<<4) +#define ST25R3911_REG_RSSI_RESULT_rssi_am_1 (1U<<5) +#define ST25R3911_REG_RSSI_RESULT_rssi_am_2 (1U<<6) +#define ST25R3911_REG_RSSI_RESULT_rssi_am_3 (1U<<7) +#define ST25R3911_REG_GAIN_RED_STATE_mask_gs_pm (0xfU) +#define ST25R3911_REG_GAIN_RED_STATE_shift_gs_pm (0U) +#define ST25R3911_REG_GAIN_RED_STATE_gs_pm_0 (1U<<0) +#define ST25R3911_REG_GAIN_RED_STATE_gs_pm_1 (1U<<1) +#define ST25R3911_REG_GAIN_RED_STATE_gs_pm_2 (1U<<2) +#define ST25R3911_REG_GAIN_RED_STATE_gs_pm_3 (1U<<3) +#define ST25R3911_REG_GAIN_RED_STATE_mask_gs_am (0xfU<<4) +#define ST25R3911_REG_GAIN_RED_STATE_shift_gs_am (4U) +#define ST25R3911_REG_GAIN_RED_STATE_gs_am_0 (1U<<4) +#define ST25R3911_REG_GAIN_RED_STATE_gs_am_1 (1U<<5) +#define ST25R3911_REG_GAIN_RED_STATE_gs_am_2 (1U<<6) +#define ST25R3911_REG_GAIN_RED_STATE_gs_am_3 (1U<<7) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_g0 (1U<<0) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_g1 (1U<<1) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_g2 (1U<<2) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_mask_cs_g (7U<<0) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_mcal0 (1U<<3) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_mcal1 (1U<<4) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_mcal2 (1U<<5) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_mcal3 (1U<<6) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_cs_mcal4 (1U<<7) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_mask_cs_mcal (0x1fU<<3) +#define ST25R3911_REG_CAP_SENSOR_CONTROL_shift_cs_mcal (3U) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_err (1U<<1) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_end (1U<<2) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal0 (1U<<3) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal1 (1U<<4) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal2 (1U<<5) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal3 (1U<<6) +#define ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal4 (1U<<7) +#define ST25R3911_REG_AUX_DISPLAY_mrt_on (1U<<0) +#define ST25R3911_REG_AUX_DISPLAY_nrt_on (1U<<1) +#define ST25R3911_REG_AUX_DISPLAY_gpt_on (1U<<2) +#define ST25R3911_REG_AUX_DISPLAY_rx_on (1U<<3) +#define ST25R3911_REG_AUX_DISPLAY_osc_ok (1U<<4) +#define ST25R3911_REG_AUX_DISPLAY_tx_on (1U<<5) +#define ST25R3911_REG_AUX_DISPLAY_efd_o (1U<<6) +#define ST25R3911_REG_AUX_DISPLAY_a_cha (1U<<7) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wcap (1U<<0) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wph (1U<<1) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wam (1U<<2) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wto (1U<<3) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wut0 (1U<<4) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wut1 (1U<<5) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wut2 (1U<<6) +#define ST25R3911_REG_WUP_TIMER_CONTROL_shift_wut (4U) +#define ST25R3911_REG_WUP_TIMER_CONTROL_wur (1U<<7) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_ae (1U<<0) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_aew0 (1U<<1) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_aew1 (1U<<2) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_shift_am_aew (1U) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_mask_am_aew (3U<<1) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_aam (1U<<3) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_d0 (1U<<4) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_d1 (1U<<5) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_d2 (1U<<6) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_am_d3 (1U<<7) +#define ST25R3911_REG_AMPLITUDE_MEASURE_CONF_shift_am_d (4U) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_ae (1U<<0) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_aew0 (1U<<1) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_aew1 (1U<<2) +#define ST25R3911_REG_PHASE_MEASURE_CONF_shift_pm_aew (1U) +#define ST25R3911_REG_PHASE_MEASURE_CONF_mask_pm_aew (3U<<1) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_aam (1U<<3) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_d0 (1U<<4) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_d1 (1U<<5) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_d2 (1U<<6) +#define ST25R3911_REG_PHASE_MEASURE_CONF_pm_d3 (1U<<7) +#define ST25R3911_REG_PHASE_MEASURE_CONF_shift_pm_d (4U) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_ae (1U<<0) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_aew0 (1U<<1) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_aew1 (1U<<2) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_shift_cm_aew (1U) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_mask_cm_aew (3U<<1) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_aam (1U<<3) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_d0 (1U<<4) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_d1 (1U<<5) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_d2 (1U<<6) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_cm_d3 (1U<<7) +#define ST25R3911_REG_CAPACITANCE_MEASURE_CONF_shift_cm_d (4U) +#define ST25R3911_REG_IC_IDENTITY_v2 (0x09U) +#define ST25R3911_REG_IC_IDENTITY_ic_type (1U<<3) +#define ST25R3911_REG_IC_IDENTITY_mask_ic_type (0x1FU<<3) +#define ST25R3911_REG_IC_IDENTITY_shift_ic_type (3U) +#define ST25R3911_REG_IC_IDENTITY_mask_ic_rev (7U) + +/*! \endcond DOXYGEN_SUPRESS */ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Returns the content of a register within the ST25R3911 + * + * This function is used to read out the content of ST25R3911 registers. + * + * \param[in] reg: Address of register to read. + * \param[out] value: Returned value. + * + ***************************************************************************** + */ +extern void st25r3911ReadRegister(uint8_t reg, uint8_t* value); + +/*! + ***************************************************************************** + * \brief Writes a given value to a register within the ST25R3911 + * + * This function is used to write \a value to address \a reg within the ST25R3911. + * + * \param[in] reg: Address of the register to write. + * \param[in] value: Value to be written. + * + ***************************************************************************** + */ +extern void st25r3911WriteRegister(uint8_t reg, uint8_t value); + +/*! + ***************************************************************************** + * \brief Cleart bits on Register + * + * This function clears the given bitmask on the register + * + * \warning This method does not guarantee consistency of register content + * when called from multiple contexts (task, ISR, thread) + * + * \param[in] reg: Address of the register clear + * \param[in] clr_mask: Bitmask of bit to be cleared + * + ***************************************************************************** + */ +extern void st25r3911ClrRegisterBits( uint8_t reg, uint8_t clr_mask ); + + +/*! + ***************************************************************************** + * \brief Set bits on Register + * + * This function sets the given bitmask on the register + * + * \warning This method does not guarantee consistency of register content + * when called from multiple contexts (task, ISR, thread) + * + * \param[in] reg: Address of the register clear + * \param[in] set_mask: Bitmask of bit to be cleared + * + ***************************************************************************** + */ +extern void st25r3911SetRegisterBits( uint8_t reg, uint8_t set_mask ); + + +/*! + ***************************************************************************** + * \brief Changes the given bits on a ST25R3911 register + * + * This function is used if only a particular bits should be changed within + * an ST25R3911 register. + * + * \warning This method does not guarantee consistency of register content + * when called from multiple contexts (task, ISR, thread) + * + * \param[in] reg: Address of the register to write. + * \param[in] valueMask: bitmask of bits to be changed + * \param[in] value: the bits to be written on the enabled valueMask bits + * + ***************************************************************************** + */ +extern void st25r3911ChangeRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value); + +/*! + ***************************************************************************** + * \brief Read a test register within the ST25R3911 + * + * This function is used to read the content of test address \a reg within the ST25R3911. + * + * \param[in] reg: Address of the register to read. + * \param[out] value: Returned read. + * + ***************************************************************************** + */ +extern void st25r3911ReadTestRegister(uint8_t reg, uint8_t* value); + +/*! + ***************************************************************************** + * \brief Writes a given value to a test register within the ST25R3911 + * + * This function is used to write \a value to test address \a reg within the ST25R3911. + * + * \param[in] reg: Address of the register to write. + * \param[in] value: Value to be written. + * + ***************************************************************************** + */ +extern void st25r3911WriteTestRegister(uint8_t reg, uint8_t value); + +/*! + ***************************************************************************** + * \brief Modifies a value within a ST25R3911 register + * + * This function is used if only a particular bits should be changed within + * an ST25R3911 register. + * + * \warning This method does not guarantee consistency of register content + * when called from multiple contexts (task, ISR, thread) + * + * \param[in] reg: Address of the register to write. + * \param[in] clr_mask: bitmask of bits to be cleared to 0. + * \param[in] set_mask: bitmask of bits to be set to 1. + * + ***************************************************************************** + */ +extern void st25r3911ModifyRegister(uint8_t reg, uint8_t clr_mask, uint8_t set_mask); + + +/*! + ***************************************************************************** + * \brief Changes the given bits on a ST25R3911 Test register + * + * This function is used if only a particular bits should be changed within + * an ST25R3916 register. + * + * \param[in] reg: Address of the Test register to change. + * \param[in] valueMask: bitmask of bits to be changed + * \param[in] value: the bits to be written on the enabled valueMask bits + * + * \warning This method does not guarantee consistency of register content + * when called from multiple contexts (task, ISR, thread) + + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +extern void st25r3911ChangeTestRegisterBits( uint8_t reg, uint8_t valueMask, uint8_t value ); + +/*! + ***************************************************************************** + * \brief Writes multiple values to ST25R3911 registers + * + * This function is used to write multiple values to the ST25R3911 using the + * auto-increment feature. That is, after each write the address pointer + * inside the ST25R3911 gets incremented automatically. + * + * \param[in] reg: Address of the frist register to write. + * \param[in] values: pointer to a buffer containing the values to be written. + * \param[in] length: Number of values to be written. + * + ***************************************************************************** + */ +extern void st25r3911WriteMultipleRegisters(uint8_t reg, const uint8_t* values, uint8_t length); + +/*! + ***************************************************************************** + * \brief Reads from multiple ST25R3911 registers + * + * This function is used to read from multiple registers using the + * auto-increment feature. That is, after each read the address pointer + * inside the ST25R3911 gets incremented automatically. + * + * \param[in] reg: Address of the frist register to read from. + * \param[in] values: pointer to a buffer where the result shall be written to. + * \param[in] length: Number of registers to be read out. + * + ***************************************************************************** + */ +extern void st25r3911ReadMultipleRegisters(uint8_t reg, uint8_t* values, uint8_t length); + +/*! + ***************************************************************************** + * \brief Writes values to ST25R3911 FIFO + * + * This function needs to be called in order to write to the ST25R3911 FIFO. + * + * \param[in] values: pointer to a buffer containing the values to be written + * to the FIFO. + * \param[in] length: Number of values to be written. + * + ***************************************************************************** + */ +extern void st25r3911WriteFifo(const uint8_t* values, uint8_t length); + +/*! + ***************************************************************************** + * \brief Read values from ST25R3911 FIFO + * + * This function needs to be called in order to read from ST25R3911 FIFO. + * + * \param[out] buf: pointer to a buffer where the FIFO content shall be + * written to. + * \param[in] length: Number of bytes to read. (= size of \a buf) + * \note: This function doesn't check whether \a length is really the + * number of available bytes in FIFO + * + ***************************************************************************** + */ +extern void st25r3911ReadFifo(uint8_t* buf, uint8_t length); + +/*! + ***************************************************************************** + * \brief Execute a direct command + * + * This function is used to start so-called direct command. These commands + * are implemented inside the chip and each command has unique code (see + * datasheet). + * + * \param[in] cmd : code of the direct command to be executed. + * + ***************************************************************************** + */ +extern void st25r3911ExecuteCommand(uint8_t cmd); + +/*! + ***************************************************************************** + * \brief Execute several direct commands + * + * This function is used to start so-called direct command. These commands + * are implemented inside the chip and each command has unique code (see + * datasheet). + * + * \param[in] cmds : codes of the direct command to be executed. + * \param[in] length : number of commands to be executed + * + ***************************************************************************** + */ +extern void st25r3911ExecuteCommands(const uint8_t *cmds, uint8_t length); + +/*! + ***************************************************************************** + * \brief Check if register ID is valid + * + * Checks if the given register ID a valid ST25R3911 register + * + * \param[in] reg: Address of register to check + * + * \return true if is a valid register ID + * \return false otherwise + * + ***************************************************************************** + */ +extern bool st25r3911IsRegValid( uint8_t reg ); + +#endif /* ST25R3911_COM_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ + diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.c b/Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.c new file mode 100644 index 0000000..abb3082 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.c @@ -0,0 +1,249 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief ST25R3911 Interrupt handling + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "st25r3911_interrupt.h" +#include "st25r3911_com.h" +#include "st25r3911.h" +#include "st_errno.h" +#include "utils.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +/*! Length of the interrupt registers */ +#define ST25R3911_INT_REGS_LEN ( (ST25R3911_REG_IRQ_ERROR_WUP - ST25R3911_REG_IRQ_MAIN) + 1U ) + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +/*! Holds current and previous interrupt callback pointer as well as current Interrupt status and mask */ +typedef struct +{ + void (*prevCallback)(void); /*!< call back function for 3911 interrupt */ + void (*callback)(void); /*!< call back function for 3911 interrupt */ + uint32_t status; /*!< latest interrupt status */ + uint32_t mask; /*!< Interrupt mask. Negative mask = ST25R3911 mask regs */ +}t_st25r3911Interrupt; + +/* +****************************************************************************** +* GLOBAL VARIABLES +****************************************************************************** +*/ + +static volatile t_st25r3911Interrupt st25r3911interrupt; /*!< Instance of ST25R3911 interrupt */ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +void st25r3911InitInterrupts( void ) +{ + platformIrqST25R3911PinInitialize(); + platformIrqST25R3911SetCallback( st25r3911Isr ); + + st25r3911interrupt.callback = NULL; + st25r3911interrupt.prevCallback = NULL; + st25r3911interrupt.status = ST25R3911_IRQ_MASK_NONE; + st25r3911interrupt.mask = ST25R3911_IRQ_MASK_NONE; + + /* Initialize LEDs if existing and defined */ + platformLedsInitialize(); + +#ifdef PLATFORM_LED_RX_PIN + platformLedOff( PLATFORM_LED_RX_PORT, PLATFORM_LED_RX_PIN ); +#endif /* PLATFORM_LED_RX_PIN */ + +#ifdef PLATFORM_LED_FIELD_PIN + platformLedOff( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN ); +#endif /* PLATFORM_LED_FIELD_PIN */ +} + +void st25r3911Isr( void ) +{ + st25r3911CheckForReceivedInterrupts(); + + if (NULL != st25r3911interrupt.callback) + { + st25r3911interrupt.callback(); + } +} + +void st25r3911CheckForReceivedInterrupts( void ) +{ + uint8_t iregs[ST25R3911_INT_REGS_LEN]; + uint32_t irqStatus; + + irqStatus = ST25R3911_IRQ_MASK_NONE; + ST_MEMSET( iregs, (int32_t)(ST25R3911_IRQ_MASK_ALL & 0xFFU), ST25R3911_INT_REGS_LEN ); /* MISRA 10.3 */ + + /* In case the IRQ is Edge (not Level) triggered read IRQs until done */ + while( platformGpioIsHigh( ST25R391X_INT_PORT, ST25R391X_INT_PIN ) ) + { + st25r3911ReadMultipleRegisters(ST25R3911_REG_IRQ_MAIN, iregs, sizeof(iregs)); + +#ifdef PLATFORM_LED_FIELD_PIN + if ((iregs[0] & ST25R3911_IRQ_MASK_TXE) != 0U) + { + platformLedOn( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN ); + } +#endif /* PLATFORM_LED_FIELD_PIN */ + +#ifdef PLATFORM_LED_RX_PIN + if ((iregs[0] & ST25R3911_IRQ_MASK_RXS) != 0) + { + platformLedOn( PLATFORM_LED_RX_PORT, PLATFORM_LED_RX_PIN ); + } + if (((iregs[0] & ST25R3911_IRQ_MASK_RXE) != 0) || ((iregs[1] & (ST25R3911_IRQ_MASK_NRE >> 8)) != 0)) /* In rare cases there is rxs but not rxe, then we have nre */ + { + platformLedOff( PLATFORM_LED_RX_PORT, PLATFORM_LED_RX_PIN ); + } +#endif /* PLATFORM_LED_RX_PIN */ + + irqStatus |= (uint32_t)iregs[0]; + irqStatus |= (uint32_t)iregs[1]<<8; + irqStatus |= (uint32_t)iregs[2]<<16; + } + + /* Forward all interrupts, even masked ones to application. */ + platformProtectST25R391xIrqStatus(); + st25r3911interrupt.status |= irqStatus; + platformUnprotectST25R391xIrqStatus(); +} + + +void st25r3911ModifyInterrupts(uint32_t clr_mask, uint32_t set_mask) +{ + uint8_t i; + uint32_t old_mask; + uint32_t new_mask; + + old_mask = st25r3911interrupt.mask; + new_mask = (~old_mask & set_mask) | (old_mask & clr_mask); + st25r3911interrupt.mask &= ~clr_mask; + st25r3911interrupt.mask |= set_mask; + for (i=0; i<3U ; i++) + { + if (((new_mask >> (i*8U)) & 0xffU) == 0U) { + continue; + } + st25r3911WriteRegister((ST25R3911_REG_IRQ_MASK_MAIN + i), (uint8_t)((st25r3911interrupt.mask>>(i*8U))&0xffU)); + } + return; +} + + +uint32_t st25r3911WaitForInterruptsTimed(uint32_t mask, uint16_t tmo) +{ + uint32_t tmr; + uint32_t status; + + tmr = platformTimerCreate(tmo); + do + { + status = (st25r3911interrupt.status & mask); + } while( ( !platformTimerIsExpired( tmr ) || (tmo == 0U)) && (status == 0U) ); + + status = st25r3911interrupt.status & mask; + + platformProtectST25R391xIrqStatus(); + st25r3911interrupt.status &= ~status; + platformUnprotectST25R391xIrqStatus(); + + return status; +} + +uint32_t st25r3911GetInterrupt(uint32_t mask) +{ + uint32_t irqs; + + irqs = (st25r3911interrupt.status & mask); + if (irqs != ST25R3911_IRQ_MASK_NONE) + { + platformProtectST25R391xIrqStatus(); + st25r3911interrupt.status &= ~irqs; + platformUnprotectST25R391xIrqStatus(); + } + return irqs; +} + +void st25r3911EnableInterrupts(uint32_t mask) +{ + st25r3911ModifyInterrupts(mask,0); +} + +void st25r3911DisableInterrupts(uint32_t mask) +{ + st25r3911ModifyInterrupts(0,mask); +} + +void st25r3911ClearInterrupts( void ) +{ + uint8_t iregs[3]; + + st25r3911ReadMultipleRegisters(ST25R3911_REG_IRQ_MAIN, iregs, 3); + + platformProtectST25R391xIrqStatus(); + st25r3911interrupt.status = 0; + platformUnprotectST25R391xIrqStatus(); + return; +} + +void st25r3911IRQCallbackSet( void (*cb)(void) ) +{ + st25r3911interrupt.prevCallback = st25r3911interrupt.callback; + st25r3911interrupt.callback = cb; +} + +void st25r3911IRQCallbackRestore( void ) +{ + st25r3911interrupt.callback = st25r3911interrupt.prevCallback; + st25r3911interrupt.prevCallback = NULL; +} + diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.h b/Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.h new file mode 100644 index 0000000..cbc9162 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911_interrupt.h @@ -0,0 +1,257 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: ST25R3911 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief ST25R3911 Interrupt header file + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3911 + * \brief RFAL ST25R3911 Driver + * @{ + * + * \addtogroup ST25R3911_Interrupt + * \brief RFAL ST25R3911 Interrupt + * @{ + * + */ + +#ifndef ST25R3911_INTERRUPT_H +#define ST25R3911_INTERRUPT_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +/* Main interrupt register. */ +#define ST25R3911_IRQ_MASK_ALL (uint32_t)(0xFFFFFFU) /*!< All ST25R3911 interrupt sources */ +#define ST25R3911_IRQ_MASK_NONE (uint32_t)(0U) /*!< No ST25R3911 interrupt source */ +#define ST25R3911_IRQ_MASK_OSC (uint32_t)(0x80U) /*!< ST25R3911 oscillator stable interrupt */ +#define ST25R3911_IRQ_MASK_FWL (uint32_t)(0x40U) /*!< ST25R3911 FIFO water level interrupt */ +#define ST25R3911_IRQ_MASK_RXS (uint32_t)(0x20U) /*!< ST25R3911 start of receive interrupt */ +#define ST25R3911_IRQ_MASK_RXE (uint32_t)(0x10U) /*!< ST25R3911 end of receive interrupt */ +#define ST25R3911_IRQ_MASK_TXE (uint32_t)(0x08U) /*!< ST25R3911 end of transmission interrupt */ +#define ST25R3911_IRQ_MASK_COL (uint32_t)(0x04U) /*!< ST25R3911 bit collision interrupt */ + +/* Timer and NFC interrupt register. */ +#define ST25R3911_IRQ_MASK_DCT (uint32_t)(0x8000U) /*!< ST25R3911 termination of direct command interrupt */ +#define ST25R3911_IRQ_MASK_NRE (uint32_t)(0x4000U) /*!< ST25R3911 no-response timer expired interrupt */ +#define ST25R3911_IRQ_MASK_GPE (uint32_t)(0x2000U) /*!< ST25R3911 general purpose timer expired interrupt */ +#define ST25R3911_IRQ_MASK_EON (uint32_t)(0x1000U) /*!< ST25R3911 external field on interrupt */ +#define ST25R3911_IRQ_MASK_EOF (uint32_t)(0x0800U) /*!< ST25R3911 external field off interrupt */ +#define ST25R3911_IRQ_MASK_CAC (uint32_t)(0x0400U) /*!< ST25R3911 collision during RF collision avoidance interrupt */ +#define ST25R3911_IRQ_MASK_CAT (uint32_t)(0x0200U) /*!< ST25R3911 minimum guard time expired interrupt */ +#define ST25R3911_IRQ_MASK_NFCT (uint32_t)(0x0100U) /*!< ST25R3911 initiator bit rate recognized interrupt */ + +/* Error and wake-up interrupt register. */ +#define ST25R3911_IRQ_MASK_CRC (uint32_t)(0x800000U) /*!< ST25R3911 CRC error interrupt */ +#define ST25R3911_IRQ_MASK_PAR (uint32_t)(0x400000U) /*!< ST25R3911 parity error interrupt */ +#define ST25R3911_IRQ_MASK_ERR2 (uint32_t)(0x200000U) /*!< ST25R3911 soft framing error interrupt */ +#define ST25R3911_IRQ_MASK_ERR1 (uint32_t)(0x100000U) /*!< ST25R3911 hard framing error interrupt */ +#define ST25R3911_IRQ_MASK_WT (uint32_t)(0x080000U) /*!< ST25R3911 wake-up interrupt */ +#define ST25R3911_IRQ_MASK_WAM (uint32_t)(0x040000U) /*!< ST25R3911 wake-up due to amplitude interrupt */ +#define ST25R3911_IRQ_MASK_WPH (uint32_t)(0x020000U) /*!< ST25R3911 wake-up due to phase interrupt */ +#define ST25R3911_IRQ_MASK_WCAP (uint32_t)(0x010000U) /*!< ST25R3911 wake-up due to capacitance measurement */ + + +#define ST25R3911_IRQ_MASK_TIM (0x02U) /*!< additional interrupts in ST25R3911_REG_IRQ_TIMER_NFC */ +#define ST25R3911_IRQ_MASK_ERR (0x01U) /*!< additional interrupts in ST25R3911_REG_IRQ_ERROR_WUP */ + + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + ***************************************************************************** + * \brief Wait until an ST25R3911 interrupt occurs + * + * This function is used to access the ST25R3911 interrupt flags. Use this + * to wait for max. \a tmo milliseconds for the \b first interrupt indicated + * with mask \a mask to occur. + * + * \param[in] mask : mask indicating the interrupts to wait for. + * \param[in] tmo : time in milliseconds until timeout occurs. If set to 0 + * the functions waits forever. + * + * \return : 0 if timeout occurred otherwise a mask indicating the cleared + * interrupts. + * + ***************************************************************************** + */ +extern uint32_t st25r3911WaitForInterruptsTimed(uint32_t mask, uint16_t tmo); + +/*! + ***************************************************************************** + * \brief Get status for the given interrupt + * + * This function is used to check whether the interrupt given by \a mask + * has occurred. If yes the interrupt gets cleared. This function returns + * only status bits which are inside \a mask. + * + * \param[in] mask : mask indicating the interrupt to check for. + * + * \return the mask of the interrupts occurred + * + ***************************************************************************** + */ +extern uint32_t st25r3911GetInterrupt(uint32_t mask); + + +/*! + ***************************************************************************** + * \brief Init the 3911 interrupt + * + * This function initiates the 3911 interrupts. + * + ***************************************************************************** + */ +extern void st25r3911InitInterrupts( void ); + + +/*! + ***************************************************************************** + * \brief Modifies the Interrupt + * + * This function modifies the interrupt + * + * \param[in] clr_mask : bit mask to be cleared on the interrupt mask + * \param[in] set_mask : bit mask to be set on the interrupt mask + ***************************************************************************** + */ +extern void st25r3911ModifyInterrupts(uint32_t clr_mask, uint32_t set_mask); + + +/*! + ***************************************************************************** + * \brief Checks received interrupts + * + * Checks received interrupts and saves the result into global params + ***************************************************************************** + */ +extern void st25r3911CheckForReceivedInterrupts( void ); + + +/*! + ***************************************************************************** + * \brief ISR Service routine + * + * This function modifies the interrupt + ***************************************************************************** + */ +extern void st25r3911Isr( void ); + +/*! + ***************************************************************************** + * \brief Enable a given ST25R3911 Interrupt source + * + * This function enables all interrupts given by \a mask, + * ST25R3911_IRQ_MASK_ALL enables all interrupts. + * + * \param[in] mask: mask indicating the interrupts to be enabled + * + ***************************************************************************** + */ +extern void st25r3911EnableInterrupts(uint32_t mask); + +/*! + ***************************************************************************** + * \brief Disable one or more a given ST25R3911 Interrupt sources + * + * This function disables all interrupts given by \a mask. 0xff disables all. + * + * \param[in] mask: mask indicating the interrupts to be disabled. + * + ***************************************************************************** + */ +extern void st25r3911DisableInterrupts(uint32_t mask); + +/*! + ***************************************************************************** + * \brief Clear all st25r3911 irq flags + * + ***************************************************************************** + */ +extern void st25r3911ClearInterrupts(void); + +/*! + ***************************************************************************** + * \brief Sets IRQ callback for the ST25R3911 interrupt + * + ***************************************************************************** + */ +extern void st25r3911IRQCallbackSet(void (*cb)(void)); + +/*! + ***************************************************************************** + * \brief Sets IRQ callback for the ST25R3911 interrupt + * + ***************************************************************************** + */ +extern void st25r3911IRQCallbackRestore(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ST25R3911_ISR_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911_spi.c b/Software/fab-reader2-c/components/st25r3911/st25r3911_spi.c new file mode 100644 index 0000000..67b9dd8 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911_spi.c @@ -0,0 +1,34 @@ +// +// Created by Kai Jan Kriegel on 12.10.22. +// + +#include +#include +#include "st25r3911_spi.h" +#include "platform.h" + +spi_device_handle_t pSpi; +#define SPI_BUF_LEN 32 + +void st25r3911_spi_init(spi_device_handle_t spi) { + pSpi = spi; +} + +esp_err_t st25r3911_spiTxRx(const uint8_t *txData, uint8_t *rxData, uint16_t length) { + if (length > SPI_BUF_LEN) { + return ESP_FAIL; + } + + spi_transaction_t t; + memset(&t, 0, sizeof(t)); + t.length = length * 8; + t.rx_buffer = rxData; + t.tx_buffer = txData; + + esp_err_t ret = spi_device_polling_transmit(pSpi, &t); + ESP_ERROR_CHECK(ret); + + return ret; +} + + diff --git a/Software/fab-reader2-c/components/st25r3911/st25r3911_spi.h b/Software/fab-reader2-c/components/st25r3911/st25r3911_spi.h new file mode 100644 index 0000000..de52750 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st25r3911_spi.h @@ -0,0 +1,23 @@ +// +// Created by Kai Jan Kriegel on 12.10.22. +// + +#ifndef FAB_READER2_C_ST25R3911_SPI_H +#define FAB_READER2_C_ST25R3911_SPI_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void st25r3911_spi_init(spi_device_handle_t spi); + +esp_err_t st25r3911_spiTxRx(const uint8_t *txData, uint8_t *rxData, uint16_t length); + +#ifdef __cplusplus +} +#endif + +#endif //FAB_READER2_C_ST25R3911_SPI_H diff --git a/Software/fab-reader2-c/components/st25r3911/st_errno.h b/Software/fab-reader2-c/components/st25r3911/st_errno.h new file mode 100644 index 0000000..aa2da83 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/st_errno.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: STxxxx firmware + * LANGUAGE: ISO C99 + */ + +/*! \file st_errno.h + * + * \author + * + * \brief Main error codes + * + */ + +#ifndef ST_ERRNO_H +#define ST_ERRNO_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + + +/* +****************************************************************************** +* GLOBAL DATA TYPES +****************************************************************************** +*/ + +typedef uint16_t ReturnCode; /*!< Standard Return Code type from function. */ + +/* +****************************************************************************** +* DEFINES +****************************************************************************** +*/ + + +/* + * Error codes to be used within the application. + * They are represented by an uint8_t + */ + +#define ERR_NONE ((ReturnCode)0U) /*!< no error occurred */ +#define ERR_NOMEM ((ReturnCode)1U) /*!< not enough memory to perform the requested operation */ +#define ERR_BUSY ((ReturnCode)2U) /*!< device or resource busy */ +#define ERR_IO ((ReturnCode)3U) /*!< generic IO error */ +#define ERR_TIMEOUT ((ReturnCode)4U) /*!< error due to timeout */ +#define ERR_REQUEST ((ReturnCode)5U) /*!< invalid request or requested function can't be executed at the moment */ +#define ERR_NOMSG ((ReturnCode)6U) /*!< No message of desired type */ +#define ERR_PARAM ((ReturnCode)7U) /*!< Parameter error */ +#define ERR_SYSTEM ((ReturnCode)8U) /*!< System error */ +#define ERR_FRAMING ((ReturnCode)9U) /*!< Framing error */ +#define ERR_OVERRUN ((ReturnCode)10U) /*!< lost one or more received bytes */ +#define ERR_PROTO ((ReturnCode)11U) /*!< protocol error */ +#define ERR_INTERNAL ((ReturnCode)12U) /*!< Internal Error */ +#define ERR_AGAIN ((ReturnCode)13U) /*!< Call again */ +#define ERR_MEM_CORRUPT ((ReturnCode)14U) /*!< memory corruption */ +#define ERR_NOT_IMPLEMENTED ((ReturnCode)15U) /*!< not implemented */ +#define ERR_PC_CORRUPT ((ReturnCode)16U) /*!< Program Counter has been manipulated or spike/noise trigger illegal operation */ +#define ERR_SEND ((ReturnCode)17U) /*!< error sending*/ +#define ERR_IGNORE ((ReturnCode)18U) /*!< indicates error detected but to be ignored */ +#define ERR_SEMANTIC ((ReturnCode)19U) /*!< indicates error in state machine (unexpected cmd) */ +#define ERR_SYNTAX ((ReturnCode)20U) /*!< indicates error in state machine (unknown cmd) */ +#define ERR_CRC ((ReturnCode)21U) /*!< crc error */ +#define ERR_NOTFOUND ((ReturnCode)22U) /*!< transponder not found */ +#define ERR_NOTUNIQUE ((ReturnCode)23U) /*!< transponder not unique - more than one transponder in field */ +#define ERR_NOTSUPP ((ReturnCode)24U) /*!< requested operation not supported */ +#define ERR_WRITE ((ReturnCode)25U) /*!< write error */ +#define ERR_FIFO ((ReturnCode)26U) /*!< fifo over or underflow error */ +#define ERR_PAR ((ReturnCode)27U) /*!< parity error */ +#define ERR_DONE ((ReturnCode)28U) /*!< transfer has already finished */ +#define ERR_RF_COLLISION ((ReturnCode)29U) /*!< collision error (Bit Collision or during RF Collision avoidance ) */ +#define ERR_HW_OVERRUN ((ReturnCode)30U) /*!< lost one or more received bytes */ +#define ERR_RELEASE_REQ ((ReturnCode)31U) /*!< device requested release */ +#define ERR_SLEEP_REQ ((ReturnCode)32U) /*!< device requested sleep */ +#define ERR_WRONG_STATE ((ReturnCode)33U) /*!< incorrent state for requested operation */ +#define ERR_MAX_RERUNS ((ReturnCode)34U) /*!< blocking procedure reached maximum runs */ +#define ERR_DISABLED ((ReturnCode)35U) /*!< operation aborted due to disabled configuration */ +#define ERR_HW_MISMATCH ((ReturnCode)36U) /*!< expected hw do not match */ +#define ERR_LINK_LOSS ((ReturnCode)37U) /*!< Other device's field didn't behave as expected: turned off by Initiator in Passive mode, or AP2P did not turn on field */ +#define ERR_INVALID_HANDLE ((ReturnCode)38U) /*!< invalid or not initalized device handle */ + +#define ERR_INCOMPLETE_BYTE ((ReturnCode)40U) /*!< Incomplete byte rcvd */ +#define ERR_INCOMPLETE_BYTE_01 ((ReturnCode)41U) /*!< Incomplete byte rcvd - 1 bit */ +#define ERR_INCOMPLETE_BYTE_02 ((ReturnCode)42U) /*!< Incomplete byte rcvd - 2 bit */ +#define ERR_INCOMPLETE_BYTE_03 ((ReturnCode)43U) /*!< Incomplete byte rcvd - 3 bit */ +#define ERR_INCOMPLETE_BYTE_04 ((ReturnCode)44U) /*!< Incomplete byte rcvd - 4 bit */ +#define ERR_INCOMPLETE_BYTE_05 ((ReturnCode)45U) /*!< Incomplete byte rcvd - 5 bit */ +#define ERR_INCOMPLETE_BYTE_06 ((ReturnCode)46U) /*!< Incomplete byte rcvd - 6 bit */ +#define ERR_INCOMPLETE_BYTE_07 ((ReturnCode)47U) /*!< Incomplete byte rcvd - 7 bit */ + + + + +/* General Sub-category number */ +#define ERR_GENERIC_GRP (0x0000) /*!< Reserved value for generic error no */ +#define ERR_WARN_GRP (0x0100) /*!< Errors which are not expected in normal operation */ +#define ERR_PROCESS_GRP (0x0200) /*!< Processes management errors */ +#define ERR_SIO_GRP (0x0800) /*!< SIO errors due to logging */ +#define ERR_RINGBUF_GRP (0x0900) /*!< Ring Buffer errors */ +#define ERR_MQ_GRP (0x0A00) /*!< MQ errors */ +#define ERR_TIMER_GRP (0x0B00) /*!< Timer errors */ +#define ERR_RFAL_GRP (0x0C00) /*!< RFAL errors */ +#define ERR_UART_GRP (0x0D00) /*!< UART errors */ +#define ERR_SPI_GRP (0x0E00) /*!< SPI errors */ +#define ERR_I2C_GRP (0x0F00) /*!< I2c errors */ + + +#define ERR_INSERT_SIO_GRP(x) (ERR_SIO_GRP | (x)) /*!< Insert the SIO grp */ +#define ERR_INSERT_RINGBUF_GRP(x) (ERR_RINGBUF_GRP | (x)) /*!< Insert the Ring Buffer grp */ +#define ERR_INSERT_RFAL_GRP(x) (ERR_RFAL_GRP | (x)) /*!< Insert the RFAL grp */ +#define ERR_INSERT_SPI_GRP(x) (ERR_SPI_GRP | (x)) /*!< Insert the spi grp */ +#define ERR_INSERT_I2C_GRP(x) (ERR_I2C_GRP | (x)) /*!< Insert the i2c grp */ +#define ERR_INSERT_UART_GRP(x) (ERR_UART_GRP | (x)) /*!< Insert the uart grp */ +#define ERR_INSERT_TIMER_GRP(x) (ERR_TIMER_GRP | (x)) /*!< Insert the timer grp */ +#define ERR_INSERT_MQ_GRP(x) (ERR_MQ_GRP | (x)) /*!< Insert the mq grp */ +#define ERR_INSERT_PROCESS_GRP(x) (ERR_PROCESS_GRP | (x)) /*!< Insert the process grp */ +#define ERR_INSERT_WARN_GRP(x) (ERR_WARN_GRP | (x)) /*!< Insert the i2c grp */ +#define ERR_INSERT_GENERIC_GRP(x) (ERR_GENERIC_GRP | (x)) /*!< Insert the generic grp */ + + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +#define ERR_NO_MASK(x) ((uint16_t)(x) & 0x00FFU) /*!< Mask the error number */ + + + +/*! Common code to exit a function with the error if function f return error */ +#define EXIT_ON_ERR(r, f) \ + (r) = (f); \ + if (ERR_NONE != (r)) \ + { \ + return (r); \ + } + +#endif /* ST_ERRNO_H */ + diff --git a/Software/fab-reader2-c/components/st25r3911/timer.c b/Software/fab-reader2-c/components/st25r3911/timer.c new file mode 100644 index 0000000..b13c7a5 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/timer.c @@ -0,0 +1,121 @@ +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ANSI C + */ + +/*! \file timer.c + * + * \brief SW Timer implementation + * + * \author Gustavo Patricio + * + * This module makes use of a System Tick in millisconds and provides + * an abstraction for SW timers + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "timer.h" + + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +static uint32_t timerStopwatchTick; + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + + +/*******************************************************************************/ +uint32_t timerCalculateTimer( uint16_t time ) +{ + return (platformGetSysTick() + time); +} + + +/*******************************************************************************/ +bool timerIsExpired( uint32_t timer ) +{ + uint32_t uDiff; + int32_t sDiff; + + uDiff = (timer - platformGetSysTick()); /* Calculate the diff between the timers */ + sDiff = uDiff; /* Convert the diff to a signed var */ + /* Having done this has two side effects: + * 1) all differences smaller than -(2^31) ms (~25d) will become positive + * Signaling not expired: acceptable! + * 2) Time roll-over case will be handled correctly: super! + */ + + /* Check if the given timer has expired already */ + if( sDiff < 0 ) + { + return true; + } + + return false; +} + + +/*******************************************************************************/ +void timerDelay( uint16_t tOut ) +{ + uint32_t t; + + /* Calculate the timer and wait blocking until is running */ + t = timerCalculateTimer( tOut ); + while( timerIsRunning(t) ); +} + + +/*******************************************************************************/ +void timerStopwatchStart( void ) +{ + timerStopwatchTick = platformGetSysTick(); +} + + +/*******************************************************************************/ +uint32_t timerStopwatchMeasure( void ) +{ + return (uint32_t)(platformGetSysTick() - timerStopwatchTick); +} + diff --git a/Software/fab-reader2-c/components/st25r3911/timer.h b/Software/fab-reader2-c/components/st25r3911/timer.h new file mode 100644 index 0000000..4446d45 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/timer.h @@ -0,0 +1,128 @@ +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ANSI C + */ + +/*! \file timer.h + * + * \brief SW Timer implementation header file + * + * This module makes use of a System Tick in millisconds and provides + * an abstraction for SW timers + * + */ + + + /* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "platform.h" + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define timerIsRunning(t) (!timerIsExpired(t)) + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + + /*! + ***************************************************************************** + * \brief Calculate Timer + * + * This method calculates when the timer will be expired given the amount + * time in milliseconds /a tOut. + * Once the timer has been calculated it will then be used to check when + * it expires. + * + * \see timersIsExpired + * + * \param[in] time : time/duration in Milliseconds for the timer + * + * \return u32 : The new timer calculated based on the given time + ***************************************************************************** + */ +uint32_t timerCalculateTimer( uint16_t time ); + + +/*! + ***************************************************************************** + * \brief Checks if a Timer is Expired + * + * This method checks if a timer has already expired. + * Based on the given timer previously calculated it checks if this timer + * has already elapsed + * + * \see timersCalculateTimer + * + * \param[in] timer : the timer to check + * + * \return true : timer has already expired + * \return false : timer is still running + ***************************************************************************** + */ +bool timerIsExpired( uint32_t timer ); + + + /*! + ***************************************************************************** + * \brief Performs a Delay + * + * This method performs a delay for the given amount of time in Milliseconds + * + * \param[in] time : time/duration in Milliseconds of the delay + * + ***************************************************************************** + */ +void timerDelay( uint16_t time ); + + +/*! + ***************************************************************************** + * \brief Stopwatch start + * + * This method initiates the stopwatch to later measure the time in ms + * + ***************************************************************************** + */ +void timerStopwatchStart( void ); + + +/*! + ***************************************************************************** + * \brief Stopwatch Measure + * + * This method returns the elapsed time in ms since the stopwatch was initiated + * + * \return The time in ms since the stopwatch was started + ***************************************************************************** + */ +uint32_t timerStopwatchMeasure( void ); diff --git a/Software/fab-reader2-c/components/st25r3911/utils.c b/Software/fab-reader2-c/components/st25r3911/utils.c new file mode 100644 index 0000000..e1fb0b6 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/utils.c @@ -0,0 +1,41 @@ +// +// Created by Kai Jan Kriegel on 17.10.22. +// + +#include "utils.h" + +#define MAX_HEX_STR 4 +#define MAX_HEX_STR_LENGTH 128 +char hexStr[MAX_HEX_STR][MAX_HEX_STR_LENGTH]; +uint8_t hexStrIdx = 0; + +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; + size_t len; + + if (dataLen == 0) { + pout[0] = 0; + } else { + /* Trim data that doesn't fit in buffer */ + len = MIN(dataLen, (MAX_HEX_STR_LENGTH / 2)); + + for (; i < (len - 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]; + } +} \ No newline at end of file diff --git a/Software/fab-reader2-c/components/st25r3911/utils.h b/Software/fab-reader2-c/components/st25r3911/utils.h new file mode 100644 index 0000000..9df9312 --- /dev/null +++ b/Software/fab-reader2-c/components/st25r3911/utils.h @@ -0,0 +1,113 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + + +/* + * PROJECT: NFCC firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief Common and helpful macros + * + */ + +#ifndef UTILS_H +#define UTILS_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +/*! + * this macro evaluates an error variable \a ERR against an error code \a EC. + * in case it is not equal it jumps to the given label \a LABEL. + */ +#define EVAL_ERR_NE_GOTO(EC, ERR, LABEL) \ + if ((EC) != (ERR)) goto LABEL; + +/*! + * this macro evaluates an error variable \a ERR against an error code \a EC. + * in case it is equal it jumps to the given label \a LABEL. + */ +#define EVAL_ERR_EQ_GOTO(EC, ERR, LABEL) \ + if ((EC) == (ERR)) goto LABEL; + +#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof((a)[0])) /*!< Compute the size of an array */ +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) /*!< Return the maximum of the 2 values */ +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) /*!< Return the minimum of the 2 values */ +#define BITMASK_1 (0x01) /*!< Bit mask for lsb bit */ +#define BITMASK_2 (0x03) /*!< Bit mask for two lsb bits */ +#define BITMASK_3 (0x07) /*!< Bit mask for three lsb bits */ +#define BITMASK_4 (0x0F) /*!< Bit mask for four lsb bits */ +#define U16TOU8(a) ((a) & 0x00FF) /*!< Cast 16-bit unsigned to 8-bit unsigned */ +#define GETU16(a) (((uint16_t)(a)[0] << 8) | (uint16_t)(a)[1])/*!< Cast two Big Endian 8-bits byte array to 16-bits unsigned */ +#define GETU32(a) (((uint32_t)(a)[0] << 24) | ((uint32_t)(a)[1] << 16) | ((uint32_t)(a)[2] << 8) | ((uint32_t)(a)[3])) /*!< Cast four Big Endian 8-bit byte array to 32-bit unsigned */ + +#define REVERSE_BYTES(pData, nDataSize) \ + {unsigned char swap, *lo = ((unsigned char *)(pData)), *hi = ((unsigned char *)(pData)) + (nDataSize) - 1; \ + while (lo < hi) { swap = *lo; *lo++ = *hi; *hi-- = swap; }} + +#ifdef __CSMC__ +/* STM8 COSMIC */ +#define ST_MEMMOVE(s1,s2,n) memmove(s1,s2,n) /*!< map memmove to string library code */ +static inline void * ST_MEMCPY(void *s1, const void *s2, uint32_t n) { return memcpy(s1,s2,(uint16_t)n); } /* PRQA S 0431 # MISRA 1.1 - string.h from Cosmic only provides functions with low qualified parameters */ +#define ST_MEMSET(s1,c,n) memset(s1,(char)(c),n) /*!< map memset to string library code */ +static inline int32_t ST_BYTECMP(void *s1, const void *s2, uint32_t n) { return (int32_t)memcmp(s1,s2,(uint16_t)n); } /* PRQA S 0431 # MISRA 1.1 - string.h from Cosmic only provides functions with low qualified parameters */ + +#else /* __CSMC__ */ + +#define ST_MEMMOVE memmove /*!< map memmove to string library code */ +#define ST_MEMCPY memcpy /*!< map memcpy to string library code */ +#define ST_MEMSET memset /*!< map memset to string library code */ +#define ST_BYTECMP memcmp /*!< map bytecmp to string library code */ +#endif /* __CSMC__ */ + +#define NO_WARNING(v) ((void) (v)) /*!< Macro to suppress compiler warning */ + + +#ifndef NULL +#define NULL (void*)0 /*!< represents a NULL pointer */ +#endif /* !NULL */ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +char *hex2Str(unsigned char *data, size_t dataLen); + +#endif /* UTILS_H */ + diff --git a/Software/fab-reader2-c/esp32s3.svd b/Software/fab-reader2-c/esp32s3.svd new file mode 100644 index 0000000..df32749 --- /dev/null +++ b/Software/fab-reader2-c/esp32s3.svd @@ -0,0 +1,59821 @@ + + + ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD. + ESPRESSIF + ESP32-S3 + ESP32-S3 + 10 + 32-bit MCU & 2.4 GHz Wi-Fi & Bluetooth 5 (LE) + + Copyright 2022 Espressif Systems (Shanghai) PTE LTD + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Xtensa LX7 + r0p0 + little + false + true + 3 + false + + 32 + 32 + 0x00000000 + 0xFFFFFFFF + + + AES + AES (Advanced Encryption Standard) Accelerator + AES + 0x6003A000 + + 0x0 + 0xB8 + registers + + + AES + 77 + + + + 8 + 0x4 + KEY_%s + AES key register %s + 0x0 + 0x20 + + + KEY_0 + Stores AES keys. + 0 + 32 + read-write + + + + + 4 + 0x4 + TEXT_IN_%s + Source data register %s + 0x20 + 0x20 + + + TEXT_IN_0 + Stores the source data when the AES accelerator operates in the Typical AES working mode. + 0 + 32 + read-write + + + + + 4 + 0x4 + TEXT_OUT_%s + Result data register %s + 0x30 + 0x20 + + + TEXT_OUT_0 + Stores the result data when the AES accelerator operates in the Typical AES working mode. + 0 + 32 + read-write + + + + + MODE + AES Mode register + 0x40 + 0x20 + + + MODE + Defines the key length and the encryption/decryption of the AES accelerator. + 0 + 3 + read-write + + + + + TRIGGER + AES trigger register + 0x48 + 0x20 + + + TRIGGER + Set this bit to 1 to start AES calculation. + 0 + 1 + write-only + + + + + STATE + AES state register + 0x4C + 0x20 + + + STATE + Stores the working status of the AES accelerator. For typical AES, 0: idle, 1: busy. For DMA-AES, 0: idle, 1: busy, 2: calculation_done. + 0 + 2 + read-only + + + + + 16 + 0x1 + IV_MEM[%s] + The memory that stores initialization vector + 0x50 + 0x8 + + + 16 + 0x1 + H_MEM[%s] + The memory that stores GCM hash subkey + 0x60 + 0x8 + + + 16 + 0x1 + J0_MEM[%s] + The memory that stores J0 + 0x70 + 0x8 + + + 16 + 0x1 + T0_MEM[%s] + The memory that stores T0 + 0x80 + 0x8 + + + DMA_ENABLE + AES accelerator working mode register + 0x90 + 0x20 + + + DMA_ENABLE + Defines the working mode of the AES accelerator. 1'b0: typical AES working mode, 1'b1: DMA-AES working mode. + 0 + 1 + read-write + + + + + BLOCK_MODE + AES cipher block mode register + 0x94 + 0x20 + + + BLOCK_MODE + Defines the block cipher mode of the AES accelerator operating under the DMA-AES working mode. 0x0: ECB, 0x1: CBC, 0x2: OFB, 0x3: CTR, 0x4: CFB-8, 0x5: CFB-128, 0x6: reserved, 0x7: reserved. + 0 + 3 + read-write + + + + + BLOCK_NUM + AES block number register + 0x98 + 0x20 + + + BLOCK_NUM + Stores the Block Number of plaintext or ciphertext when the AES accelerator operates under the DMA-AES working mode. + 0 + 32 + read-write + + + + + INC_SEL + Standard incrementing function configure register + 0x9C + 0x20 + + + INC_SEL + Defines the Standard Incrementing Function for CTR block operation. Set this bit to 0 or 1 to choose INC32 or INC128. + 0 + 1 + read-write + + + + + AAD_BLOCK_NUM + Additional Authential Data block number register + 0xA0 + 0x20 + + + AAD_BLOCK_NUM + Those bits stores the number of AAD block. + 0 + 32 + read-write + + + + + REMAINDER_BIT_NUM + AES remainder bit number register + 0xA4 + 0x20 + + + REMAINDER_BIT_NUM + Those bits stores the number of remainder bit. + 0 + 7 + read-write + + + + + CONTINUE + AES continue register + 0xA8 + 0x20 + + + CONTINUE + Set this bit to 1 to continue GCM operation. + 0 + 1 + write-only + + + + + INT_CLR + AES Interrupt clear register + 0xAC + 0x20 + + + INT_CLEAR + Set this bit to 1 to clear AES interrupt. + 0 + 1 + write-only + + + + + INT_ENA + DMA-AES Interrupt enable register + 0xB0 + 0x20 + + + INT_ENA + Set this bit to 1 to enable AES interrupt and 0 to disable interrupt. This field is only effective for DMA-AES operation. + 0 + 1 + read-write + + + + + DATE + AES version control register + 0xB4 + 0x20 + 0x20191210 + + + DATE + This bits stores the version information of AES. + 0 + 30 + read-write + + + + + DMA_EXIT + AES-DMA exit config + 0xB8 + 0x20 + + + DMA_EXIT + Set this bit to 1 to exit AES operation. This field is only effective for DMA-AES operation. + 0 + 1 + write-only + + + + + + + APB_CTRL + Advanced Peripheral Bus Controller + APB_CTRL + 0x60026000 + + 0x0 + 0xCC + registers + + + + SYSCLK_CONF + ******* Description *********** + 0x0 + 0x20 + 0x00000001 + + + PRE_DIV_CNT + ******* Description *********** + 0 + 10 + read-write + + + CLK_320M_EN + ******* Description *********** + 10 + 1 + read-write + + + CLK_EN + ******* Description *********** + 11 + 1 + read-write + + + RST_TICK_CNT + ******* Description *********** + 12 + 1 + read-write + + + + + TICK_CONF + ******* Description *********** + 0x4 + 0x20 + 0x00010727 + + + XTAL_TICK_NUM + ******* Description *********** + 0 + 8 + read-write + + + CK8M_TICK_NUM + ******* Description *********** + 8 + 8 + read-write + + + TICK_ENABLE + ******* Description *********** + 16 + 1 + read-write + + + + + CLK_OUT_EN + ******* Description *********** + 0x8 + 0x20 + 0x000007FF + + + CLK20_OEN + ******* Description *********** + 0 + 1 + read-write + + + CLK22_OEN + ******* Description *********** + 1 + 1 + read-write + + + CLK44_OEN + ******* Description *********** + 2 + 1 + read-write + + + CLK_BB_OEN + ******* Description *********** + 3 + 1 + read-write + + + CLK80_OEN + ******* Description *********** + 4 + 1 + read-write + + + CLK160_OEN + ******* Description *********** + 5 + 1 + read-write + + + CLK_320M_OEN + ******* Description *********** + 6 + 1 + read-write + + + CLK_ADC_INF_OEN + ******* Description *********** + 7 + 1 + read-write + + + CLK_DAC_CPU_OEN + ******* Description *********** + 8 + 1 + read-write + + + CLK40X_BB_OEN + ******* Description *********** + 9 + 1 + read-write + + + CLK_XTAL_OEN + ******* Description *********** + 10 + 1 + read-write + + + + + WIFI_BB_CFG + ******* Description *********** + 0xC + 0x20 + + + WIFI_BB_CFG + ******* Description *********** + 0 + 32 + read-write + + + + + WIFI_BB_CFG_2 + ******* Description *********** + 0x10 + 0x20 + + + WIFI_BB_CFG_2 + ******* Description *********** + 0 + 32 + read-write + + + + + WIFI_CLK_EN + ******* Description *********** + 0x14 + 0x20 + 0xFFFCE030 + + + WIFI_CLK_EN + ******* Description *********** + 0 + 32 + read-write + + + + + WIFI_RST_EN + ******* Description *********** + 0x18 + 0x20 + + + WIFI_RST + ******* Description *********** + 0 + 32 + read-write + + + + + HOST_INF_SEL + ******* Description *********** + 0x1C + 0x20 + + + PERI_IO_SWAP + ******* Description *********** + 0 + 8 + read-write + + + + + EXT_MEM_PMS_LOCK + ******* Description *********** + 0x20 + 0x20 + + + EXT_MEM_PMS_LOCK + ******* Description *********** + 0 + 1 + read-write + + + + + EXT_MEM_WRITEBACK_BYPASS + ******* Description *********** + 0x24 + 0x20 + + + WRITEBACK_BYPASS + Set 1 to bypass cache writeback request to external memory so that spi will not check its attribute. + 0 + 1 + read-write + + + + + FLASH_ACE0_ATTR + ******* Description *********** + 0x28 + 0x20 + 0x000000FF + + + FLASH_ACE0_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + FLASH_ACE1_ATTR + ******* Description *********** + 0x2C + 0x20 + 0x000000FF + + + FLASH_ACE1_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + FLASH_ACE2_ATTR + ******* Description *********** + 0x30 + 0x20 + 0x000000FF + + + FLASH_ACE2_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + FLASH_ACE3_ATTR + ******* Description *********** + 0x34 + 0x20 + 0x000000FF + + + FLASH_ACE3_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + FLASH_ACE0_ADDR + ******* Description *********** + 0x38 + 0x20 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + FLASH_ACE1_ADDR + ******* Description *********** + 0x3C + 0x20 + 0x10000000 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + FLASH_ACE2_ADDR + ******* Description *********** + 0x40 + 0x20 + 0x20000000 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + FLASH_ACE3_ADDR + ******* Description *********** + 0x44 + 0x20 + 0x30000000 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + FLASH_ACE0_SIZE + ******* Description *********** + 0x48 + 0x20 + 0x00001000 + + + FLASH_ACE0_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + FLASH_ACE1_SIZE + ******* Description *********** + 0x4C + 0x20 + 0x00001000 + + + FLASH_ACE1_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + FLASH_ACE2_SIZE + ******* Description *********** + 0x50 + 0x20 + 0x00001000 + + + FLASH_ACE2_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + FLASH_ACE3_SIZE + ******* Description *********** + 0x54 + 0x20 + 0x00001000 + + + FLASH_ACE3_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + SRAM_ACE0_ATTR + ******* Description *********** + 0x58 + 0x20 + 0x000000FF + + + SRAM_ACE0_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + SRAM_ACE1_ATTR + ******* Description *********** + 0x5C + 0x20 + 0x000000FF + + + SRAM_ACE1_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + SRAM_ACE2_ATTR + ******* Description *********** + 0x60 + 0x20 + 0x000000FF + + + SRAM_ACE2_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + SRAM_ACE3_ATTR + ******* Description *********** + 0x64 + 0x20 + 0x000000FF + + + SRAM_ACE3_ATTR + ******* Description *********** + 0 + 9 + read-write + + + + + SRAM_ACE0_ADDR + ******* Description *********** + 0x68 + 0x20 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + SRAM_ACE1_ADDR + ******* Description *********** + 0x6C + 0x20 + 0x10000000 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + SRAM_ACE2_ADDR + ******* Description *********** + 0x70 + 0x20 + 0x20000000 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + SRAM_ACE3_ADDR + ******* Description *********** + 0x74 + 0x20 + 0x30000000 + + + S + ******* Description *********** + 0 + 32 + read-write + + + + + SRAM_ACE0_SIZE + ******* Description *********** + 0x78 + 0x20 + 0x00001000 + + + SRAM_ACE0_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + SRAM_ACE1_SIZE + ******* Description *********** + 0x7C + 0x20 + 0x00001000 + + + SRAM_ACE1_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + SRAM_ACE2_SIZE + ******* Description *********** + 0x80 + 0x20 + 0x00001000 + + + SRAM_ACE2_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + SRAM_ACE3_SIZE + ******* Description *********** + 0x84 + 0x20 + 0x00001000 + + + SRAM_ACE3_SIZE + ******* Description *********** + 0 + 16 + read-write + + + + + SPI_MEM_PMS_CTRL + ******* Description *********** + 0x88 + 0x20 + + + SPI_MEM_REJECT_INT + ******* Description *********** + 0 + 1 + read-only + + + SPI_MEM_REJECT_CLR + ******* Description *********** + 1 + 1 + write-only + + + SPI_MEM_REJECT_CDE + ******* Description *********** + 2 + 5 + read-only + + + + + SPI_MEM_REJECT_ADDR + ******* Description *********** + 0x8C + 0x20 + + + SPI_MEM_REJECT_ADDR + ******* Description *********** + 0 + 32 + read-only + + + + + SDIO_CTRL + ******* Description *********** + 0x90 + 0x20 + + + SDIO_WIN_ACCESS_EN + ******* Description *********** + 0 + 1 + read-write + + + + + REDCY_SIG0 + ******* Description *********** + 0x94 + 0x20 + + + REDCY_SIG0 + ******* Description *********** + 0 + 31 + read-write + + + REDCY_ANDOR + ******* Description *********** + 31 + 1 + read-only + + + + + REDCY_SIG1 + ******* Description *********** + 0x98 + 0x20 + + + REDCY_SIG1 + ******* Description *********** + 0 + 31 + read-write + + + REDCY_NANDOR + ******* Description *********** + 31 + 1 + read-only + + + + + FRONT_END_MEM_PD + ******* Description *********** + 0x9C + 0x20 + 0x00000055 + + + AGC_MEM_FORCE_PU + ******* Description *********** + 0 + 1 + read-write + + + AGC_MEM_FORCE_PD + ******* Description *********** + 1 + 1 + read-write + + + PBUS_MEM_FORCE_PU + ******* Description *********** + 2 + 1 + read-write + + + PBUS_MEM_FORCE_PD + ******* Description *********** + 3 + 1 + read-write + + + DC_MEM_FORCE_PU + ******* Description *********** + 4 + 1 + read-write + + + DC_MEM_FORCE_PD + ******* Description *********** + 5 + 1 + read-write + + + FREQ_MEM_FORCE_PU + ******* Description *********** + 6 + 1 + read-write + + + FREQ_MEM_FORCE_PD + ******* Description *********** + 7 + 1 + read-write + + + + + SPI_MEM_ECC_CTRL + ******* Description *********** + 0xA0 + 0x20 + 0x00200000 + + + FLASH_PAGE_SIZE + Set the page size of the used MSPI flash. 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes. + 18 + 2 + read-write + + + SRAM_PAGE_SIZE + Set the page size of the used MSPI external RAM. 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes. + 20 + 2 + read-write + + + + + CLKGATE_FORCE_ON + ******* Description *********** + 0xA8 + 0x20 + 0x00003FFF + + + ROM_CLKGATE_FORCE_ON + ******* Description *********** + 0 + 3 + read-write + + + SRAM_CLKGATE_FORCE_ON + ******* Description *********** + 3 + 11 + read-write + + + + + MEM_POWER_DOWN + ******* Description *********** + 0xAC + 0x20 + + + ROM_POWER_DOWN + ******* Description *********** + 0 + 3 + read-write + + + SRAM_POWER_DOWN + ******* Description *********** + 3 + 11 + read-write + + + + + MEM_POWER_UP + ******* Description *********** + 0xB0 + 0x20 + 0x00003FFF + + + ROM_POWER_UP + ******* Description *********** + 0 + 3 + read-write + + + SRAM_POWER_UP + ******* Description *********** + 3 + 11 + read-write + + + + + RETENTION_CTRL + ******* Description *********** + 0xB4 + 0x20 + + + RETENTION_CPU_LINK_ADDR + ******* Description *********** + 0 + 27 + read-write + + + NOBYPASS_CPU_ISO_RST + ******* Description *********** + 27 + 1 + read-write + + + + + RETENTION_CTRL1 + ******* Description *********** + 0xB8 + 0x20 + + + RETENTION_TAG_LINK_ADDR + ******* Description *********** + 0 + 27 + read-write + + + + + RETENTION_CTRL2 + ******* Description *********** + 0xBC + 0x20 + 0x001FEFF0 + + + RET_ICACHE_SIZE + ******* Description *********** + 4 + 8 + read-write + + + RET_ICACHE_VLD_SIZE + ******* Description *********** + 13 + 8 + read-write + + + RET_ICACHE_START_POINT + ******* Description *********** + 22 + 8 + read-write + + + RET_ICACHE_ENABLE + ******* Description *********** + 31 + 1 + read-write + + + + + RETENTION_CTRL3 + ******* Description *********** + 0xC0 + 0x20 + 0x003FFFF0 + + + RET_DCACHE_SIZE + ******* Description *********** + 4 + 9 + read-write + + + RET_DCACHE_VLD_SIZE + ******* Description *********** + 13 + 9 + read-write + + + RET_DCACHE_START_POINT + ******* Description *********** + 22 + 9 + read-write + + + RET_DCACHE_ENABLE + ******* Description *********** + 31 + 1 + read-write + + + + + RETENTION_CTRL4 + ******* Description *********** + 0xC4 + 0x20 + 0xFFFFFFFF + + + RETENTION_INV_CFG + ******* Description *********** + 0 + 32 + read-write + + + + + RETENTION_CTRL5 + ******* Description *********** + 0xC8 + 0x20 + + + RETENTION_DISABLE + ******* Description *********** + 0 + 1 + read-write + + + + + DATE + ******* Description *********** + 0x3FC + 0x20 + 0x02101150 + + + DATE + Version control + 0 + 32 + read-write + + + + + + + APB_SARADC + Successive Approximation Register Analog to Digital Converter + APB_SARADC + 0x60040000 + + 0x0 + 0x70 + registers + + + APB_ADC + 65 + + + + CTRL + configure apb saradc controller + 0x0 + 0x20 + 0x407F8240 + + + SARADC_START_FORCE + enable start saradc by sw + 0 + 1 + read-write + + + SARADC_START + start saradc by sw + 1 + 1 + read-write + + + SARADC_WORK_MODE + 0: single mode, 1: double mode, 2: alternate mode + 3 + 2 + read-write + + + SARADC_SAR_SEL + 0: SAR1, 1: SAR2, only work for single SAR mode + 5 + 1 + read-write + + + SARADC_SAR_CLK_GATED + enable SAR CLK gate when saradc idle + 6 + 1 + read-write + + + SARADC_SAR_CLK_DIV + SAR clock divider + 7 + 8 + read-write + + + SARADC_SAR1_PATT_LEN + 0 ~ 15 means length 1 ~ 16 + 15 + 4 + read-write + + + SARADC_SAR2_PATT_LEN + 0 ~ 15 means length 1 ~ 16 + 19 + 4 + read-write + + + SARADC_SAR1_PATT_P_CLEAR + clear the pointer of pattern table for DIG ADC1 CTRL + 23 + 1 + read-write + + + SARADC_SAR2_PATT_P_CLEAR + clear the pointer of pattern table for DIG ADC2 CTRL + 24 + 1 + read-write + + + SARADC_DATA_SAR_SEL + 1: sar_sel will be coded by the MSB of the 16-bit output data, in this case the resolution should not be larger than 11 bits. + 25 + 1 + read-write + + + SARADC_DATA_TO_I2S + 1: I2S input data is from SAR ADC (for DMA), 0: I2S input data is from GPIO matrix + 26 + 1 + read-write + + + SARADC_XPD_SAR_FORCE + force option to xpd sar blocks + 27 + 2 + read-write + + + SARADC_WAIT_ARB_CYCLE + wait arbit signal stable after sar_done + 30 + 2 + read-write + + + + + CTRL2 + configure apb saradc controller + 0x4 + 0x20 + 0x0000A1FE + + + SARADC_MEAS_NUM_LIMIT + enable apb saradc limit the sample num + 0 + 1 + read-write + + + SARADC_MAX_MEAS_NUM + max conversion number + 1 + 8 + read-write + + + SARADC_SAR1_INV + 1: data to DIG ADC1 CTRL is inverted, otherwise not + 9 + 1 + read-write + + + SARADC_SAR2_INV + 1: data to DIG ADC2 CTRL is inverted, otherwise not + 10 + 1 + read-write + + + SARADC_TIMER_SEL + 1: select saradc timer 0: i2s_ws trigger + 11 + 1 + read-write + + + SARADC_TIMER_TARGET + to set saradc timer target + 12 + 12 + read-write + + + SARADC_TIMER_EN + to enable saradc timer trigger + 24 + 1 + read-write + + + + + FILTER_CTRL1 + configure saradc filter + 0x8 + 0x20 + + + FILTER_FACTOR1 + apb saradc factor1 + 26 + 3 + read-write + + + FILTER_FACTOR0 + apb saradc factor0 + 29 + 3 + read-write + + + + + FSM_WAIT + configure apb saradc fsm + 0xC + 0x20 + 0x00FF0808 + + + SARADC_XPD_WAIT + the cycle which saradc controller in xpd state + 0 + 8 + read-write + + + SARADC_RSTB_WAIT + the cycle which saradc controller in rst state + 8 + 8 + read-write + + + SARADC_STANDBY_WAIT + the cycle which saradc controller in standby state + 16 + 8 + read-write + + + + + SAR1_STATUS + saradc1 status for debug + 0x10 + 0x20 + + + SARADC_SAR1_STATUS + saradc1 status + 0 + 32 + read-only + + + + + SAR2_STATUS + saradc2 status for debug + 0x14 + 0x20 + + + SARADC_SAR2_STATUS + saradc2 status + 0 + 32 + read-only + + + + + SAR1_PATT_TAB1 + configure apb saradc pattern table + 0x18 + 0x20 + + + SARADC_SAR1_PATT_TAB1 + item 0 ~ 3 for pattern table 1 (each item 6bit) + 0 + 24 + read-write + + + + + SAR1_PATT_TAB2 + configure apb saradc pattern table + 0x1C + 0x20 + + + SARADC_SAR1_PATT_TAB2 + Item 4 ~ 7 for pattern table 1 (each item 6bit) + 0 + 24 + read-write + + + + + SAR1_PATT_TAB3 + configure apb saradc pattern table + 0x20 + 0x20 + + + SARADC_SAR1_PATT_TAB3 + Item 8 ~ 11 for pattern table 1 (each item 6bit) + 0 + 24 + read-write + + + + + SAR1_PATT_TAB4 + configure apb saradc pattern table + 0x24 + 0x20 + + + SARADC_SAR1_PATT_TAB4 + Item 12 ~ 15 for pattern table 1 (each item 6bit) + 0 + 24 + read-write + + + + + SAR2_PATT_TAB1 + configure apb saradc pattern table + 0x28 + 0x20 + + + SARADC_SAR2_PATT_TAB1 + item 0 ~ 3 for pattern table 2 (each item 6bit) + 0 + 24 + read-write + + + + + SAR2_PATT_TAB2 + configure apb saradc pattern table + 0x2C + 0x20 + + + SARADC_SAR2_PATT_TAB2 + Item 4 ~ 7 for pattern table 2 (each item 6bit) + 0 + 24 + read-write + + + + + SAR2_PATT_TAB3 + configure apb saradc pattern table + 0x30 + 0x20 + + + SARADC_SAR2_PATT_TAB3 + Item 8 ~ 11 for pattern table 2 (each item 6bit) + 0 + 24 + read-write + + + + + SAR2_PATT_TAB4 + configure apb saradc pattern table + 0x34 + 0x20 + + + SARADC_SAR2_PATT_TAB4 + Item 12 ~ 15 for pattern table 2 (each item 6bit) + 0 + 24 + read-write + + + + + APB_ADC_ARB_CTRL + configure apb saradc arbit + 0x38 + 0x20 + 0x00000900 + + + ADC_ARB_APB_FORCE + adc2 arbiter force to enableapb controller + 2 + 1 + read-write + + + ADC_ARB_RTC_FORCE + adc2 arbiter force to enable rtc controller + 3 + 1 + read-write + + + ADC_ARB_WIFI_FORCE + adc2 arbiter force to enable wifi controller + 4 + 1 + read-write + + + ADC_ARB_GRANT_FORCE + adc2 arbiter force grant + 5 + 1 + read-write + + + ADC_ARB_APB_PRIORITY + Set adc2 arbiterapb priority + 6 + 2 + read-write + + + ADC_ARB_RTC_PRIORITY + Set adc2 arbiter rtc priority + 8 + 2 + read-write + + + ADC_ARB_WIFI_PRIORITY + Set adc2 arbiter wifi priority + 10 + 2 + read-write + + + ADC_ARB_FIX_PRIORITY + adc2 arbiter uses fixed priority + 12 + 1 + read-write + + + + + FILTER_CTRL0 + configure apb saradc arbit + 0x3C + 0x20 + 0x006B4000 + + + FILTER_CHANNEL1 + configure the filter1 channel + 14 + 5 + read-write + + + FILTER_CHANNEL0 + configure the filter0 channel + 19 + 5 + read-write + + + FILTER_RESET + enable apb_adc1_filter + 31 + 1 + read-write + + + + + APB_SARADC1_DATA_STATUS + get apb saradc sample data + 0x40 + 0x20 + + + APB_SARADC1_DATA + apbsaradc sample data + 0 + 17 + read-only + + + + + THRES0_CTRL + configure apb saradc thres monitor + 0x44 + 0x20 + 0x0003FFED + + + THRES0_CHANNEL + configure which channel thres0 monitor + 0 + 5 + read-write + + + THRES0_HIGH + thres0 monitor high thres + 5 + 13 + read-write + + + THRES0_LOW + thres0 monitor low thres + 18 + 13 + read-write + + + + + THRES1_CTRL + configure apb saradc thres monitor + 0x48 + 0x20 + 0x0003FFED + + + THRES1_CHANNEL + configure which channel thres0 monitor + 0 + 5 + read-write + + + THRES1_HIGH + thres1 monitor high thres + 5 + 13 + read-write + + + THRES1_LOW + thres1 monitor low thres + 18 + 13 + read-write + + + + + THRES_CTRL + configure thres monitor enable + 0x58 + 0x20 + + + THRES_ALL_EN + enable thres0 to monitor all channel + 27 + 1 + read-write + + + THRES3_EN + no public + 28 + 1 + read-write + + + THRES2_EN + no public + 29 + 1 + read-write + + + THRES1_EN + enable thres1 + 30 + 1 + read-write + + + THRES0_EN + enable thres0 + 31 + 1 + read-write + + + + + INT_ENA + enable interrupt + 0x5C + 0x20 + + + THRES1_LOW_INT_ENA + interrupt of thres1 low + 26 + 1 + read-write + + + THRES0_LOW_INT_ENA + interrupt of thres0 low + 27 + 1 + read-write + + + THRES1_HIGH_INT_ENA + interrupt of thres1 high + 28 + 1 + read-write + + + THRES0_HIGH_INT_ENA + interrupt of thres0 high + 29 + 1 + read-write + + + APB_SARADC2_DONE_INT_ENA + interrupt of sar2 done + 30 + 1 + read-write + + + APB_SARADC1_DONE_INT_ENA + interrupt of sar1 done + 31 + 1 + read-write + + + + + INT_RAW + raw of interrupt + 0x60 + 0x20 + + + THRES1_LOW_INT_RAW + interrupt of thres1 low + 26 + 1 + read-only + + + THRES0_LOW_INT_RAW + interrupt of thres0 low + 27 + 1 + read-only + + + THRES1_HIGH_INT_RAW + interrupt of thres1 high + 28 + 1 + read-only + + + THRES0_HIGH_INT_RAW + interrupt of thres0 high + 29 + 1 + read-only + + + APB_SARADC2_DONE_INT_RAW + interrupt of sar2 done + 30 + 1 + read-only + + + APB_SARADC1_DONE_INT_RAW + interrupt of sar1 done + 31 + 1 + read-only + + + + + INT_ST + state of interrupt + 0x64 + 0x20 + + + THRES1_LOW_INT_ST + interrupt of thres1 low + 26 + 1 + read-only + + + THRES0_LOW_INT_ST + interrupt of thres0 low + 27 + 1 + read-only + + + THRES1_HIGH_INT_ST + interrupt of thres1 high + 28 + 1 + read-only + + + THRES0_HIGH_INT_ST + interrupt of thres0 high + 29 + 1 + read-only + + + APB_SARADC2_DONE_INT_ST + interrupt of sar2 done + 30 + 1 + read-only + + + APB_SARADC1_DONE_INT_ST + interrupt of sar1 done + 31 + 1 + read-only + + + + + INT_CLR + clear interrupt + 0x68 + 0x20 + + + THRES1_LOW_INT_CLR + interrupt of thres1 low + 26 + 1 + write-only + + + THRES0_LOW_INT_CLR + interrupt of thres0 low + 27 + 1 + write-only + + + THRES1_HIGH_INT_CLR + interrupt of thres1 high + 28 + 1 + write-only + + + THRES0_HIGH_INT_CLR + interrupt of thres0 high + 29 + 1 + write-only + + + APB_SARADC2_DONE_INT_CLR + interrupt of sar2 done + 30 + 1 + write-only + + + APB_SARADC1_DONE_INT_CLR + interrupt of sar1 done + 31 + 1 + write-only + + + + + DMA_CONF + configure apb saradc dma + 0x6C + 0x20 + 0x000000FF + + + APB_ADC_EOF_NUM + the dma_in_suc_eof gen when sample cnt = spi_eof_num + 0 + 16 + read-write + + + APB_ADC_RESET_FSM + reset_apb_adc_state + 30 + 1 + read-write + + + APB_ADC_TRANS + enable apb_adc use spi_dma + 31 + 1 + read-write + + + + + APB_ADC_CLKM_CONF + configure apb saradc clock + 0x70 + 0x20 + 0x00000004 + + + CLKM_DIV_NUM + Integral clock divider value + 0 + 8 + read-write + + + CLKM_DIV_B + Fractional clock divider numerator value + 8 + 6 + read-write + + + CLKM_DIV_A + Fractional clock divider denominator value + 14 + 6 + read-write + + + CLK_EN + no public + 20 + 1 + read-write + + + CLK_SEL + Set this bit to enable clk_apll + 21 + 2 + read-write + + + + + APB_SARADC2_DATA_STATUS + get apb saradc2 sample data + 0x78 + 0x20 + + + APB_SARADC2_DATA + apb saradc2 sample data + 0 + 17 + read-only + + + + + APB_CTRL_DATE + version + 0x3FC + 0x20 + 0x02101180 + + + APB_CTRL_DATE + version + 0 + 32 + read-write + + + + + + + DEBUG_ASSIST + Debug Assist + DEBUG_ASSIST + 0x600CE000 + + 0x0 + 0x15C + registers + + + ASSIST_DEBUG + 83 + + + + CORE_0_INTERRUPT_ENA + core0 monitor enable configuration register + 0x0 + 0x20 + + + CORE_0_AREA_DRAM0_0_RD_ENA + Core0 dram0 area0 read monitor enable + 0 + 1 + read-write + + + CORE_0_AREA_DRAM0_0_WR_ENA + Core0 dram0 area0 write monitor enable + 1 + 1 + read-write + + + CORE_0_AREA_DRAM0_1_RD_ENA + Core0 dram0 area1 read monitor enable + 2 + 1 + read-write + + + CORE_0_AREA_DRAM0_1_WR_ENA + Core0 dram0 area1 write monitor enable + 3 + 1 + read-write + + + CORE_0_AREA_PIF_0_RD_ENA + Core0 PIF area0 read monitor enable + 4 + 1 + read-write + + + CORE_0_AREA_PIF_0_WR_ENA + Core0 PIF area0 write monitor enable + 5 + 1 + read-write + + + CORE_0_AREA_PIF_1_RD_ENA + Core0 PIF area1 read monitor enable + 6 + 1 + read-write + + + CORE_0_AREA_PIF_1_WR_ENA + Core0 PIF area1 write monitor enable + 7 + 1 + read-write + + + CORE_0_SP_SPILL_MIN_ENA + Core0 stackpoint overflow monitor enable + 8 + 1 + read-write + + + CORE_0_SP_SPILL_MAX_ENA + Core0 stackpoint underflow monitor enable + 9 + 1 + read-write + + + CORE_0_IRAM0_EXCEPTION_MONITOR_ENA + IBUS busy monitor enable + 10 + 1 + read-write + + + CORE_0_DRAM0_EXCEPTION_MONITOR_ENA + DBUS busy monitor enbale + 11 + 1 + read-write + + + + + CORE_0_INTERRUPT_RAW + core0 monitor interrupt status register + 0x4 + 0x20 + + + CORE_0_AREA_DRAM0_0_RD_RAW + Core0 dram0 area0 read monitor interrupt status + 0 + 1 + read-only + + + CORE_0_AREA_DRAM0_0_WR_RAW + Core0 dram0 area0 write monitor interrupt status + 1 + 1 + read-only + + + CORE_0_AREA_DRAM0_1_RD_RAW + Core0 dram0 area1 read monitor interrupt status + 2 + 1 + read-only + + + CORE_0_AREA_DRAM0_1_WR_RAW + Core0 dram0 area1 write monitor interrupt status + 3 + 1 + read-only + + + CORE_0_AREA_PIF_0_RD_RAW + Core0 PIF area0 read monitor interrupt status + 4 + 1 + read-only + + + CORE_0_AREA_PIF_0_WR_RAW + Core0 PIF area0 write monitor interrupt status + 5 + 1 + read-only + + + CORE_0_AREA_PIF_1_RD_RAW + Core0 PIF area1 read monitor interrupt status + 6 + 1 + read-only + + + CORE_0_AREA_PIF_1_WR_RAW + Core0 PIF area1 write monitor interrupt status + 7 + 1 + read-only + + + CORE_0_SP_SPILL_MIN_RAW + Core0 stackpoint overflow monitor interrupt status + 8 + 1 + read-only + + + CORE_0_SP_SPILL_MAX_RAW + Core0 stackpoint underflow monitor interrupt status + 9 + 1 + read-only + + + CORE_0_IRAM0_EXCEPTION_MONITOR_RAW + IBUS busy monitor interrupt status + 10 + 1 + read-only + + + CORE_0_DRAM0_EXCEPTION_MONITOR_RAW + DBUS busy monitor initerrupt status + 11 + 1 + read-only + + + + + CORE_0_INTERRUPT_RLS + core0 monitor interrupt enable register + 0x8 + 0x20 + + + CORE_0_AREA_DRAM0_0_RD_RLS + Core0 dram0 area0 read monitor interrupt enable + 0 + 1 + read-write + + + CORE_0_AREA_DRAM0_0_WR_RLS + Core0 dram0 area0 write monitor interrupt enable + 1 + 1 + read-write + + + CORE_0_AREA_DRAM0_1_RD_RLS + Core0 dram0 area1 read monitor interrupt enable + 2 + 1 + read-write + + + CORE_0_AREA_DRAM0_1_WR_RLS + Core0 dram0 area1 write monitor interrupt enable + 3 + 1 + read-write + + + CORE_0_AREA_PIF_0_RD_RLS + Core0 PIF area0 read monitor interrupt enable + 4 + 1 + read-write + + + CORE_0_AREA_PIF_0_WR_RLS + Core0 PIF area0 write monitor interrupt enable + 5 + 1 + read-write + + + CORE_0_AREA_PIF_1_RD_RLS + Core0 PIF area1 read monitor interrupt enable + 6 + 1 + read-write + + + CORE_0_AREA_PIF_1_WR_RLS + Core0 PIF area1 write monitor interrupt enable + 7 + 1 + read-write + + + CORE_0_SP_SPILL_MIN_RLS + Core0 stackpoint overflow monitor interrupt enable + 8 + 1 + read-write + + + CORE_0_SP_SPILL_MAX_RLS + Core0 stackpoint underflow monitor interrupt enable + 9 + 1 + read-write + + + CORE_0_IRAM0_EXCEPTION_MONITOR_RLS + IBUS busy monitor interrupt enable + 10 + 1 + read-write + + + CORE_0_DRAM0_EXCEPTION_MONITOR_RLS + DBUS busy monitor interrupt enbale + 11 + 1 + read-write + + + + + CORE_0_INTERRUPT_CLR + core0 monitor interrupt clr register + 0xC + 0x20 + + + CORE_0_AREA_DRAM0_0_RD_CLR + Core0 dram0 area0 read monitor interrupt clr + 0 + 1 + read-write + + + CORE_0_AREA_DRAM0_0_WR_CLR + Core0 dram0 area0 write monitor interrupt clr + 1 + 1 + read-write + + + CORE_0_AREA_DRAM0_1_RD_CLR + Core0 dram0 area1 read monitor interrupt clr + 2 + 1 + read-write + + + CORE_0_AREA_DRAM0_1_WR_CLR + Core0 dram0 area1 write monitor interrupt clr + 3 + 1 + read-write + + + CORE_0_AREA_PIF_0_RD_CLR + Core0 PIF area0 read monitor interrupt clr + 4 + 1 + read-write + + + CORE_0_AREA_PIF_0_WR_CLR + Core0 PIF area0 write monitor interrupt clr + 5 + 1 + read-write + + + CORE_0_AREA_PIF_1_RD_CLR + Core0 PIF area1 read monitor interrupt clr + 6 + 1 + read-write + + + CORE_0_AREA_PIF_1_WR_CLR + Core0 PIF area1 write monitor interrupt clr + 7 + 1 + read-write + + + CORE_0_SP_SPILL_MIN_CLR + Core0 stackpoint overflow monitor interrupt clr + 8 + 1 + read-write + + + CORE_0_SP_SPILL_MAX_CLR + Core0 stackpoint underflow monitor interrupt clr + 9 + 1 + read-write + + + CORE_0_IRAM0_EXCEPTION_MONITOR_CLR + IBUS busy monitor interrupt clr + 10 + 1 + read-write + + + CORE_0_DRAM0_EXCEPTION_MONITOR_CLR + DBUS busy monitor interrupt clr + 11 + 1 + read-write + + + + + CORE_0_AREA_DRAM0_0_MIN + core0 dram0 region0 addr configuration register + 0x10 + 0x20 + 0xFFFFFFFF + + + CORE_0_AREA_DRAM0_0_MIN + Core0 dram0 region0 start addr + 0 + 32 + read-write + + + + + CORE_0_AREA_DRAM0_0_MAX + core0 dram0 region0 addr configuration register + 0x14 + 0x20 + + + CORE_0_AREA_DRAM0_0_MAX + Core0 dram0 region0 end addr + 0 + 32 + read-write + + + + + CORE_0_AREA_DRAM0_1_MIN + core0 dram0 region1 addr configuration register + 0x18 + 0x20 + 0xFFFFFFFF + + + CORE_0_AREA_DRAM0_1_MIN + Core0 dram0 region1 start addr + 0 + 32 + read-write + + + + + CORE_0_AREA_DRAM0_1_MAX + core0 dram0 region1 addr configuration register + 0x1C + 0x20 + + + CORE_0_AREA_DRAM0_1_MAX + Core0 dram0 region1 end addr + 0 + 32 + read-write + + + + + CORE_0_AREA_PIF_0_MIN + core0 PIF region0 addr configuration register + 0x20 + 0x20 + 0xFFFFFFFF + + + CORE_0_AREA_PIF_0_MIN + Core0 PIF region0 start addr + 0 + 32 + read-write + + + + + CORE_0_AREA_PIF_0_MAX + core0 PIF region0 addr configuration register + 0x24 + 0x20 + + + CORE_0_AREA_PIF_0_MAX + Core0 PIF region0 end addr + 0 + 32 + read-write + + + + + CORE_0_AREA_PIF_1_MIN + core0 PIF region1 addr configuration register + 0x28 + 0x20 + 0xFFFFFFFF + + + CORE_0_AREA_PIF_1_MIN + Core0 PIF region1 start addr + 0 + 32 + read-write + + + + + CORE_0_AREA_PIF_1_MAX + core0 PIF region1 addr configuration register + 0x2C + 0x20 + + + CORE_0_AREA_PIF_1_MAX + Core0 PIF region1 end addr + 0 + 32 + read-write + + + + + CORE_0_AREA_SP + core0 area sp status register + 0x30 + 0x20 + 0xFFFFFFFF + + + CORE_0_AREA_SP + the stackpointer when first touch region monitor interrupt + 0 + 32 + read-only + + + + + CORE_0_AREA_PC + core0 area pc status register + 0x34 + 0x20 + + + CORE_0_AREA_PC + the PC when first touch region monitor interrupt + 0 + 32 + read-only + + + + + CORE_0_SP_UNSTABLE + core0 sp unstable configuration register + 0x38 + 0x20 + 0x0000000B + + + CORE_0_SP_UNSTABLE + unstable period when window change,during this period no check stackpointer + 0 + 8 + read-write + + + + + CORE_0_SP_MIN + core0 sp region configuration regsiter + 0x3C + 0x20 + + + CORE_0_SP_MIN + stack min value + 0 + 32 + read-write + + + + + CORE_0_SP_MAX + core0 sp region configuration regsiter + 0x40 + 0x20 + 0xFFFFFFFF + + + CORE_0_SP_MAX + stack max value + 0 + 32 + read-write + + + + + CORE_0_SP_PC + core0 sp pc status register + 0x44 + 0x20 + + + CORE_0_SP_PC + the PC when first touch stack monitor interrupt + 0 + 32 + read-only + + + + + CORE_0_RCD_PDEBUGENABLE + core0 pdebug configuration register + 0x48 + 0x20 + + + CORE_0_RCD_PDEBUGENABLE + Core0 Pdebugenable,set 1 to open core0 Pdebug interface,then can get core0 PC + 0 + 1 + read-write + + + + + CORE_0_RCD_RECORDING + core0 pdebug status register + 0x4C + 0x20 + + + CORE_0_RCD_RECORDING + Pdebug record enable,set 1 to record core0 pdebug interface signal + 0 + 1 + read-write + + + + + CORE_0_RCD_PDEBUGINST + core0 pdebug status register + 0x50 + 0x20 + + + CORE_0_RCD_PDEBUGINST + core0 pdebuginst + 0 + 32 + read-only + + + + + CORE_0_RCD_PDEBUGSTATUS + core0 pdebug status register + 0x54 + 0x20 + + + CORE_0_RCD_PDEBUGSTATUS + core0 pdebugstatus + 0 + 8 + read-only + + + + + CORE_0_RCD_PDEBUGDATA + core0 pdebug status register + 0x58 + 0x20 + + + CORE_0_RCD_PDEBUGDATA + core0_pdebugdata + 0 + 32 + read-only + + + + + CORE_0_RCD_PDEBUGPC + core0 pdebug status register + 0x5C + 0x20 + + + CORE_0_RCD_PDEBUGPC + core0_pdebugPC + 0 + 32 + read-only + + + + + CORE_0_RCD_PDEBUGLS0STAT + core0 pdebug status register + 0x60 + 0x20 + + + CORE_0_RCD_PDEBUGLS0STAT + core0_pdebug_s0stat + 0 + 32 + read-only + + + + + CORE_0_RCD_PDEBUGLS0ADDR + core0 pdebug status register + 0x64 + 0x20 + + + CORE_0_RCD_PDEBUGLS0ADDR + core0_pdebug_s0addr + 0 + 32 + read-only + + + + + CORE_0_RCD_PDEBUGLS0DATA + core0 pdebug status register + 0x68 + 0x20 + + + CORE_0_RCD_PDEBUGLS0DATA + core0_pdebug_s0data + 0 + 32 + read-only + + + + + CORE_0_RCD_SP + core0 pdebug status register + 0x6C + 0x20 + + + CORE_0_RCD_SP + core0_stack pointer + 0 + 32 + read-only + + + + + CORE_0_IRAM0_EXCEPTION_MONITOR_0 + core0 bus busy status regsiter + 0x70 + 0x20 + + + CORE_0_IRAM0_RECORDING_ADDR_0 + The first iram0's addr[25:2] status when trigger IRAM busy interrupt + 0 + 24 + read-only + + + CORE_0_IRAM0_RECORDING_WR_0 + The first iram0's wr status when trigger IRAM busy interrupt + 24 + 1 + read-only + + + CORE_0_IRAM0_RECORDING_LOADSTORE_0 + The first iram0's loadstore status when trigger IRAM busy interrupt + 25 + 1 + read-only + + + + + CORE_0_IRAM0_EXCEPTION_MONITOR_1 + core0 bus busy status regsiter + 0x74 + 0x20 + + + CORE_0_IRAM0_RECORDING_ADDR_1 + The second iram0's addr[25:2] status when trigger IRAM busy interrupt + 0 + 24 + read-only + + + CORE_0_IRAM0_RECORDING_WR_1 + The second iram0's wr status when trigger IRAM busy interrupt + 24 + 1 + read-only + + + CORE_0_IRAM0_RECORDING_LOADSTORE_1 + The second iram0's loadstore status when trigger IRAM busy interrupt + 25 + 1 + read-only + + + + + CORE_0_DRAM0_EXCEPTION_MONITOR_0 + core0 bus busy status regsiter + 0x78 + 0x20 + + + CORE_0_DRAM0_RECORDING_ADDR_0 + The first dram0's addr[25:4] status when trigger DRAM busy interrupt + 0 + 22 + read-only + + + CORE_0_DRAM0_RECORDING_WR_0 + The first dram0's wr status when trigger DRAM busy interrupt + 22 + 1 + read-only + + + + + CORE_0_DRAM0_EXCEPTION_MONITOR_1 + core0 bus busy status regsiter + 0x7C + 0x20 + + + CORE_0_DRAM0_RECORDING_BYTEEN_0 + The first dram0's byteen status when trigger DRAM busy interrupt + 0 + 16 + read-only + + + + + CORE_0_DRAM0_EXCEPTION_MONITOR_2 + core0 bus busy status regsiter + 0x80 + 0x20 + 0xFFFFFFFF + + + CORE_0_DRAM0_RECORDING_PC_0 + The first dram0's PC status when trigger DRAM busy interrupt + 0 + 32 + read-only + + + + + CORE_0_DRAM0_EXCEPTION_MONITOR_3 + core0 bus busy status regsiter + 0x84 + 0x20 + + + CORE_0_DRAM0_RECORDING_ADDR_1 + The second dram0's addr[25:4] status when trigger DRAM busy interrupt + 0 + 22 + read-only + + + CORE_0_DRAM0_RECORDING_WR_1 + The second dram0's wr status when trigger DRAM busy interrupt + 22 + 1 + read-only + + + + + CORE_0_DRAM0_EXCEPTION_MONITOR_4 + core0 bus busy configuration regsiter + 0x88 + 0x20 + + + CORE_0_DRAM0_RECORDING_BYTEEN_1 + The second dram0's byteen status when trigger DRAM busy interrupt + 0 + 16 + read-only + + + + + CORE_0_DRAM0_EXCEPTION_MONITOR_5 + core0 bus busy configuration regsiter + 0x8C + 0x20 + 0xFFFFFFFF + + + CORE_0_DRAM0_RECORDING_PC_1 + The second dram0's PC status when trigger DRAM busy interrupt + 0 + 32 + read-only + + + + + CORE_1_INTERRUPT_ENA + Core1 monitor enable configuration register + 0x90 + 0x20 + + + CORE_1_AREA_DRAM0_0_RD_ENA + Core1 dram0 area0 read monitor enable + 0 + 1 + read-write + + + CORE_1_AREA_DRAM0_0_WR_ENA + Core1 dram0 area0 write monitor enable + 1 + 1 + read-write + + + CORE_1_AREA_DRAM0_1_RD_ENA + Core1 dram0 area1 read monitor enable + 2 + 1 + read-write + + + CORE_1_AREA_DRAM0_1_WR_ENA + Core1 dram0 area1 write monitor enable + 3 + 1 + read-write + + + CORE_1_AREA_PIF_0_RD_ENA + Core1 PIF area0 read monitor enable + 4 + 1 + read-write + + + CORE_1_AREA_PIF_0_WR_ENA + Core1 PIF area0 write monitor enable + 5 + 1 + read-write + + + CORE_1_AREA_PIF_1_RD_ENA + Core1 PIF area1 read monitor enable + 6 + 1 + read-write + + + CORE_1_AREA_PIF_1_WR_ENA + Core1 PIF area1 write monitor enable + 7 + 1 + read-write + + + CORE_1_SP_SPILL_MIN_ENA + Core1 stackpoint overflow monitor enable + 8 + 1 + read-write + + + CORE_1_SP_SPILL_MAX_ENA + Core1 stackpoint underflow monitor enable + 9 + 1 + read-write + + + CORE_1_IRAM0_EXCEPTION_MONITOR_ENA + IBUS busy monitor enable + 10 + 1 + read-write + + + CORE_1_DRAM0_EXCEPTION_MONITOR_ENA + DBUS busy monitor enbale + 11 + 1 + read-write + + + + + CORE_1_INTERRUPT_RAW + Core1 monitor interrupt status register + 0x94 + 0x20 + + + CORE_1_AREA_DRAM0_0_RD_RAW + Core1 dram0 area0 read monitor interrupt status + 0 + 1 + read-only + + + CORE_1_AREA_DRAM0_0_WR_RAW + Core1 dram0 area0 write monitor interrupt status + 1 + 1 + read-only + + + CORE_1_AREA_DRAM0_1_RD_RAW + Core1 dram0 area1 read monitor interrupt status + 2 + 1 + read-only + + + CORE_1_AREA_DRAM0_1_WR_RAW + Core1 dram0 area1 write monitor interrupt status + 3 + 1 + read-only + + + CORE_1_AREA_PIF_0_RD_RAW + Core1 PIF area0 read monitor interrupt status + 4 + 1 + read-only + + + CORE_1_AREA_PIF_0_WR_RAW + Core1 PIF area0 write monitor interrupt status + 5 + 1 + read-only + + + CORE_1_AREA_PIF_1_RD_RAW + Core1 PIF area1 read monitor interrupt status + 6 + 1 + read-only + + + CORE_1_AREA_PIF_1_WR_RAW + Core1 PIF area1 write monitor interrupt status + 7 + 1 + read-only + + + CORE_1_SP_SPILL_MIN_RAW + Core1 stackpoint overflow monitor interrupt status + 8 + 1 + read-only + + + CORE_1_SP_SPILL_MAX_RAW + Core1 stackpoint underflow monitor interrupt status + 9 + 1 + read-only + + + CORE_1_IRAM0_EXCEPTION_MONITOR_RAW + IBUS busy monitor interrupt status + 10 + 1 + read-only + + + CORE_1_DRAM0_EXCEPTION_MONITOR_RAW + DBUS busy monitor initerrupt status + 11 + 1 + read-only + + + + + CORE_1_INTERRUPT_RLS + Core1 monitor interrupt enable register + 0x98 + 0x20 + + + CORE_1_AREA_DRAM0_0_RD_RLS + Core1 dram0 area0 read monitor interrupt enable + 0 + 1 + read-write + + + CORE_1_AREA_DRAM0_0_WR_RLS + Core1 dram0 area0 write monitor interrupt enable + 1 + 1 + read-write + + + CORE_1_AREA_DRAM0_1_RD_RLS + Core1 dram0 area1 read monitor interrupt enable + 2 + 1 + read-write + + + CORE_1_AREA_DRAM0_1_WR_RLS + Core1 dram0 area1 write monitor interrupt enable + 3 + 1 + read-write + + + CORE_1_AREA_PIF_0_RD_RLS + Core1 PIF area0 read monitor interrupt enable + 4 + 1 + read-write + + + CORE_1_AREA_PIF_0_WR_RLS + Core1 PIF area0 write monitor interrupt enable + 5 + 1 + read-write + + + CORE_1_AREA_PIF_1_RD_RLS + Core1 PIF area1 read monitor interrupt enable + 6 + 1 + read-write + + + CORE_1_AREA_PIF_1_WR_RLS + Core1 PIF area1 write monitor interrupt enable + 7 + 1 + read-write + + + CORE_1_SP_SPILL_MIN_RLS + Core1 stackpoint overflow monitor interrupt enable + 8 + 1 + read-write + + + CORE_1_SP_SPILL_MAX_RLS + Core1 stackpoint underflow monitor interrupt enable + 9 + 1 + read-write + + + CORE_1_IRAM0_EXCEPTION_MONITOR_RLS + IBUS busy monitor interrupt enable + 10 + 1 + read-write + + + CORE_1_DRAM0_EXCEPTION_MONITOR_RLS + DBUS busy monitor interrupt enbale + 11 + 1 + read-write + + + + + CORE_1_INTERRUPT_CLR + Core1 monitor interrupt clr register + 0x9C + 0x20 + + + CORE_1_AREA_DRAM0_0_RD_CLR + Core1 dram0 area0 read monitor interrupt clr + 0 + 1 + read-write + + + CORE_1_AREA_DRAM0_0_WR_CLR + Core1 dram0 area0 write monitor interrupt clr + 1 + 1 + read-write + + + CORE_1_AREA_DRAM0_1_RD_CLR + Core1 dram0 area1 read monitor interrupt clr + 2 + 1 + read-write + + + CORE_1_AREA_DRAM0_1_WR_CLR + Core1 dram0 area1 write monitor interrupt clr + 3 + 1 + read-write + + + CORE_1_AREA_PIF_0_RD_CLR + Core1 PIF area0 read monitor interrupt clr + 4 + 1 + read-write + + + CORE_1_AREA_PIF_0_WR_CLR + Core1 PIF area0 write monitor interrupt clr + 5 + 1 + read-write + + + CORE_1_AREA_PIF_1_RD_CLR + Core1 PIF area1 read monitor interrupt clr + 6 + 1 + read-write + + + CORE_1_AREA_PIF_1_WR_CLR + Core1 PIF area1 write monitor interrupt clr + 7 + 1 + read-write + + + CORE_1_SP_SPILL_MIN_CLR + Core1 stackpoint overflow monitor interrupt clr + 8 + 1 + read-write + + + CORE_1_SP_SPILL_MAX_CLR + Core1 stackpoint underflow monitor interrupt clr + 9 + 1 + read-write + + + CORE_1_IRAM0_EXCEPTION_MONITOR_CLR + IBUS busy monitor interrupt clr + 10 + 1 + read-write + + + CORE_1_DRAM0_EXCEPTION_MONITOR_CLR + DBUS busy monitor interrupt clr + 11 + 1 + read-write + + + + + CORE_1_AREA_DRAM0_0_MIN + Core1 dram0 region0 addr configuration register + 0xA0 + 0x20 + 0xFFFFFFFF + + + CORE_1_AREA_DRAM0_0_MIN + Core1 dram0 region0 start addr + 0 + 32 + read-write + + + + + CORE_1_AREA_DRAM0_0_MAX + Core1 dram0 region0 addr configuration register + 0xA4 + 0x20 + + + CORE_1_AREA_DRAM0_0_MAX + Core1 dram0 region0 end addr + 0 + 32 + read-write + + + + + CORE_1_AREA_DRAM0_1_MIN + Core1 dram0 region1 addr configuration register + 0xA8 + 0x20 + 0xFFFFFFFF + + + CORE_1_AREA_DRAM0_1_MIN + Core1 dram0 region1 start addr + 0 + 32 + read-write + + + + + CORE_1_AREA_DRAM0_1_MAX + Core1 dram0 region1 addr configuration register + 0xAC + 0x20 + + + CORE_1_AREA_DRAM0_1_MAX + Core1 dram0 region1 end addr + 0 + 32 + read-write + + + + + CORE_1_AREA_PIF_0_MIN + Core1 PIF region0 addr configuration register + 0xB0 + 0x20 + 0xFFFFFFFF + + + CORE_1_AREA_PIF_0_MIN + Core1 PIF region0 start addr + 0 + 32 + read-write + + + + + CORE_1_AREA_PIF_0_MAX + Core1 PIF region0 addr configuration register + 0xB4 + 0x20 + + + CORE_1_AREA_PIF_0_MAX + Core1 PIF region0 end addr + 0 + 32 + read-write + + + + + CORE_1_AREA_PIF_1_MIN + Core1 PIF region1 addr configuration register + 0xB8 + 0x20 + 0xFFFFFFFF + + + CORE_1_AREA_PIF_1_MIN + Core1 PIF region1 start addr + 0 + 32 + read-write + + + + + CORE_1_AREA_PIF_1_MAX + Core1 PIF region1 addr configuration register + 0xBC + 0x20 + + + CORE_1_AREA_PIF_1_MAX + Core1 PIF region1 end addr + 0 + 32 + read-write + + + + + CORE_1_AREA_PC + Core1 area sp status register + 0xC0 + 0x20 + + + CORE_1_AREA_PC + the stackpointer when first touch region monitor interrupt + 0 + 32 + read-only + + + + + CORE_1_AREA_SP + Core1 area pc status register + 0xC4 + 0x20 + + + CORE_1_AREA_SP + the PC when first touch region monitor interrupt + 0 + 32 + read-only + + + + + CORE_1_SP_UNSTABLE + Core1 sp unstable configuration register + 0xC8 + 0x20 + 0x0000000B + + + CORE_1_SP_UNSTABLE + unstable period when window change,during this period no check stackpointer + 0 + 8 + read-write + + + + + CORE_1_SP_MIN + Core1 sp region configuration regsiter + 0xCC + 0x20 + + + CORE_1_SP_MIN + stack min value + 0 + 32 + read-write + + + + + CORE_1_SP_MAX + Core1 sp region configuration regsiter + 0xD0 + 0x20 + 0xFFFFFFFF + + + CORE_1_SP_MAX + stack max value + 0 + 32 + read-write + + + + + CORE_1_SP_PC + Core1 sp pc status register + 0xD4 + 0x20 + + + CORE_1_SP_PC + the PC when first touch stack monitor interrupt + 0 + 32 + read-only + + + + + CORE_1_RCD_PDEBUGENABLE + Core1 pdebug configuration register + 0xD8 + 0x20 + + + CORE_1_RCD_PDEBUGENABLE + Core1 Pdebugenable,set 1 to open Core1 Pdebug interface, then can get Core1 PC + 0 + 1 + read-write + + + + + CORE_1_RCD_RECORDING + Core1 pdebug status register + 0xDC + 0x20 + + + CORE_1_RCD_RECORDING + Pdebug record enable,set 1 to record Core1 pdebug interface signal + 0 + 1 + read-write + + + + + CORE_1_RCD_PDEBUGINST + Core1 pdebug status register + 0xE0 + 0x20 + + + CORE_1_RCD_PDEBUGINST + Core1 pdebuginst + 0 + 32 + read-only + + + + + CORE_1_RCD_PDEBUGSTATUS + Core1 pdebug status register + 0xE4 + 0x20 + + + CORE_1_RCD_PDEBUGSTATUS + Core1 pdebugstatus + 0 + 8 + read-only + + + + + CORE_1_RCD_PDEBUGDATA + Core1 pdebug status register + 0xE8 + 0x20 + + + CORE_1_RCD_PDEBUGDATA + Core1_pdebugdata + 0 + 32 + read-only + + + + + CORE_1_RCD_PDEBUGPC + Core1 pdebug status register + 0xEC + 0x20 + + + CORE_1_RCD_PDEBUGPC + Core1_pdebugPC + 0 + 32 + read-only + + + + + CORE_1_RCD_PDEBUGLS0STAT + Core1 pdebug status register + 0xF0 + 0x20 + + + CORE_1_RCD_PDEBUGLS0STAT + Core1_pdebug_s0stat + 0 + 32 + read-only + + + + + CORE_1_RCD_PDEBUGLS0ADDR + Core1 pdebug status register + 0xF4 + 0x20 + + + CORE_1_RCD_PDEBUGLS0ADDR + Core1_pdebug_s0addr + 0 + 32 + read-only + + + + + CORE_1_RCD_PDEBUGLS0DATA + Core1 pdebug status register + 0xF8 + 0x20 + + + CORE_1_RCD_PDEBUGLS0DATA + Core1_pdebug_s0data + 0 + 32 + read-only + + + + + CORE_1_RCD_SP + Core1 pdebug status register + 0xFC + 0x20 + + + CORE_1_RCD_SP + Core1_stack pointer + 0 + 32 + read-only + + + + + CORE_1_IRAM0_EXCEPTION_MONITOR_0 + Core1 bus busy status regsiter + 0x100 + 0x20 + + + CORE_1_IRAM0_RECORDING_ADDR_0 + The first iram0's addr[25:2] status when trigger IRAM busy interrupt + 0 + 24 + read-only + + + CORE_1_IRAM0_RECORDING_WR_0 + The first iram0's wr status when trigger IRAM busy interrupt + 24 + 1 + read-only + + + CORE_1_IRAM0_RECORDING_LOADSTORE_0 + The first iram0's loadstore status when trigger IRAM busy interrupt + 25 + 1 + read-only + + + + + CORE_1_IRAM0_EXCEPTION_MONITOR_1 + Core1 bus busy status regsiter + 0x104 + 0x20 + + + CORE_1_IRAM0_RECORDING_ADDR_1 + The second iram0's addr[25:2] status when trigger IRAM busy interrupt + 0 + 24 + read-only + + + CORE_1_IRAM0_RECORDING_WR_1 + The second iram0's wr status when trigger IRAM busy interrupt + 24 + 1 + read-only + + + CORE_1_IRAM0_RECORDING_LOADSTORE_1 + The second iram0's loadstore status when trigger IRAM busy interrupt + 25 + 1 + read-only + + + + + CORE_1_DRAM0_EXCEPTION_MONITOR_0 + Core1 bus busy status regsiter + 0x108 + 0x20 + + + CORE_1_DRAM0_RECORDING_ADDR_0 + The first dram0's addr[25:4] status when trigger DRAM busy interrupt + 0 + 22 + read-only + + + CORE_1_DRAM0_RECORDING_WR_0 + The first dram0's wr status when trigger DRAM busy interrupt + 22 + 1 + read-only + + + + + CORE_1_DRAM0_EXCEPTION_MONITOR_1 + Core1 bus busy status regsiter + 0x10C + 0x20 + + + CORE_1_DRAM0_RECORDING_BYTEEN_0 + The first dram0's byteen status when trigger DRAM busy interrupt + 0 + 16 + read-only + + + + + CORE_1_DRAM0_EXCEPTION_MONITOR_2 + Core1 bus busy status regsiter + 0x110 + 0x20 + 0xFFFFFFFF + + + CORE_1_DRAM0_RECORDING_PC_0 + The first dram0's PC status when trigger DRAM busy interrupt + 0 + 32 + read-only + + + + + CORE_1_DRAM0_EXCEPTION_MONITOR_3 + Core1 bus busy status regsiter + 0x114 + 0x20 + + + CORE_1_DRAM0_RECORDING_ADDR_1 + The second dram0's addr[25:4] status when trigger DRAM busy interrupt + 0 + 22 + read-only + + + CORE_1_DRAM0_RECORDING_WR_1 + The second dram0's wr status when trigger DRAM busy interrupt + 22 + 1 + read-only + + + + + CORE_1_DRAM0_EXCEPTION_MONITOR_4 + Core1 bus busy status regsiter + 0x118 + 0x20 + + + CORE_1_DRAM0_RECORDING_BYTEEN_1 + The second dram0's byteen status when trigger DRAM busy interrupt + 0 + 16 + read-only + + + + + CORE_1_DRAM0_EXCEPTION_MONITOR_5 + Core1 bus busy status regsiter + 0x11C + 0x20 + 0xFFFFFFFF + + + CORE_1_DRAM0_RECORDING_PC_1 + The second dram0's PC status when trigger DRAM busy interrupt + 0 + 32 + read-only + + + + + CORE_X_IRAM0_DRAM0_EXCEPTION_MONITOR_0 + bus busy configuration register + 0x120 + 0x20 + 0x000FFFFF + + + CORE_X_IRAM0_DRAM0_LIMIT_CYCLE_0 + busy monitor window cycle + 0 + 20 + read-write + + + + + CORE_X_IRAM0_DRAM0_EXCEPTION_MONITOR_1 + bus busy configuration register + 0x124 + 0x20 + 0x000FFFFF + + + CORE_X_IRAM0_DRAM0_LIMIT_CYCLE_1 + non busy cycle,for example: when cycle=100 and cycle=10,it means that in 100 cycle, if busy access success time less than 10, it will trigger interrutpt + 0 + 20 + read-write + + + + + LOG_SETTING + log set register + 0x128 + 0x20 + 0x00000040 + + + LOG_ENA + bus moniter enable: [0]Core1,[1]core1,[2]dma + 0 + 3 + read-write + + + LOG_MODE + check_mode:0:write,1:word,2:halword,3:byte,4:doubleword,5:4word + 3 + 3 + read-write + + + LOG_MEM_LOOP_ENABLE + mem_loop enable,1 means that loop write + 6 + 1 + read-write + + + + + LOG_DATA_0 + log check data register + 0x12C + 0x20 + + + LOG_DATA_0 + check data0 + 0 + 32 + read-write + + + + + LOG_DATA_1 + log check data register + 0x130 + 0x20 + + + LOG_DATA_1 + check data1 + 0 + 32 + read-write + + + + + LOG_DATA_2 + log check data register + 0x134 + 0x20 + + + LOG_DATA_2 + check data2 + 0 + 32 + read-write + + + + + LOG_DATA_3 + log check data register + 0x138 + 0x20 + + + LOG_DATA_3 + check data3 + 0 + 32 + read-write + + + + + LOG_DATA_MASK + log check data mask register + 0x13C + 0x20 + + + LOG_DATA_SIZE + data mask + 0 + 16 + read-write + + + + + LOG_MIN + log check region configuration register + 0x140 + 0x20 + + + LOG_MIN + check region min addr + 0 + 32 + read-write + + + + + LOG_MAX + log check region configuration register + 0x144 + 0x20 + + + LOG_MAX + check region max addr + 0 + 32 + read-write + + + + + LOG_MEM_START + log mem region configuration register + 0x148 + 0x20 + + + LOG_MEM_START + mem start addr + 0 + 32 + read-write + + + + + LOG_MEM_END + log mem region configuration register + 0x14C + 0x20 + + + LOG_MEM_END + mem end addr + 0 + 32 + read-write + + + + + LOG_MEM_WRITING_ADDR + log mem addr status register + 0x150 + 0x20 + + + LOG_MEM_WRITING_ADDR + mem current addr, it means next writing addr + 0 + 32 + read-only + + + + + LOG_MEM_FULL_FLAG + log mem status register + 0x154 + 0x20 + + + LOG_MEM_FULL_FLAG + when it's 1,show that mem write loop morte than one time. + 0 + 1 + read-write + + + + + DATE + version register + 0x1FC + 0x20 + 0x02003040 + + + DATE + version register + 0 + 28 + read-write + + + + + + + DMA + DMA (Direct Memory Access) Controller + DMA + 0x6003F000 + + 0x0 + 0x320 + registers + + + DMA_IN_CH0 + 66 + + + DMA_IN_CH1 + 67 + + + DMA_IN_CH2 + 68 + + + DMA_IN_CH3 + 69 + + + DMA_IN_CH4 + 70 + + + DMA_OUT_CH0 + 71 + + + DMA_OUT_CH1 + 72 + + + DMA_OUT_CH2 + 73 + + + DMA_OUT_CH3 + 74 + + + DMA_OUT_CH4 + 75 + + + APB_PMS_MONITOR_VIOLATE + 84 + + + DMA_EXTMEM_REJECT + 98 + + + + 5 + 0xC0 + IN_CONF0_CH%s + Configure 0 register of Rx channel 0 + 0x0 + 0x20 + + + IN_RST_CH + This bit is used to reset DMA channel 0 Rx FSM and Rx FIFO pointer. + 0 + 1 + read-write + + + IN_LOOP_TEST_CH + reserved + 1 + 1 + read-write + + + INDSCR_BURST_EN_CH + Set this bit to 1 to enable INCR burst transfer for Rx channel 0 reading link descriptor when accessing internal SRAM. + 2 + 1 + read-write + + + IN_DATA_BURST_EN_CH + Set this bit to 1 to enable INCR burst transfer for Rx channel 0 receiving data when accessing internal SRAM. + 3 + 1 + read-write + + + MEM_TRANS_EN_CH + Set this bit 1 to enable automatic transmitting data from memory to memory via DMA. + 4 + 1 + read-write + + + + + 5 + 0xC0 + IN_CONF1_CH%s + Configure 1 register of Rx channel 0 + 0x4 + 0x20 + 0x0000000C + + + DMA_INFIFO_FULL_THRS_CH + This register is used to generate the INFIFO_FULL_WM_INT interrupt when Rx channel 0 received byte number in Rx FIFO is up to the value of the register. + 0 + 12 + read-write + + + IN_CHECK_OWNER_CH + Set this bit to enable checking the owner attribute of the link descriptor. + 12 + 1 + read-write + + + IN_EXT_MEM_BK_SIZE_CH + Block size of Rx channel 0 when DMA access external SRAM. 0: 16 bytes 1: 32 bytes 2/3:reserved + 13 + 2 + read-write + + + + + 5 + 0xC0 + IN_INT_RAW_CH%s + Raw status interrupt of Rx channel 0 + 0x8 + 0x20 + + + IN_DONE_CH_INT_RAW + The raw interrupt bit turns to high level when the last data pointed by one inlink descriptor has been received for Rx channel 0. + 0 + 1 + read-only + + + IN_SUC_EOF_CH_INT_RAW + The raw interrupt bit turns to high level when the last data pointed by one inlink descriptor has been received for Rx channel 0. For UHCI0, the raw interrupt bit turns to high level when the last data pointed by one inlink descriptor has been received and no data error is detected for Rx channel 0. + 1 + 1 + read-only + + + IN_ERR_EOF_CH_INT_RAW + The raw interrupt bit turns to high level when data error is detected only in the case that the peripheral is UHCI0 for Rx channel 0. For other peripherals, this raw interrupt is reserved. + 2 + 1 + read-only + + + IN_DSCR_ERR_CH_INT_RAW + The raw interrupt bit turns to high level when detecting inlink descriptor error, including owner error, the second and third word error of inlink descriptor for Rx channel 0. + 3 + 1 + read-only + + + IN_DSCR_EMPTY_CH_INT_RAW + The raw interrupt bit turns to high level when Rx buffer pointed by inlink is full and receiving data is not completed, but there is no more inlink for Rx channel 0. + 4 + 1 + read-only + + + INFIFO_FULL_WM_CH_INT_RAW + The raw interrupt bit turns to high level when received data byte number is up to threshold configured by REG_DMA_INFIFO_FULL_THRS_CH0 in Rx FIFO of channel 0. + 5 + 1 + read-only + + + INFIFO_OVF_L1_CH_INT_RAW + This raw interrupt bit turns to high level when level 1 fifo of Rx channel 0 is overflow. + 6 + 1 + read-only + + + INFIFO_UDF_L1_CH_INT_RAW + This raw interrupt bit turns to high level when level 1 fifo of Rx channel 0 is underflow. + 7 + 1 + read-only + + + INFIFO_OVF_L3_CH_INT_RAW + This raw interrupt bit turns to high level when level 3 fifo of Rx channel 0 is overflow. + 8 + 1 + read-only + + + INFIFO_UDF_L3_CH_INT_RAW + This raw interrupt bit turns to high level when level 3 fifo of Rx channel 0 is underflow. + 9 + 1 + read-only + + + + + 5 + 0xC0 + IN_INT_ST_CH%s + Masked interrupt of Rx channel 0 + 0xC + 0x20 + + + IN_DONE_CH_INT_ST + The raw interrupt status bit for the IN_DONE_CH_INT interrupt. + 0 + 1 + read-only + + + IN_SUC_EOF_CH_INT_ST + The raw interrupt status bit for the IN_SUC_EOF_CH_INT interrupt. + 1 + 1 + read-only + + + IN_ERR_EOF_CH_INT_ST + The raw interrupt status bit for the IN_ERR_EOF_CH_INT interrupt. + 2 + 1 + read-only + + + IN_DSCR_ERR_CH_INT_ST + The raw interrupt status bit for the IN_DSCR_ERR_CH_INT interrupt. + 3 + 1 + read-only + + + IN_DSCR_EMPTY_CH_INT_ST + The raw interrupt status bit for the IN_DSCR_EMPTY_CH_INT interrupt. + 4 + 1 + read-only + + + INFIFO_FULL_WM_CH_INT_ST + The raw interrupt status bit for the INFIFO_FULL_WM_CH_INT interrupt. + 5 + 1 + read-only + + + INFIFO_OVF_L1_CH_INT_ST + The raw interrupt status bit for the INFIFO_OVF_L1_CH_INT interrupt. + 6 + 1 + read-only + + + INFIFO_UDF_L1_CH_INT_ST + The raw interrupt status bit for the INFIFO_UDF_L1_CH_INT interrupt. + 7 + 1 + read-only + + + INFIFO_OVF_L3_CH_INT_ST + The raw interrupt status bit for the INFIFO_OVF_L3_CH_INT interrupt. + 8 + 1 + read-only + + + INFIFO_UDF_L3_CH_INT_ST + The raw interrupt status bit for the INFIFO_UDF_L3_CH_INT interrupt. + 9 + 1 + read-only + + + + + 5 + 0xC0 + IN_INT_ENA_CH%s + Interrupt enable bits of Rx channel 0 + 0x10 + 0x20 + + + IN_DONE_CH_INT_ENA + The interrupt enable bit for the IN_DONE_CH_INT interrupt. + 0 + 1 + read-write + + + IN_SUC_EOF_CH_INT_ENA + The interrupt enable bit for the IN_SUC_EOF_CH_INT interrupt. + 1 + 1 + read-write + + + IN_ERR_EOF_CH_INT_ENA + The interrupt enable bit for the IN_ERR_EOF_CH_INT interrupt. + 2 + 1 + read-write + + + IN_DSCR_ERR_CH_INT_ENA + The interrupt enable bit for the IN_DSCR_ERR_CH_INT interrupt. + 3 + 1 + read-write + + + IN_DSCR_EMPTY_CH_INT_ENA + The interrupt enable bit for the IN_DSCR_EMPTY_CH_INT interrupt. + 4 + 1 + read-write + + + INFIFO_FULL_WM_CH_INT_ENA + The interrupt enable bit for the INFIFO_FULL_WM_CH_INT interrupt. + 5 + 1 + read-write + + + INFIFO_OVF_L1_CH_INT_ENA + The interrupt enable bit for the INFIFO_OVF_L1_CH_INT interrupt. + 6 + 1 + read-write + + + INFIFO_UDF_L1_CH_INT_ENA + The interrupt enable bit for the INFIFO_UDF_L1_CH_INT interrupt. + 7 + 1 + read-write + + + INFIFO_OVF_L3_CH_INT_ENA + The interrupt enable bit for the INFIFO_OVF_L3_CH_INT interrupt. + 8 + 1 + read-write + + + INFIFO_UDF_L3_CH_INT_ENA + The interrupt enable bit for the INFIFO_UDF_L3_CH_INT interrupt. + 9 + 1 + read-write + + + + + 5 + 0xC0 + IN_INT_CLR_CH%s + Interrupt clear bits of Rx channel 0 + 0x14 + 0x20 + + + IN_DONE_CH_INT_CLR + Set this bit to clear the IN_DONE_CH_INT interrupt. + 0 + 1 + write-only + + + IN_SUC_EOF_CH_INT_CLR + Set this bit to clear the IN_SUC_EOF_CH_INT interrupt. + 1 + 1 + write-only + + + IN_ERR_EOF_CH_INT_CLR + Set this bit to clear the IN_ERR_EOF_CH_INT interrupt. + 2 + 1 + write-only + + + IN_DSCR_ERR_CH_INT_CLR + Set this bit to clear the IN_DSCR_ERR_CH_INT interrupt. + 3 + 1 + write-only + + + IN_DSCR_EMPTY_CH_INT_CLR + Set this bit to clear the IN_DSCR_EMPTY_CH_INT interrupt. + 4 + 1 + write-only + + + DMA_INFIFO_FULL_WM_CH_INT_CLR + Set this bit to clear the INFIFO_FULL_WM_CH_INT interrupt. + 5 + 1 + write-only + + + INFIFO_OVF_L1_CH_INT_CLR + Set this bit to clear the INFIFO_OVF_L1_CH_INT interrupt. + 6 + 1 + write-only + + + INFIFO_UDF_L1_CH_INT_CLR + Set this bit to clear the INFIFO_UDF_L1_CH_INT interrupt. + 7 + 1 + write-only + + + INFIFO_OVF_L3_CH_INT_CLR + Set this bit to clear the INFIFO_OVF_L3_CH_INT interrupt. + 8 + 1 + write-only + + + INFIFO_UDF_L3_CH_INT_CLR + Set this bit to clear the INFIFO_UDF_L3_CH_INT interrupt. + 9 + 1 + write-only + + + + + 5 + 0xC0 + INFIFO_STATUS_CH%s + Receive FIFO status of Rx channel 0 + 0x18 + 0x20 + 0x0F00003A + + + INFIFO_FULL_L1_CH + L1 Rx FIFO full signal for Rx channel 0. + 0 + 1 + read-only + + + INFIFO_EMPTY_L1_CH + L1 Rx FIFO empty signal for Rx channel 0. + 1 + 1 + read-only + + + INFIFO_FULL_L2_CH + L2 Rx FIFO full signal for Rx channel 0. + 2 + 1 + read-only + + + INFIFO_EMPTY_L2_CH + L2 Rx FIFO empty signal for Rx channel 0. + 3 + 1 + read-only + + + INFIFO_FULL_L3_CH + L3 Rx FIFO full signal for Rx channel 0. + 4 + 1 + read-only + + + INFIFO_EMPTY_L3_CH + L3 Rx FIFO empty signal for Rx channel 0. + 5 + 1 + read-only + + + INFIFO_CNT_L1_CH + The register stores the byte number of the data in L1 Rx FIFO for Rx channel 0. + 6 + 6 + read-only + + + INFIFO_CNT_L2_CH + The register stores the byte number of the data in L2 Rx FIFO for Rx channel 0. + 12 + 7 + read-only + + + INFIFO_CNT_L3_CH + The register stores the byte number of the data in L3 Rx FIFO for Rx channel 0. + 19 + 5 + read-only + + + IN_REMAIN_UNDER_1B_L3_CH + reserved + 24 + 1 + read-only + + + IN_REMAIN_UNDER_2B_L3_CH + reserved + 25 + 1 + read-only + + + IN_REMAIN_UNDER_3B_L3_CH + reserved + 26 + 1 + read-only + + + IN_REMAIN_UNDER_4B_L3_CH + reserved + 27 + 1 + read-only + + + IN_BUF_HUNGRY_CH + reserved + 28 + 1 + read-only + + + + + 5 + 0xC0 + IN_POP_CH%s + Pop control register of Rx channel 0 + 0x1C + 0x20 + 0x00000800 + + + INFIFO_RDATA_CH + This register stores the data popping from DMA FIFO. + 0 + 12 + read-only + + + INFIFO_POP_CH + Set this bit to pop data from DMA FIFO. + 12 + 1 + read-write + + + + + 5 + 0xC0 + IN_LINK_CH%s + Link descriptor configure and control register of Rx channel 0 + 0x20 + 0x20 + 0x01100000 + + + INLINK_ADDR_CH + This register stores the 20 least significant bits of the first inlink descriptor's address. + 0 + 20 + read-write + + + INLINK_AUTO_RET_CH + Set this bit to return to current inlink descriptor's address, when there are some errors in current receiving data. + 20 + 1 + read-write + + + INLINK_STOP_CH + Set this bit to stop dealing with the inlink descriptors. + 21 + 1 + read-write + + + INLINK_START_CH + Set this bit to start dealing with the inlink descriptors. + 22 + 1 + read-write + + + INLINK_RESTART_CH + Set this bit to mount a new inlink descriptor. + 23 + 1 + read-write + + + INLINK_PARK_CH + 1: the inlink descriptor's FSM is in idle state. 0: the inlink descriptor's FSM is working. + 24 + 1 + read-only + + + + + 5 + 0xC0 + IN_STATE_CH%s + Receive status of Rx channel 0 + 0x24 + 0x20 + + + INLINK_DSCR_ADDR_CH + This register stores the current inlink descriptor's address. + 0 + 18 + read-only + + + IN_DSCR_STATE_CH + reserved + 18 + 2 + read-only + + + IN_STATE_CH + reserved + 20 + 3 + read-only + + + + + 5 + 0xC0 + IN_SUC_EOF_DES_ADDR_CH%s + Inlink descriptor address when EOF occurs of Rx channel 0 + 0x28 + 0x20 + + + IN_SUC_EOF_DES_ADDR_CH + This register stores the address of the inlink descriptor when the EOF bit in this descriptor is 1. + 0 + 32 + read-only + + + + + 5 + 0xC0 + IN_ERR_EOF_DES_ADDR_CH%s + Inlink descriptor address when errors occur of Rx channel 0 + 0x2C + 0x20 + + + IN_ERR_EOF_DES_ADDR_CH + This register stores the address of the inlink descriptor when there are some errors in current receiving data. Only used when peripheral is UHCI0. + 0 + 32 + read-only + + + + + 5 + 0xC0 + IN_DSCR_CH%s + Current inlink descriptor address of Rx channel 0 + 0x30 + 0x20 + + + INLINK_DSCR_CH + The address of the current inlink descriptor x. + 0 + 32 + read-only + + + + + 5 + 0xC0 + IN_DSCR_BF0_CH%s + The last inlink descriptor address of Rx channel 0 + 0x34 + 0x20 + + + INLINK_DSCR_BF0_CH + The address of the last inlink descriptor x-1. + 0 + 32 + read-only + + + + + 5 + 0xC0 + IN_DSCR_BF1_CH%s + The second-to-last inlink descriptor address of Rx channel 0 + 0x38 + 0x20 + + + INLINK_DSCR_BF1_CH + The address of the second-to-last inlink descriptor x-2. + 0 + 32 + read-only + + + + + 5 + 0xC0 + IN_WIGHT_CH%s + Weight register of Rx channel 0 + 0x3C + 0x20 + 0x00000F00 + + + RX_WEIGHT_CH + The weight of Rx channel 0. + 8 + 4 + read-write + + + + + 5 + 0xC0 + IN_PRI_CH%s + Priority register of Rx channel 0 + 0x44 + 0x20 + + + RX_PRI_CH + The priority of Rx channel 0. The larger of the value, the higher of the priority. + 0 + 4 + read-write + + + + + 5 + 0xC0 + IN_PERI_SEL_CH%s + Peripheral selection of Rx channel 0 + 0x48 + 0x20 + 0x0000003F + + + PERI_IN_SEL_CH + This register is used to select peripheral for Rx channel 0. 0:SPI2. 1: SPI3. 2: UHCI0. 3: I2S0. 4: I2S1. 5: LCD_CAM. 6: AES. 7: SHA. 8: ADC_DAC. 9: RMT. + 0 + 6 + read-write + + + + + 5 + 0xC0 + OUT_CONF0_CH%s + Configure 0 register of Tx channel 0 + 0x60 + 0x20 + 0x00000008 + + + OUT_RST_CH + This bit is used to reset DMA channel 0 Tx FSM and Tx FIFO pointer. + 0 + 1 + read-write + + + OUT_LOOP_TEST_CH + reserved + 1 + 1 + read-write + + + OUT_AUTO_WRBACK_CH + Set this bit to enable automatic outlink-writeback when all the data in tx buffer has been transmitted. + 2 + 1 + read-write + + + OUT_EOF_MODE_CH + EOF flag generation mode when transmitting data. 1: EOF flag for Tx channel 0 is generated when data need to transmit has been popped from FIFO in DMA + 3 + 1 + read-write + + + OUTDSCR_BURST_EN_CH + Set this bit to 1 to enable INCR burst transfer for Tx channel 0 reading link descriptor when accessing internal SRAM. + 4 + 1 + read-write + + + OUT_DATA_BURST_EN_CH + Set this bit to 1 to enable INCR burst transfer for Tx channel 0 transmitting data when accessing internal SRAM. + 5 + 1 + read-write + + + + + 5 + 0xC0 + OUT_CONF1_CH%s + Configure 1 register of Tx channel 0 + 0x64 + 0x20 + + + OUT_CHECK_OWNER_CH + Set this bit to enable checking the owner attribute of the link descriptor. + 12 + 1 + read-write + + + OUT_EXT_MEM_BK_SIZE_CH + Block size of Tx channel 0 when DMA access external SRAM. 0: 16 bytes 1: 32 bytes 2/3:reserved + 13 + 2 + read-write + + + + + 5 + 0xC0 + OUT_INT_RAW_CH%s + Raw status interrupt of Tx channel 0 + 0x68 + 0x20 + + + OUT_DONE_CH_INT_RAW + The raw interrupt bit turns to high level when the last data pointed by one outlink descriptor has been transmitted to peripherals for Tx channel 0. + 0 + 1 + read-only + + + OUT_EOF_CH_INT_RAW + The raw interrupt bit turns to high level when the last data pointed by one outlink descriptor has been read from memory for Tx channel 0. + 1 + 1 + read-only + + + OUT_DSCR_ERR_CH_INT_RAW + The raw interrupt bit turns to high level when detecting outlink descriptor error, including owner error, the second and third word error of outlink descriptor for Tx channel 0. + 2 + 1 + read-only + + + OUT_TOTAL_EOF_CH_INT_RAW + The raw interrupt bit turns to high level when data corresponding a outlink (includes one link descriptor or few link descriptors) is transmitted out for Tx channel 0. + 3 + 1 + read-only + + + OUTFIFO_OVF_L1_CH_INT_RAW + This raw interrupt bit turns to high level when level 1 fifo of Tx channel 0 is overflow. + 4 + 1 + read-only + + + OUTFIFO_UDF_L1_CH_INT_RAW + This raw interrupt bit turns to high level when level 1 fifo of Tx channel 0 is underflow. + 5 + 1 + read-only + + + OUTFIFO_OVF_L3_CH_INT_RAW + This raw interrupt bit turns to high level when level 3 fifo of Tx channel 0 is overflow. + 6 + 1 + read-only + + + OUTFIFO_UDF_L3_CH_INT_RAW + This raw interrupt bit turns to high level when level 3 fifo of Tx channel 0 is underflow. + 7 + 1 + read-only + + + + + 5 + 0xC0 + OUT_INT_ST_CH%s + Masked interrupt of Tx channel 0 + 0x6C + 0x20 + + + OUT_DONE_CH_INT_ST + The raw interrupt status bit for the OUT_DONE_CH_INT interrupt. + 0 + 1 + read-only + + + OUT_EOF_CH_INT_ST + The raw interrupt status bit for the OUT_EOF_CH_INT interrupt. + 1 + 1 + read-only + + + OUT_DSCR_ERR_CH_INT_ST + The raw interrupt status bit for the OUT_DSCR_ERR_CH_INT interrupt. + 2 + 1 + read-only + + + OUT_TOTAL_EOF_CH_INT_ST + The raw interrupt status bit for the OUT_TOTAL_EOF_CH_INT interrupt. + 3 + 1 + read-only + + + OUTFIFO_OVF_L1_CH_INT_ST + The raw interrupt status bit for the OUTFIFO_OVF_L1_CH_INT interrupt. + 4 + 1 + read-only + + + OUTFIFO_UDF_L1_CH_INT_ST + The raw interrupt status bit for the OUTFIFO_UDF_L1_CH_INT interrupt. + 5 + 1 + read-only + + + OUTFIFO_OVF_L3_CH_INT_ST + The raw interrupt status bit for the OUTFIFO_OVF_L3_CH_INT interrupt. + 6 + 1 + read-only + + + OUTFIFO_UDF_L3_CH_INT_ST + The raw interrupt status bit for the OUTFIFO_UDF_L3_CH_INT interrupt. + 7 + 1 + read-only + + + + + 5 + 0xC0 + OUT_INT_ENA_CH%s + Interrupt enable bits of Tx channel 0 + 0x70 + 0x20 + + + OUT_DONE_CH_INT_ENA + The interrupt enable bit for the OUT_DONE_CH_INT interrupt. + 0 + 1 + read-write + + + OUT_EOF_CH_INT_ENA + The interrupt enable bit for the OUT_EOF_CH_INT interrupt. + 1 + 1 + read-write + + + OUT_DSCR_ERR_CH_INT_ENA + The interrupt enable bit for the OUT_DSCR_ERR_CH_INT interrupt. + 2 + 1 + read-write + + + OUT_TOTAL_EOF_CH_INT_ENA + The interrupt enable bit for the OUT_TOTAL_EOF_CH_INT interrupt. + 3 + 1 + read-write + + + OUTFIFO_OVF_L1_CH_INT_ENA + The interrupt enable bit for the OUTFIFO_OVF_L1_CH_INT interrupt. + 4 + 1 + read-write + + + OUTFIFO_UDF_L1_CH_INT_ENA + The interrupt enable bit for the OUTFIFO_UDF_L1_CH_INT interrupt. + 5 + 1 + read-write + + + OUTFIFO_OVF_L3_CH_INT_ENA + The interrupt enable bit for the OUTFIFO_OVF_L3_CH_INT interrupt. + 6 + 1 + read-write + + + OUTFIFO_UDF_L3_CH_INT_ENA + The interrupt enable bit for the OUTFIFO_UDF_L3_CH_INT interrupt. + 7 + 1 + read-write + + + + + 5 + 0xC0 + OUT_INT_CLR_CH%s + Interrupt clear bits of Tx channel 0 + 0x74 + 0x20 + + + OUT_DONE_CH_INT_CLR + Set this bit to clear the OUT_DONE_CH_INT interrupt. + 0 + 1 + write-only + + + OUT_EOF_CH_INT_CLR + Set this bit to clear the OUT_EOF_CH_INT interrupt. + 1 + 1 + write-only + + + OUT_DSCR_ERR_CH_INT_CLR + Set this bit to clear the OUT_DSCR_ERR_CH_INT interrupt. + 2 + 1 + write-only + + + OUT_TOTAL_EOF_CH_INT_CLR + Set this bit to clear the OUT_TOTAL_EOF_CH_INT interrupt. + 3 + 1 + write-only + + + OUTFIFO_OVF_L1_CH_INT_CLR + Set this bit to clear the OUTFIFO_OVF_L1_CH_INT interrupt. + 4 + 1 + write-only + + + OUTFIFO_UDF_L1_CH_INT_CLR + Set this bit to clear the OUTFIFO_UDF_L1_CH_INT interrupt. + 5 + 1 + write-only + + + OUTFIFO_OVF_L3_CH_INT_CLR + Set this bit to clear the OUTFIFO_OVF_L3_CH_INT interrupt. + 6 + 1 + write-only + + + OUTFIFO_UDF_L3_CH_INT_CLR + Set this bit to clear the OUTFIFO_UDF_L3_CH_INT interrupt. + 7 + 1 + write-only + + + + + 5 + 0xC0 + OUTFIFO_STATUS_CH%s + Transmit FIFO status of Tx channel 0 + 0x78 + 0x20 + 0x0780002A + + + OUTFIFO_FULL_L1_CH + L1 Tx FIFO full signal for Tx channel 0. + 0 + 1 + read-only + + + OUTFIFO_EMPTY_L1_CH + L1 Tx FIFO empty signal for Tx channel 0. + 1 + 1 + read-only + + + OUTFIFO_FULL_L2_CH + L2 Tx FIFO full signal for Tx channel 0. + 2 + 1 + read-only + + + OUTFIFO_EMPTY_L2_CH + L2 Tx FIFO empty signal for Tx channel 0. + 3 + 1 + read-only + + + OUTFIFO_FULL_L3_CH + L3 Tx FIFO full signal for Tx channel 0. + 4 + 1 + read-only + + + OUTFIFO_EMPTY_L3_CH + L3 Tx FIFO empty signal for Tx channel 0. + 5 + 1 + read-only + + + OUTFIFO_CNT_L1_CH + The register stores the byte number of the data in L1 Tx FIFO for Tx channel 0. + 6 + 5 + read-only + + + OUTFIFO_CNT_L2_CH + The register stores the byte number of the data in L2 Tx FIFO for Tx channel 0. + 11 + 7 + read-only + + + OUTFIFO_CNT_L3_CH + The register stores the byte number of the data in L3 Tx FIFO for Tx channel 0. + 18 + 5 + read-only + + + OUT_REMAIN_UNDER_1B_L3_CH + reserved + 23 + 1 + read-only + + + OUT_REMAIN_UNDER_2B_L3_CH + reserved + 24 + 1 + read-only + + + OUT_REMAIN_UNDER_3B_L3_CH + reserved + 25 + 1 + read-only + + + OUT_REMAIN_UNDER_4B_L3_CH + reserved + 26 + 1 + read-only + + + + + 5 + 0xC0 + OUT_PUSH_CH%s + Push control register of Rx channel 0 + 0x7C + 0x20 + + + OUTFIFO_WDATA_CH + This register stores the data that need to be pushed into DMA FIFO. + 0 + 9 + read-write + + + OUTFIFO_PUSH_CH + Set this bit to push data into DMA FIFO. + 9 + 1 + read-write + + + + + 5 + 0xC0 + OUT_LINK_CH%s + Link descriptor configure and control register of Tx channel 0 + 0x80 + 0x20 + 0x00800000 + + + OUTLINK_ADDR_CH + This register stores the 20 least significant bits of the first outlink descriptor's address. + 0 + 20 + read-write + + + OUTLINK_STOP_CH + Set this bit to stop dealing with the outlink descriptors. + 20 + 1 + read-write + + + OUTLINK_START_CH + Set this bit to start dealing with the outlink descriptors. + 21 + 1 + read-write + + + OUTLINK_RESTART_CH + Set this bit to restart a new outlink from the last address. + 22 + 1 + read-write + + + OUTLINK_PARK_CH + 1: the outlink descriptor's FSM is in idle state. 0: the outlink descriptor's FSM is working. + 23 + 1 + read-only + + + + + 5 + 0xC0 + OUT_STATE_CH%s + Transmit status of Tx channel 0 + 0x84 + 0x20 + + + OUTLINK_DSCR_ADDR_CH + This register stores the current outlink descriptor's address. + 0 + 18 + read-only + + + OUT_DSCR_STATE_CH + reserved + 18 + 2 + read-only + + + OUT_STATE_CH + reserved + 20 + 3 + read-only + + + + + 5 + 0xC0 + OUT_EOF_DES_ADDR_CH%s + Outlink descriptor address when EOF occurs of Tx channel 0 + 0x88 + 0x20 + + + OUT_EOF_DES_ADDR_CH + This register stores the address of the outlink descriptor when the EOF bit in this descriptor is 1. + 0 + 32 + read-only + + + + + 5 + 0xC0 + OUT_EOF_BFR_DES_ADDR_CH%s + The last outlink descriptor address when EOF occurs of Tx channel 0 + 0x8C + 0x20 + + + OUT_EOF_BFR_DES_ADDR_CH + This register stores the address of the outlink descriptor before the last outlink descriptor. + 0 + 32 + read-only + + + + + 5 + 0xC0 + OUT_DSCR_CH%s + Current inlink descriptor address of Tx channel 0 + 0x90 + 0x20 + + + OUTLINK_DSCR_CH + The address of the current outlink descriptor y. + 0 + 32 + read-only + + + + + 5 + 0xC0 + OUT_DSCR_BF0_CH%s + The last inlink descriptor address of Tx channel 0 + 0x94 + 0x20 + + + OUTLINK_DSCR_BF0_CH + The address of the last outlink descriptor y-1. + 0 + 32 + read-only + + + + + 5 + 0xC0 + OUT_DSCR_BF1_CH%s + The second-to-last inlink descriptor address of Tx channel 0 + 0x98 + 0x20 + + + OUTLINK_DSCR_BF1_CH + The address of the second-to-last inlink descriptor x-2. + 0 + 32 + read-only + + + + + 5 + 0xC0 + OUT_WIGHT_CH%s + Weight register of Rx channel 0 + 0x9C + 0x20 + 0x00000F00 + + + TX_WEIGHT_CH + The weight of Tx channel 0. + 8 + 4 + read-write + + + + + 5 + 0xC0 + OUT_PRI_CH%s + Priority register of Tx channel 0. + 0xA4 + 0x20 + + + TX_PRI_CH + The priority of Tx channel 0. The larger of the value, the higher of the priority. + 0 + 4 + read-write + + + + + 5 + 0xC0 + OUT_PERI_SEL_CH%s + Peripheral selection of Tx channel 0 + 0xA8 + 0x20 + 0x0000003F + + + PERI_OUT_SEL_CH + This register is used to select peripheral for Tx channel 0. 0:SPI2. 1: SPI3. 2: UHCI0. 3: I2S0. 4: I2S1. 5: LCD_CAM. 6: AES. 7: SHA. 8: ADC_DAC. 9: RMT. + 0 + 6 + read-write + + + + + AHB_TEST + reserved + 0x3C0 + 0x20 + + + AHB_TESTMODE + reserved + 0 + 3 + read-write + + + AHB_TESTADDR + reserved + 4 + 2 + read-write + + + + + PD_CONF + reserved + 0x3C4 + 0x20 + 0x00000020 + + + DMA_RAM_FORCE_PD + Set this bit to force power down DMA internal memory. + 4 + 1 + read-write + + + DMA_RAM_FORCE_PU + Set this bit to force power up DMA internal memory + 5 + 1 + read-write + + + DMA_RAM_CLK_FO + 1: Force to open the clock and bypass the gate-clock when accessing the RAM in DMA. 0: A gate-clock will be used when accessing the RAM in DMA. + 6 + 1 + read-write + + + + + MISC_CONF + MISC register + 0x3C8 + 0x20 + + + AHBM_RST_INTER + Set this bit, then clear this bit to reset the internal ahb FSM. + 0 + 1 + read-write + + + AHBM_RST_EXTER + Set this bit, then clear this bit to reset the external ahb FSM. + 1 + 1 + read-write + + + ARB_PRI_DIS + Set this bit to disable priority arbitration function. + 2 + 1 + read-write + + + CLK_EN + 1'h1: Force clock on for register. 1'h0: Support clock only when application writes registers. + 4 + 1 + read-write + + + + + 5 + 0x8 + IN_SRAM_SIZE_CH%s + Receive L2 FIFO depth of Rx channel 0 + 0x3CC + 0x20 + 0x0000000E + + + IN_SIZE_CH + This register is used to configure the size of L2 Tx FIFO for Rx channel 0. 0:16 bytes. 1:24 bytes. 2:32 bytes. 3: 40 bytes. 4: 48 bytes. 5:56 bytes. 6: 64 bytes. 7: 72 bytes. 8: 80 bytes. + 0 + 7 + read-write + + + + + 5 + 0x8 + OUT_SRAM_SIZE_CH%s + Transmit L2 FIFO depth of Tx channel 0 + 0x3D0 + 0x20 + 0x0000000E + + + OUT_SIZE_CH + This register is used to configure the size of L2 Tx FIFO for Tx channel 0. 0:16 bytes. 1:24 bytes. 2:32 bytes. 3: 40 bytes. 4: 48 bytes. 5:56 bytes. 6: 64 bytes. 7: 72 bytes. 8: 80 bytes. + 0 + 7 + read-write + + + + + EXTMEM_REJECT_ADDR + Reject address accessing external RAM + 0x3F4 + 0x20 + + + EXTMEM_REJECT_ADDR + This register store the first address rejected by permission control when accessing external RAM. + 0 + 32 + read-only + + + + + EXTMEM_REJECT_ST + Reject status accessing external RAM + 0x3F8 + 0x20 + + + EXTMEM_REJECT_ATRR + The reject accessing. Bit 0: if this bit is 1, the rejected accessing is READ. Bit 1: if this bit is 1, the rejected accessing is WRITE. + 0 + 2 + read-only + + + EXTMEM_REJECT_CHANNEL_NUM + The register indicate the reject accessing from which channel. + 2 + 4 + read-only + + + EXTMEM_REJECT_PERI_NUM + This register indicate reject accessing from which peripheral. + 6 + 6 + read-only + + + + + EXTMEM_REJECT_INT_RAW + Raw interrupt status of external RAM permission + 0x3FC + 0x20 + + + EXTMEM_REJECT_INT_RAW + The raw interrupt bit turns to high level when accessing external RAM is rejected by permission control. + 0 + 1 + read-only + + + + + EXTMEM_REJECT_INT_ST + Masked interrupt status of external RAM permission + 0x400 + 0x20 + + + EXTMEM_REJECT_INT_ST + The raw interrupt status bit for the EXTMEM_REJECT_INT interrupt. + 0 + 1 + read-only + + + + + EXTMEM_REJECT_INT_ENA + Interrupt enable bits of external RAM permission + 0x404 + 0x20 + + + EXTMEM_REJECT_INT_ENA + The interrupt enable bit for the EXTMEM_REJECT_INT interrupt. + 0 + 1 + read-write + + + + + EXTMEM_REJECT_INT_CLR + Interrupt clear bits of external RAM permission + 0x408 + 0x20 + + + EXTMEM_REJECT_INT_CLR + Set this bit to clear the EXTMEM_REJECT_INT interrupt. + 0 + 1 + write-only + + + + + DATE + Version control register + 0x40C + 0x20 + 0x02101180 + + + DATE + register version. + 0 + 32 + read-write + + + + + + + DS + Digital Signature + DS + 0x6003D000 + + 0x0 + 0xA5C + registers + + + + 1584 + 0x1 + C_MEM[%s] + Memory C + 0x0 + 0x8 + + + 4 + 0x4 + IV_%s + IV block data + 0x630 + 0x20 + + + IV_0 + Stores IV block data + 0 + 32 + read-write + + + + + 512 + 0x1 + X_MEM[%s] + Memory X + 0x800 + 0x8 + + + 512 + 0x1 + Z_MEM[%s] + Memory Z + 0xA00 + 0x8 + + + SET_START + Activates the DS peripheral + 0xE00 + 0x20 + + + SET_START + Write 1 to this register to active the DS peripheral + 0 + 1 + write-only + + + + + SET_ME + Starts DS operation + 0xE04 + 0x20 + + + SET_ME + Write 1 to this register to start DS operation. + 0 + 1 + write-only + + + + + SET_FINISH + Ends DS operation + 0xE08 + 0x20 + + + SET_FINISH + Write 1 to this register to end DS operation. + 0 + 1 + write-only + + + + + QUERY_BUSY + Status of the DS perihperal + 0xE0C + 0x20 + + + QUERY_BUSY + Stores the status of the DS peripheral. 1: The DS peripheral is busy. 0: The DS peripheral is idle. + 0 + 1 + read-only + + + + + QUERY_KEY_WRONG + Checks the reason why DS_KEY is not ready + 0xE10 + 0x20 + + + QUERY_KEY_WRONG + 1-15: HMAC was activated, but the DS peripheral did not successfully receive the DS_KEY from the HMAC peripheral. (The biggest value is 15). 0: HMAC is not activated. + 0 + 4 + read-only + + + + + QUERY_CHECK + Queries DS check result + 0xE14 + 0x20 + + + MD_ERROR + MD checkout result. 1: The MD check fails. 0: The MD check passes. + 0 + 1 + read-only + + + PADDING_BAD + padding checkout result. 1: The padding check fails. 0: The padding check passes. + 1 + 1 + read-only + + + + + DATE + DS version control register + 0xE20 + 0x20 + 0x20191217 + + + DATE + ds version information + 0 + 30 + read-write + + + + + + + EFUSE + eFuse Controller + EFUSE + 0x60007000 + + 0x0 + 0x1CC + registers + + + EFUSE + 36 + + + + PGM_DATA0 + Register 0 that stores data to be programmed. + 0x0 + 0x20 + + + PGM_DATA_0 + The content of the 0th 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA1 + Register 1 that stores data to be programmed. + 0x4 + 0x20 + + + PGM_DATA_1 + The content of the 1st 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA2 + Register 2 that stores data to be programmed. + 0x8 + 0x20 + + + PGM_DATA_2 + The content of the 2nd 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA3 + Register 3 that stores data to be programmed. + 0xC + 0x20 + + + PGM_DATA_3 + The content of the 3rd 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA4 + Register 4 that stores data to be programmed. + 0x10 + 0x20 + + + PGM_DATA_4 + The content of the 4th 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA5 + Register 5 that stores data to be programmed. + 0x14 + 0x20 + + + PGM_DATA_5 + The content of the 5th 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA6 + Register 6 that stores data to be programmed. + 0x18 + 0x20 + + + PGM_DATA_6 + The content of the 6th 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_DATA7 + Register 7 that stores data to be programmed. + 0x1C + 0x20 + + + PGM_DATA_7 + The content of the 7th 32-bit data to be programmed. + 0 + 32 + read-write + + + + + PGM_CHECK_VALUE0 + Register 0 that stores the RS code to be programmed. + 0x20 + 0x20 + + + PGM_RS_DATA_0 + The content of the 0th 32-bit RS code to be programmed. + 0 + 32 + read-write + + + + + PGM_CHECK_VALUE1 + Register 1 that stores the RS code to be programmed. + 0x24 + 0x20 + + + PGM_RS_DATA_1 + The content of the 1st 32-bit RS code to be programmed. + 0 + 32 + read-write + + + + + PGM_CHECK_VALUE2 + Register 2 that stores the RS code to be programmed. + 0x28 + 0x20 + + + PGM_RS_DATA_2 + The content of the 2nd 32-bit RS code to be programmed. + 0 + 32 + read-write + + + + + RD_WR_DIS + BLOCK0 data register 0. + 0x2C + 0x20 + + + WR_DIS + Disable programming of individual eFuses. + 0 + 32 + read-only + + + + + RD_REPEAT_DATA0 + BLOCK0 data register 1. + 0x30 + 0x20 + + + RD_DIS + Set this bit to disable reading from BlOCK4-10. + 0 + 7 + read-only + + + DIS_RTC_RAM_BOOT + Set this bit to disable boot from RTC RAM. + 7 + 1 + read-only + + + DIS_ICACHE + Set this bit to disable Icache. + 8 + 1 + read-only + + + DIS_DCACHE + Set this bit to disable Dcache. + 9 + 1 + read-only + + + DIS_DOWNLOAD_ICACHE + Set this bit to disable Icache in download mode (boot_mode[3:0] is 0, 1, 2, 3, 6, 7). + 10 + 1 + read-only + + + DIS_DOWNLOAD_DCACHE + Set this bit to disable Dcache in download mode ( boot_mode[3:0] is 0, 1, 2, 3, 6, 7). + 11 + 1 + read-only + + + DIS_FORCE_DOWNLOAD + Set this bit to disable the function that forces chip into download mode. + 12 + 1 + read-only + + + DIS_USB + Set this bit to disable USB function. + 13 + 1 + read-only + + + DIS_CAN + Set this bit to disable CAN function. + 14 + 1 + read-only + + + DIS_APP_CPU + Disable app cpu. + 15 + 1 + read-only + + + SOFT_DIS_JTAG + Set these bits to disable JTAG in the soft way (odd number 1 means disable ). JTAG can be enabled in HMAC module. + 16 + 3 + read-only + + + DIS_PAD_JTAG + Set this bit to disable JTAG in the hard way. JTAG is disabled permanently. + 19 + 1 + read-only + + + DIS_DOWNLOAD_MANUAL_ENCRYPT + Set this bit to disable flash encryption when in download boot modes. + 20 + 1 + read-only + + + USB_DREFH + Controls single-end input threshold vrefh, 1.76 V to 2 V with step of 80 mV, stored in eFuse. + 21 + 2 + read-only + + + USB_DREFL + Controls single-end input threshold vrefl, 0.8 V to 1.04 V with step of 80 mV, stored in eFuse. + 23 + 2 + read-only + + + USB_EXCHG_PINS + Set this bit to exchange USB D+ and D- pins. + 25 + 1 + read-only + + + EXT_PHY_ENABLE + Set this bit to enable external PHY. + 26 + 1 + read-only + + + BTLC_GPIO_ENABLE + Bluetooth GPIO signal output security level control. + 27 + 2 + read-only + + + VDD_SPI_MODECURLIM + SPI regulator switches current limit mode. + 29 + 1 + read-only + + + VDD_SPI_DREFH + SPI regulator high voltage reference. + 30 + 2 + read-only + + + + + RD_REPEAT_DATA1 + BLOCK0 data register 2. + 0x34 + 0x20 + + + VDD_SPI_DREFM + SPI regulator medium voltage reference. + 0 + 2 + read-only + + + VDD_SPI_DREFL + SPI regulator low voltage reference. + 2 + 2 + read-only + + + VDD_SPI_XPD + SPI regulator power up signal. + 4 + 1 + read-only + + + VDD_SPI_TIEH + SPI regulator output is short connected to VDD3P3_RTC_IO. + 5 + 1 + read-only + + + VDD_SPI_FORCE + Set this bit and force to use the configuration of eFuse to configure VDD_SPI. + 6 + 1 + read-only + + + VDD_SPI_EN_INIT + Set SPI regulator to 0 to configure init[1:0]=0. + 7 + 1 + read-only + + + VDD_SPI_ENCURLIM + Set SPI regulator to 1 to enable output current limit. + 8 + 1 + read-only + + + VDD_SPI_DCURLIM + Tunes the current limit threshold of SPI regulator when tieh=0, about 800 mA/(8+d). + 9 + 3 + read-only + + + VDD_SPI_INIT + Adds resistor from LDO output to ground. 0: no resistance 1: 6 K 2: 4 K 3: 2 K. + 12 + 2 + read-only + + + VDD_SPI_DCAP + Prevents SPI regulator from overshoot. + 14 + 2 + read-only + + + WDT_DELAY_SEL + Selects RTC watchdog timeout threshold, in unit of slow clock cycle. 0: 40000. 1: 80000. 2: 160000. 3:320000. + 16 + 2 + read-only + + + SPI_BOOT_CRYPT_CNT + Set this bit to enable SPI boot encrypt/decrypt. Odd number of 1: enable. even number of 1: disable. + 18 + 3 + read-only + + + SECURE_BOOT_KEY_REVOKE0 + Set this bit to enable revoking first secure boot key. + 21 + 1 + read-only + + + SECURE_BOOT_KEY_REVOKE1 + Set this bit to enable revoking second secure boot key. + 22 + 1 + read-only + + + SECURE_BOOT_KEY_REVOKE2 + Set this bit to enable revoking third secure boot key. + 23 + 1 + read-only + + + KEY_PURPOSE_0 + Purpose of Key0. + 24 + 4 + read-only + + + KEY_PURPOSE_1 + Purpose of Key1. + 28 + 4 + read-only + + + + + RD_REPEAT_DATA2 + BLOCK0 data register 3. + 0x38 + 0x20 + + + KEY_PURPOSE_2 + Purpose of Key2. + 0 + 4 + read-only + + + KEY_PURPOSE_3 + Purpose of Key3. + 4 + 4 + read-only + + + KEY_PURPOSE_4 + Purpose of Key4. + 8 + 4 + read-only + + + KEY_PURPOSE_5 + Purpose of Key5. + 12 + 4 + read-only + + + RPT4_RESERVED0 + Reserved (used for four backups method). + 16 + 4 + read-only + + + SECURE_BOOT_EN + Set this bit to enable secure boot. + 20 + 1 + read-only + + + SECURE_BOOT_AGGRESSIVE_REVOKE + Set this bit to enable revoking aggressive secure boot. + 21 + 1 + read-only + + + DIS_USB_JTAG + Set this bit to disable function of usb switch to jtag in module of usb device. + 22 + 1 + read-only + + + DIS_USB_DEVICE + Set this bit to disable usb device. + 23 + 1 + read-only + + + STRAP_JTAG_SEL + Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0. + 24 + 1 + read-only + + + USB_PHY_SEL + This bit is used to switch internal PHY and external PHY for USB OTG and USB Device. 0: internal PHY is assigned to USB Device while external PHY is assigned to USB OTG. 1: internal PHY is assigned to USB OTG while external PHY is assigned to USB Device. + 25 + 1 + read-only + + + POWER_GLITCH_DSENSE + Sample delay configuration of power glitch. + 26 + 2 + read-only + + + FLASH_TPUW + Configures flash waiting time after power-up, in unit of ms. If the value is less than 15, the waiting time is the configurable value. Otherwise, the waiting time is twice the configurable value. + 28 + 4 + read-only + + + + + RD_REPEAT_DATA3 + BLOCK0 data register 4. + 0x3C + 0x20 + + + DIS_DOWNLOAD_MODE + Set this bit to disable download mode (boot_mode[3:0] = 0, 1, 2, 3, 6, 7). + 0 + 1 + read-only + + + DIS_LEGACY_SPI_BOOT + Set this bit to disable Legacy SPI boot mode (boot_mode[3:0] = 4). + 1 + 1 + read-only + + + UART_PRINT_CHANNEL + Selectes the default UART print channel. 0: UART0. 1: UART1. + 2 + 1 + read-only + + + FLASH_ECC_MODE + Set ECC mode in ROM, 0: ROM would Enable Flash ECC 16to18 byte mode. 1:ROM would use 16to17 byte mode. + 3 + 1 + read-only + + + DIS_USB_DOWNLOAD_MODE + Set this bit to disable UART download mode through USB. + 4 + 1 + read-only + + + ENABLE_SECURITY_DOWNLOAD + Set this bit to enable secure UART download mode. + 5 + 1 + read-only + + + UART_PRINT_CONTROL + Set the default UARTboot message output mode. 00: Enabled. 01: Enabled when GPIO8 is low at reset. 10: Enabled when GPIO8 is high at reset. 11:disabled. + 6 + 2 + read-only + + + PIN_POWER_SELECTION + GPIO33-GPIO37 power supply selection in ROM code. 0: VDD3P3_CPU. 1: VDD_SPI. + 8 + 1 + read-only + + + FLASH_TYPE + Set the maximum lines of SPI flash. 0: four lines. 1: eight lines. + 9 + 1 + read-only + + + FLASH_PAGE_SIZE + Set Flash page size. + 10 + 2 + read-only + + + FLASH_ECC_EN + Set 1 to enable ECC for flash boot. + 12 + 1 + read-only + + + FORCE_SEND_RESUME + Set this bit to force ROM code to send a resume command during SPI boot. + 13 + 1 + read-only + + + SECURE_VERSION + Secure version (used by ESP-IDF anti-rollback feature). + 14 + 16 + read-only + + + POWERGLITCH_EN + Set this bit to enable power glitch function. + 30 + 1 + read-only + + + RPT4_RESERVED1 + Reserved (used for four backups method). + 31 + 1 + read-only + + + + + RD_REPEAT_DATA4 + BLOCK0 data register 5. + 0x40 + 0x20 + + + RPT4_RESERVED2 + Reserved (used for four backups method). + 0 + 24 + read-only + + + + + RD_MAC_SPI_SYS_0 + BLOCK1 data register 0. + 0x44 + 0x20 + + + MAC_0 + Stores the low 32 bits of MAC address. + 0 + 32 + read-only + + + + + RD_MAC_SPI_SYS_1 + BLOCK1 data register 1. + 0x48 + 0x20 + + + MAC_1 + Stores the high 16 bits of MAC address. + 0 + 16 + read-only + + + SPI_PAD_CONF_0 + Stores the zeroth part of SPI_PAD_CONF. + 16 + 16 + read-only + + + + + RD_MAC_SPI_SYS_2 + BLOCK1 data register 2. + 0x4C + 0x20 + + + SPI_PAD_CONF_1 + Stores the first part of SPI_PAD_CONF. + 0 + 32 + read-only + + + + + RD_MAC_SPI_SYS_3 + BLOCK1 data register 3. + 0x50 + 0x20 + + + SPI_PAD_CONF_2 + Stores the second part of SPI_PAD_CONF. + 0 + 18 + read-only + + + SYS_DATA_PART0_0 + Stores the fist 14 bits of the zeroth part of system data. + 18 + 14 + read-only + + + + + RD_MAC_SPI_SYS_4 + BLOCK1 data register 4. + 0x54 + 0x20 + + + SYS_DATA_PART0_1 + Stores the fist 32 bits of the zeroth part of system data. + 0 + 32 + read-only + + + + + RD_MAC_SPI_SYS_5 + BLOCK1 data register 5. + 0x58 + 0x20 + + + SYS_DATA_PART0_2 + Stores the second 32 bits of the zeroth part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA0 + Register 0 of BLOCK2 (system). + 0x5C + 0x20 + + + SYS_DATA_PART1_0 + Stores the zeroth 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA1 + Register 1 of BLOCK2 (system). + 0x60 + 0x20 + + + SYS_DATA_PART1_1 + Stores the first 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA2 + Register 2 of BLOCK2 (system). + 0x64 + 0x20 + + + SYS_DATA_PART1_2 + Stores the second 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA3 + Register 3 of BLOCK2 (system). + 0x68 + 0x20 + + + SYS_DATA_PART1_3 + Stores the third 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA4 + Register 4 of BLOCK2 (system). + 0x6C + 0x20 + + + SYS_DATA_PART1_4 + Stores the fourth 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA5 + Register 5 of BLOCK2 (system). + 0x70 + 0x20 + + + SYS_DATA_PART1_5 + Stores the fifth 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA6 + Register 6 of BLOCK2 (system). + 0x74 + 0x20 + + + SYS_DATA_PART1_6 + Stores the sixth 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART1_DATA7 + Register 7 of BLOCK2 (system). + 0x78 + 0x20 + + + SYS_DATA_PART1_7 + Stores the seventh 32 bits of the first part of system data. + 0 + 32 + read-only + + + + + RD_USR_DATA0 + Register 0 of BLOCK3 (user). + 0x7C + 0x20 + + + USR_DATA0 + Stores the zeroth 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA1 + Register 1 of BLOCK3 (user). + 0x80 + 0x20 + + + USR_DATA1 + Stores the first 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA2 + Register 2 of BLOCK3 (user). + 0x84 + 0x20 + + + USR_DATA2 + Stores the second 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA3 + Register 3 of BLOCK3 (user). + 0x88 + 0x20 + + + USR_DATA3 + Stores the third 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA4 + Register 4 of BLOCK3 (user). + 0x8C + 0x20 + + + USR_DATA4 + Stores the fourth 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA5 + Register 5 of BLOCK3 (user). + 0x90 + 0x20 + + + USR_DATA5 + Stores the fifth 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA6 + Register 6 of BLOCK3 (user). + 0x94 + 0x20 + + + USR_DATA6 + Stores the sixth 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_USR_DATA7 + Register 7 of BLOCK3 (user). + 0x98 + 0x20 + + + USR_DATA7 + Stores the seventh 32 bits of BLOCK3 (user). + 0 + 32 + read-only + + + + + RD_KEY0_DATA0 + Register 0 of BLOCK4 (KEY0). + 0x9C + 0x20 + + + KEY0_DATA0 + Stores the zeroth 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA1 + Register 1 of BLOCK4 (KEY0). + 0xA0 + 0x20 + + + KEY0_DATA1 + Stores the first 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA2 + Register 2 of BLOCK4 (KEY0). + 0xA4 + 0x20 + + + KEY0_DATA2 + Stores the second 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA3 + Register 3 of BLOCK4 (KEY0). + 0xA8 + 0x20 + + + KEY0_DATA3 + Stores the third 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA4 + Register 4 of BLOCK4 (KEY0). + 0xAC + 0x20 + + + KEY0_DATA4 + Stores the fourth 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA5 + Register 5 of BLOCK4 (KEY0). + 0xB0 + 0x20 + + + KEY0_DATA5 + Stores the fifth 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA6 + Register 6 of BLOCK4 (KEY0). + 0xB4 + 0x20 + + + KEY0_DATA6 + Stores the sixth 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY0_DATA7 + Register 7 of BLOCK4 (KEY0). + 0xB8 + 0x20 + + + KEY0_DATA7 + Stores the seventh 32 bits of KEY0. + 0 + 32 + read-only + + + + + RD_KEY1_DATA0 + Register 0 of BLOCK5 (KEY1). + 0xBC + 0x20 + + + KEY1_DATA0 + Stores the zeroth 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA1 + Register 1 of BLOCK5 (KEY1). + 0xC0 + 0x20 + + + KEY1_DATA1 + Stores the first 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA2 + Register 2 of BLOCK5 (KEY1). + 0xC4 + 0x20 + + + KEY1_DATA2 + Stores the second 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA3 + Register 3 of BLOCK5 (KEY1). + 0xC8 + 0x20 + + + KEY1_DATA3 + Stores the third 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA4 + Register 4 of BLOCK5 (KEY1). + 0xCC + 0x20 + + + KEY1_DATA4 + Stores the fourth 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA5 + Register 5 of BLOCK5 (KEY1). + 0xD0 + 0x20 + + + KEY1_DATA5 + Stores the fifth 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA6 + Register 6 of BLOCK5 (KEY1). + 0xD4 + 0x20 + + + KEY1_DATA6 + Stores the sixth 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY1_DATA7 + Register 7 of BLOCK5 (KEY1). + 0xD8 + 0x20 + + + KEY1_DATA7 + Stores the seventh 32 bits of KEY1. + 0 + 32 + read-only + + + + + RD_KEY2_DATA0 + Register 0 of BLOCK6 (KEY2). + 0xDC + 0x20 + + + KEY2_DATA0 + Stores the zeroth 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA1 + Register 1 of BLOCK6 (KEY2). + 0xE0 + 0x20 + + + KEY2_DATA1 + Stores the first 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA2 + Register 2 of BLOCK6 (KEY2). + 0xE4 + 0x20 + + + KEY2_DATA2 + Stores the second 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA3 + Register 3 of BLOCK6 (KEY2). + 0xE8 + 0x20 + + + KEY2_DATA3 + Stores the third 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA4 + Register 4 of BLOCK6 (KEY2). + 0xEC + 0x20 + + + KEY2_DATA4 + Stores the fourth 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA5 + Register 5 of BLOCK6 (KEY2). + 0xF0 + 0x20 + + + KEY2_DATA5 + Stores the fifth 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA6 + Register 6 of BLOCK6 (KEY2). + 0xF4 + 0x20 + + + KEY2_DATA6 + Stores the sixth 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY2_DATA7 + Register 7 of BLOCK6 (KEY2). + 0xF8 + 0x20 + + + KEY2_DATA7 + Stores the seventh 32 bits of KEY2. + 0 + 32 + read-only + + + + + RD_KEY3_DATA0 + Register 0 of BLOCK7 (KEY3). + 0xFC + 0x20 + + + KEY3_DATA0 + Stores the zeroth 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA1 + Register 1 of BLOCK7 (KEY3). + 0x100 + 0x20 + + + KEY3_DATA1 + Stores the first 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA2 + Register 2 of BLOCK7 (KEY3). + 0x104 + 0x20 + + + KEY3_DATA2 + Stores the second 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA3 + Register 3 of BLOCK7 (KEY3). + 0x108 + 0x20 + + + KEY3_DATA3 + Stores the third 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA4 + Register 4 of BLOCK7 (KEY3). + 0x10C + 0x20 + + + KEY3_DATA4 + Stores the fourth 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA5 + Register 5 of BLOCK7 (KEY3). + 0x110 + 0x20 + + + KEY3_DATA5 + Stores the fifth 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA6 + Register 6 of BLOCK7 (KEY3). + 0x114 + 0x20 + + + KEY3_DATA6 + Stores the sixth 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY3_DATA7 + Register 7 of BLOCK7 (KEY3). + 0x118 + 0x20 + + + KEY3_DATA7 + Stores the seventh 32 bits of KEY3. + 0 + 32 + read-only + + + + + RD_KEY4_DATA0 + Register 0 of BLOCK8 (KEY4). + 0x11C + 0x20 + + + KEY4_DATA0 + Stores the zeroth 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA1 + Register 1 of BLOCK8 (KEY4). + 0x120 + 0x20 + + + KEY4_DATA1 + Stores the first 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA2 + Register 2 of BLOCK8 (KEY4). + 0x124 + 0x20 + + + KEY4_DATA2 + Stores the second 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA3 + Register 3 of BLOCK8 (KEY4). + 0x128 + 0x20 + + + KEY4_DATA3 + Stores the third 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA4 + Register 4 of BLOCK8 (KEY4). + 0x12C + 0x20 + + + KEY4_DATA4 + Stores the fourth 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA5 + Register 5 of BLOCK8 (KEY4). + 0x130 + 0x20 + + + KEY4_DATA5 + Stores the fifth 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA6 + Register 6 of BLOCK8 (KEY4). + 0x134 + 0x20 + + + KEY4_DATA6 + Stores the sixth 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY4_DATA7 + Register 7 of BLOCK8 (KEY4). + 0x138 + 0x20 + + + KEY4_DATA7 + Stores the seventh 32 bits of KEY4. + 0 + 32 + read-only + + + + + RD_KEY5_DATA0 + Register 0 of BLOCK9 (KEY5). + 0x13C + 0x20 + + + KEY5_DATA0 + Stores the zeroth 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA1 + Register 1 of BLOCK9 (KEY5). + 0x140 + 0x20 + + + KEY5_DATA1 + Stores the first 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA2 + Register 2 of BLOCK9 (KEY5). + 0x144 + 0x20 + + + KEY5_DATA2 + Stores the second 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA3 + Register 3 of BLOCK9 (KEY5). + 0x148 + 0x20 + + + KEY5_DATA3 + Stores the third 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA4 + Register 4 of BLOCK9 (KEY5). + 0x14C + 0x20 + + + KEY5_DATA4 + Stores the fourth 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA5 + Register 5 of BLOCK9 (KEY5). + 0x150 + 0x20 + + + KEY5_DATA5 + Stores the fifth 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA6 + Register 6 of BLOCK9 (KEY5). + 0x154 + 0x20 + + + KEY5_DATA6 + Stores the sixth 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_KEY5_DATA7 + Register 7 of BLOCK9 (KEY5). + 0x158 + 0x20 + + + KEY5_DATA7 + Stores the seventh 32 bits of KEY5. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA0 + Register 0 of BLOCK10 (system). + 0x15C + 0x20 + + + SYS_DATA_PART2_0 + Stores the 0th 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA1 + Register 1 of BLOCK9 (KEY5). + 0x160 + 0x20 + + + SYS_DATA_PART2_1 + Stores the 1st 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA2 + Register 2 of BLOCK10 (system). + 0x164 + 0x20 + + + SYS_DATA_PART2_2 + Stores the 2nd 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA3 + Register 3 of BLOCK10 (system). + 0x168 + 0x20 + + + SYS_DATA_PART2_3 + Stores the 3rd 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA4 + Register 4 of BLOCK10 (system). + 0x16C + 0x20 + + + SYS_DATA_PART2_4 + Stores the 4th 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA5 + Register 5 of BLOCK10 (system). + 0x170 + 0x20 + + + SYS_DATA_PART2_5 + Stores the 5th 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA6 + Register 6 of BLOCK10 (system). + 0x174 + 0x20 + + + SYS_DATA_PART2_6 + Stores the 6th 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_SYS_PART2_DATA7 + Register 7 of BLOCK10 (system). + 0x178 + 0x20 + + + SYS_DATA_PART2_7 + Stores the 7th 32 bits of the 2nd part of system data. + 0 + 32 + read-only + + + + + RD_REPEAT_ERR0 + Programming error record register 0 of BLOCK0. + 0x17C + 0x20 + + + RD_DIS_ERR + If any bits in this filed are 1, then it indicates a programming error. + 0 + 7 + read-only + + + DIS_RTC_RAM_BOOT_ERR + If any bits in this filed are 1, then it indicates a programming error. + 7 + 1 + read-only + + + DIS_ICACHE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 8 + 1 + read-only + + + DIS_DCACHE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 9 + 1 + read-only + + + DIS_DOWNLOAD_ICACHE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 10 + 1 + read-only + + + DIS_DOWNLOAD_DCACHE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 11 + 1 + read-only + + + DIS_FORCE_DOWNLOAD_ERR + If any bits in this filed are 1, then it indicates a programming error. + 12 + 1 + read-only + + + DIS_USB_ERR + If any bits in this filed are 1, then it indicates a programming error. + 13 + 1 + read-only + + + DIS_CAN_ERR + If any bits in this filed are 1, then it indicates a programming error. + 14 + 1 + read-only + + + DIS_APP_CPU_ERR + If any bits in this filed are 1, then it indicates a programming error. + 15 + 1 + read-only + + + SOFT_DIS_JTAG_ERR + If any bits in this filed are 1, then it indicates a programming error. + 16 + 3 + read-only + + + DIS_PAD_JTAG_ERR + If any bits in this filed are 1, then it indicates a programming error. + 19 + 1 + read-only + + + DIS_DOWNLOAD_MANUAL_ENCRYPT_ERR + If any bits in this filed are 1, then it indicates a programming error. + 20 + 1 + read-only + + + USB_DREFH_ERR + If any bits in this filed are 1, then it indicates a programming error. + 21 + 2 + read-only + + + USB_DREFL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 23 + 2 + read-only + + + USB_EXCHG_PINS_ERR + If any bits in this filed are 1, then it indicates a programming error. + 25 + 1 + read-only + + + EXT_PHY_ENABLE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 26 + 1 + read-only + + + BTLC_GPIO_ENABLE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 27 + 2 + read-only + + + VDD_SPI_MODECURLIM_ERR + If any bits in this filed are 1, then it indicates a programming error. + 29 + 1 + read-only + + + VDD_SPI_DREFH_ERR + If any bits in this filed are 1, then it indicates a programming error. + 30 + 2 + read-only + + + + + RD_REPEAT_ERR1 + Programming error record register 1 of BLOCK0. + 0x180 + 0x20 + + + VDD_SPI_DREFM_ERR + If any bits in this filed are 1, then it indicates a programming error. + 0 + 2 + read-only + + + VDD_SPI_DREFL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 2 + 2 + read-only + + + VDD_SPI_XPD_ERR + If any bits in this filed are 1, then it indicates a programming error. + 4 + 1 + read-only + + + VDD_SPI_TIEH_ERR + If any bits in this filed are 1, then it indicates a programming error. + 5 + 1 + read-only + + + VDD_SPI_FORCE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 6 + 1 + read-only + + + VDD_SPI_EN_INIT_ERR + If any bits in this filed are 1, then it indicates a programming error. + 7 + 1 + read-only + + + VDD_SPI_ENCURLIM_ERR + If any bits in this filed are 1, then it indicates a programming error. + 8 + 1 + read-only + + + VDD_SPI_DCURLIM_ERR + If any bits in this filed are 1, then it indicates a programming error. + 9 + 3 + read-only + + + VDD_SPI_INIT_ERR + If any bits in this filed are 1, then it indicates a programming error. + 12 + 2 + read-only + + + VDD_SPI_DCAP_ERR + If any bits in this filed are 1, then it indicates a programming error. + 14 + 2 + read-only + + + WDT_DELAY_SEL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 16 + 2 + read-only + + + SPI_BOOT_CRYPT_CNT_ERR + If any bits in this filed are 1, then it indicates a programming error. + 18 + 3 + read-only + + + SECURE_BOOT_KEY_REVOKE0_ERR + If any bits in this filed are 1, then it indicates a programming error. + 21 + 1 + read-only + + + SECURE_BOOT_KEY_REVOKE1_ERR + If any bits in this filed are 1, then it indicates a programming error. + 22 + 1 + read-only + + + SECURE_BOOT_KEY_REVOKE2_ERR + If any bits in this filed are 1, then it indicates a programming error. + 23 + 1 + read-only + + + KEY_PURPOSE_0_ERR + If any bits in this filed are 1, then it indicates a programming error. + 24 + 4 + read-only + + + KEY_PURPOSE_1_ERR + If any bits in this filed are 1, then it indicates a programming error. + 28 + 4 + read-only + + + + + RD_REPEAT_ERR2 + Programming error record register 2 of BLOCK0. + 0x184 + 0x20 + + + KEY_PURPOSE_2_ERR + If any bits in this filed are 1, then it indicates a programming error. + 0 + 4 + read-only + + + KEY_PURPOSE_3_ERR + If any bits in this filed are 1, then it indicates a programming error. + 4 + 4 + read-only + + + KEY_PURPOSE_4_ERR + If any bits in this filed are 1, then it indicates a programming error. + 8 + 4 + read-only + + + KEY_PURPOSE_5_ERR + If any bits in this filed are 1, then it indicates a programming error. + 12 + 4 + read-only + + + RPT4_RESERVED0_ERR + If any bits in this filed are 1, then it indicates a programming error. + 16 + 4 + read-only + + + SECURE_BOOT_EN_ERR + If any bits in this filed are 1, then it indicates a programming error. + 20 + 1 + read-only + + + SECURE_BOOT_AGGRESSIVE_REVOKE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 21 + 1 + read-only + + + DIS_USB_JTAG_ERR + If any bits in this filed are 1, then it indicates a programming error. + 22 + 1 + read-only + + + DIS_USB_DEVICE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 23 + 1 + read-only + + + STRAP_JTAG_SEL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 24 + 1 + read-only + + + USB_PHY_SEL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 25 + 1 + read-only + + + POWER_GLITCH_DSENSE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 26 + 2 + read-only + + + FLASH_TPUW_ERR + If any bits in this filed are 1, then it indicates a programming error. + 28 + 4 + read-only + + + + + RD_REPEAT_ERR3 + Programming error record register 3 of BLOCK0. + 0x188 + 0x20 + + + DIS_DOWNLOAD_MODE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 0 + 1 + read-only + + + DIS_LEGACY_SPI_BOOT_ERR + If any bits in this filed are 1, then it indicates a programming error. + 1 + 1 + read-only + + + UART_PRINT_CHANNEL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 2 + 1 + read-only + + + FLASH_ECC_MODE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 3 + 1 + read-only + + + DIS_USB_DOWNLOAD_MODE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 4 + 1 + read-only + + + ENABLE_SECURITY_DOWNLOAD_ERR + If any bits in this filed are 1, then it indicates a programming error. + 5 + 1 + read-only + + + UART_PRINT_CONTROL_ERR + If any bits in this filed are 1, then it indicates a programming error. + 6 + 2 + read-only + + + PIN_POWER_SELECTION_ERR + If any bits in this filed are 1, then it indicates a programming error. + 8 + 1 + read-only + + + FLASH_TYPE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 9 + 1 + read-only + + + FLASH_PAGE_SIZE_ERR + If any bits in this filed are 1, then it indicates a programming error. + 10 + 2 + read-only + + + FLASH_ECC_EN_ERR + If any bits in this filed are 1, then it indicates a programming error. + 12 + 1 + read-only + + + FORCE_SEND_RESUME_ERR + If any bits in this filed are 1, then it indicates a programming error. + 13 + 1 + read-only + + + SECURE_VERSION_ERR + If any bits in this filed are 1, then it indicates a programming error. + 14 + 16 + read-only + + + POWERGLITCH_EN_ERR + If any bits in this filed are 1, then it indicates a programming error. + 30 + 1 + read-only + + + RPT4_RESERVED1_ERR + Reserved. + 31 + 1 + read-only + + + + + RD_REPEAT_ERR4 + Programming error record register 4 of BLOCK0. + 0x190 + 0x20 + + + RPT4_RESERVED2_ERR + If any bits in this filed are 1, then it indicates a programming error. + 0 + 24 + read-only + + + + + RD_RS_ERR0 + Programming error record register 0 of BLOCK1-10. + 0x1C0 + 0x20 + + + MAC_SPI_8M_ERR_NUM + The value of this signal means the number of error bytes. + 0 + 3 + read-only + + + MAC_SPI_8M_FAIL + 0: Means no failure and that the data of MAC_SPI_8M is reliable 1: Means that programming user data failed and the number of error bytes is over 6. + 3 + 1 + read-only + + + SYS_PART1_NUM + The value of this signal means the number of error bytes. + 4 + 3 + read-only + + + SYS_PART1_FAIL + 0: Means no failure and that the data of system part1 is reliable 1: Means that programming user data failed and the number of error bytes is over 6. + 7 + 1 + read-only + + + USR_DATA_ERR_NUM + The value of this signal means the number of error bytes. + 8 + 3 + read-only + + + USR_DATA_FAIL + 0: Means no failure and that the user data is reliable 1: Means that programming user data failed and the number of error bytes is over 6. + 11 + 1 + read-only + + + KEY0_ERR_NUM + The value of this signal means the number of error bytes. + 12 + 3 + read-only + + + KEY0_FAIL + 0: Means no failure and that the data of key0 is reliable 1: Means that programming key0 failed and the number of error bytes is over 6. + 15 + 1 + read-only + + + KEY1_ERR_NUM + The value of this signal means the number of error bytes. + 16 + 3 + read-only + + + KEY1_FAIL + 0: Means no failure and that the data of key1 is reliable 1: Means that programming key1 failed and the number of error bytes is over 6. + 19 + 1 + read-only + + + KEY2_ERR_NUM + The value of this signal means the number of error bytes. + 20 + 3 + read-only + + + KEY2_FAIL + 0: Means no failure and that the data of key2 is reliable 1: Means that programming key2 failed and the number of error bytes is over 6. + 23 + 1 + read-only + + + KEY3_ERR_NUM + The value of this signal means the number of error bytes. + 24 + 3 + read-only + + + KEY3_FAIL + 0: Means no failure and that the data of key3 is reliable 1: Means that programming key3 failed and the number of error bytes is over 6. + 27 + 1 + read-only + + + KEY4_ERR_NUM + The value of this signal means the number of error bytes. + 28 + 3 + read-only + + + KEY4_FAIL + 0: Means no failure and that the data of key4 is reliable 1: Means that programming key4 failed and the number of error bytes is over 6. + 31 + 1 + read-only + + + + + RD_RS_ERR1 + Programming error record register 1 of BLOCK1-10. + 0x1C4 + 0x20 + + + KEY5_ERR_NUM + The value of this signal means the number of error bytes. + 0 + 3 + read-only + + + KEY5_FAIL + 0: Means no failure and that the data of KEY5 is reliable 1: Means that programming user data failed and the number of error bytes is over 6. + 3 + 1 + read-only + + + SYS_PART2_ERR_NUM + The value of this signal means the number of error bytes. + 4 + 3 + read-only + + + SYS_PART2_FAIL + 0: Means no failure and that the data of system part2 is reliable 1: Means that programming user data failed and the number of error bytes is over 6. + 7 + 1 + read-only + + + + + CLK + eFuse clcok configuration register. + 0x1C8 + 0x20 + 0x00000002 + + + EFUSE_MEM_FORCE_PD + Set this bit to force eFuse SRAM into power-saving mode. + 0 + 1 + read-write + + + MEM_CLK_FORCE_ON + Set this bit and force to activate clock signal of eFuse SRAM. + 1 + 1 + read-write + + + EFUSE_MEM_FORCE_PU + Set this bit to force eFuse SRAM into working mode. + 2 + 1 + read-write + + + EN + Set this bit and force to enable clock signal of eFuse memory. + 16 + 1 + read-write + + + + + CONF + eFuse operation mode configuraiton register + 0x1CC + 0x20 + + + OP_CODE + 0x5A5A: Operate programming command 0x5AA5: Operate read command. + 0 + 16 + read-write + + + + + STATUS + eFuse status register. + 0x1D0 + 0x20 + + + STATE + Indicates the state of the eFuse state machine. + 0 + 4 + read-only + + + OTP_LOAD_SW + The value of OTP_LOAD_SW. + 4 + 1 + read-only + + + OTP_VDDQ_C_SYNC2 + The value of OTP_VDDQ_C_SYNC2. + 5 + 1 + read-only + + + OTP_STROBE_SW + The value of OTP_STROBE_SW. + 6 + 1 + read-only + + + OTP_CSB_SW + The value of OTP_CSB_SW. + 7 + 1 + read-only + + + OTP_PGENB_SW + The value of OTP_PGENB_SW. + 8 + 1 + read-only + + + OTP_VDDQ_IS_SW + The value of OTP_VDDQ_IS_SW. + 9 + 1 + read-only + + + REPEAT_ERR_CNT + Indicates the number of error bits during programming BLOCK0. + 10 + 8 + read-only + + + + + CMD + eFuse command register. + 0x1D4 + 0x20 + + + READ_CMD + Set this bit to send read command. + 0 + 1 + read-write + + + PGM_CMD + Set this bit to send programming command. + 1 + 1 + read-write + + + BLK_NUM + The serial number of the block to be programmed. Value 0-10 corresponds to block number 0-10, respectively. + 2 + 4 + read-write + + + + + INT_RAW + eFuse raw interrupt register. + 0x1D8 + 0x20 + + + READ_DONE_INT_RAW + The raw bit signal for read_done interrupt. + 0 + 1 + read-write + + + PGM_DONE_INT_RAW + The raw bit signal for pgm_done interrupt. + 1 + 1 + read-write + + + + + INT_ST + eFuse interrupt status register. + 0x1DC + 0x20 + + + READ_DONE_INT_ST + The status signal for read_done interrupt. + 0 + 1 + read-only + + + PGM_DONE_INT_ST + The status signal for pgm_done interrupt. + 1 + 1 + read-only + + + + + INT_ENA + eFuse interrupt enable register. + 0x1E0 + 0x20 + + + READ_DONE_INT_ENA + The enable signal for read_done interrupt. + 0 + 1 + read-write + + + PGM_DONE_INT_ENA + The enable signal for pgm_done interrupt. + 1 + 1 + read-write + + + + + INT_CLR + eFuse interrupt clear register. + 0x1E4 + 0x20 + + + READ_DONE_INT_CLR + The clear signal for read_done interrupt. + 0 + 1 + write-only + + + PGM_DONE_INT_CLR + The clear signal for pgm_done interrupt. + 1 + 1 + write-only + + + + + DAC_CONF + Controls the eFuse programming voltage. + 0x1E8 + 0x20 + 0x0001FE1C + + + DAC_CLK_DIV + Controls the division factor of the rising clock of the programming voltage. + 0 + 8 + read-write + + + DAC_CLK_PAD_SEL + Don't care. + 8 + 1 + read-write + + + DAC_NUM + Controls the rising period of the programming voltage. + 9 + 8 + read-write + + + OE_CLR + Reduces the power supply of the programming voltage. + 17 + 1 + read-write + + + + + RD_TIM_CONF + Configures read timing parameters. + 0x1EC + 0x20 + 0x12000000 + + + READ_INIT_NUM + Configures the initial read time of eFuse. + 24 + 8 + read-write + + + + + WR_TIM_CONF1 + Configurarion register 1 of eFuse programming timing parameters. + 0x1F4 + 0x20 + 0x00288000 + + + PWR_ON_NUM + Configures the power up time for VDDQ. + 8 + 16 + read-write + + + + + WR_TIM_CONF2 + Configurarion register 2 of eFuse programming timing parameters. + 0x1F8 + 0x20 + 0x00000190 + + + PWR_OFF_NUM + Configures the power outage time for VDDQ. + 0 + 16 + read-write + + + + + DATE + eFuse version register. + 0x1FC + 0x20 + 0x02101290 + + + DATE + Stores eFuse version. + 0 + 28 + read-write + + + + + + + EXTMEM + External Memory + EXTMEM + 0x600C4000 + + 0x0 + 0x17C + registers + + + + DCACHE_CTRL + ******* Description *********** + 0x0 + 0x20 + + + DCACHE_ENABLE + The bit is used to activate the data cache. 0: disable, 1: enable + 0 + 1 + read-write + + + DCACHE_SIZE_MODE + The bit is used to configure cache memory size.0: 32KB, 1: 64KB + 2 + 1 + read-write + + + DCACHE_BLOCKSIZE_MODE + The bit is used to configure cache block size.0: 16 bytes, 1: 32 bytes,2: 64 bytes + 3 + 2 + read-write + + + + + DCACHE_CTRL1 + ******* Description *********** + 0x4 + 0x20 + 0x00000003 + + + DCACHE_SHUT_CORE0_BUS + The bit is used to disable core0 dbus, 0: enable, 1: disable + 0 + 1 + read-write + + + DCACHE_SHUT_CORE1_BUS + The bit is used to disable core1 dbus, 0: enable, 1: disable + 1 + 1 + read-write + + + + + DCACHE_TAG_POWER_CTRL + ******* Description *********** + 0x8 + 0x20 + 0x00000005 + + + DCACHE_TAG_MEM_FORCE_ON + The bit is used to close clock gating of dcache tag memory. 1: close gating, 0: open clock gating. + 0 + 1 + read-write + + + DCACHE_TAG_MEM_FORCE_PD + The bit is used to power dcache tag memory down, 0: follow rtc_lslp_pd, 1: power down + 1 + 1 + read-write + + + DCACHE_TAG_MEM_FORCE_PU + The bit is used to power dcache tag memory up, 0: follow rtc_lslp_pd, 1: power up + 2 + 1 + read-write + + + + + DCACHE_PRELOCK_CTRL + ******* Description *********** + 0xC + 0x20 + + + DCACHE_PRELOCK_SCT0_EN + The bit is used to enable the first section of prelock function. + 0 + 1 + read-write + + + DCACHE_PRELOCK_SCT1_EN + The bit is used to enable the second section of prelock function. + 1 + 1 + read-write + + + + + DCACHE_PRELOCK_SCT0_ADDR + ******* Description *********** + 0x10 + 0x20 + + + DCACHE_PRELOCK_SCT0_ADDR + The bits are used to configure the first start virtual address of data prelock, which is combined with DCACHE_PRELOCK_SCT0_SIZE_REG + 0 + 32 + read-write + + + + + DCACHE_PRELOCK_SCT1_ADDR + ******* Description *********** + 0x14 + 0x20 + + + DCACHE_PRELOCK_SCT1_ADDR + The bits are used to configure the second start virtual address of data prelock, which is combined with DCACHE_PRELOCK_SCT1_SIZE_REG + 0 + 32 + read-write + + + + + DCACHE_PRELOCK_SCT_SIZE + ******* Description *********** + 0x18 + 0x20 + + + DCACHE_PRELOCK_SCT1_SIZE + The bits are used to configure the second length of data locking, which is combined with DCACHE_PRELOCK_SCT1_ADDR_REG + 0 + 16 + read-write + + + DCACHE_PRELOCK_SCT0_SIZE + The bits are used to configure the first length of data locking, which is combined with DCACHE_PRELOCK_SCT0_ADDR_REG + 16 + 16 + read-write + + + + + DCACHE_LOCK_CTRL + ******* Description *********** + 0x1C + 0x20 + 0x00000004 + + + DCACHE_LOCK_ENA + The bit is used to enable lock operation. It will be cleared by hardware after lock operation done. + 0 + 1 + read-write + + + DCACHE_UNLOCK_ENA + The bit is used to enable unlock operation. It will be cleared by hardware after unlock operation done. + 1 + 1 + read-write + + + DCACHE_LOCK_DONE + The bit is used to indicate unlock/lock operation is finished. + 2 + 1 + read-only + + + + + DCACHE_LOCK_ADDR + ******* Description *********** + 0x20 + 0x20 + + + DCACHE_LOCK_ADDR + The bits are used to configure the start virtual address for lock operations. It should be combined with DCACHE_LOCK_SIZE_REG. + 0 + 32 + read-write + + + + + DCACHE_LOCK_SIZE + ******* Description *********** + 0x24 + 0x20 + + + DCACHE_LOCK_SIZE + The bits are used to configure the length for lock operations. The bits are the counts of cache block. It should be combined with DCACHE_LOCK_ADDR_REG. + 0 + 16 + read-write + + + + + DCACHE_SYNC_CTRL + ******* Description *********** + 0x28 + 0x20 + 0x00000001 + + + DCACHE_INVALIDATE_ENA + The bit is used to enable invalidate operation. It will be cleared by hardware after invalidate operation done. + 0 + 1 + read-write + + + DCACHE_WRITEBACK_ENA + The bit is used to enable writeback operation. It will be cleared by hardware after writeback operation done. + 1 + 1 + read-write + + + DCACHE_CLEAN_ENA + The bit is used to enable clean operation. It will be cleared by hardware after clean operation done. + 2 + 1 + read-write + + + DCACHE_SYNC_DONE + The bit is used to indicate clean/writeback/invalidate operation is finished. + 3 + 1 + read-only + + + + + DCACHE_SYNC_ADDR + ******* Description *********** + 0x2C + 0x20 + + + DCACHE_SYNC_ADDR + The bits are used to configure the start virtual address for clean operations. It should be combined with DCACHE_SYNC_SIZE_REG. + 0 + 32 + read-write + + + + + DCACHE_SYNC_SIZE + ******* Description *********** + 0x30 + 0x20 + + + DCACHE_SYNC_SIZE + The bits are used to configure the length for sync operations. The bits are the counts of cache block. It should be combined with DCACHE_SYNC_ADDR_REG. + 0 + 23 + read-write + + + + + DCACHE_OCCUPY_CTRL + ******* Description *********** + 0x34 + 0x20 + 0x00000002 + + + DCACHE_OCCUPY_ENA + The bit is used to enable occupy operation. It will be cleared by hardware after issuing Auot-Invalidate Operation. + 0 + 1 + read-write + + + DCACHE_OCCUPY_DONE + The bit is used to indicate occupy operation is finished. + 1 + 1 + read-only + + + + + DCACHE_OCCUPY_ADDR + ******* Description *********** + 0x38 + 0x20 + + + DCACHE_OCCUPY_ADDR + The bits are used to configure the start virtual address for occupy operation. It should be combined with DCACHE_OCCUPY_SIZE_REG. + 0 + 32 + read-write + + + + + DCACHE_OCCUPY_SIZE + ******* Description *********** + 0x3C + 0x20 + + + DCACHE_OCCUPY_SIZE + The bits are used to configure the length for occupy operation. The bits are the counts of cache block. It should be combined with DCACHE_OCCUPY_ADDR_REG. + 0 + 16 + read-write + + + + + DCACHE_PRELOAD_CTRL + ******* Description *********** + 0x40 + 0x20 + 0x00000002 + + + DCACHE_PRELOAD_ENA + The bit is used to enable preload operation. It will be cleared by hardware after preload operation done. + 0 + 1 + read-write + + + DCACHE_PRELOAD_DONE + The bit is used to indicate preload operation is finished. + 1 + 1 + read-only + + + DCACHE_PRELOAD_ORDER + The bit is used to configure the direction of preload operation. 1: descending, 0: ascending. + 2 + 1 + read-write + + + + + DCACHE_PRELOAD_ADDR + ******* Description *********** + 0x44 + 0x20 + + + DCACHE_PRELOAD_ADDR + The bits are used to configure the start virtual address for preload operation. It should be combined with DCACHE_PRELOAD_SIZE_REG. + 0 + 32 + read-write + + + + + DCACHE_PRELOAD_SIZE + ******* Description *********** + 0x48 + 0x20 + + + DCACHE_PRELOAD_SIZE + The bits are used to configure the length for preload operation. The bits are the counts of cache block. It should be combined with DCACHE_PRELOAD_ADDR_REG.. + 0 + 16 + read-write + + + + + DCACHE_AUTOLOAD_CTRL + ******* Description *********** + 0x4C + 0x20 + 0x00000008 + + + DCACHE_AUTOLOAD_SCT0_ENA + The bits are used to enable the first section for autoload operation. + 0 + 1 + read-write + + + DCACHE_AUTOLOAD_SCT1_ENA + The bits are used to enable the second section for autoload operation. + 1 + 1 + read-write + + + DCACHE_AUTOLOAD_ENA + The bit is used to enable and disable autoload operation. It is combined with dcache_autoload_done. 1: enable, 0: disable. + 2 + 1 + read-write + + + DCACHE_AUTOLOAD_DONE + The bit is used to indicate autoload operation is finished. + 3 + 1 + read-only + + + DCACHE_AUTOLOAD_ORDER + The bits are used to configure the direction of autoload. 1: descending, 0: ascending. + 4 + 1 + read-write + + + DCACHE_AUTOLOAD_RQST + The bits are used to configure trigger conditions for autoload. 0/3: cache miss, 1: cache hit, 2: both cache miss and hit. + 5 + 2 + read-write + + + DCACHE_AUTOLOAD_SIZE + The bits are used to configure the numbers of the cache block for the issuing autoload operation. + 7 + 2 + read-write + + + DCACHE_AUTOLOAD_BUFFER_CLEAR + The bit is used to clear autoload buffer in dcache. + 9 + 1 + read-write + + + + + DCACHE_AUTOLOAD_SCT0_ADDR + ******* Description *********** + 0x50 + 0x20 + + + DCACHE_AUTOLOAD_SCT0_ADDR + The bits are used to configure the start virtual address of the first section for autoload operation. It should be combined with dcache_autoload_sct0_ena. + 0 + 32 + read-write + + + + + DCACHE_AUTOLOAD_SCT0_SIZE + ******* Description *********** + 0x54 + 0x20 + + + DCACHE_AUTOLOAD_SCT0_SIZE + The bits are used to configure the length of the first section for autoload operation. It should be combined with dcache_autoload_sct0_ena. + 0 + 27 + read-write + + + + + DCACHE_AUTOLOAD_SCT1_ADDR + ******* Description *********** + 0x58 + 0x20 + + + DCACHE_AUTOLOAD_SCT1_ADDR + The bits are used to configure the start virtual address of the second section for autoload operation. It should be combined with dcache_autoload_sct1_ena. + 0 + 32 + read-write + + + + + DCACHE_AUTOLOAD_SCT1_SIZE + ******* Description *********** + 0x5C + 0x20 + + + DCACHE_AUTOLOAD_SCT1_SIZE + The bits are used to configure the length of the second section for autoload operation. It should be combined with dcache_autoload_sct1_ena. + 0 + 27 + read-write + + + + + ICACHE_CTRL + ******* Description *********** + 0x60 + 0x20 + + + ICACHE_ENABLE + The bit is used to activate the data cache. 0: disable, 1: enable + 0 + 1 + read-write + + + ICACHE_WAY_MODE + The bit is used to configure cache way mode.0: 4-way, 1: 8-way + 1 + 1 + read-write + + + ICACHE_SIZE_MODE + The bit is used to configure cache memory size.0: 16KB, 1: 32KB + 2 + 1 + read-write + + + ICACHE_BLOCKSIZE_MODE + The bit is used to configure cache block size.0: 16 bytes, 1: 32 bytes + 3 + 1 + read-write + + + + + ICACHE_CTRL1 + ******* Description *********** + 0x64 + 0x20 + 0x00000003 + + + ICACHE_SHUT_CORE0_BUS + The bit is used to disable core0 ibus, 0: enable, 1: disable + 0 + 1 + read-write + + + ICACHE_SHUT_CORE1_BUS + The bit is used to disable core1 ibus, 0: enable, 1: disable + 1 + 1 + read-write + + + + + ICACHE_TAG_POWER_CTRL + ******* Description *********** + 0x68 + 0x20 + 0x00000005 + + + ICACHE_TAG_MEM_FORCE_ON + The bit is used to close clock gating of icache tag memory. 1: close gating, 0: open clock gating. + 0 + 1 + read-write + + + ICACHE_TAG_MEM_FORCE_PD + The bit is used to power icache tag memory down, 0: follow rtc_lslp, 1: power down + 1 + 1 + read-write + + + ICACHE_TAG_MEM_FORCE_PU + The bit is used to power icache tag memory up, 0: follow rtc_lslp, 1: power up + 2 + 1 + read-write + + + + + ICACHE_PRELOCK_CTRL + ******* Description *********** + 0x6C + 0x20 + + + ICACHE_PRELOCK_SCT0_EN + The bit is used to enable the first section of prelock function. + 0 + 1 + read-write + + + ICACHE_PRELOCK_SCT1_EN + The bit is used to enable the second section of prelock function. + 1 + 1 + read-write + + + + + ICACHE_PRELOCK_SCT0_ADDR + ******* Description *********** + 0x70 + 0x20 + + + ICACHE_PRELOCK_SCT0_ADDR + The bits are used to configure the first start virtual address of data prelock, which is combined with ICACHE_PRELOCK_SCT0_SIZE_REG + 0 + 32 + read-write + + + + + ICACHE_PRELOCK_SCT1_ADDR + ******* Description *********** + 0x74 + 0x20 + + + ICACHE_PRELOCK_SCT1_ADDR + The bits are used to configure the second start virtual address of data prelock, which is combined with ICACHE_PRELOCK_SCT1_SIZE_REG + 0 + 32 + read-write + + + + + ICACHE_PRELOCK_SCT_SIZE + ******* Description *********** + 0x78 + 0x20 + + + ICACHE_PRELOCK_SCT1_SIZE + The bits are used to configure the second length of data locking, which is combined with ICACHE_PRELOCK_SCT1_ADDR_REG + 0 + 16 + read-write + + + ICACHE_PRELOCK_SCT0_SIZE + The bits are used to configure the first length of data locking, which is combined with ICACHE_PRELOCK_SCT0_ADDR_REG + 16 + 16 + read-write + + + + + ICACHE_LOCK_CTRL + ******* Description *********** + 0x7C + 0x20 + 0x00000004 + + + ICACHE_LOCK_ENA + The bit is used to enable lock operation. It will be cleared by hardware after lock operation done. + 0 + 1 + read-write + + + ICACHE_UNLOCK_ENA + The bit is used to enable unlock operation. It will be cleared by hardware after unlock operation done. + 1 + 1 + read-write + + + ICACHE_LOCK_DONE + The bit is used to indicate unlock/lock operation is finished. + 2 + 1 + read-only + + + + + ICACHE_LOCK_ADDR + ******* Description *********** + 0x80 + 0x20 + + + ICACHE_LOCK_ADDR + The bits are used to configure the start virtual address for lock operations. It should be combined with ICACHE_LOCK_SIZE_REG. + 0 + 32 + read-write + + + + + ICACHE_LOCK_SIZE + ******* Description *********** + 0x84 + 0x20 + + + ICACHE_LOCK_SIZE + The bits are used to configure the length for lock operations. The bits are the counts of cache block. It should be combined with ICACHE_LOCK_ADDR_REG. + 0 + 16 + read-write + + + + + ICACHE_SYNC_CTRL + ******* Description *********** + 0x88 + 0x20 + 0x00000001 + + + ICACHE_INVALIDATE_ENA + The bit is used to enable invalidate operation. It will be cleared by hardware after invalidate operation done. + 0 + 1 + read-write + + + ICACHE_SYNC_DONE + The bit is used to indicate invalidate operation is finished. + 1 + 1 + read-only + + + + + ICACHE_SYNC_ADDR + ******* Description *********** + 0x8C + 0x20 + + + ICACHE_SYNC_ADDR + The bits are used to configure the start virtual address for clean operations. It should be combined with ICACHE_SYNC_SIZE_REG. + 0 + 32 + read-write + + + + + ICACHE_SYNC_SIZE + ******* Description *********** + 0x90 + 0x20 + + + ICACHE_SYNC_SIZE + The bits are used to configure the length for sync operations. The bits are the counts of cache block. It should be combined with ICACHE_SYNC_ADDR_REG. + 0 + 23 + read-write + + + + + ICACHE_PRELOAD_CTRL + ******* Description *********** + 0x94 + 0x20 + 0x00000002 + + + ICACHE_PRELOAD_ENA + The bit is used to enable preload operation. It will be cleared by hardware after preload operation done. + 0 + 1 + read-write + + + ICACHE_PRELOAD_DONE + The bit is used to indicate preload operation is finished. + 1 + 1 + read-only + + + ICACHE_PRELOAD_ORDER + The bit is used to configure the direction of preload operation. 1: descending, 0: ascending. + 2 + 1 + read-write + + + + + ICACHE_PRELOAD_ADDR + ******* Description *********** + 0x98 + 0x20 + + + ICACHE_PRELOAD_ADDR + The bits are used to configure the start virtual address for preload operation. It should be combined with ICACHE_PRELOAD_SIZE_REG. + 0 + 32 + read-write + + + + + ICACHE_PRELOAD_SIZE + ******* Description *********** + 0x9C + 0x20 + + + ICACHE_PRELOAD_SIZE + The bits are used to configure the length for preload operation. The bits are the counts of cache block. It should be combined with ICACHE_PRELOAD_ADDR_REG.. + 0 + 16 + read-write + + + + + ICACHE_AUTOLOAD_CTRL + ******* Description *********** + 0xA0 + 0x20 + 0x00000008 + + + ICACHE_AUTOLOAD_SCT0_ENA + The bits are used to enable the first section for autoload operation. + 0 + 1 + read-write + + + ICACHE_AUTOLOAD_SCT1_ENA + The bits are used to enable the second section for autoload operation. + 1 + 1 + read-write + + + ICACHE_AUTOLOAD_ENA + The bit is used to enable and disable autoload operation. It is combined with icache_autoload_done. 1: enable, 0: disable. + 2 + 1 + read-write + + + ICACHE_AUTOLOAD_DONE + The bit is used to indicate autoload operation is finished. + 3 + 1 + read-only + + + ICACHE_AUTOLOAD_ORDER + The bits are used to configure the direction of autoload. 1: descending, 0: ascending. + 4 + 1 + read-write + + + ICACHE_AUTOLOAD_RQST + The bits are used to configure trigger conditions for autoload. 0/3: cache miss, 1: cache hit, 2: both cache miss and hit. + 5 + 2 + read-write + + + ICACHE_AUTOLOAD_SIZE + The bits are used to configure the numbers of the cache block for the issuing autoload operation. + 7 + 2 + read-write + + + ICACHE_AUTOLOAD_BUFFER_CLEAR + The bit is used to clear autoload buffer in icache. + 9 + 1 + read-write + + + + + ICACHE_AUTOLOAD_SCT0_ADDR + ******* Description *********** + 0xA4 + 0x20 + + + ICACHE_AUTOLOAD_SCT0_ADDR + The bits are used to configure the start virtual address of the first section for autoload operation. It should be combined with icache_autoload_sct0_ena. + 0 + 32 + read-write + + + + + ICACHE_AUTOLOAD_SCT0_SIZE + ******* Description *********** + 0xA8 + 0x20 + + + ICACHE_AUTOLOAD_SCT0_SIZE + The bits are used to configure the length of the first section for autoload operation. It should be combined with icache_autoload_sct0_ena. + 0 + 27 + read-write + + + + + ICACHE_AUTOLOAD_SCT1_ADDR + ******* Description *********** + 0xAC + 0x20 + + + ICACHE_AUTOLOAD_SCT1_ADDR + The bits are used to configure the start virtual address of the second section for autoload operation. It should be combined with icache_autoload_sct1_ena. + 0 + 32 + read-write + + + + + ICACHE_AUTOLOAD_SCT1_SIZE + ******* Description *********** + 0xB0 + 0x20 + + + ICACHE_AUTOLOAD_SCT1_SIZE + The bits are used to configure the length of the second section for autoload operation. It should be combined with icache_autoload_sct1_ena. + 0 + 27 + read-write + + + + + IBUS_TO_FLASH_START_VADDR + ******* Description *********** + 0xB4 + 0x20 + 0x44000000 + + + IBUS_TO_FLASH_START_VADDR + The bits are used to configure the start virtual address of ibus to access flash. The register is used to give constraints to ibus access counter. + 0 + 32 + read-write + + + + + IBUS_TO_FLASH_END_VADDR + ******* Description *********** + 0xB8 + 0x20 + 0x47FFFFFF + + + IBUS_TO_FLASH_END_VADDR + The bits are used to configure the end virtual address of ibus to access flash. The register is used to give constraints to ibus access counter. + 0 + 32 + read-write + + + + + DBUS_TO_FLASH_START_VADDR + ******* Description *********** + 0xBC + 0x20 + + + DBUS_TO_FLASH_START_VADDR + The bits are used to configure the start virtual address of dbus to access flash. The register is used to give constraints to dbus access counter. + 0 + 32 + read-write + + + + + DBUS_TO_FLASH_END_VADDR + ******* Description *********** + 0xC0 + 0x20 + + + DBUS_TO_FLASH_END_VADDR + The bits are used to configure the end virtual address of dbus to access flash. The register is used to give constraints to dbus access counter. + 0 + 32 + read-write + + + + + CACHE_ACS_CNT_CLR + ******* Description *********** + 0xC4 + 0x20 + + + DCACHE_ACS_CNT_CLR + The bit is used to clear dcache counter. + 0 + 1 + write-only + + + ICACHE_ACS_CNT_CLR + The bit is used to clear icache counter. + 1 + 1 + write-only + + + + + IBUS_ACS_MISS_CNT + ******* Description *********** + 0xC8 + 0x20 + + + IBUS_ACS_MISS_CNT + The bits are used to count the number of the cache miss caused by ibus access flash/spiram. + 0 + 32 + read-only + + + + + IBUS_ACS_CNT + ******* Description *********** + 0xCC + 0x20 + + + IBUS_ACS_CNT + The bits are used to count the number of ibus access flash/spiram through icache. + 0 + 32 + read-only + + + + + DBUS_ACS_FLASH_MISS_CNT + ******* Description *********** + 0xD0 + 0x20 + + + DBUS_ACS_FLASH_MISS_CNT + The bits are used to count the number of the cache miss caused by dbus access flash. + 0 + 32 + read-only + + + + + DBUS_ACS_SPIRAM_MISS_CNT + ******* Description *********** + 0xD4 + 0x20 + + + DBUS_ACS_SPIRAM_MISS_CNT + The bits are used to count the number of the cache miss caused by dbus access spiram. + 0 + 32 + read-only + + + + + DBUS_ACS_CNT + ******* Description *********** + 0xD8 + 0x20 + + + DBUS_ACS_CNT + The bits are used to count the number of dbus access flash/spiram through dcache. + 0 + 32 + read-only + + + + + CACHE_ILG_INT_ENA + ******* Description *********** + 0xDC + 0x20 + + + ICACHE_SYNC_OP_FAULT_INT_ENA + The bit is used to enable interrupt by sync configurations fault. + 0 + 1 + read-write + + + ICACHE_PRELOAD_OP_FAULT_INT_ENA + The bit is used to enable interrupt by preload configurations fault. + 1 + 1 + read-write + + + DCACHE_SYNC_OP_FAULT_INT_ENA + The bit is used to enable interrupt by sync configurations fault. + 2 + 1 + read-write + + + DCACHE_PRELOAD_OP_FAULT_INT_ENA + The bit is used to enable interrupt by preload configurations fault. + 3 + 1 + read-write + + + DCACHE_WRITE_FLASH_INT_ENA + The bit is used to enable interrupt by dcache trying to write flash. + 4 + 1 + read-write + + + MMU_ENTRY_FAULT_INT_ENA + The bit is used to enable interrupt by mmu entry fault. + 5 + 1 + read-write + + + DCACHE_OCCUPY_EXC_INT_ENA + The bit is used to enable interrupt by dcache trying to replace a line whose blocks all have been occupied by occupy-mode. + 6 + 1 + read-write + + + IBUS_CNT_OVF_INT_ENA + The bit is used to enable interrupt by ibus counter overflow. + 7 + 1 + read-write + + + DBUS_CNT_OVF_INT_ENA + The bit is used to enable interrupt by dbus counter overflow. + 8 + 1 + read-write + + + + + CACHE_ILG_INT_CLR + ******* Description *********** + 0xE0 + 0x20 + + + ICACHE_SYNC_OP_FAULT_INT_CLR + The bit is used to clear interrupt by sync configurations fault. + 0 + 1 + write-only + + + ICACHE_PRELOAD_OP_FAULT_INT_CLR + The bit is used to clear interrupt by preload configurations fault. + 1 + 1 + write-only + + + DCACHE_SYNC_OP_FAULT_INT_CLR + The bit is used to clear interrupt by sync configurations fault. + 2 + 1 + write-only + + + DCACHE_PRELOAD_OP_FAULT_INT_CLR + The bit is used to clear interrupt by preload configurations fault. + 3 + 1 + write-only + + + DCACHE_WRITE_FLASH_INT_CLR + The bit is used to clear interrupt by dcache trying to write flash. + 4 + 1 + write-only + + + MMU_ENTRY_FAULT_INT_CLR + The bit is used to clear interrupt by mmu entry fault. + 5 + 1 + write-only + + + DCACHE_OCCUPY_EXC_INT_CLR + The bit is used to clear interrupt by dcache trying to replace a line whose blocks all have been occupied by occupy-mode. + 6 + 1 + write-only + + + IBUS_CNT_OVF_INT_CLR + The bit is used to clear interrupt by ibus counter overflow. + 7 + 1 + write-only + + + DBUS_CNT_OVF_INT_CLR + The bit is used to clear interrupt by dbus counter overflow. + 8 + 1 + write-only + + + + + CACHE_ILG_INT_ST + ******* Description *********** + 0xE4 + 0x20 + + + ICACHE_SYNC_OP_FAULT_ST + The bit is used to indicate interrupt by sync configurations fault. + 0 + 1 + read-only + + + ICACHE_PRELOAD_OP_FAULT_ST + The bit is used to indicate interrupt by preload configurations fault. + 1 + 1 + read-only + + + DCACHE_SYNC_OP_FAULT_ST + The bit is used to indicate interrupt by sync configurations fault. + 2 + 1 + read-only + + + DCACHE_PRELOAD_OP_FAULT_ST + The bit is used to indicate interrupt by preload configurations fault. + 3 + 1 + read-only + + + DCACHE_WRITE_FLASH_ST + The bit is used to indicate interrupt by dcache trying to write flash. + 4 + 1 + read-only + + + MMU_ENTRY_FAULT_ST + The bit is used to indicate interrupt by mmu entry fault. + 5 + 1 + read-only + + + DCACHE_OCCUPY_EXC_ST + The bit is used to indicate interrupt by dcache trying to replace a line whose blocks all have been occupied by occupy-mode. + 6 + 1 + read-only + + + IBUS_ACS_CNT_OVF_ST + The bit is used to indicate interrupt by ibus access flash/spiram counter overflow. + 7 + 1 + read-only + + + IBUS_ACS_MISS_CNT_OVF_ST + The bit is used to indicate interrupt by ibus access flash/spiram miss counter overflow. + 8 + 1 + read-only + + + DBUS_ACS_CNT_OVF_ST + The bit is used to indicate interrupt by dbus access flash/spiram counter overflow. + 9 + 1 + read-only + + + DBUS_ACS_FLASH_MISS_CNT_OVF_ST + The bit is used to indicate interrupt by dbus access flash miss counter overflow. + 10 + 1 + read-only + + + DBUS_ACS_SPIRAM_MISS_CNT_OVF_ST + The bit is used to indicate interrupt by dbus access spiram miss counter overflow. + 11 + 1 + read-only + + + + + CORE0_ACS_CACHE_INT_ENA + ******* Description *********** + 0xE8 + 0x20 + + + CORE0_IBUS_ACS_MSK_IC_INT_ENA + The bit is used to enable interrupt by cpu access icache while the corresponding ibus is disabled which include speculative access. + 0 + 1 + read-write + + + CORE0_IBUS_WR_IC_INT_ENA + The bit is used to enable interrupt by ibus trying to write icache + 1 + 1 + read-write + + + CORE0_IBUS_REJECT_INT_ENA + The bit is used to enable interrupt by authentication fail. + 2 + 1 + read-write + + + CORE0_DBUS_ACS_MSK_DC_INT_ENA + The bit is used to enable interrupt by cpu access dcache while the corresponding dbus is disabled which include speculative access. + 3 + 1 + read-write + + + CORE0_DBUS_REJECT_INT_ENA + The bit is used to enable interrupt by authentication fail. + 4 + 1 + read-write + + + + + CORE0_ACS_CACHE_INT_CLR + ******* Description *********** + 0xEC + 0x20 + + + CORE0_IBUS_ACS_MSK_IC_INT_CLR + The bit is used to clear interrupt by cpu access icache while the corresponding ibus is disabled or icache is disabled which include speculative access. + 0 + 1 + write-only + + + CORE0_IBUS_WR_IC_INT_CLR + The bit is used to clear interrupt by ibus trying to write icache + 1 + 1 + write-only + + + CORE0_IBUS_REJECT_INT_CLR + The bit is used to clear interrupt by authentication fail. + 2 + 1 + write-only + + + CORE0_DBUS_ACS_MSK_DC_INT_CLR + The bit is used to clear interrupt by cpu access dcache while the corresponding dbus is disabled or dcache is disabled which include speculative access. + 3 + 1 + write-only + + + CORE0_DBUS_REJECT_INT_CLR + The bit is used to clear interrupt by authentication fail. + 4 + 1 + write-only + + + + + CORE0_ACS_CACHE_INT_ST + ******* Description *********** + 0xF0 + 0x20 + + + CORE0_IBUS_ACS_MSK_ICACHE_ST + The bit is used to indicate interrupt by cpu access icache while the core0_ibus is disabled or icache is disabled which include speculative access. + 0 + 1 + read-only + + + CORE0_IBUS_WR_ICACHE_ST + The bit is used to indicate interrupt by ibus trying to write icache + 1 + 1 + read-only + + + CORE0_IBUS_REJECT_ST + The bit is used to indicate interrupt by authentication fail. + 2 + 1 + read-only + + + CORE0_DBUS_ACS_MSK_DCACHE_ST + The bit is used to indicate interrupt by cpu access dcache while the core0_dbus is disabled or dcache is disabled which include speculative access. + 3 + 1 + read-only + + + CORE0_DBUS_REJECT_ST + The bit is used to indicate interrupt by authentication fail. + 4 + 1 + read-only + + + + + CORE1_ACS_CACHE_INT_ENA + ******* Description *********** + 0xF4 + 0x20 + + + CORE1_IBUS_ACS_MSK_IC_INT_ENA + The bit is used to enable interrupt by cpu access icache while the corresponding ibus is disabled which include speculative access. + 0 + 1 + read-write + + + CORE1_IBUS_WR_IC_INT_ENA + The bit is used to enable interrupt by ibus trying to write icache + 1 + 1 + read-write + + + CORE1_IBUS_REJECT_INT_ENA + The bit is used to enable interrupt by authentication fail. + 2 + 1 + read-write + + + CORE1_DBUS_ACS_MSK_DC_INT_ENA + The bit is used to enable interrupt by cpu access dcache while the corresponding dbus is disabled which include speculative access. + 3 + 1 + read-write + + + CORE1_DBUS_REJECT_INT_ENA + The bit is used to enable interrupt by authentication fail. + 4 + 1 + read-write + + + + + CORE1_ACS_CACHE_INT_CLR + ******* Description *********** + 0xF8 + 0x20 + + + CORE1_IBUS_ACS_MSK_IC_INT_CLR + The bit is used to clear interrupt by cpu access icache while the corresponding ibus is disabled or icache is disabled which include speculative access. + 0 + 1 + write-only + + + CORE1_IBUS_WR_IC_INT_CLR + The bit is used to clear interrupt by ibus trying to write icache + 1 + 1 + write-only + + + CORE1_IBUS_REJECT_INT_CLR + The bit is used to clear interrupt by authentication fail. + 2 + 1 + write-only + + + CORE1_DBUS_ACS_MSK_DC_INT_CLR + The bit is used to clear interrupt by cpu access dcache while the corresponding dbus is disabled or dcache is disabled which include speculative access. + 3 + 1 + write-only + + + CORE1_DBUS_REJECT_INT_CLR + The bit is used to clear interrupt by authentication fail. + 4 + 1 + write-only + + + + + CORE1_ACS_CACHE_INT_ST + ******* Description *********** + 0xFC + 0x20 + + + CORE1_IBUS_ACS_MSK_ICACHE_ST + The bit is used to indicate interrupt by cpu access icache while the core1_ibus is disabled or icache is disabled which include speculative access. + 0 + 1 + read-only + + + CORE1_IBUS_WR_ICACHE_ST + The bit is used to indicate interrupt by ibus trying to write icache + 1 + 1 + read-only + + + CORE1_IBUS_REJECT_ST + The bit is used to indicate interrupt by authentication fail. + 2 + 1 + read-only + + + CORE1_DBUS_ACS_MSK_DCACHE_ST + The bit is used to indicate interrupt by cpu access dcache while the core1_dbus is disabled or dcache is disabled which include speculative access. + 3 + 1 + read-only + + + CORE1_DBUS_REJECT_ST + The bit is used to indicate interrupt by authentication fail. + 4 + 1 + read-only + + + + + CORE0_DBUS_REJECT_ST + ******* Description *********** + 0x100 + 0x20 + + + CORE0_DBUS_TAG_ATTR + The bits are used to indicate the attribute of data from external memory when authentication fail. 0: invalidate, 1: execute-able, 2: read-able, 4: write-able. + 0 + 3 + read-only + + + CORE0_DBUS_ATTR + The bits are used to indicate the attribute of CPU access dbus when authentication fail. 0: invalidate, 1: execute-able, 2: read-able, 4: write-able. + 3 + 3 + read-only + + + CORE0_DBUS_WORLD + The bit is used to indicate the world of CPU access dbus when authentication fail. 0: WORLD0, 1: WORLD1 + 6 + 1 + read-only + + + + + CORE0_DBUS_REJECT_VADDR + ******* Description *********** + 0x104 + 0x20 + 0xFFFFFFFF + + + CORE0_DBUS_VADDR + The bits are used to indicate the virtual address of CPU access dbus when authentication fail. + 0 + 32 + read-only + + + + + CORE0_IBUS_REJECT_ST + ******* Description *********** + 0x108 + 0x20 + + + CORE0_IBUS_TAG_ATTR + The bits are used to indicate the attribute of data from external memory when authentication fail. 0: invalidate, 1: execute-able, 2: read-able, 4: write-able. + 0 + 3 + read-only + + + CORE0_IBUS_ATTR + The bits are used to indicate the attribute of CPU access ibus when authentication fail. 0: invalidate, 1: execute-able, 2: read-able + 3 + 3 + read-only + + + CORE0_IBUS_WORLD + The bit is used to indicate the world of CPU access ibus when authentication fail. 0: WORLD0, 1: WORLD1 + 6 + 1 + read-only + + + + + CORE0_IBUS_REJECT_VADDR + ******* Description *********** + 0x10C + 0x20 + 0xFFFFFFFF + + + CORE0_IBUS_VADDR + The bits are used to indicate the virtual address of CPU access ibus when authentication fail. + 0 + 32 + read-only + + + + + CORE1_DBUS_REJECT_ST + ******* Description *********** + 0x110 + 0x20 + + + CORE1_DBUS_TAG_ATTR + The bits are used to indicate the attribute of data from external memory when authentication fail. 0: invalidate, 1: execute-able, 2: read-able, 4: write-able. + 0 + 3 + read-only + + + CORE1_DBUS_ATTR + The bits are used to indicate the attribute of CPU access dbus when authentication fail. 0: invalidate, 1: execute-able, 2: read-able, 4: write-able. + 3 + 3 + read-only + + + CORE1_DBUS_WORLD + The bit is used to indicate the world of CPU access dbus when authentication fail. 0: WORLD0, 1: WORLD1 + 6 + 1 + read-only + + + + + CORE1_DBUS_REJECT_VADDR + ******* Description *********** + 0x114 + 0x20 + 0xFFFFFFFF + + + CORE1_DBUS_VADDR + The bits are used to indicate the virtual address of CPU access dbus when authentication fail. + 0 + 32 + read-only + + + + + CORE1_IBUS_REJECT_ST + ******* Description *********** + 0x118 + 0x20 + + + CORE1_IBUS_TAG_ATTR + The bits are used to indicate the attribute of data from external memory when authentication fail. 0: invalidate, 1: execute-able, 2: read-able, 4: write-able. + 0 + 3 + read-only + + + CORE1_IBUS_ATTR + The bits are used to indicate the attribute of CPU access ibus when authentication fail. 0: invalidate, 1: execute-able, 2: read-able + 3 + 3 + read-only + + + CORE1_IBUS_WORLD + The bit is used to indicate the world of CPU access ibus when authentication fail. 0: WORLD0, 1: WORLD1 + 6 + 1 + read-only + + + + + CORE1_IBUS_REJECT_VADDR + ******* Description *********** + 0x11C + 0x20 + 0xFFFFFFFF + + + CORE1_IBUS_VADDR + The bits are used to indicate the virtual address of CPU access ibus when authentication fail. + 0 + 32 + read-only + + + + + CACHE_MMU_FAULT_CONTENT + ******* Description *********** + 0x120 + 0x20 + + + CACHE_MMU_FAULT_CONTENT + The bits are used to indicate the content of mmu entry which cause mmu fault.. + 0 + 16 + read-only + + + CACHE_MMU_FAULT_CODE + The right-most 3 bits are used to indicate the operations which cause mmu fault occurrence. 0: default, 1: cpu miss, 2: preload miss, 3: writeback, 4: cpu miss evict recovery address, 5: load miss evict recovery address, 6: external dma tx, 7: external dma rx. The most significant bit is used to indicate this operation occurs in which one icache. + 16 + 4 + read-only + + + + + CACHE_MMU_FAULT_VADDR + ******* Description *********** + 0x124 + 0x20 + + + CACHE_MMU_FAULT_VADDR + The bits are used to indicate the virtual address which cause mmu fault.. + 0 + 32 + read-only + + + + + CACHE_WRAP_AROUND_CTRL + ******* Description *********** + 0x128 + 0x20 + + + CACHE_FLASH_WRAP_AROUND + The bit is used to enable wrap around mode when read data from flash. + 0 + 1 + read-write + + + CACHE_SRAM_RD_WRAP_AROUND + The bit is used to enable wrap around mode when read data from spiram. + 1 + 1 + read-write + + + + + CACHE_MMU_POWER_CTRL + ******* Description *********** + 0x12C + 0x20 + 0x00000005 + + + CACHE_MMU_MEM_FORCE_ON + The bit is used to enable clock gating to save power when access mmu memory, 0: enable, 1: disable + 0 + 1 + read-write + + + CACHE_MMU_MEM_FORCE_PD + The bit is used to power mmu memory down, 0: follow_rtc_lslp_pd, 1: power down + 1 + 1 + read-write + + + CACHE_MMU_MEM_FORCE_PU + The bit is used to power mmu memory down, 0: follow_rtc_lslp_pd, 1: power up + 2 + 1 + read-write + + + + + CACHE_STATE + ******* Description *********** + 0x130 + 0x20 + + + ICACHE_STATE + The bit is used to indicate whether icache main fsm is in idle state or not. 1: in idle state, 0: not in idle state + 0 + 12 + read-only + + + DCACHE_STATE + The bit is used to indicate whether dcache main fsm is in idle state or not. 1: in idle state, 0: not in idle state + 12 + 12 + read-only + + + + + CACHE_ENCRYPT_DECRYPT_RECORD_DISABLE + ******* Description *********** + 0x134 + 0x20 + + + RECORD_DISABLE_DB_ENCRYPT + Reserved + 0 + 1 + read-write + + + RECORD_DISABLE_G0CB_DECRYPT + Reserved + 1 + 1 + read-write + + + + + CACHE_ENCRYPT_DECRYPT_CLK_FORCE_ON + ******* Description *********** + 0x138 + 0x20 + 0x00000007 + + + CLK_FORCE_ON_MANUAL_CRYPT + The bit is used to close clock gating of manual crypt clock. 1: close gating, 0: open clock gating. + 0 + 1 + read-write + + + CLK_FORCE_ON_AUTO_CRYPT + The bit is used to close clock gating of automatic crypt clock. 1: close gating, 0: open clock gating. + 1 + 1 + read-write + + + CLK_FORCE_ON_CRYPT + The bit is used to close clock gating of external memory encrypt and decrypt clock. 1: close gating, 0: open clock gating. + 2 + 1 + read-write + + + + + CACHE_BRIDGE_ARBITER_CTRL + ******* Description *********** + 0x13C + 0x20 + + + ALLOC_WB_HOLD_ARBITER + Reserved + 0 + 1 + read-write + + + + + CACHE_PRELOAD_INT_CTRL + ******* Description *********** + 0x140 + 0x20 + + + ICACHE_PRELOAD_INT_ST + The bit is used to indicate the interrupt by icache pre-load done. + 0 + 1 + read-only + + + ICACHE_PRELOAD_INT_ENA + The bit is used to enable the interrupt by icache pre-load done. + 1 + 1 + read-write + + + ICACHE_PRELOAD_INT_CLR + The bit is used to clear the interrupt by icache pre-load done. + 2 + 1 + write-only + + + DCACHE_PRELOAD_INT_ST + The bit is used to indicate the interrupt by dcache pre-load done. + 3 + 1 + read-only + + + DCACHE_PRELOAD_INT_ENA + The bit is used to enable the interrupt by dcache pre-load done. + 4 + 1 + read-write + + + DCACHE_PRELOAD_INT_CLR + The bit is used to clear the interrupt by dcache pre-load done. + 5 + 1 + write-only + + + + + CACHE_SYNC_INT_CTRL + ******* Description *********** + 0x144 + 0x20 + + + ICACHE_SYNC_INT_ST + The bit is used to indicate the interrupt by icache sync done. + 0 + 1 + read-only + + + ICACHE_SYNC_INT_ENA + The bit is used to enable the interrupt by icache sync done. + 1 + 1 + read-write + + + ICACHE_SYNC_INT_CLR + The bit is used to clear the interrupt by icache sync done. + 2 + 1 + write-only + + + DCACHE_SYNC_INT_ST + The bit is used to indicate the interrupt by dcache sync done. + 3 + 1 + read-only + + + DCACHE_SYNC_INT_ENA + The bit is used to enable the interrupt by dcache sync done. + 4 + 1 + read-write + + + DCACHE_SYNC_INT_CLR + The bit is used to clear the interrupt by dcache sync done. + 5 + 1 + write-only + + + + + CACHE_MMU_OWNER + ******* Description *********** + 0x148 + 0x20 + + + CACHE_MMU_OWNER + The bits are used to specify the owner of MMU.bit0: icache, bit1: dcache, bit2: dma, bit3: reserved. + 0 + 24 + read-write + + + + + CACHE_CONF_MISC + ******* Description *********** + 0x14C + 0x20 + 0x00000007 + + + CACHE_IGNORE_PRELOAD_MMU_ENTRY_FAULT + The bit is used to disable checking mmu entry fault by preload operation. + 0 + 1 + read-write + + + CACHE_IGNORE_SYNC_MMU_ENTRY_FAULT + The bit is used to disable checking mmu entry fault by sync operation. + 1 + 1 + read-write + + + CACHE_TRACE_ENA + The bit is used to enable cache trace function. + 2 + 1 + read-write + + + + + DCACHE_FREEZE + ******* Description *********** + 0x150 + 0x20 + 0x00000004 + + + ENA + The bit is used to enable dcache freeze mode + 0 + 1 + read-write + + + MODE + The bit is used to configure freeze mode, 0: assert busy if CPU miss 1: assert hit if CPU miss + 1 + 1 + read-write + + + DONE + The bit is used to indicate dcache freeze success + 2 + 1 + read-only + + + + + ICACHE_FREEZE + ******* Description *********** + 0x154 + 0x20 + 0x00000004 + + + ENA + The bit is used to enable icache freeze mode + 0 + 1 + read-write + + + MODE + The bit is used to configure freeze mode, 0: assert busy if CPU miss 1: assert hit if CPU miss + 1 + 1 + read-write + + + DONE + The bit is used to indicate icache freeze success + 2 + 1 + read-only + + + + + ICACHE_ATOMIC_OPERATE_ENA + ******* Description *********** + 0x158 + 0x20 + 0x00000001 + + + ICACHE_ATOMIC_OPERATE_ENA + The bit is used to activate icache atomic operation protection. In this case, sync/lock operation can not interrupt miss-work. This feature does not work during invalidateAll operation. + 0 + 1 + read-write + + + + + DCACHE_ATOMIC_OPERATE_ENA + ******* Description *********** + 0x15C + 0x20 + 0x00000001 + + + DCACHE_ATOMIC_OPERATE_ENA + The bit is used to activate dcache atomic operation protection. In this case, sync/lock/occupy operation can not interrupt miss-work. This feature does not work during invalidateAll operation. + 0 + 1 + read-write + + + + + CACHE_REQUEST + ******* Description *********** + 0x160 + 0x20 + + + BYPASS + The bit is used to disable request recording which could cause performance issue + 0 + 1 + read-write + + + + + CLOCK_GATE + ******* Description *********** + 0x164 + 0x20 + 0x00000001 + + + CLK_EN + Reserved + 0 + 1 + read-write + + + + + CACHE_TAG_OBJECT_CTRL + ******* Description *********** + 0x180 + 0x20 + + + ICACHE_TAG_OBJECT + Set this bit to set icache tag memory as object. This bit should be onehot with the others fields inside this register. + 0 + 1 + read-write + + + DCACHE_TAG_OBJECT + Set this bit to set dcache tag memory as object. This bit should be onehot with the others fields inside this register. + 1 + 1 + read-write + + + + + CACHE_TAG_WAY_OBJECT + ******* Description *********** + 0x184 + 0x20 + + + CACHE_TAG_WAY_OBJECT + Set this bits to select which way of the tag-object will be accessed. 0: way0, 1: way1, 2: way2, 3: way3, .., 7: way7. + 0 + 3 + read-write + + + + + CACHE_VADDR + ******* Description *********** + 0x188 + 0x20 + + + CACHE_VADDR + Those bits stores the virtual address which will decide where inside the specified tag memory object will be accessed. + 0 + 32 + read-write + + + + + CACHE_TAG_CONTENT + ******* Description *********** + 0x18C + 0x20 + + + CACHE_TAG_CONTENT + This is a constant place where we can write data to or read data from the tag memory on the specified cache. + 0 + 32 + read-write + + + + + DATE + ******* Description *********** + 0x3FC + 0x20 + 0x02012310 + + + DATE + version information. + 0 + 28 + read-write + + + + + + + GPIO + General Purpose Input/Output + GPIO + 0x60004000 + + 0x0 + 0x634 + registers + + + GPIO + 16 + + + GPIO_NMI + 17 + + + + BT_SELECT + GPIO bit select register + 0x0 + 0x20 + + + BT_SEL + GPIO bit select register + 0 + 32 + read-write + + + + + OUT + GPIO output register for GPIO0-31 + 0x4 + 0x20 + + + DATA_ORIG + GPIO output register for GPIO0-31 + 0 + 32 + + + + + OUT_W1TS + GPIO output set register for GPIO0-31 + 0x8 + 0x20 + + + OUT_W1TS + GPIO output set register for GPIO0-31 + 0 + 32 + write-only + + + + + OUT_W1TC + GPIO output clear register for GPIO0-31 + 0xC + 0x20 + + + OUT_W1TC + GPIO output clear register for GPIO0-31 + 0 + 32 + write-only + + + + + OUT1 + GPIO output register for GPIO32-53 + 0x10 + 0x20 + + + DATA_ORIG + GPIO output register for GPIO32-53 + 0 + 22 + + + + + OUT1_W1TS + GPIO output set register for GPIO32-53 + 0x14 + 0x20 + + + OUT1_W1TS + GPIO output set register for GPIO32-53 + 0 + 22 + write-only + + + + + OUT1_W1TC + GPIO output clear register for GPIO32-53 + 0x18 + 0x20 + + + OUT1_W1TC + GPIO output clear register for GPIO32-53 + 0 + 22 + write-only + + + + + SDIO_SELECT + GPIO sdio select register + 0x1C + 0x20 + + + SDIO_SEL + GPIO sdio select register + 0 + 8 + read-write + + + + + ENABLE + GPIO output enable register for GPIO0-31 + 0x20 + 0x20 + + + DATA + GPIO output enable register for GPIO0-31 + 0 + 32 + read-write + + + + + ENABLE_W1TS + GPIO output enable set register for GPIO0-31 + 0x24 + 0x20 + + + ENABLE_W1TS + GPIO output enable set register for GPIO0-31 + 0 + 32 + write-only + + + + + ENABLE_W1TC + GPIO output enable clear register for GPIO0-31 + 0x28 + 0x20 + + + ENABLE_W1TC + GPIO output enable clear register for GPIO0-31 + 0 + 32 + write-only + + + + + ENABLE1 + GPIO output enable register for GPIO32-53 + 0x2C + 0x20 + + + DATA + GPIO output enable register for GPIO32-53 + 0 + 22 + read-write + + + + + ENABLE1_W1TS + GPIO output enable set register for GPIO32-53 + 0x30 + 0x20 + + + ENABLE1_W1TS + GPIO output enable set register for GPIO32-53 + 0 + 22 + write-only + + + + + ENABLE1_W1TC + GPIO output enable clear register for GPIO32-53 + 0x34 + 0x20 + + + ENABLE1_W1TC + GPIO output enable clear register for GPIO32-53 + 0 + 22 + write-only + + + + + STRAP + pad strapping register + 0x38 + 0x20 + + + STRAPPING + pad strapping register + 0 + 16 + read-only + + + + + IN + GPIO input register for GPIO0-31 + 0x3C + 0x20 + + + DATA_NEXT + GPIO input register for GPIO0-31 + 0 + 32 + read-write + + + + + IN1 + GPIO input register for GPIO32-53 + 0x40 + 0x20 + + + DATA_NEXT + GPIO input register for GPIO32-53 + 0 + 22 + read-write + + + + + STATUS + GPIO interrupt status register for GPIO0-31 + 0x44 + 0x20 + + + INTERRUPT + GPIO interrupt status register for GPIO0-31 + 0 + 32 + read-write + + + + + STATUS_W1TS + GPIO interrupt status set register for GPIO0-31 + 0x48 + 0x20 + + + STATUS_W1TS + GPIO interrupt status set register for GPIO0-31 + 0 + 32 + write-only + + + + + STATUS_W1TC + GPIO interrupt status clear register for GPIO0-31 + 0x4C + 0x20 + + + STATUS_W1TC + GPIO interrupt status clear register for GPIO0-31 + 0 + 32 + write-only + + + + + STATUS1 + GPIO interrupt status register for GPIO32-53 + 0x50 + 0x20 + + + INTERRUPT + GPIO interrupt status register for GPIO32-53 + 0 + 22 + read-write + + + + + STATUS1_W1TS + GPIO interrupt status set register for GPIO32-53 + 0x54 + 0x20 + + + STATUS1_W1TS + GPIO interrupt status set register for GPIO32-53 + 0 + 22 + write-only + + + + + STATUS1_W1TC + GPIO interrupt status clear register for GPIO32-53 + 0x58 + 0x20 + + + STATUS1_W1TC + GPIO interrupt status clear register for GPIO32-53 + 0 + 22 + write-only + + + + + PCPU_INT + GPIO PRO_CPU interrupt status register for GPIO0-31 + 0x5C + 0x20 + + + PROCPU_INT + GPIO PRO_CPU interrupt status register for GPIO0-31 + 0 + 32 + read-only + + + + + PCPU_NMI_INT + GPIO PRO_CPU(not shielded) interrupt status register for GPIO0-31 + 0x60 + 0x20 + + + PROCPU_NMI_INT + GPIO PRO_CPU(not shielded) interrupt status register for GPIO0-31 + 0 + 32 + read-only + + + + + CPUSDIO_INT + GPIO CPUSDIO interrupt status register for GPIO0-31 + 0x64 + 0x20 + + + SDIO_INT + GPIO CPUSDIO interrupt status register for GPIO0-31 + 0 + 32 + read-only + + + + + PCPU_INT1 + GPIO PRO_CPU interrupt status register for GPIO32-53 + 0x68 + 0x20 + + + PROCPU_INT1 + GPIO PRO_CPU interrupt status register for GPIO32-53 + 0 + 22 + read-only + + + + + PCPU_NMI_INT1 + GPIO PRO_CPU(not shielded) interrupt status register for GPIO32-53 + 0x6C + 0x20 + + + PROCPU_NMI_INT1 + GPIO PRO_CPU(not shielded) interrupt status register for GPIO32-53 + 0 + 22 + read-only + + + + + CPUSDIO_INT1 + GPIO CPUSDIO interrupt status register for GPIO32-53 + 0x70 + 0x20 + + + SDIO_INT1 + GPIO CPUSDIO interrupt status register for GPIO32-53 + 0 + 22 + read-only + + + + + 54 + 0x4 + 0-53 + PIN%s + GPIO pin configuration register + 0x74 + 0x20 + + + SYNC2_BYPASS + set GPIO input_sync2 signal mode. 0:disable. 1:trigger at negedge. 2or3:trigger at posedge. + 0 + 2 + read-write + + + PAD_DRIVER + set this bit to select pad driver. 1:open-drain. 0:normal. + 2 + 1 + read-write + + + SYNC1_BYPASS + set GPIO input_sync1 signal mode. 0:disable. 1:trigger at negedge. 2or3:trigger at posedge. + 3 + 2 + read-write + + + INT_TYPE + set this value to choose interrupt mode. 0:disable GPIO interrupt. 1:trigger at posedge. 2:trigger at negedge. 3:trigger at any edge. 4:valid at low level. 5:valid at high level + 7 + 3 + read-write + + + WAKEUP_ENABLE + set this bit to enable GPIO wakeup.(can only wakeup CPU from Light-sleep Mode) + 10 + 1 + read-write + + + CONFIG + reserved + 11 + 2 + read-write + + + INT_ENA + set bit 13 to enable CPU interrupt. set bit 14 to enable CPU(not shielded) interrupt. + 13 + 5 + read-write + + + + + STATUS_NEXT + GPIO interrupt source register for GPIO0-31 + 0x14C + 0x20 + + + STATUS_INTERRUPT_NEXT + GPIO interrupt source register for GPIO0-31 + 0 + 32 + read-only + + + + + STATUS_NEXT1 + GPIO interrupt source register for GPIO32-53 + 0x150 + 0x20 + + + STATUS_INTERRUPT_NEXT1 + GPIO interrupt source register for GPIO32-53 + 0 + 22 + read-only + + + + + 256 + 0x4 + 0-255 + FUNC%s_IN_SEL_CFG + GPIO input function configuration register + 0x154 + 0x20 + + + IN_SEL + set this value: s=0-53: connect GPIO[s] to this port. s=0x38: set this port always high level. s=0x3C: set this port always low level. + 0 + 6 + read-write + + + IN_INV_SEL + set this bit to invert input signal. 1:invert. 0:not invert. + 6 + 1 + read-write + + + SEL + set this bit to bypass GPIO. 1:do not bypass GPIO. 0:bypass GPIO. + 7 + 1 + read-write + + + + + 54 + 0x4 + 0-53 + FUNC%s_OUT_SEL_CFG + GPIO output function select register + 0x554 + 0x20 + 0x00000100 + + + OUT_SEL + The value of the bits: 0<=s<=256. Set the value to select output signal. s=0-255: output of GPIO[n] equals input of peripheral[s]. s=256: output of GPIO[n] equals GPIO_OUT_REG[n]. + 0 + 9 + read-write + + + INV_SEL + set this bit to invert output signal.1:invert.0:not invert. + 9 + 1 + read-write + + + OEN_SEL + set this bit to select output enable signal.1:use GPIO_ENABLE_REG[n] as output enable signal.0:use peripheral output enable signal. + 10 + 1 + read-write + + + OEN_INV_SEL + set this bit to invert output enable signal.1:invert.0:not invert. + 11 + 1 + read-write + + + + + CLOCK_GATE + GPIO clock gate register + 0x62C + 0x20 + 0x00000001 + + + CLK_EN + set this bit to enable GPIO clock gate + 0 + 1 + read-write + + + + + REG_DATE + GPIO version register + 0x6FC + 0x20 + 0x01907040 + + + REG_DATE + version register + 0 + 28 + read-write + + + + + + + GPIOSD + Sigma-Delta Modulation + GPIOSD + 0x60004F00 + + 0x0 + 0x2C + registers + + + + 8 + 0x4 + SIGMADELTA%s + Duty Cycle Configure Register of SDM%s + 0x0 + 0x20 + 0x0000FF00 + + + SD_IN + This field is used to configure the duty cycle of sigma delta modulation output. + 0 + 8 + read-write + + + SD_PRESCALE + This field is used to set a divider value to divide APB clock. + 8 + 8 + read-write + + + + + SIGMADELTA_CG + Clock Gating Configure Register + 0x20 + 0x20 + + + CLK_EN + Clock enable bit of configuration registers for sigma delta modulation. + 31 + 1 + read-write + + + + + SIGMADELTA_MISC + MISC Register + 0x24 + 0x20 + + + FUNCTION_CLK_EN + Clock enable bit of sigma delta modulation. + 30 + 1 + read-write + + + SPI_SWAP + Reserved. + 31 + 1 + read-write + + + + + SIGMADELTA_VERSION + Version Control Register + 0x28 + 0x20 + 0x01802260 + + + GPIO_SD_DATE + Version control register. + 0 + 28 + read-write + + + + + + + HMAC + HMAC (Hash-based Message Authentication Code) Accelerator + HMAC + 0x6003E000 + + 0x0 + 0xA4 + registers + + + + SET_START + Process control register 0. + 0x40 + 0x20 + + + SET_START + Start hmac operation. + 0 + 1 + write-only + + + + + SET_PARA_PURPOSE + Configure purpose. + 0x44 + 0x20 + + + PURPOSE_SET + Set hmac parameter purpose. + 0 + 4 + write-only + + + + + SET_PARA_KEY + Configure key. + 0x48 + 0x20 + + + KEY_SET + Set hmac parameter key. + 0 + 3 + write-only + + + + + SET_PARA_FINISH + Finish initial configuration. + 0x4C + 0x20 + + + SET_PARA_END + Finish hmac configuration. + 0 + 1 + write-only + + + + + SET_MESSAGE_ONE + Process control register 1. + 0x50 + 0x20 + + + SET_TEXT_ONE + Call SHA to calculate one message block. + 0 + 1 + write-only + + + + + SET_MESSAGE_ING + Process control register 2. + 0x54 + 0x20 + + + SET_TEXT_ING + Continue typical hmac. + 0 + 1 + write-only + + + + + SET_MESSAGE_END + Process control register 3. + 0x58 + 0x20 + + + SET_TEXT_END + Start hardware padding. + 0 + 1 + write-only + + + + + SET_RESULT_FINISH + Process control register 4. + 0x5C + 0x20 + + + SET_RESULT_END + After read result from upstream, then let hmac back to idle. + 0 + 1 + write-only + + + + + SET_INVALIDATE_JTAG + Invalidate register 0. + 0x60 + 0x20 + + + SET_INVALIDATE_JTAG + Clear result from hmac downstream JTAG. + 0 + 1 + write-only + + + + + SET_INVALIDATE_DS + Invalidate register 1. + 0x64 + 0x20 + + + SET_INVALIDATE_DS + Clear result from hmac downstream DS. + 0 + 1 + write-only + + + + + QUERY_ERROR + Error register. + 0x68 + 0x20 + + + QUREY_CHECK + Hmac configuration state. 0: key are agree with purpose. 1: error + 0 + 1 + read-only + + + + + QUERY_BUSY + Busy register. + 0x6C + 0x20 + + + BUSY_STATE + Hmac state. 1'b0: idle. 1'b1: busy + 0 + 1 + read-only + + + + + 64 + 0x1 + WR_MESSAGE_MEM[%s] + Message block memory. + 0x80 + 0x8 + + + 32 + 0x1 + RD_RESULT_MEM[%s] + Result from upstream. + 0xC0 + 0x8 + + + SET_MESSAGE_PAD + Process control register 5. + 0xF0 + 0x20 + + + SET_TEXT_PAD + Start software padding. + 0 + 1 + write-only + + + + + ONE_BLOCK + Process control register 6. + 0xF4 + 0x20 + + + SET_ONE_BLOCK + Don't have to do padding. + 0 + 1 + write-only + + + + + SOFT_JTAG_CTRL + Jtag register 0. + 0xF8 + 0x20 + + + SOFT_JTAG_CTRL + Turn on JTAG verification. + 0 + 1 + write-only + + + + + WR_JTAG + Jtag register 1. + 0xFC + 0x20 + + + WR_JTAG + 32-bit of key to be compared. + 0 + 32 + write-only + + + + + DATE + Date register. + 0x1FC + 0x20 + 0x02101070 + + + DATE + Hmac date information/ hmac version information. + 0 + 28 + read-write + + + + + + + I2C0 + I2C (Inter-Integrated Circuit) Controller + I2C + 0x60013000 + + 0x0 + 0x90 + registers + + + I2C_MST + 11 + + + I2C_EXT0 + 42 + + + + SCL_LOW_PERIOD + Configures the low level width of the SCL +Clock + 0x0 + 0x20 + + + SCL_LOW_PERIOD + This register is used to configure for how long SCL remains low in master mode, in I2C module clock cycles. + 0 + 9 + read-write + + + + + CTR + Transmission setting + 0x4 + 0x20 + 0x0000020B + + + SDA_FORCE_OUT + 0: direct output; 1: open drain output. + 0 + 1 + read-write + + + SCL_FORCE_OUT + 0: direct output; 1: open drain output. + 1 + 1 + read-write + + + SAMPLE_SCL_LEVEL + This register is used to select the sample mode. +1: sample SDA data on the SCL low level. +0: sample SDA data on the SCL high level. + 2 + 1 + read-write + + + RX_FULL_ACK_LEVEL + This register is used to configure the ACK value that need to sent by master when the rx_fifo_cnt has reached the threshold. + 3 + 1 + read-write + + + MS_MODE + Set this bit to configure the module as an I2C Master. Clear this bit to configure the +module as an I2C Slave. + 4 + 1 + read-write + + + TRANS_START + Set this bit to start sending the data in txfifo. + 5 + 1 + write-only + + + TX_LSB_FIRST + This bit is used to control the sending mode for data needing to be sent. +1: send data from the least significant bit; +0: send data from the most significant bit. + 6 + 1 + read-write + + + RX_LSB_FIRST + This bit is used to control the storage mode for received data. +1: receive data from the least significant bit; +0: receive data from the most significant bit. + 7 + 1 + read-write + + + CLK_EN + Reserved + 8 + 1 + read-write + + + ARBITRATION_EN + This is the enable bit for arbitration_lost. + 9 + 1 + read-write + + + FSM_RST + This register is used to reset the scl FMS. + 10 + 1 + write-only + + + CONF_UPGATE + synchronization bit + 11 + 1 + write-only + + + SLV_TX_AUTO_START_EN + This is the enable bit for slave to send data automatically + 12 + 1 + read-write + + + ADDR_10BIT_RW_CHECK_EN + This is the enable bit to check if the r/w bit of 10bit addressing consists with I2C protocol + 13 + 1 + read-write + + + ADDR_BROADCASTING_EN + This is the enable bit to support the 7bit general call function. + 14 + 1 + read-write + + + + + SR + Describe I2C work status. + 0x8 + 0x20 + 0x0000C000 + + + RESP_REC + The received ACK value in master mode or slave mode. 0: ACK, 1: NACK. + 0 + 1 + read-only + + + SLAVE_RW + When in slave mode, 1: master reads from slave; 0: master writes to slave. + 1 + 1 + read-only + + + ARB_LOST + When the I2C controller loses control of SCL line, this register changes to 1. + 3 + 1 + read-only + + + BUS_BUSY + 1: the I2C bus is busy transferring data; 0: the I2C bus is in idle state. + 4 + 1 + read-only + + + SLAVE_ADDRESSED + When configured as an I2C Slave, and the address sent by the master is +equal to the address of the slave, then this bit will be of high level. + 5 + 1 + read-only + + + RXFIFO_CNT + This field represents the amount of data needed to be sent. + 8 + 6 + read-only + + + STRETCH_CAUSE + The cause of stretching SCL low in slave mode. 0: stretching SCL low at the beginning of I2C read data state. 1: stretching SCL low when I2C Tx FIFO is empty in slave mode. 2: stretching SCL low when I2C Rx FIFO is full in slave mode. + 14 + 2 + read-only + + + TXFIFO_CNT + This field stores the amount of received data in RAM. + 18 + 6 + read-only + + + SCL_MAIN_STATE_LAST + This field indicates the states of the I2C module state machine. +0: Idle; 1: Address shift; 2: ACK address; 3: Rx data; 4: Tx data; 5: Send ACK; 6: Wait ACK + 24 + 3 + read-only + + + SCL_STATE_LAST + This field indicates the states of the state machine used to produce SCL. +0: Idle; 1: Start; 2: Negative edge; 3: Low; 4: Positive edge; 5: High; 6: Stop + 28 + 3 + read-only + + + + + TO + Setting time out control for receiving data. + 0xC + 0x20 + 0x00000010 + + + TIME_OUT_VALUE + This register is used to configure the timeout for receiving a data bit in APB +clock cycles. + 0 + 5 + read-write + + + TIME_OUT_EN + This is the enable bit for time out control. + 5 + 1 + read-write + + + + + SLAVE_ADDR + Local slave address setting + 0x10 + 0x20 + + + SLAVE_ADDR + When configured as an I2C Slave, this field is used to configure the slave address. + 0 + 15 + read-write + + + ADDR_10BIT_EN + This field is used to enable the slave 10-bit addressing mode in master mode. + 31 + 1 + read-write + + + + + FIFO_ST + FIFO status register. + 0x14 + 0x20 + + + RXFIFO_RADDR + This is the offset address of the APB reading from rxfifo + 0 + 5 + read-only + + + RXFIFO_WADDR + This is the offset address of i2c module receiving data and writing to rxfifo. + 5 + 5 + read-only + + + TXFIFO_RADDR + This is the offset address of i2c module reading from txfifo. + 10 + 5 + read-only + + + TXFIFO_WADDR + This is the offset address of APB bus writing to txfifo. + 15 + 5 + read-only + + + SLAVE_RW_POINT + The received data in I2C slave mode. + 22 + 8 + read-only + + + + + FIFO_CONF + FIFO configuration register. + 0x18 + 0x20 + 0x0000408B + + + RXFIFO_WM_THRHD + The water mark threshold of rx FIFO in nonfifo access mode. When reg_reg_fifo_prt_en is 1 and rx FIFO counter is bigger than reg_rxfifo_wm_thrhd[4:0], reg_rxfifo_wm_int_raw bit will be valid. + 0 + 5 + read-write + + + TXFIFO_WM_THRHD + The water mark threshold of tx FIFO in nonfifo access mode. When reg_reg_fifo_prt_en is 1 and tx FIFO counter is smaller than reg_txfifo_wm_thrhd[4:0], reg_txfifo_wm_int_raw bit will be valid. + 5 + 5 + read-write + + + NONFIFO_EN + Set this bit to enable APB nonfifo access. + 10 + 1 + read-write + + + FIFO_ADDR_CFG_EN + When this bit is set to 1, the byte received after the I2C address byte represents the offset address in the I2C Slave RAM. + 11 + 1 + read-write + + + RX_FIFO_RST + Set this bit to reset rx-fifo. + 12 + 1 + read-write + + + TX_FIFO_RST + Set this bit to reset tx-fifo. + 13 + 1 + read-write + + + FIFO_PRT_EN + The control enable bit of FIFO pointer in non-fifo access mode. This bit controls the valid bits and the interrupts of tx/rx_fifo overflow, underflow, full and empty. + 14 + 1 + read-write + + + + + DATA + Rx FIFO read data. + 0x1C + 0x20 + + + FIFO_RDATA + The value of rx FIFO read data. + 0 + 8 + read-write + + + + + INT_RAW + Raw interrupt status + 0x20 + 0x20 + 0x00000002 + + + RXFIFO_WM_INT_RAW + The raw interrupt bit for I2C_RXFIFO_WM_INT interrupt. + 0 + 1 + read-only + + + TXFIFO_WM_INT_RAW + The raw interrupt bit for I2C_TXFIFO_WM_INT interrupt. + 1 + 1 + read-only + + + RXFIFO_OVF_INT_RAW + The raw interrupt bit for I2C_RXFIFO_OVF_INT interrupt. + 2 + 1 + read-only + + + END_DETECT_INT_RAW + The raw interrupt bit for the I2C_END_DETECT_INT interrupt. + 3 + 1 + read-only + + + BYTE_TRANS_DONE_INT_RAW + The raw interrupt bit for the I2C_END_DETECT_INT interrupt. + 4 + 1 + read-only + + + ARBITRATION_LOST_INT_RAW + The raw interrupt bit for the I2C_ARBITRATION_LOST_INT interrupt. + 5 + 1 + read-only + + + MST_TXFIFO_UDF_INT_RAW + The raw interrupt bit for I2C_TRANS_COMPLETE_INT interrupt. + 6 + 1 + read-only + + + TRANS_COMPLETE_INT_RAW + The raw interrupt bit for the I2C_TRANS_COMPLETE_INT interrupt. + 7 + 1 + read-only + + + TIME_OUT_INT_RAW + The raw interrupt bit for the I2C_TIME_OUT_INT interrupt. + 8 + 1 + read-only + + + TRANS_START_INT_RAW + The raw interrupt bit for the I2C_TRANS_START_INT interrupt. + 9 + 1 + read-only + + + NACK_INT_RAW + The raw interrupt bit for I2C_SLAVE_STRETCH_INT interrupt. + 10 + 1 + read-only + + + TXFIFO_OVF_INT_RAW + The raw interrupt bit for I2C_TXFIFO_OVF_INT interrupt. + 11 + 1 + read-only + + + RXFIFO_UDF_INT_RAW + The raw interrupt bit for I2C_RXFIFO_UDF_INT interrupt. + 12 + 1 + read-only + + + SCL_ST_TO_INT_RAW + The raw interrupt bit for I2C_SCL_ST_TO_INT interrupt. + 13 + 1 + read-only + + + SCL_MAIN_ST_TO_INT_RAW + The raw interrupt bit for I2C_SCL_MAIN_ST_TO_INT interrupt. + 14 + 1 + read-only + + + DET_START_INT_RAW + The raw interrupt bit for I2C_DET_START_INT interrupt. + 15 + 1 + read-only + + + SLAVE_STRETCH_INT_RAW + The raw interrupt bit for I2C_SLAVE_STRETCH_INT interrupt. + 16 + 1 + read-only + + + GENERAL_CALL_INT_RAW + The raw interrupt bit for I2C_GENARAL_CALL_INT interrupt. + 17 + 1 + read-only + + + + + INT_CLR + Interrupt clear bits + 0x24 + 0x20 + + + RXFIFO_WM_INT_CLR + Set this bit to clear I2C_RXFIFO_WM_INT interrupt. + 0 + 1 + write-only + + + TXFIFO_WM_INT_CLR + Set this bit to clear I2C_TXFIFO_WM_INT interrupt. + 1 + 1 + write-only + + + RXFIFO_OVF_INT_CLR + Set this bit to clear I2C_RXFIFO_OVF_INT interrupt. + 2 + 1 + write-only + + + END_DETECT_INT_CLR + Set this bit to clear the I2C_END_DETECT_INT interrupt. + 3 + 1 + write-only + + + BYTE_TRANS_DONE_INT_CLR + Set this bit to clear the I2C_END_DETECT_INT interrupt. + 4 + 1 + write-only + + + ARBITRATION_LOST_INT_CLR + Set this bit to clear the I2C_ARBITRATION_LOST_INT interrupt. + 5 + 1 + write-only + + + MST_TXFIFO_UDF_INT_CLR + Set this bit to clear I2C_TRANS_COMPLETE_INT interrupt. + 6 + 1 + write-only + + + TRANS_COMPLETE_INT_CLR + Set this bit to clear the I2C_TRANS_COMPLETE_INT interrupt. + 7 + 1 + write-only + + + TIME_OUT_INT_CLR + Set this bit to clear the I2C_TIME_OUT_INT interrupt. + 8 + 1 + write-only + + + TRANS_START_INT_CLR + Set this bit to clear the I2C_TRANS_START_INT interrupt. + 9 + 1 + write-only + + + NACK_INT_CLR + Set this bit to clear I2C_SLAVE_STRETCH_INT interrupt. + 10 + 1 + write-only + + + TXFIFO_OVF_INT_CLR + Set this bit to clear I2C_TXFIFO_OVF_INT interrupt. + 11 + 1 + write-only + + + RXFIFO_UDF_INT_CLR + Set this bit to clear I2C_RXFIFO_UDF_INT interrupt. + 12 + 1 + write-only + + + SCL_ST_TO_INT_CLR + Set this bit to clear I2C_SCL_ST_TO_INT interrupt. + 13 + 1 + write-only + + + SCL_MAIN_ST_TO_INT_CLR + Set this bit to clear I2C_SCL_MAIN_ST_TO_INT interrupt. + 14 + 1 + write-only + + + DET_START_INT_CLR + Set this bit to clear I2C_DET_START_INT interrupt. + 15 + 1 + write-only + + + SLAVE_STRETCH_INT_CLR + Set this bit to clear I2C_SLAVE_STRETCH_INT interrupt. + 16 + 1 + write-only + + + GENERAL_CALL_INT_CLR + Set this bit for I2C_GENARAL_CALL_INT interrupt. + 17 + 1 + write-only + + + + + INT_ENA + Interrupt enable bits + 0x28 + 0x20 + + + RXFIFO_WM_INT_ENA + The interrupt enable bit for I2C_RXFIFO_WM_INT interrupt. + 0 + 1 + read-write + + + TXFIFO_WM_INT_ENA + The interrupt enable bit for I2C_TXFIFO_WM_INT interrupt. + 1 + 1 + read-write + + + RXFIFO_OVF_INT_ENA + The interrupt enable bit for I2C_RXFIFO_OVF_INT interrupt. + 2 + 1 + read-write + + + END_DETECT_INT_ENA + The interrupt enable bit for the I2C_END_DETECT_INT interrupt. + 3 + 1 + read-write + + + BYTE_TRANS_DONE_INT_ENA + The interrupt enable bit for the I2C_END_DETECT_INT interrupt. + 4 + 1 + read-write + + + ARBITRATION_LOST_INT_ENA + The interrupt enable bit for the I2C_ARBITRATION_LOST_INT interrupt. + 5 + 1 + read-write + + + MST_TXFIFO_UDF_INT_ENA + The interrupt enable bit for I2C_TRANS_COMPLETE_INT interrupt. + 6 + 1 + read-write + + + TRANS_COMPLETE_INT_ENA + The interrupt enable bit for the I2C_TRANS_COMPLETE_INT interrupt. + 7 + 1 + read-write + + + TIME_OUT_INT_ENA + The interrupt enable bit for the I2C_TIME_OUT_INT interrupt. + 8 + 1 + read-write + + + TRANS_START_INT_ENA + The interrupt enable bit for the I2C_TRANS_START_INT interrupt. + 9 + 1 + read-write + + + NACK_INT_ENA + The interrupt enable bit for I2C_SLAVE_STRETCH_INT interrupt. + 10 + 1 + read-write + + + TXFIFO_OVF_INT_ENA + The interrupt enable bit for I2C_TXFIFO_OVF_INT interrupt. + 11 + 1 + read-write + + + RXFIFO_UDF_INT_ENA + The interrupt enable bit for I2C_RXFIFO_UDF_INT interrupt. + 12 + 1 + read-write + + + SCL_ST_TO_INT_ENA + The interrupt enable bit for I2C_SCL_ST_TO_INT interrupt. + 13 + 1 + read-write + + + SCL_MAIN_ST_TO_INT_ENA + The interrupt enable bit for I2C_SCL_MAIN_ST_TO_INT interrupt. + 14 + 1 + read-write + + + DET_START_INT_ENA + The interrupt enable bit for I2C_DET_START_INT interrupt. + 15 + 1 + read-write + + + SLAVE_STRETCH_INT_ENA + The interrupt enable bit for I2C_SLAVE_STRETCH_INT interrupt. + 16 + 1 + read-write + + + GENERAL_CALL_INT_ENA + The interrupt enable bit for I2C_GENARAL_CALL_INT interrupt. + 17 + 1 + read-write + + + + + INT_STATUS + Status of captured I2C communication events + 0x2C + 0x20 + + + RXFIFO_WM_INT_ST + The masked interrupt status bit for I2C_RXFIFO_WM_INT interrupt. + 0 + 1 + read-only + + + TXFIFO_WM_INT_ST + The masked interrupt status bit for I2C_TXFIFO_WM_INT interrupt. + 1 + 1 + read-only + + + RXFIFO_OVF_INT_ST + The masked interrupt status bit for I2C_RXFIFO_OVF_INT interrupt. + 2 + 1 + read-only + + + END_DETECT_INT_ST + The masked interrupt status bit for the I2C_END_DETECT_INT interrupt. + 3 + 1 + read-only + + + BYTE_TRANS_DONE_INT_ST + The masked interrupt status bit for the I2C_END_DETECT_INT interrupt. + 4 + 1 + read-only + + + ARBITRATION_LOST_INT_ST + The masked interrupt status bit for the I2C_ARBITRATION_LOST_INT interrupt. + 5 + 1 + read-only + + + MST_TXFIFO_UDF_INT_ST + The masked interrupt status bit for I2C_TRANS_COMPLETE_INT interrupt. + 6 + 1 + read-only + + + TRANS_COMPLETE_INT_ST + The masked interrupt status bit for the I2C_TRANS_COMPLETE_INT interrupt. + 7 + 1 + read-only + + + TIME_OUT_INT_ST + The masked interrupt status bit for the I2C_TIME_OUT_INT interrupt. + 8 + 1 + read-only + + + TRANS_START_INT_ST + The masked interrupt status bit for the I2C_TRANS_START_INT interrupt. + 9 + 1 + read-only + + + NACK_INT_ST + The masked interrupt status bit for I2C_SLAVE_STRETCH_INT interrupt. + 10 + 1 + read-only + + + TXFIFO_OVF_INT_ST + The masked interrupt status bit for I2C_TXFIFO_OVF_INT interrupt. + 11 + 1 + read-only + + + RXFIFO_UDF_INT_ST + The masked interrupt status bit for I2C_RXFIFO_UDF_INT interrupt. + 12 + 1 + read-only + + + SCL_ST_TO_INT_ST + The masked interrupt status bit for I2C_SCL_ST_TO_INT interrupt. + 13 + 1 + read-only + + + SCL_MAIN_ST_TO_INT_ST + The masked interrupt status bit for I2C_SCL_MAIN_ST_TO_INT interrupt. + 14 + 1 + read-only + + + DET_START_INT_ST + The masked interrupt status bit for I2C_DET_START_INT interrupt. + 15 + 1 + read-only + + + SLAVE_STRETCH_INT_ST + The masked interrupt status bit for I2C_SLAVE_STRETCH_INT interrupt. + 16 + 1 + read-only + + + GENERAL_CALL_INT_ST + The masked interrupt status bit for I2C_GENARAL_CALL_INT interrupt. + 17 + 1 + read-only + + + + + SDA_HOLD + Configures the hold time after a negative SCL edge. + 0x30 + 0x20 + + + TIME + This register is used to configure the time to hold the data after the negative +edge of SCL, in I2C module clock cycles. + 0 + 9 + read-write + + + + + SDA_SAMPLE + Configures the sample time after a positive SCL edge. + 0x34 + 0x20 + + + TIME + This register is used to configure for how long SDA is sampled, in I2C module clock cycles. + 0 + 9 + read-write + + + + + SCL_HIGH_PERIOD + Configures the high level width of SCL + 0x38 + 0x20 + + + SCL_HIGH_PERIOD + This register is used to configure for how long SCL remains high in master mode, in I2C module clock cycles. + 0 + 9 + read-write + + + SCL_WAIT_HIGH_PERIOD + This register is used to configure for the SCL_FSM's waiting period for SCL high level in master mode, in I2C module clock cycles. + 9 + 7 + read-write + + + + + SCL_START_HOLD + Configures the delay between the SDA and SCL negative edge for a start condition + 0x40 + 0x20 + 0x00000008 + + + TIME + This register is used to configure the time between the negative edge +of SDA and the negative edge of SCL for a START condition, in I2C module clock cycles. + 0 + 9 + read-write + + + + + SCL_RSTART_SETUP + Configures the delay between the positive +edge of SCL and the negative edge of SDA + 0x44 + 0x20 + 0x00000008 + + + TIME + This register is used to configure the time between the positive +edge of SCL and the negative edge of SDA for a RESTART condition, in I2C module clock cycles. + 0 + 9 + read-write + + + + + SCL_STOP_HOLD + Configures the delay after the SCL clock +edge for a stop condition + 0x48 + 0x20 + 0x00000008 + + + TIME + This register is used to configure the delay after the STOP condition, +in I2C module clock cycles. + 0 + 9 + read-write + + + + + SCL_STOP_SETUP + Configures the delay between the SDA and +SCL positive edge for a stop condition + 0x4C + 0x20 + 0x00000008 + + + TIME + This register is used to configure the time between the positive edge +of SCL and the positive edge of SDA, in I2C module clock cycles. + 0 + 9 + read-write + + + + + FILTER_CFG + SCL and SDA filter configuration register + 0x50 + 0x20 + 0x00000300 + + + SCL_FILTER_THRES + When a pulse on the SCL input has smaller width than this register value +in I2C module clock cycles, the I2C controller will ignore that pulse. + 0 + 4 + read-write + + + SDA_FILTER_THRES + When a pulse on the SDA input has smaller width than this register value +in I2C module clock cycles, the I2C controller will ignore that pulse. + 4 + 4 + read-write + + + SCL_FILTER_EN + This is the filter enable bit for SCL. + 8 + 1 + read-write + + + SDA_FILTER_EN + This is the filter enable bit for SDA. + 9 + 1 + read-write + + + + + CLK_CONF + I2C CLK configuration register + 0x54 + 0x20 + 0x00200000 + + + SCLK_DIV_NUM + the integral part of the fractional divisor for i2c module + 0 + 8 + read-write + + + SCLK_DIV_A + the numerator of the fractional part of the fractional divisor for i2c module + 8 + 6 + read-write + + + SCLK_DIV_B + the denominator of the fractional part of the fractional divisor for i2c module + 14 + 6 + read-write + + + SCLK_SEL + The clock selection for i2c module:0-XTAL;1-CLK_8MHz. + 20 + 1 + read-write + + + SCLK_ACTIVE + The clock switch for i2c module + 21 + 1 + read-write + + + + + 8 + 0x4 + 0-7 + COMD%s + I2C command register %s + 0x58 + 0x20 + + + COMMAND + This is the content of command 0. It consists of three parts: +op_code is the command, 0: RSTART; 1: WRITE; 2: READ; 3: STOP; 4: END. +Byte_num represents the number of bytes that need to be sent or received. +ack_check_en, ack_exp and ack are used to control the ACK bit. See I2C cmd structure for more +Information. + 0 + 14 + read-write + + + COMMAND_DONE + When command 0 is done in I2C Master mode, this bit changes to high +level. + 31 + 1 + read-write + + + + + SCL_ST_TIME_OUT + SCL status time out register + 0x78 + 0x20 + 0x00000010 + + + SCL_ST_TO_I2C + The threshold value of SCL_FSM state unchanged period. It should be o more than 23 + 0 + 5 + read-write + + + + + SCL_MAIN_ST_TIME_OUT + SCL main status time out register + 0x7C + 0x20 + 0x00000010 + + + SCL_MAIN_ST_TO_I2C + The threshold value of SCL_MAIN_FSM state unchanged period.nIt should be o more than 23 + 0 + 5 + read-write + + + + + SCL_SP_CONF + Power configuration register + 0x80 + 0x20 + + + SCL_RST_SLV_EN + When I2C master is IDLE, set this bit to send out SCL pulses. The number of pulses equals to reg_scl_rst_slv_num[4:0]. + 0 + 1 + read-write + + + SCL_RST_SLV_NUM + Configure the pulses of SCL generated in I2C master mode. Valid when reg_scl_rst_slv_en is 1. + 1 + 5 + read-write + + + SCL_PD_EN + The power down enable bit for the I2C output SCL line. 1: Power down. 0: Not power down. Set reg_scl_force_out and reg_scl_pd_en to 1 to stretch SCL low. + 6 + 1 + read-write + + + SDA_PD_EN + The power down enable bit for the I2C output SDA line. 1: Power down. 0: Not power down. Set reg_sda_force_out and reg_sda_pd_en to 1 to stretch SDA low. + 7 + 1 + read-write + + + + + SCL_STRETCH_CONF + Set SCL stretch of I2C slave + 0x84 + 0x20 + + + STRETCH_PROTECT_NUM + Configure the period of I2C slave stretching SCL line. + 0 + 10 + read-write + + + SLAVE_SCL_STRETCH_EN + The enable bit for slave SCL stretch function. 1: Enable. 0: Disable. The SCL output line will be stretched low when reg_slave_scl_stretch_en is 1 and stretch event happens. The stretch cause can be seen in reg_stretch_cause. + 10 + 1 + read-write + + + SLAVE_SCL_STRETCH_CLR + Set this bit to clear the I2C slave SCL stretch function. + 11 + 1 + write-only + + + SLAVE_BYTE_ACK_CTL_EN + The enable bit for slave to control ACK level function. + 12 + 1 + read-write + + + SLAVE_BYTE_ACK_LVL + Set the ACK level when slave controlling ACK level function enables. + 13 + 1 + read-write + + + + + DATE + Version register + 0xF8 + 0x20 + 0x20070201 + + + DATE + This is the the version register. + 0 + 32 + read-write + + + + + TXFIFO_START_ADDR + I2C TXFIFO base address register + 0x100 + 0x20 + + + TXFIFO_START_ADDR + This is the I2C txfifo first address. + 0 + 32 + read-only + + + + + RXFIFO_START_ADDR + I2C RXFIFO base address register + 0x180 + 0x20 + + + RXFIFO_START_ADDR + This is the I2C rxfifo first address. + 0 + 32 + read-only + + + + + + + I2C1 + I2C (Inter-Integrated Circuit) Controller + 0x60027000 + + I2C_EXT1 + 43 + + + + I2S0 + I2S (Inter-IC Sound) Controller + I2S + 0x6000F000 + + 0x0 + 0x5C + registers + + + I2S0 + 25 + + + + INT_RAW + I2S interrupt raw register, valid in level. + 0xC + 0x20 + + + RX_DONE_INT_RAW + The raw interrupt status bit for the i2s_rx_done_int interrupt + 0 + 1 + read-only + + + TX_DONE_INT_RAW + The raw interrupt status bit for the i2s_tx_done_int interrupt + 1 + 1 + read-only + + + RX_HUNG_INT_RAW + The raw interrupt status bit for the i2s_rx_hung_int interrupt + 2 + 1 + read-only + + + TX_HUNG_INT_RAW + The raw interrupt status bit for the i2s_tx_hung_int interrupt + 3 + 1 + read-only + + + + + INT_ST + I2S interrupt status register. + 0x10 + 0x20 + + + RX_DONE_INT_ST + The masked interrupt status bit for the i2s_rx_done_int interrupt + 0 + 1 + read-only + + + TX_DONE_INT_ST + The masked interrupt status bit for the i2s_tx_done_int interrupt + 1 + 1 + read-only + + + RX_HUNG_INT_ST + The masked interrupt status bit for the i2s_rx_hung_int interrupt + 2 + 1 + read-only + + + TX_HUNG_INT_ST + The masked interrupt status bit for the i2s_tx_hung_int interrupt + 3 + 1 + read-only + + + + + INT_ENA + I2S interrupt enable register. + 0x14 + 0x20 + + + RX_DONE_INT_ENA + The interrupt enable bit for the i2s_rx_done_int interrupt + 0 + 1 + read-write + + + TX_DONE_INT_ENA + The interrupt enable bit for the i2s_tx_done_int interrupt + 1 + 1 + read-write + + + RX_HUNG_INT_ENA + The interrupt enable bit for the i2s_rx_hung_int interrupt + 2 + 1 + read-write + + + TX_HUNG_INT_ENA + The interrupt enable bit for the i2s_tx_hung_int interrupt + 3 + 1 + read-write + + + + + INT_CLR + I2S interrupt clear register. + 0x18 + 0x20 + + + RX_DONE_INT_CLR + Set this bit to clear the i2s_rx_done_int interrupt + 0 + 1 + write-only + + + TX_DONE_INT_CLR + Set this bit to clear the i2s_tx_done_int interrupt + 1 + 1 + write-only + + + RX_HUNG_INT_CLR + Set this bit to clear the i2s_rx_hung_int interrupt + 2 + 1 + write-only + + + TX_HUNG_INT_CLR + Set this bit to clear the i2s_tx_hung_int interrupt + 3 + 1 + write-only + + + + + RX_CONF + I2S RX configure register + 0x20 + 0x20 + 0x00009600 + + + RX_RESET + Set this bit to reset receiver + 0 + 1 + write-only + + + RX_FIFO_RESET + Set this bit to reset Rx AFIFO + 1 + 1 + write-only + + + RX_START + Set this bit to start receiving data + 2 + 1 + read-write + + + RX_SLAVE_MOD + Set this bit to enable slave receiver mode + 3 + 1 + read-write + + + RX_MONO + Set this bit to enable receiver in mono mode + 5 + 1 + read-write + + + RX_BIG_ENDIAN + I2S Rx byte endian, 1: low addr value to high addr. 0: low addr with low addr value. + 7 + 1 + read-write + + + RX_UPDATE + Set 1 to update I2S RX registers from APB clock domain to I2S RX clock domain. This bit will be cleared by hardware after update register done. + 8 + 1 + read-write + + + RX_MONO_FST_VLD + 1: The first channel data value is valid in I2S RX mono mode. 0: The second channel data value is valid in I2S RX mono mode. + 9 + 1 + read-write + + + RX_PCM_CONF + I2S RX compress/decompress configuration bit. & 0 (atol): A-Law decompress, 1 (ltoa) : A-Law compress, 2 (utol) : u-Law decompress, 3 (ltou) : u-Law compress. & + 10 + 2 + read-write + + + RX_PCM_BYPASS + Set this bit to bypass Compress/Decompress module for received data. + 12 + 1 + read-write + + + RX_STOP_MODE + 0 : I2S Rx only stop when reg_rx_start is cleared. 1: Stop when reg_rx_start is 0 or in_suc_eof is 1. 2: Stop I2S RX when reg_rx_start is 0 or RX FIFO is full. + 13 + 2 + read-write + + + RX_LEFT_ALIGN + 1: I2S RX left alignment mode. 0: I2S RX right alignment mode. + 15 + 1 + read-write + + + RX_24_FILL_EN + 1: store 24 channel bits to 32 bits. 0:store 24 channel bits to 24 bits. + 16 + 1 + read-write + + + RX_WS_IDLE_POL + 0: WS should be 0 when receiving left channel data, and WS is 1in right channel. 1: WS should be 1 when receiving left channel data, and WS is 0in right channel. + 17 + 1 + read-write + + + RX_BIT_ORDER + I2S Rx bit endian. 1:small endian, the LSB is received first. 0:big endian, the MSB is received first. + 18 + 1 + read-write + + + RX_TDM_EN + 1: Enable I2S TDM Rx mode . 0: Disable. + 19 + 1 + read-write + + + RX_PDM_EN + 1: Enable I2S PDM Rx mode . 0: Disable. + 20 + 1 + read-write + + + RX_PDM2PCM_EN + 1: Enable PDM2PCM RX mode. 0: DIsable. + 21 + 1 + read-write + + + RX_PDM_SINC_DSR_16_EN + Configure the down sampling rate of PDM RX filter group1 module. 1: The down sampling rate is 128. 0: down sampling rate is 64. + 22 + 1 + read-write + + + + + TX_CONF + I2S TX configure register + 0x24 + 0x20 + 0x0000B200 + + + TX_RESET + Set this bit to reset transmitter + 0 + 1 + write-only + + + TX_FIFO_RESET + Set this bit to reset Tx AFIFO + 1 + 1 + write-only + + + TX_START + Set this bit to start transmitting data + 2 + 1 + read-write + + + TX_SLAVE_MOD + Set this bit to enable slave transmitter mode + 3 + 1 + read-write + + + TX_MONO + Set this bit to enable transmitter in mono mode + 5 + 1 + read-write + + + TX_CHAN_EQUAL + 1: The value of Left channel data is equal to the value of right channel data in I2S TX mono mode or TDM channel select mode. 0: The invalid channel data is reg_i2s_single_data in I2S TX mono mode or TDM channel select mode. + 6 + 1 + read-write + + + TX_BIG_ENDIAN + I2S Tx byte endian, 1: low addr value to high addr. 0: low addr with low addr value. + 7 + 1 + read-write + + + TX_UPDATE + Set 1 to update I2S TX registers from APB clock domain to I2S TX clock domain. This bit will be cleared by hardware after update register done. + 8 + 1 + read-write + + + TX_MONO_FST_VLD + 1: The first channel data value is valid in I2S TX mono mode. 0: The second channel data value is valid in I2S TX mono mode. + 9 + 1 + read-write + + + TX_PCM_CONF + I2S TX compress/decompress configuration bit. & 0 (atol): A-Law decompress, 1 (ltoa) : A-Law compress, 2 (utol) : u-Law decompress, 3 (ltou) : u-Law compress. & + 10 + 2 + read-write + + + TX_PCM_BYPASS + Set this bit to bypass Compress/Decompress module for transmitted data. + 12 + 1 + read-write + + + TX_STOP_EN + Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + 13 + 1 + read-write + + + TX_LEFT_ALIGN + 1: I2S TX left alignment mode. 0: I2S TX right alignment mode. + 15 + 1 + read-write + + + TX_24_FILL_EN + 1: Sent 32 bits in 24 channel bits mode. 0: Sent 24 bits in 24 channel bits mode + 16 + 1 + read-write + + + TX_WS_IDLE_POL + 0: WS should be 0 when sending left channel data, and WS is 1in right channel. 1: WS should be 1 when sending left channel data, and WS is 0in right channel. + 17 + 1 + read-write + + + TX_BIT_ORDER + I2S Tx bit endian. 1:small endian, the LSB is sent first. 0:big endian, the MSB is sent first. + 18 + 1 + read-write + + + TX_TDM_EN + 1: Enable I2S TDM Tx mode . 0: Disable. + 19 + 1 + read-write + + + TX_PDM_EN + 1: Enable I2S PDM Tx mode . 0: Disable. + 20 + 1 + read-write + + + TX_CHAN_MOD + I2S transmitter channel mode configuration bits. + 24 + 3 + read-write + + + SIG_LOOPBACK + Enable signal loop back mode with transmitter module and receiver module sharing the same WS and BCK signals. + 27 + 1 + read-write + + + + + RX_CONF1 + I2S RX configure register 1 + 0x28 + 0x20 + 0x2F3DE300 + + + RX_TDM_WS_WIDTH + The width of rx_ws_out in TDM mode is (I2S_RX_TDM_WS_WIDTH[6:0] +1) * T_bck + 0 + 7 + read-write + + + RX_BCK_DIV_NUM + Bit clock configuration bits in receiver mode. + 7 + 6 + read-write + + + RX_BITS_MOD + Set the bits to configure the valid data bit length of I2S receiver channel. 7: all the valid channel data is in 8-bit-mode. 15: all the valid channel data is in 16-bit-mode. 23: all the valid channel data is in 24-bit-mode. 31:all the valid channel data is in 32-bit-mode. + 13 + 5 + read-write + + + RX_HALF_SAMPLE_BITS + I2S Rx half sample bits -1. + 18 + 6 + read-write + + + RX_TDM_CHAN_BITS + The Rx bit number for each channel minus 1in TDM mode. + 24 + 5 + read-write + + + RX_MSB_SHIFT + Set this bit to enable receiver in Phillips standard mode + 29 + 1 + read-write + + + + + TX_CONF1 + I2S TX configure register 1 + 0x2C + 0x20 + 0x6F3DE300 + + + TX_TDM_WS_WIDTH + The width of tx_ws_out in TDM mode is (I2S_TX_TDM_WS_WIDTH[6:0] +1) * T_bck + 0 + 7 + read-write + + + TX_BCK_DIV_NUM + Bit clock configuration bits in transmitter mode. + 7 + 6 + read-write + + + TX_BITS_MOD + Set the bits to configure the valid data bit length of I2S transmitter channel. 7: all the valid channel data is in 8-bit-mode. 15: all the valid channel data is in 16-bit-mode. 23: all the valid channel data is in 24-bit-mode. 31:all the valid channel data is in 32-bit-mode. + 13 + 5 + read-write + + + TX_HALF_SAMPLE_BITS + I2S Tx half sample bits -1. + 18 + 6 + read-write + + + TX_TDM_CHAN_BITS + The Tx bit number for each channel minus 1in TDM mode. + 24 + 5 + read-write + + + TX_MSB_SHIFT + Set this bit to enable transmitter in Phillips standard mode + 29 + 1 + read-write + + + TX_BCK_NO_DLY + 1: BCK is not delayed to generate pos/neg edge in master mode. 0: BCK is delayed to generate pos/neg edge in master mode. + 30 + 1 + read-write + + + + + RX_CLKM_CONF + I2S RX clock configure register + 0x30 + 0x20 + 0x00000002 + + + RX_CLKM_DIV_NUM + Integral I2S clock divider value + 0 + 8 + read-write + + + RX_CLK_ACTIVE + I2S Rx module clock enable signal. + 26 + 1 + read-write + + + RX_CLK_SEL + Select I2S Rx module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: I2S_MCLK_in. + 27 + 2 + read-write + + + MCLK_SEL + 0: UseI2S Tx module clock as I2S_MCLK_OUT. 1: UseI2S Rx module clock as I2S_MCLK_OUT. + 29 + 1 + read-write + + + + + TX_CLKM_CONF + I2S TX clock configure register + 0x34 + 0x20 + 0x00000002 + + + TX_CLKM_DIV_NUM + Integral I2S TX clock divider value. f_I2S_CLK = f_I2S_CLK_S/(N+b/a). There will be (a-b) * n-div and b * (n+1)-div. So the average combination will be: for b <= a/2, z * [x * n-div + (n+1)-div] + y * n-div. For b > a/2, z * [n-div + x * (n+1)-div] + y * (n+1)-div. + 0 + 8 + read-write + + + TX_CLK_ACTIVE + I2S Tx module clock enable signal. + 26 + 1 + read-write + + + TX_CLK_SEL + Select I2S Tx module source clock. 0: XTAL clock. 1: APLL. 2: CLK160. 3: I2S_MCLK_in. + 27 + 2 + read-write + + + CLK_EN + Set this bit to enable clk gate + 29 + 1 + read-write + + + + + RX_CLKM_DIV_CONF + I2S RX module clock divider configure register + 0x38 + 0x20 + 0x00000200 + + + RX_CLKM_DIV_Z + For b <= a/2, the value of I2S_RX_CLKM_DIV_Z is b. For b > a/2, the value of I2S_RX_CLKM_DIV_Z is (a-b). + 0 + 9 + read-write + + + RX_CLKM_DIV_Y + For b <= a/2, the value of I2S_RX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of I2S_RX_CLKM_DIV_Y is (a%(a-b)). + 9 + 9 + read-write + + + RX_CLKM_DIV_X + For b <= a/2, the value of I2S_RX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value of I2S_RX_CLKM_DIV_X is (a/(a-b)) - 1. + 18 + 9 + read-write + + + RX_CLKM_DIV_YN1 + For b <= a/2, the value of I2S_RX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of I2S_RX_CLKM_DIV_YN1 is 1. + 27 + 1 + read-write + + + + + TX_CLKM_DIV_CONF + I2S TX module clock divider configure register + 0x3C + 0x20 + 0x00000200 + + + TX_CLKM_DIV_Z + For b <= a/2, the value of I2S_TX_CLKM_DIV_Z is b. For b > a/2, the value of I2S_TX_CLKM_DIV_Z is (a-b). + 0 + 9 + read-write + + + TX_CLKM_DIV_Y + For b <= a/2, the value of I2S_TX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of I2S_TX_CLKM_DIV_Y is (a%(a-b)). + 9 + 9 + read-write + + + TX_CLKM_DIV_X + For b <= a/2, the value of I2S_TX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value of I2S_TX_CLKM_DIV_X is (a/(a-b)) - 1. + 18 + 9 + read-write + + + TX_CLKM_DIV_YN1 + For b <= a/2, the value of I2S_TX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of I2S_TX_CLKM_DIV_YN1 is 1. + 27 + 1 + read-write + + + + + TX_PCM2PDM_CONF + I2S TX PCM2PDM configuration register + 0x40 + 0x20 + 0x004AA004 + + + TX_PDM_HP_BYPASS + I2S TX PDM bypass hp filter or not. The option has been removed. + 0 + 1 + read-write + + + TX_PDM_SINC_OSR2 + I2S TX PDM OSR2 value + 1 + 4 + read-write + + + TX_PDM_PRESCALE + I2S TX PDM prescale for sigmadelta + 5 + 8 + read-write + + + TX_PDM_HP_IN_SHIFT + I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + 13 + 2 + read-write + + + TX_PDM_LP_IN_SHIFT + I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + 15 + 2 + read-write + + + TX_PDM_SINC_IN_SHIFT + I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + 17 + 2 + read-write + + + TX_PDM_SIGMADELTA_IN_SHIFT + I2S TX PDM sigmadelta scale shift number: 0:/2 , 1:x1 , 2:x2 , 3: x4 + 19 + 2 + read-write + + + TX_PDM_SIGMADELTA_DITHER2 + I2S TX PDM sigmadelta dither2 value + 21 + 1 + read-write + + + TX_PDM_SIGMADELTA_DITHER + I2S TX PDM sigmadelta dither value + 22 + 1 + read-write + + + TX_PDM_DAC_2OUT_EN + I2S TX PDM dac mode enable + 23 + 1 + read-write + + + TX_PDM_DAC_MODE_EN + I2S TX PDM dac 2channel enable + 24 + 1 + read-write + + + PCM2PDM_CONV_EN + I2S TX PDM Converter enable + 25 + 1 + read-write + + + + + TX_PCM2PDM_CONF1 + I2S TX PCM2PDM configuration register + 0x44 + 0x20 + 0x03F783C0 + + + TX_PDM_FP + I2S TX PDM Fp + 0 + 10 + read-write + + + TX_PDM_FS + I2S TX PDM Fs + 10 + 10 + read-write + + + TX_IIR_HP_MULT12_5 + The fourth parameter of PDM TX IIR_HP filter stage 2 is (504 + I2S_TX_IIR_HP_MULT12_5[2:0]) + 20 + 3 + read-write + + + TX_IIR_HP_MULT12_0 + The fourth parameter of PDM TX IIR_HP filter stage 1 is (504 + I2S_TX_IIR_HP_MULT12_0[2:0]) + 23 + 3 + read-write + + + + + RX_TDM_CTRL + I2S TX TDM mode control register + 0x50 + 0x20 + 0x0000FFFF + + + RX_TDM_PDM_CHAN0_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 0. 0: Disable, just input 0 in this channel. + 0 + 1 + read-write + + + RX_TDM_PDM_CHAN1_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 1. 0: Disable, just input 0 in this channel. + 1 + 1 + read-write + + + RX_TDM_PDM_CHAN2_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 2. 0: Disable, just input 0 in this channel. + 2 + 1 + read-write + + + RX_TDM_PDM_CHAN3_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 3. 0: Disable, just input 0 in this channel. + 3 + 1 + read-write + + + RX_TDM_PDM_CHAN4_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 4. 0: Disable, just input 0 in this channel. + 4 + 1 + read-write + + + RX_TDM_PDM_CHAN5_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 5. 0: Disable, just input 0 in this channel. + 5 + 1 + read-write + + + RX_TDM_PDM_CHAN6_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 6. 0: Disable, just input 0 in this channel. + 6 + 1 + read-write + + + RX_TDM_PDM_CHAN7_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 7. 0: Disable, just input 0 in this channel. + 7 + 1 + read-write + + + RX_TDM_CHAN8_EN + 1: Enable the valid data input of I2S RX TDM channel 8. 0: Disable, just input 0 in this channel. + 8 + 1 + read-write + + + RX_TDM_CHAN9_EN + 1: Enable the valid data input of I2S RX TDM channel 9. 0: Disable, just input 0 in this channel. + 9 + 1 + read-write + + + RX_TDM_CHAN10_EN + 1: Enable the valid data input of I2S RX TDM channel 10. 0: Disable, just input 0 in this channel. + 10 + 1 + read-write + + + RX_TDM_CHAN11_EN + 1: Enable the valid data input of I2S RX TDM channel 11. 0: Disable, just input 0 in this channel. + 11 + 1 + read-write + + + RX_TDM_CHAN12_EN + 1: Enable the valid data input of I2S RX TDM channel 12. 0: Disable, just input 0 in this channel. + 12 + 1 + read-write + + + RX_TDM_CHAN13_EN + 1: Enable the valid data input of I2S RX TDM channel 13. 0: Disable, just input 0 in this channel. + 13 + 1 + read-write + + + RX_TDM_CHAN14_EN + 1: Enable the valid data input of I2S RX TDM channel 14. 0: Disable, just input 0 in this channel. + 14 + 1 + read-write + + + RX_TDM_CHAN15_EN + 1: Enable the valid data input of I2S RX TDM channel 15. 0: Disable, just input 0 in this channel. + 15 + 1 + read-write + + + RX_TDM_TOT_CHAN_NUM + The total channel number of I2S TX TDM mode. + 16 + 4 + read-write + + + + + TX_TDM_CTRL + I2S TX TDM mode control register + 0x54 + 0x20 + 0x0000FFFF + + + TX_TDM_CHAN0_EN + 1: Enable the valid data output of I2S TX TDM channel 0. 0: Disable, just output 0 in this channel. + 0 + 1 + read-write + + + TX_TDM_CHAN1_EN + 1: Enable the valid data output of I2S TX TDM channel 1. 0: Disable, just output 0 in this channel. + 1 + 1 + read-write + + + TX_TDM_CHAN2_EN + 1: Enable the valid data output of I2S TX TDM channel 2. 0: Disable, just output 0 in this channel. + 2 + 1 + read-write + + + TX_TDM_CHAN3_EN + 1: Enable the valid data output of I2S TX TDM channel 3. 0: Disable, just output 0 in this channel. + 3 + 1 + read-write + + + TX_TDM_CHAN4_EN + 1: Enable the valid data output of I2S TX TDM channel 4. 0: Disable, just output 0 in this channel. + 4 + 1 + read-write + + + TX_TDM_CHAN5_EN + 1: Enable the valid data output of I2S TX TDM channel 5. 0: Disable, just output 0 in this channel. + 5 + 1 + read-write + + + TX_TDM_CHAN6_EN + 1: Enable the valid data output of I2S TX TDM channel 6. 0: Disable, just output 0 in this channel. + 6 + 1 + read-write + + + TX_TDM_CHAN7_EN + 1: Enable the valid data output of I2S TX TDM channel 7. 0: Disable, just output 0 in this channel. + 7 + 1 + read-write + + + TX_TDM_CHAN8_EN + 1: Enable the valid data output of I2S TX TDM channel 8. 0: Disable, just output 0 in this channel. + 8 + 1 + read-write + + + TX_TDM_CHAN9_EN + 1: Enable the valid data output of I2S TX TDM channel 9. 0: Disable, just output 0 in this channel. + 9 + 1 + read-write + + + TX_TDM_CHAN10_EN + 1: Enable the valid data output of I2S TX TDM channel 10. 0: Disable, just output 0 in this channel. + 10 + 1 + read-write + + + TX_TDM_CHAN11_EN + 1: Enable the valid data output of I2S TX TDM channel 11. 0: Disable, just output 0 in this channel. + 11 + 1 + read-write + + + TX_TDM_CHAN12_EN + 1: Enable the valid data output of I2S TX TDM channel 12. 0: Disable, just output 0 in this channel. + 12 + 1 + read-write + + + TX_TDM_CHAN13_EN + 1: Enable the valid data output of I2S TX TDM channel 13. 0: Disable, just output 0 in this channel. + 13 + 1 + read-write + + + TX_TDM_CHAN14_EN + 1: Enable the valid data output of I2S TX TDM channel 14. 0: Disable, just output 0 in this channel. + 14 + 1 + read-write + + + TX_TDM_CHAN15_EN + 1: Enable the valid data output of I2S TX TDM channel 15. 0: Disable, just output 0 in this channel. + 15 + 1 + read-write + + + TX_TDM_TOT_CHAN_NUM + The total channel number of I2S TX TDM mode. + 16 + 4 + read-write + + + TX_TDM_SKIP_MSK_EN + When DMA TX buffer stores the data of (REG_TX_TDM_TOT_CHAN_NUM + 1) channels, and only the data of the enabled channels is sent, then this bit should be set. Clear it when all the data stored in DMA TX buffer is for enabled channels. + 20 + 1 + read-write + + + + + RX_TIMING + I2S RX timing control register + 0x58 + 0x20 + + + RX_SD_IN_DM + The delay mode of I2S Rx SD input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 0 + 2 + read-write + + + RX_SD1_IN_DM + The delay mode of I2S Rx SD1 input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 4 + 2 + read-write + + + RX_SD2_IN_DM + The delay mode of I2S Rx SD2 input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 8 + 2 + read-write + + + RX_SD3_IN_DM + The delay mode of I2S Rx SD3 input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 12 + 2 + read-write + + + RX_WS_OUT_DM + The delay mode of I2S Rx WS output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 16 + 2 + read-write + + + RX_BCK_OUT_DM + The delay mode of I2S Rx BCK output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 20 + 2 + read-write + + + RX_WS_IN_DM + The delay mode of I2S Rx WS input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 24 + 2 + read-write + + + RX_BCK_IN_DM + The delay mode of I2S Rx BCK input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 28 + 2 + read-write + + + + + TX_TIMING + I2S TX timing control register + 0x5C + 0x20 + + + TX_SD_OUT_DM + The delay mode of I2S TX SD output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 0 + 2 + read-write + + + TX_SD1_OUT_DM + The delay mode of I2S TX SD1 output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 4 + 2 + read-write + + + TX_WS_OUT_DM + The delay mode of I2S TX WS output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 16 + 2 + read-write + + + TX_BCK_OUT_DM + The delay mode of I2S TX BCK output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 20 + 2 + read-write + + + TX_WS_IN_DM + The delay mode of I2S TX WS input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 24 + 2 + read-write + + + TX_BCK_IN_DM + The delay mode of I2S TX BCK input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 28 + 2 + read-write + + + + + LC_HUNG_CONF + I2S HUNG configure register. + 0x60 + 0x20 + 0x00000810 + + + LC_FIFO_TIMEOUT + the i2s_tx_hung_int interrupt or the i2s_rx_hung_int interrupt will be triggered when fifo hung counter is equal to this value + 0 + 8 + read-write + + + LC_FIFO_TIMEOUT_SHIFT + The bits are used to scale tick counter threshold. The tick counter is reset when counter value >= 88000/2^i2s_lc_fifo_timeout_shift + 8 + 3 + read-write + + + LC_FIFO_TIMEOUT_ENA + The enable bit for FIFO timeout + 11 + 1 + read-write + + + + + RXEOF_NUM + I2S RX data number control register. + 0x64 + 0x20 + 0x00000040 + + + RX_EOF_NUM + The receive data bit length is (I2S_RX_BITS_MOD[4:0] + 1) * (REG_RX_EOF_NUM[11:0] + 1) . It will trigger in_suc_eof interrupt in the configured DMA RX channel. + 0 + 12 + read-write + + + + + CONF_SIGLE_DATA + I2S signal data register + 0x68 + 0x20 + + + SINGLE_DATA + The configured constant channel data to be sent out. + 0 + 32 + read-write + + + + + STATE + I2S TX status register + 0x6C + 0x20 + 0x00000001 + + + TX_IDLE + 1: i2s_tx is idle state. 0: i2s_tx is working. + 0 + 1 + read-only + + + + + DATE + Version control register + 0x80 + 0x20 + 0x02009070 + + + DATE + I2S version control register + 0 + 28 + read-write + + + + + + + I2S1 + I2S (Inter-IC Sound) Controller + I2S1 + 0x6002D000 + + 0x0 + 0x54 + registers + + + I2S1 + 26 + + + + I2S_INT_RAW + I2S interrupt raw register, valid in level. + 0xC + 0x20 + + + I2S_RX_DONE_INT_RAW + The raw interrupt status bit for the i2s_rx_done_int interrupt + 0 + 1 + read-only + + + I2S_TX_DONE_INT_RAW + The raw interrupt status bit for the i2s_tx_done_int interrupt + 1 + 1 + read-only + + + I2S_RX_HUNG_INT_RAW + The raw interrupt status bit for the i2s_rx_hung_int interrupt + 2 + 1 + read-only + + + I2S_TX_HUNG_INT_RAW + The raw interrupt status bit for the i2s_tx_hung_int interrupt + 3 + 1 + read-only + + + + + I2S_INT_ST + I2S interrupt status register. + 0x10 + 0x20 + + + I2S_RX_DONE_INT_ST + The masked interrupt status bit for the i2s_rx_done_int interrupt + 0 + 1 + read-only + + + I2S_TX_DONE_INT_ST + The masked interrupt status bit for the i2s_tx_done_int interrupt + 1 + 1 + read-only + + + I2S_RX_HUNG_INT_ST + The masked interrupt status bit for the i2s_rx_hung_int interrupt + 2 + 1 + read-only + + + I2S_TX_HUNG_INT_ST + The masked interrupt status bit for the i2s_tx_hung_int interrupt + 3 + 1 + read-only + + + + + I2S_INT_ENA + I2S interrupt enable register. + 0x14 + 0x20 + + + I2S_RX_DONE_INT_ENA + The interrupt enable bit for the i2s_rx_done_int interrupt + 0 + 1 + read-write + + + I2S_TX_DONE_INT_ENA + The interrupt enable bit for the i2s_tx_done_int interrupt + 1 + 1 + read-write + + + I2S_RX_HUNG_INT_ENA + The interrupt enable bit for the i2s_rx_hung_int interrupt + 2 + 1 + read-write + + + I2S_TX_HUNG_INT_ENA + The interrupt enable bit for the i2s_tx_hung_int interrupt + 3 + 1 + read-write + + + + + I2S_INT_CLR + I2S interrupt clear register. + 0x18 + 0x20 + + + I2S_RX_DONE_INT_CLR + Set this bit to clear the i2s_rx_done_int interrupt + 0 + 1 + write-only + + + I2S_TX_DONE_INT_CLR + Set this bit to clear the i2s_tx_done_int interrupt + 1 + 1 + write-only + + + I2S_RX_HUNG_INT_CLR + Set this bit to clear the i2s_rx_hung_int interrupt + 2 + 1 + write-only + + + I2S_TX_HUNG_INT_CLR + Set this bit to clear the i2s_tx_hung_int interrupt + 3 + 1 + write-only + + + + + I2S_RX_CONF + I2S RX configure register + 0x20 + 0x20 + 0x00009600 + + + I2S_RX_RESET + Set this bit to reset receiver + 0 + 1 + write-only + + + I2S_RX_FIFO_RESET + Set this bit to reset Rx AFIFO + 1 + 1 + write-only + + + I2S_RX_START + Set this bit to start receiving data + 2 + 1 + read-write + + + I2S_RX_SLAVE_MOD + Set this bit to enable slave receiver mode + 3 + 1 + read-write + + + I2S_RX_MONO + Set this bit to enable receiver in mono mode + 5 + 1 + read-write + + + I2S_RX_BIG_ENDIAN + I2S Rx byte endian, 1: low addr value to high addr. 0: low addr with low addr value. + 7 + 1 + read-write + + + I2S_RX_UPDATE + Set 1 to update I2S RX registers from APB clock domain to I2S RX clock domain. This bit will be cleared by hardware after update register done. + 8 + 1 + read-write + + + I2S_RX_MONO_FST_VLD + 1: The first channel data value is valid in I2S RX mono mode. 0: The second channel data value is valid in I2S RX mono mode. + 9 + 1 + read-write + + + I2S_RX_PCM_CONF + I2S RX compress/decompress configuration bit. & 0 (atol): A-Law decompress, 1 (ltoa) : A-Law compress, 2 (utol) : u-Law decompress, 3 (ltou) : u-Law compress. & + 10 + 2 + read-write + + + I2S_RX_PCM_BYPASS + Set this bit to bypass Compress/Decompress module for received data. + 12 + 1 + read-write + + + I2S_RX_STOP_MODE + 0 : I2S Rx only stop when reg_rx_start is cleared. 1: Stop when reg_rx_start is 0 or in_suc_eof is 1. 2: Stop I2S RX when reg_rx_start is 0 or RX FIFO is full. + 13 + 2 + read-write + + + I2S_RX_LEFT_ALIGN + 1: I2S RX left alignment mode. 0: I2S RX right alignment mode. + 15 + 1 + read-write + + + I2S_RX_24_FILL_EN + 1: store 24 channel bits to 32 bits. 0:store 24 channel bits to 24 bits. + 16 + 1 + read-write + + + I2S_RX_WS_IDLE_POL + 0: WS should be 0 when receiving left channel data, and WS is 1in right channel. 1: WS should be 1 when receiving left channel data, and WS is 0in right channel. + 17 + 1 + read-write + + + I2S_RX_BIT_ORDER + I2S Rx bit endian. 1:small endian, the LSB is received first. 0:big endian, the MSB is received first. + 18 + 1 + read-write + + + I2S_RX_TDM_EN + 1: Enable I2S TDM Rx mode . 0: Disable. + 19 + 1 + read-write + + + I2S_RX_PDM_EN + 1: Enable I2S PDM Rx mode . 0: Disable. + 20 + 1 + read-write + + + + + I2S_TX_CONF + I2S TX configure register + 0x24 + 0x20 + 0x0000B200 + + + I2S_TX_RESET + Set this bit to reset transmitter + 0 + 1 + write-only + + + I2S_TX_FIFO_RESET + Set this bit to reset Tx AFIFO + 1 + 1 + write-only + + + I2S_TX_START + Set this bit to start transmitting data + 2 + 1 + read-write + + + I2S_TX_SLAVE_MOD + Set this bit to enable slave transmitter mode + 3 + 1 + read-write + + + I2S_TX_MONO + Set this bit to enable transmitter in mono mode + 5 + 1 + read-write + + + I2S_TX_CHAN_EQUAL + 1: The value of Left channel data is equal to the value of right channel data in I2S TX mono mode or TDM channel select mode. 0: The invalid channel data is reg_i2s_single_data in I2S TX mono mode or TDM channel select mode. + 6 + 1 + read-write + + + I2S_TX_BIG_ENDIAN + I2S Tx byte endian, 1: low addr value to high addr. 0: low addr with low addr value. + 7 + 1 + read-write + + + I2S_TX_UPDATE + Set 1 to update I2S TX registers from APB clock domain to I2S TX clock domain. This bit will be cleared by hardware after update register done. + 8 + 1 + read-write + + + I2S_TX_MONO_FST_VLD + 1: The first channel data value is valid in I2S TX mono mode. 0: The second channel data value is valid in I2S TX mono mode. + 9 + 1 + read-write + + + I2S_TX_PCM_CONF + I2S TX compress/decompress configuration bit. & 0 (atol): A-Law decompress, 1 (ltoa) : A-Law compress, 2 (utol) : u-Law decompress, 3 (ltou) : u-Law compress. & + 10 + 2 + read-write + + + I2S_TX_PCM_BYPASS + Set this bit to bypass Compress/Decompress module for transmitted data. + 12 + 1 + read-write + + + I2S_TX_STOP_EN + Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy + 13 + 1 + read-write + + + I2S_TX_LEFT_ALIGN + 1: I2S TX left alignment mode. 0: I2S TX right alignment mode. + 15 + 1 + read-write + + + I2S_TX_24_FILL_EN + 1: Sent 32 bits in 24 channel bits mode. 0: Sent 24 bits in 24 channel bits mode + 16 + 1 + read-write + + + I2S_TX_WS_IDLE_POL + 0: WS should be 0 when sending left channel data, and WS is 1in right channel. 1: WS should be 1 when sending left channel data, and WS is 0in right channel. + 17 + 1 + read-write + + + I2S_TX_BIT_ORDER + I2S Tx bit endian. 1:small endian, the LSB is sent first. 0:big endian, the MSB is sent first. + 18 + 1 + read-write + + + I2S_TX_TDM_EN + 1: Enable I2S TDM Tx mode . 0: Disable. + 19 + 1 + read-write + + + I2S_TX_PDM_EN + 1: Enable I2S PDM Tx mode . 0: Disable. + 20 + 1 + read-write + + + I2S_TX_CHAN_MOD + I2S transmitter channel mode configuration bits. + 24 + 3 + read-write + + + I2S_SIG_LOOPBACK + Enable signal loop back mode with transmitter module and receiver module sharing the same WS and BCK signals. + 27 + 1 + read-write + + + + + I2S_RX_CONF1 + I2S RX configure register 1 + 0x28 + 0x20 + 0x2F3DE300 + + + I2S_RX_TDM_WS_WIDTH + The width of rx_ws_out in TDM mode is (I2S_RX_TDM_WS_WIDTH[6:0] +1) * T_bck + 0 + 7 + read-write + + + I2S_RX_BCK_DIV_NUM + Bit clock configuration bits in receiver mode. + 7 + 6 + read-write + + + I2S_RX_BITS_MOD + Set the bits to configure the valid data bit length of I2S receiver channel. 7: all the valid channel data is in 8-bit-mode. 15: all the valid channel data is in 16-bit-mode. 23: all the valid channel data is in 24-bit-mode. 31:all the valid channel data is in 32-bit-mode. + 13 + 5 + read-write + + + I2S_RX_HALF_SAMPLE_BITS + I2S Rx half sample bits -1. + 18 + 6 + read-write + + + I2S_RX_TDM_CHAN_BITS + The Rx bit number for each channel minus 1in TDM mode. + 24 + 5 + read-write + + + I2S_RX_MSB_SHIFT + Set this bit to enable receiver in Phillips standard mode + 29 + 1 + read-write + + + + + I2S_TX_CONF1 + I2S TX configure register 1 + 0x2C + 0x20 + 0x6F3DE300 + + + I2S_TX_TDM_WS_WIDTH + The width of tx_ws_out in TDM mode is (I2S_TX_TDM_WS_WIDTH[6:0] +1) * T_bck + 0 + 7 + read-write + + + I2S_TX_BCK_DIV_NUM + Bit clock configuration bits in transmitter mode. + 7 + 6 + read-write + + + I2S_TX_BITS_MOD + Set the bits to configure the valid data bit length of I2S transmitter channel. 7: all the valid channel data is in 8-bit-mode. 15: all the valid channel data is in 16-bit-mode. 23: all the valid channel data is in 24-bit-mode. 31:all the valid channel data is in 32-bit-mode. + 13 + 5 + read-write + + + I2S_TX_HALF_SAMPLE_BITS + I2S Tx half sample bits -1. + 18 + 6 + read-write + + + I2S_TX_TDM_CHAN_BITS + The Tx bit number for each channel minus 1in TDM mode. + 24 + 5 + read-write + + + I2S_TX_MSB_SHIFT + Set this bit to enable transmitter in Phillips standard mode + 29 + 1 + read-write + + + I2S_TX_BCK_NO_DLY + 1: BCK is not delayed to generate pos/neg edge in master mode. 0: BCK is delayed to generate pos/neg edge in master mode. + 30 + 1 + read-write + + + + + I2S_RX_CLKM_CONF + I2S RX clock configure register + 0x30 + 0x20 + 0x00000002 + + + I2S_RX_CLKM_DIV_NUM + Integral I2S clock divider value + 0 + 8 + read-write + + + I2S_RX_CLK_ACTIVE + I2S Rx module clock enable signal. + 26 + 1 + read-write + + + I2S_RX_CLK_SEL + Select I2S Rx module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: I2S_MCLK_in. + 27 + 2 + read-write + + + I2S_MCLK_SEL + 0: UseI2S Tx module clock as I2S_MCLK_OUT. 1: UseI2S Rx module clock as I2S_MCLK_OUT. + 29 + 1 + read-write + + + + + I2S_TX_CLKM_CONF + I2S TX clock configure register + 0x34 + 0x20 + 0x00000002 + + + I2S_TX_CLKM_DIV_NUM + Integral I2S TX clock divider value. f_I2S_CLK = f_I2S_CLK_S/(N+b/a). There will be (a-b) * n-div and b * (n+1)-div. So the average combination will be: for b <= a/2, z * [x * n-div + (n+1)-div] + y * n-div. For b > a/2, z * [n-div + x * (n+1)-div] + y * (n+1)-div. + 0 + 8 + read-write + + + I2S_TX_CLK_ACTIVE + I2S Tx module clock enable signal. + 26 + 1 + read-write + + + I2S_TX_CLK_SEL + Select I2S Tx module source clock. 0: XTAL clock. 1: APLL. 2: CLK160. 3: I2S_MCLK_in. + 27 + 2 + read-write + + + I2S_CLK_EN + Set this bit to enable clk gate + 29 + 1 + read-write + + + + + I2S_RX_CLKM_DIV_CONF + I2S RX module clock divider configure register + 0x38 + 0x20 + 0x00000200 + + + I2S_RX_CLKM_DIV_Z + For b <= a/2, the value of I2S_RX_CLKM_DIV_Z is b. For b > a/2, the value of I2S_RX_CLKM_DIV_Z is (a-b). + 0 + 9 + read-write + + + I2S_RX_CLKM_DIV_Y + For b <= a/2, the value of I2S_RX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of I2S_RX_CLKM_DIV_Y is (a%(a-b)). + 9 + 9 + read-write + + + I2S_RX_CLKM_DIV_X + For b <= a/2, the value of I2S_RX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value of I2S_RX_CLKM_DIV_X is (a/(a-b)) - 1. + 18 + 9 + read-write + + + I2S_RX_CLKM_DIV_YN1 + For b <= a/2, the value of I2S_RX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of I2S_RX_CLKM_DIV_YN1 is 1. + 27 + 1 + read-write + + + + + I2S_TX_CLKM_DIV_CONF + I2S TX module clock divider configure register + 0x3C + 0x20 + 0x00000200 + + + I2S_TX_CLKM_DIV_Z + For b <= a/2, the value of I2S_TX_CLKM_DIV_Z is b. For b > a/2, the value of I2S_TX_CLKM_DIV_Z is (a-b). + 0 + 9 + read-write + + + I2S_TX_CLKM_DIV_Y + For b <= a/2, the value of I2S_TX_CLKM_DIV_Y is (a%b) . For b > a/2, the value of I2S_TX_CLKM_DIV_Y is (a%(a-b)). + 9 + 9 + read-write + + + I2S_TX_CLKM_DIV_X + For b <= a/2, the value of I2S_TX_CLKM_DIV_X is (a/b) - 1. For b > a/2, the value of I2S_TX_CLKM_DIV_X is (a/(a-b)) - 1. + 18 + 9 + read-write + + + I2S_TX_CLKM_DIV_YN1 + For b <= a/2, the value of I2S_TX_CLKM_DIV_YN1 is 0 . For b > a/2, the value of I2S_TX_CLKM_DIV_YN1 is 1. + 27 + 1 + read-write + + + + + I2S_RX_TDM_CTRL + I2S TX TDM mode control register + 0x50 + 0x20 + 0x0000FFFF + + + I2S_RX_TDM_PDM_CHAN0_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 0. 0: Disable, just input 0 in this channel. + 0 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN1_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 1. 0: Disable, just input 0 in this channel. + 1 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN2_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 2. 0: Disable, just input 0 in this channel. + 2 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN3_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 3. 0: Disable, just input 0 in this channel. + 3 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN4_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 4. 0: Disable, just input 0 in this channel. + 4 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN5_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 5. 0: Disable, just input 0 in this channel. + 5 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN6_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 6. 0: Disable, just input 0 in this channel. + 6 + 1 + read-write + + + I2S_RX_TDM_PDM_CHAN7_EN + 1: Enable the valid data input of I2S RX TDM or PDM channel 7. 0: Disable, just input 0 in this channel. + 7 + 1 + read-write + + + I2S_RX_TDM_CHAN8_EN + 1: Enable the valid data input of I2S RX TDM channel 8. 0: Disable, just input 0 in this channel. + 8 + 1 + read-write + + + I2S_RX_TDM_CHAN9_EN + 1: Enable the valid data input of I2S RX TDM channel 9. 0: Disable, just input 0 in this channel. + 9 + 1 + read-write + + + I2S_RX_TDM_CHAN10_EN + 1: Enable the valid data input of I2S RX TDM channel 10. 0: Disable, just input 0 in this channel. + 10 + 1 + read-write + + + I2S_RX_TDM_CHAN11_EN + 1: Enable the valid data input of I2S RX TDM channel 11. 0: Disable, just input 0 in this channel. + 11 + 1 + read-write + + + I2S_RX_TDM_CHAN12_EN + 1: Enable the valid data input of I2S RX TDM channel 12. 0: Disable, just input 0 in this channel. + 12 + 1 + read-write + + + I2S_RX_TDM_CHAN13_EN + 1: Enable the valid data input of I2S RX TDM channel 13. 0: Disable, just input 0 in this channel. + 13 + 1 + read-write + + + I2S_RX_TDM_CHAN14_EN + 1: Enable the valid data input of I2S RX TDM channel 14. 0: Disable, just input 0 in this channel. + 14 + 1 + read-write + + + I2S_RX_TDM_CHAN15_EN + 1: Enable the valid data input of I2S RX TDM channel 15. 0: Disable, just input 0 in this channel. + 15 + 1 + read-write + + + I2S_RX_TDM_TOT_CHAN_NUM + The total channel number of I2S TX TDM mode. + 16 + 4 + read-write + + + + + I2S_TX_TDM_CTRL + I2S TX TDM mode control register + 0x54 + 0x20 + 0x0000FFFF + + + I2S_TX_TDM_CHAN0_EN + 1: Enable the valid data output of I2S TX TDM channel 0. 0: Disable, just output 0 in this channel. + 0 + 1 + read-write + + + I2S_TX_TDM_CHAN1_EN + 1: Enable the valid data output of I2S TX TDM channel 1. 0: Disable, just output 0 in this channel. + 1 + 1 + read-write + + + I2S_TX_TDM_CHAN2_EN + 1: Enable the valid data output of I2S TX TDM channel 2. 0: Disable, just output 0 in this channel. + 2 + 1 + read-write + + + I2S_TX_TDM_CHAN3_EN + 1: Enable the valid data output of I2S TX TDM channel 3. 0: Disable, just output 0 in this channel. + 3 + 1 + read-write + + + I2S_TX_TDM_CHAN4_EN + 1: Enable the valid data output of I2S TX TDM channel 4. 0: Disable, just output 0 in this channel. + 4 + 1 + read-write + + + I2S_TX_TDM_CHAN5_EN + 1: Enable the valid data output of I2S TX TDM channel 5. 0: Disable, just output 0 in this channel. + 5 + 1 + read-write + + + I2S_TX_TDM_CHAN6_EN + 1: Enable the valid data output of I2S TX TDM channel 6. 0: Disable, just output 0 in this channel. + 6 + 1 + read-write + + + I2S_TX_TDM_CHAN7_EN + 1: Enable the valid data output of I2S TX TDM channel 7. 0: Disable, just output 0 in this channel. + 7 + 1 + read-write + + + I2S_TX_TDM_CHAN8_EN + 1: Enable the valid data output of I2S TX TDM channel 8. 0: Disable, just output 0 in this channel. + 8 + 1 + read-write + + + I2S_TX_TDM_CHAN9_EN + 1: Enable the valid data output of I2S TX TDM channel 9. 0: Disable, just output 0 in this channel. + 9 + 1 + read-write + + + I2S_TX_TDM_CHAN10_EN + 1: Enable the valid data output of I2S TX TDM channel 10. 0: Disable, just output 0 in this channel. + 10 + 1 + read-write + + + I2S_TX_TDM_CHAN11_EN + 1: Enable the valid data output of I2S TX TDM channel 11. 0: Disable, just output 0 in this channel. + 11 + 1 + read-write + + + I2S_TX_TDM_CHAN12_EN + 1: Enable the valid data output of I2S TX TDM channel 12. 0: Disable, just output 0 in this channel. + 12 + 1 + read-write + + + I2S_TX_TDM_CHAN13_EN + 1: Enable the valid data output of I2S TX TDM channel 13. 0: Disable, just output 0 in this channel. + 13 + 1 + read-write + + + I2S_TX_TDM_CHAN14_EN + 1: Enable the valid data output of I2S TX TDM channel 14. 0: Disable, just output 0 in this channel. + 14 + 1 + read-write + + + I2S_TX_TDM_CHAN15_EN + 1: Enable the valid data output of I2S TX TDM channel 15. 0: Disable, just output 0 in this channel. + 15 + 1 + read-write + + + I2S_TX_TDM_TOT_CHAN_NUM + The total channel number of I2S TX TDM mode. + 16 + 4 + read-write + + + I2S_TX_TDM_SKIP_MSK_EN + When DMA TX buffer stores the data of (REG_TX_TDM_TOT_CHAN_NUM + 1) channels, and only the data of the enabled channels is sent, then this bit should be set. Clear it when all the data stored in DMA TX buffer is for enabled channels. + 20 + 1 + read-write + + + + + I2S_RX_TIMING + I2S RX timing control register + 0x58 + 0x20 + + + I2S_RX_SD_IN_DM + The delay mode of I2S Rx SD input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 0 + 2 + read-write + + + I2S_RX_WS_OUT_DM + The delay mode of I2S Rx WS output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 16 + 2 + read-write + + + I2S_RX_BCK_OUT_DM + The delay mode of I2S Rx BCK output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 20 + 2 + read-write + + + I2S_RX_WS_IN_DM + The delay mode of I2S Rx WS input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 24 + 2 + read-write + + + I2S_RX_BCK_IN_DM + The delay mode of I2S Rx BCK input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 28 + 2 + read-write + + + + + I2S_TX_TIMING + I2S TX timing control register + 0x5C + 0x20 + + + I2S_TX_SD_OUT_DM + The delay mode of I2S TX SD output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 0 + 2 + read-write + + + I2S_TX_SD1_OUT_DM + The delay mode of I2S TX SD1 output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 4 + 2 + read-write + + + I2S_TX_WS_OUT_DM + The delay mode of I2S TX WS output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 16 + 2 + read-write + + + I2S_TX_BCK_OUT_DM + The delay mode of I2S TX BCK output signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 20 + 2 + read-write + + + I2S_TX_WS_IN_DM + The delay mode of I2S TX WS input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 24 + 2 + read-write + + + I2S_TX_BCK_IN_DM + The delay mode of I2S TX BCK input signal. 0: bypass. 1: delay by pos edge. 2: delay by neg edge. 3: not used. + 28 + 2 + read-write + + + + + I2S_LC_HUNG_CONF + I2S HUNG configure register. + 0x60 + 0x20 + 0x00000810 + + + I2S_LC_FIFO_TIMEOUT + the i2s_tx_hung_int interrupt or the i2s_rx_hung_int interrupt will be triggered when fifo hung counter is equal to this value + 0 + 8 + read-write + + + I2S_LC_FIFO_TIMEOUT_SHIFT + The bits are used to scale tick counter threshold. The tick counter is reset when counter value >= 88000/2^i2s_lc_fifo_timeout_shift + 8 + 3 + read-write + + + I2S_LC_FIFO_TIMEOUT_ENA + The enable bit for FIFO timeout + 11 + 1 + read-write + + + + + I2S_RXEOF_NUM + I2S RX data number control register. + 0x64 + 0x20 + 0x00000040 + + + I2S_RX_EOF_NUM + The receive data bit length is (I2S_RX_BITS_MOD[4:0] + 1) * (REG_RX_EOF_NUM[11:0] + 1) . It will trigger in_suc_eof interrupt in the configured DMA RX channel. + 0 + 12 + read-write + + + + + I2S_CONF_SIGLE_DATA + I2S signal data register + 0x68 + 0x20 + + + I2S_SINGLE_DATA + The configured constant channel data to be sent out. + 0 + 32 + read-write + + + + + I2S_STATE + I2S TX status register + 0x6C + 0x20 + 0x00000001 + + + I2S_TX_IDLE + 1: i2s_tx is idle state. 0: i2s_tx is working. + 0 + 1 + read-only + + + + + I2S_DATE + Version control register + 0x80 + 0x20 + 0x02009070 + + + I2S_DATE + I2S version control register + 0 + 28 + read-write + + + + + + + INTERRUPT_CORE0 + Interrupt Core + INTERRUPT_CORE0 + 0x600C2000 + + 0x0 + 0x1A4 + registers + + + WIFI_MAC + 0 + + + WIFI_NMI + 1 + + + WIFI_BB + 2 + + + BT_MAC + 3 + + + BT_BB + 4 + + + BT_BB_NMI + 5 + + + RWBT + 6 + + + RWBLE + 7 + + + RWBT_NMI + 8 + + + RWBLE_NMI + 9 + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE + 85 + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE + 86 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE + 87 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_SIZE + 88 + + + CACHE_CORE0_ACS + 94 + + + + PRO_MAC_INTR_MAP + mac interrupt configuration register + 0x0 + 0x20 + 0x00000010 + + + MAC_INTR_MAP + this register used to map mac interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + MAC_NMI_MAP + mac_nmi interrupt configuration register + 0x4 + 0x20 + 0x00000010 + + + MAC_NMI_MAP + this register used to map_nmi interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PWR_INTR_MAP + pwr interrupt configuration register + 0x8 + 0x20 + 0x00000010 + + + PWR_INTR_MAP + this register used to map pwr interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + BB_INT_MAP + bb interrupt configuration register + 0xC + 0x20 + 0x00000010 + + + BB_INT_MAP + this register used to map bb interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + BT_MAC_INT_MAP + bb_mac interrupt configuration register + 0x10 + 0x20 + 0x00000010 + + + BT_MAC_INT_MAP + this register used to map bb_mac interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + BT_BB_INT_MAP + bt_bb interrupt configuration register + 0x14 + 0x20 + 0x00000010 + + + BT_BB_INT_MAP + this register used to map bt_bb interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + BT_BB_NMI_MAP + bt_bb_nmi interrupt configuration register + 0x18 + 0x20 + 0x00000010 + + + BT_BB_NMI_MAP + this register used to map bb_bt_nmi interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + RWBT_IRQ_MAP + rwbt_irq interrupt configuration register + 0x1C + 0x20 + 0x00000010 + + + RWBT_IRQ_MAP + this register used to map rwbt_irq interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + RWBLE_IRQ_MAP + rwble_irq interrupt configuration register + 0x20 + 0x20 + 0x00000010 + + + RWBLE_IRQ_MAP + this register used to map rwble_irq interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + RWBT_NMI_MAP + rwbt_nmi interrupt configuration register + 0x24 + 0x20 + 0x00000010 + + + RWBT_NMI_MAP + this register used to map mac rwbt_nmi to one of core0's external interrupt + 0 + 5 + read-write + + + + + RWBLE_NMI_MAP + rwble_nmi interrupt configuration register + 0x28 + 0x20 + 0x00000010 + + + RWBLE_NMI_MAP + this register used to map rwble_nmi interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + I2C_MST_INT_MAP + i2c_mst interrupt configuration register + 0x2C + 0x20 + 0x00000010 + + + I2C_MST_INT_MAP + this register used to map i2c_mst interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SLC0_INTR_MAP + slc0 interrupt configuration register + 0x30 + 0x20 + 0x00000010 + + + SLC0_INTR_MAP + this register used to map slc0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SLC1_INTR_MAP + slc1 interrupt configuration register + 0x34 + 0x20 + 0x00000010 + + + SLC1_INTR_MAP + this register used to map slc1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + UHCI0_INTR_MAP + uhci0 interrupt configuration register + 0x38 + 0x20 + 0x00000010 + + + UHCI0_INTR_MAP + this register used to map uhci0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + UHCI1_INTR_MAP + uhci1 interrupt configuration register + 0x3C + 0x20 + 0x00000010 + + + UHCI1_INTR_MAP + this register used to map uhci1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_PRO_MAP + gpio_interrupt_pro interrupt configuration register + 0x40 + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_PRO_MAP + this register used to map gpio_interrupt_pro interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_PRO_NMI_MAP + gpio_interrupt_pro_nmi interrupt configuration register + 0x44 + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_PRO_NMI_MAP + this register used to map gpio_interrupt_pro_nmi interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_APP_MAP + gpio_interrupt_app interrupt configuration register + 0x48 + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_APP_MAP + this register used to map gpio_interrupt_app interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_APP_NMI_MAP + gpio_interrupt_app_nmi interrupt configuration register + 0x4C + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_APP_NMI_MAP + this register used to map gpio_interrupt_app_nmi interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_1_MAP + spi_intr_1 interrupt configuration register + 0x50 + 0x20 + 0x00000010 + + + SPI_INTR_1_MAP + this register used to map spi_intr_1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_2_MAP + spi_intr_2 interrupt configuration register + 0x54 + 0x20 + 0x00000010 + + + SPI_INTR_2_MAP + this register used to map spi_intr_2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_3_MAP + spi_intr_3 interrupt configuration register + 0x58 + 0x20 + 0x00000010 + + + SPI_INTR_3_MAP + this register used to map spi_intr_3 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_4_MAP + spi_intr_4 interrupt configuration register + 0x5C + 0x20 + 0x00000010 + + + SPI_INTR_4_MAP + this register used to map spi_intr_4 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + LCD_CAM_INT_MAP + lcd_cam interrupt configuration register + 0x60 + 0x20 + 0x00000010 + + + LCD_CAM_INT_MAP + this register used to map lcd_cam interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + I2S0_INT_MAP + i2s0 interrupt configuration register + 0x64 + 0x20 + 0x00000010 + + + I2S0_INT_MAP + this register used to map i2s0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + I2S1_INT_MAP + i2s1 interrupt configuration register + 0x68 + 0x20 + 0x00000010 + + + I2S1_INT_MAP + this register used to map i2s1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + UART_INTR_MAP + uart interrupt configuration register + 0x6C + 0x20 + 0x00000010 + + + UART_INTR_MAP + this register used to map uart interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + UART1_INTR_MAP + uart1 interrupt configuration register + 0x70 + 0x20 + 0x00000010 + + + UART1_INTR_MAP + this register used to map uart1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + UART2_INTR_MAP + uart2 interrupt configuration register + 0x74 + 0x20 + 0x00000010 + + + UART2_INTR_MAP + this register used to map uart2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SDIO_HOST_INTERRUPT_MAP + sdio_host interrupt configuration register + 0x78 + 0x20 + 0x00000010 + + + SDIO_HOST_INTERRUPT_MAP + this register used to map sdio_host interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PWM0_INTR_MAP + pwm0 interrupt configuration register + 0x7C + 0x20 + 0x00000010 + + + PWM0_INTR_MAP + this register used to map pwm0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PWM1_INTR_MAP + pwm1 interrupt configuration register + 0x80 + 0x20 + 0x00000010 + + + PWM1_INTR_MAP + this register used to map pwm1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PWM2_INTR_MAP + pwm2 interrupt configuration register + 0x84 + 0x20 + 0x00000010 + + + PWM2_INTR_MAP + this register used to map pwm2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PWM3_INTR_MAP + pwm3 interrupt configuration register + 0x88 + 0x20 + 0x00000010 + + + PWM3_INTR_MAP + this register used to map pwm3 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + LEDC_INT_MAP + ledc interrupt configuration register + 0x8C + 0x20 + 0x00000010 + + + LEDC_INT_MAP + this register used to map ledc interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + EFUSE_INT_MAP + efuse interrupt configuration register + 0x90 + 0x20 + 0x00000010 + + + EFUSE_INT_MAP + this register used to map efuse interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CAN_INT_MAP + can interrupt configuration register + 0x94 + 0x20 + 0x00000010 + + + CAN_INT_MAP + this register used to map can interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + USB_INTR_MAP + usb interrupt configuration register + 0x98 + 0x20 + 0x00000010 + + + USB_INTR_MAP + this register used to map usb interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + RTC_CORE_INTR_MAP + rtc_core interrupt configuration register + 0x9C + 0x20 + 0x00000010 + + + RTC_CORE_INTR_MAP + this register used to map rtc_core interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + RMT_INTR_MAP + rmt interrupt configuration register + 0xA0 + 0x20 + 0x00000010 + + + RMT_INTR_MAP + this register used to map rmt interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PCNT_INTR_MAP + pcnt interrupt configuration register + 0xA4 + 0x20 + 0x00000010 + + + PCNT_INTR_MAP + this register used to map pcnt interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + I2C_EXT0_INTR_MAP + i2c_ext0 interrupt configuration register + 0xA8 + 0x20 + 0x00000010 + + + I2C_EXT0_INTR_MAP + this register used to map i2c_ext0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + I2C_EXT1_INTR_MAP + i2c_ext1 interrupt configuration register + 0xAC + 0x20 + 0x00000010 + + + I2C_EXT1_INTR_MAP + this register used to map i2c_ext1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI2_DMA_INT_MAP + spi2_dma interrupt configuration register + 0xB0 + 0x20 + 0x00000010 + + + SPI2_DMA_INT_MAP + this register used to map spi2_dma interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI3_DMA_INT_MAP + spi3_dma interrupt configuration register + 0xB4 + 0x20 + 0x00000010 + + + SPI3_DMA_INT_MAP + this register used to map spi3_dma interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI4_DMA_INT_MAP + spi4_dma interrupt configuration register + 0xB8 + 0x20 + 0x00000010 + + + SPI4_DMA_INT_MAP + this register used to map spi4_dma interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + WDG_INT_MAP + wdg interrupt configuration register + 0xBC + 0x20 + 0x00000010 + + + WDG_INT_MAP + this register used to map wdg interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TIMER_INT1_MAP + timer_int1 interrupt configuration register + 0xC0 + 0x20 + 0x00000010 + + + TIMER_INT1_MAP + this register used to map timer_int1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TIMER_INT2_MAP + timer_int2 interrupt configuration register + 0xC4 + 0x20 + 0x00000010 + + + TIMER_INT2_MAP + this register used to map timer_int2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TG_T0_INT_MAP + tg_t0 interrupt configuration register + 0xC8 + 0x20 + 0x00000010 + + + TG_T0_INT_MAP + this register used to map tg_t0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TG_T1_INT_MAP + tg_t1 interrupt configuration register + 0xCC + 0x20 + 0x00000010 + + + TG_T1_INT_MAP + this register used to map tg_t1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TG_WDT_INT_MAP + tg_wdt interrupt configuration register + 0xD0 + 0x20 + 0x00000010 + + + TG_WDT_INT_MAP + this register used to map rg_wdt interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TG1_T0_INT_MAP + tg1_t0 interrupt configuration register + 0xD4 + 0x20 + 0x00000010 + + + TG1_T0_INT_MAP + this register used to map tg1_t0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TG1_T1_INT_MAP + tg1_t1 interrupt configuration register + 0xD8 + 0x20 + 0x00000010 + + + TG1_T1_INT_MAP + this register used to map tg1_t1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + TG1_WDT_INT_MAP + tg1_wdt interrupt configuration register + 0xDC + 0x20 + 0x00000010 + + + TG1_WDT_INT_MAP + this register used to map tg1_wdt interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CACHE_IA_INT_MAP + cache_ia interrupt configuration register + 0xE0 + 0x20 + 0x00000010 + + + CACHE_IA_INT_MAP + this register used to map cache_ia interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SYSTIMER_TARGET0_INT_MAP + systimer_target0 interrupt configuration register + 0xE4 + 0x20 + 0x00000010 + + + SYSTIMER_TARGET0_INT_MAP + this register used to map systimer_target0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SYSTIMER_TARGET1_INT_MAP + systimer_target1 interrupt configuration register + 0xE8 + 0x20 + 0x00000010 + + + SYSTIMER_TARGET1_INT_MAP + this register used to map systimer_target1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SYSTIMER_TARGET2_INT_MAP + systimer_target2 interrupt configuration register + 0xEC + 0x20 + 0x00000010 + + + SYSTIMER_TARGET2_INT_MAP + this register used to map systimer_target2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SPI_MEM_REJECT_INTR_MAP + spi_mem_reject interrupt configuration register + 0xF0 + 0x20 + 0x00000010 + + + SPI_MEM_REJECT_INTR_MAP + this register used to map spi_mem_reject interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DCACHE_PRELOAD_INT_MAP + dcache_prelaod interrupt configuration register + 0xF4 + 0x20 + 0x00000010 + + + DCACHE_PRELOAD_INT_MAP + this register used to map dcache_prelaod interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + ICACHE_PRELOAD_INT_MAP + icache_preload interrupt configuration register + 0xF8 + 0x20 + 0x00000010 + + + ICACHE_PRELOAD_INT_MAP + this register used to map icache_preload interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DCACHE_SYNC_INT_MAP + dcache_sync interrupt configuration register + 0xFC + 0x20 + 0x00000010 + + + DCACHE_SYNC_INT_MAP + this register used to map dcache_sync interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + ICACHE_SYNC_INT_MAP + icache_sync interrupt configuration register + 0x100 + 0x20 + 0x00000010 + + + ICACHE_SYNC_INT_MAP + this register used to map icache_sync interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + APB_ADC_INT_MAP + apb_adc interrupt configuration register + 0x104 + 0x20 + 0x00000010 + + + APB_ADC_INT_MAP + this register used to map apb_adc interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH0_INT_MAP + dma_in_ch0 interrupt configuration register + 0x108 + 0x20 + 0x00000010 + + + DMA_IN_CH0_INT_MAP + this register used to map dma_in_ch0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH1_INT_MAP + dma_in_ch1 interrupt configuration register + 0x10C + 0x20 + 0x00000010 + + + DMA_IN_CH1_INT_MAP + this register used to map dma_in_ch1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH2_INT_MAP + dma_in_ch2 interrupt configuration register + 0x110 + 0x20 + 0x00000010 + + + DMA_IN_CH2_INT_MAP + this register used to map dma_in_ch2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH3_INT_MAP + dma_in_ch3 interrupt configuration register + 0x114 + 0x20 + 0x00000010 + + + DMA_IN_CH3_INT_MAP + this register used to map dma_in_ch3 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH4_INT_MAP + dma_in_ch4 interrupt configuration register + 0x118 + 0x20 + 0x00000010 + + + DMA_IN_CH4_INT_MAP + this register used to map dma_in_ch4 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH0_INT_MAP + dma_out_ch0 interrupt configuration register + 0x11C + 0x20 + 0x00000010 + + + DMA_OUT_CH0_INT_MAP + this register used to map dma_out_ch0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH1_INT_MAP + dma_out_ch1 interrupt configuration register + 0x120 + 0x20 + 0x00000010 + + + DMA_OUT_CH1_INT_MAP + this register used to map dma_out_ch1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH2_INT_MAP + dma_out_ch2 interrupt configuration register + 0x124 + 0x20 + 0x00000010 + + + DMA_OUT_CH2_INT_MAP + this register used to map dma_out_ch2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH3_INT_MAP + dma_out_ch3 interrupt configuration register + 0x128 + 0x20 + 0x00000010 + + + DMA_OUT_CH3_INT_MAP + this register used to map dma_out_ch3 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH4_INT_MAP + dma_out_ch4 interrupt configuration register + 0x12C + 0x20 + 0x00000010 + + + DMA_OUT_CH4_INT_MAP + this register used to map dma_out_ch4 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + RSA_INT_MAP + rsa interrupt configuration register + 0x130 + 0x20 + 0x00000010 + + + RSA_INT_MAP + this register used to map rsa interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + AES_INT_MAP + aes interrupt configuration register + 0x134 + 0x20 + 0x00000010 + + + AES_INT_MAP + this register used to map aes interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + SHA_INT_MAP + sha interrupt configuration register + 0x138 + 0x20 + 0x00000010 + + + SHA_INT_MAP + this register used to map sha interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_0_MAP + cpu_intr_from_cpu_0 interrupt configuration register + 0x13C + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_0_MAP + this register used to map cpu_intr_from_cpu_0 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_1_MAP + cpu_intr_from_cpu_1 interrupt configuration register + 0x140 + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_1_MAP + this register used to map cpu_intr_from_cpu_1 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_2_MAP + cpu_intr_from_cpu_2 interrupt configuration register + 0x144 + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_2_MAP + this register used to map cpu_intr_from_cpu_2 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_3_MAP + cpu_intr_from_cpu_3 interrupt configuration register + 0x148 + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_3_MAP + this register used to map cpu_intr_from_cpu_3 interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + ASSIST_DEBUG_INTR_MAP + assist_debug interrupt configuration register + 0x14C + 0x20 + 0x00000010 + + + ASSIST_DEBUG_INTR_MAP + this register used to map assist_debug interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_INTR_MAP + dma_pms_monitor_violatile interrupt configuration register + 0x150 + 0x20 + 0x00000010 + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map dma_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core0_IRam0_pms_monitor_violatile interrupt configuration register + 0x154 + 0x20 + 0x00000010 + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core0_IRam0_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core0_DRam0_pms_monitor_violatile interrupt configuration register + 0x158 + 0x20 + 0x00000010 + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core0_DRam0_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + core0_PIF_pms_monitor_violatile interrupt configuration register + 0x15C + 0x20 + 0x00000010 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core0_PIF_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + core0_PIF_pms_monitor_violatile_size interrupt configuration register + 0x160 + 0x20 + 0x00000010 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + this register used to map core0_PIF_pms_monitor_violatile_size interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core1_IRam0_pms_monitor_violatile interrupt configuration register + 0x164 + 0x20 + 0x00000010 + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core1_IRam0_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core1_DRam0_pms_monitor_violatile interrupt configuration register + 0x168 + 0x20 + 0x00000010 + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core1_DRam0_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + core1_PIF_pms_monitor_violatile interrupt configuration register + 0x16C + 0x20 + 0x00000010 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core1_PIF_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + core1_PIF_pms_monitor_violatile_size interrupt configuration register + 0x170 + 0x20 + 0x00000010 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + this register used to map core1_PIF_pms_monitor_violatile_size interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + BACKUP_PMS_VIOLATE_INTR_MAP + backup_pms_monitor_violatile interrupt configuration register + 0x174 + 0x20 + 0x00000010 + + + BACKUP_PMS_VIOLATE_INTR_MAP + this register used to map backup_pms_monitor_violatile interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CACHE_CORE0_ACS_INT_MAP + cache_core0_acs interrupt configuration register + 0x178 + 0x20 + 0x00000010 + + + CACHE_CORE0_ACS_INT_MAP + this register used to map cache_core0_acs interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + CACHE_CORE1_ACS_INT_MAP + cache_core1_acs interrupt configuration register + 0x17C + 0x20 + 0x00000010 + + + CACHE_CORE1_ACS_INT_MAP + this register used to map cache_core1_acs interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + USB_DEVICE_INT_MAP + usb_device interrupt configuration register + 0x180 + 0x20 + 0x00000010 + + + USB_DEVICE_INT_MAP + this register used to map usb_device interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PERI_BACKUP_INT_MAP + peri_backup interrupt configuration register + 0x184 + 0x20 + 0x00000010 + + + PERI_BACKUP_INT_MAP + this register used to map peri_backup interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + DMA_EXTMEM_REJECT_INT_MAP + dma_extmem_reject interrupt configuration register + 0x188 + 0x20 + 0x00000010 + + + DMA_EXTMEM_REJECT_INT_MAP + this register used to map dma_extmem_reject interrupt to one of core0's external interrupt + 0 + 5 + read-write + + + + + PRO_INTR_STATUS_0 + interrupt status register + 0x18C + 0x20 + + + INTR_STATUS_0 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + PRO_INTR_STATUS_1 + interrupt status register + 0x190 + 0x20 + + + INTR_STATUS_1 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + PRO_INTR_STATUS_2 + interrupt status register + 0x194 + 0x20 + + + INTR_STATUS_2 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + PRO_INTR_STATUS_3 + interrupt status register + 0x198 + 0x20 + + + INTR_STATUS_3 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + CLOCK_GATE + clock gate register + 0x19C + 0x20 + 0x00000001 + + + REG_CLK_EN + this register uesd to control clock-gating interupt martrix + 0 + 1 + read-write + + + + + DATE + version register + 0x7FC + 0x20 + 0x02012300 + + + INTERRUPT_REG_DATE + version register + 0 + 28 + read-write + + + + + + + INTERRUPT_CORE1 + Interrupt Core + INTERRUPT_CORE1 + 0x600C2800 + + 0x0 + 0x1A4 + registers + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE + 89 + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE + 90 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE + 91 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_SIZE + 92 + + + CACHE_CORE1_ACS + 95 + + + + APP_MAC_INTR_MAP + mac interrupt configuration register + 0x800 + 0x20 + 0x00000010 + + + MAC_INTR_MAP + this register used to map mac interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + MAC_NMI_MAP + mac_nmi interrupt configuration register + 0x804 + 0x20 + 0x00000010 + + + MAC_NMI_MAP + this register used to map_nmi interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PWR_INTR_MAP + pwr interrupt configuration register + 0x808 + 0x20 + 0x00000010 + + + PWR_INTR_MAP + this register used to map pwr interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + BB_INT_MAP + bb interrupt configuration register + 0x80C + 0x20 + 0x00000010 + + + BB_INT_MAP + this register used to map bb interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + BT_MAC_INT_MAP + bb_mac interrupt configuration register + 0x810 + 0x20 + 0x00000010 + + + BT_MAC_INT_MAP + this register used to map bb_mac interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + BT_BB_INT_MAP + bt_bb interrupt configuration register + 0x814 + 0x20 + 0x00000010 + + + BT_BB_INT_MAP + this register used to map bt_bb interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + BT_BB_NMI_MAP + bt_bb_nmi interrupt configuration register + 0x818 + 0x20 + 0x00000010 + + + BT_BB_NMI_MAP + this register used to map bb_bt_nmi interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RWBT_IRQ_MAP + rwbt_irq interrupt configuration register + 0x81C + 0x20 + 0x00000010 + + + RWBT_IRQ_MAP + this register used to map rwbt_irq interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RWBLE_IRQ_MAP + rwble_irq interrupt configuration register + 0x820 + 0x20 + 0x00000010 + + + RWBLE_IRQ_MAP + this register used to map rwble_irq interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RWBT_NMI_MAP + rwbt_nmi interrupt configuration register + 0x824 + 0x20 + 0x00000010 + + + RWBT_NMI_MAP + this register used to map rwbt_nmi interupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RWBLE_NMI_MAP + rwble_nmi interrupt configuration register + 0x828 + 0x20 + 0x00000010 + + + RWBLE_NMI_MAP + this register used to map rwble_nmi interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + I2C_MST_INT_MAP + i2c_mst interrupt configuration register + 0x82C + 0x20 + 0x00000010 + + + I2C_MST_INT_MAP + this register used to map i2c_mst interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SLC0_INTR_MAP + slc0 interrupt configuration register + 0x830 + 0x20 + 0x00000010 + + + SLC0_INTR_MAP + this register used to map slc0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SLC1_INTR_MAP + slc1 interrupt configuration register + 0x834 + 0x20 + 0x00000010 + + + SLC1_INTR_MAP + this register used to map slc1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + UHCI0_INTR_MAP + uhci0 interrupt configuration register + 0x838 + 0x20 + 0x00000010 + + + UHCI0_INTR_MAP + this register used to map uhci0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + UHCI1_INTR_MAP + uhci1 interrupt configuration register + 0x83C + 0x20 + 0x00000010 + + + UHCI1_INTR_MAP + this register used to map uhci1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_PRO_MAP + gpio_interrupt_pro interrupt configuration register + 0x840 + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_PRO_MAP + this register used to map gpio_interrupt_pro interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_PRO_NMI_MAP + gpio_interrupt_pro_nmi interrupt configuration register + 0x844 + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_PRO_NMI_MAP + this register used to map gpio_interrupt_pro_nmi interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_APP_MAP + gpio_interrupt_app interrupt configuration register + 0x848 + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_APP_MAP + this register used to map gpio_interrupt_app interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + GPIO_INTERRUPT_APP_NMI_MAP + gpio_interrupt_app_nmi interrupt configuration register + 0x84C + 0x20 + 0x00000010 + + + GPIO_INTERRUPT_APP_NMI_MAP + this register used to map gpio_interrupt_app_nmi interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_1_MAP + spi_intr_1 interrupt configuration register + 0x850 + 0x20 + 0x00000010 + + + SPI_INTR_1_MAP + this register used to map spi_intr_1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_2_MAP + spi_intr_2 interrupt configuration register + 0x854 + 0x20 + 0x00000010 + + + SPI_INTR_2_MAP + this register used to map spi_intr_2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_3_MAP + spi_intr_3 interrupt configuration register + 0x858 + 0x20 + 0x00000010 + + + SPI_INTR_3_MAP + this register used to map spi_intr_3 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI_INTR_4_MAP + spi_intr_4 interrupt configuration register + 0x85C + 0x20 + 0x00000010 + + + SPI_INTR_4_MAP + this register used to map spi_intr_4 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + LCD_CAM_INT_MAP + lcd_cam interrupt configuration register + 0x860 + 0x20 + 0x00000010 + + + LCD_CAM_INT_MAP + this register used to map lcd_cam interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + I2S0_INT_MAP + i2s0 interrupt configuration register + 0x864 + 0x20 + 0x00000010 + + + I2S0_INT_MAP + this register used to map i2s0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + I2S1_INT_MAP + i2s1 interrupt configuration register + 0x868 + 0x20 + 0x00000010 + + + I2S1_INT_MAP + this register used to map i2s1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + UART_INTR_MAP + uart interrupt configuration register + 0x86C + 0x20 + 0x00000010 + + + UART_INTR_MAP + this register used to map uart interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + UART1_INTR_MAP + uart1 interrupt configuration register + 0x870 + 0x20 + 0x00000010 + + + UART1_INTR_MAP + this register used to map uart1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + UART2_INTR_MAP + uart2 interrupt configuration register + 0x874 + 0x20 + 0x00000010 + + + UART2_INTR_MAP + this register used to map uart2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SDIO_HOST_INTERRUPT_MAP + sdio_host interrupt configuration register + 0x878 + 0x20 + 0x00000010 + + + SDIO_HOST_INTERRUPT_MAP + this register used to map sdio_host interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PWM0_INTR_MAP + pwm0 interrupt configuration register + 0x87C + 0x20 + 0x00000010 + + + PWM0_INTR_MAP + this register used to map pwm0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PWM1_INTR_MAP + pwm1 interrupt configuration register + 0x880 + 0x20 + 0x00000010 + + + PWM1_INTR_MAP + this register used to map pwm1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PWM2_INTR_MAP + pwm2 interrupt configuration register + 0x884 + 0x20 + 0x00000010 + + + PWM2_INTR_MAP + this register used to map pwm2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PWM3_INTR_MAP + pwm3 interrupt configuration register + 0x888 + 0x20 + 0x00000010 + + + PWM3_INTR_MAP + this register used to map pwm3 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + LEDC_INT_MAP + ledc interrupt configuration register + 0x88C + 0x20 + 0x00000010 + + + LEDC_INT_MAP + this register used to map ledc interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + EFUSE_INT_MAP + efuse interrupt configuration register + 0x890 + 0x20 + 0x00000010 + + + EFUSE_INT_MAP + this register used to map efuse interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CAN_INT_MAP + can interrupt configuration register + 0x894 + 0x20 + 0x00000010 + + + CAN_INT_MAP + this register used to map can interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + USB_INTR_MAP + usb interrupt configuration register + 0x898 + 0x20 + 0x00000010 + + + USB_INTR_MAP + this register used to map usb interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RTC_CORE_INTR_MAP + rtc_core interrupt configuration register + 0x89C + 0x20 + 0x00000010 + + + RTC_CORE_INTR_MAP + this register used to map rtc_core interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RMT_INTR_MAP + rmt interrupt configuration register + 0x8A0 + 0x20 + 0x00000010 + + + RMT_INTR_MAP + this register used to map rmt interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PCNT_INTR_MAP + pcnt interrupt configuration register + 0x8A4 + 0x20 + 0x00000010 + + + PCNT_INTR_MAP + this register used to map pcnt interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + I2C_EXT0_INTR_MAP + i2c_ext0 interrupt configuration register + 0x8A8 + 0x20 + 0x00000010 + + + I2C_EXT0_INTR_MAP + this register used to map i2c_ext0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + I2C_EXT1_INTR_MAP + i2c_ext1 interrupt configuration register + 0x8AC + 0x20 + 0x00000010 + + + I2C_EXT1_INTR_MAP + this register used to map i2c_ext1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI2_DMA_INT_MAP + spi2_dma interrupt configuration register + 0x8B0 + 0x20 + 0x00000010 + + + SPI2_DMA_INT_MAP + this register used to map spi2_dma interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI3_DMA_INT_MAP + spi3_dma interrupt configuration register + 0x8B4 + 0x20 + 0x00000010 + + + SPI3_DMA_INT_MAP + this register used to map spi3_dma interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI4_DMA_INT_MAP + spi4_dma interrupt configuration register + 0x8B8 + 0x20 + 0x00000010 + + + SPI4_DMA_INT_MAP + this register used to map spi4_dma interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + WDG_INT_MAP + wdg interrupt configuration register + 0x8BC + 0x20 + 0x00000010 + + + WDG_INT_MAP + this register used to map wdg interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TIMER_INT1_MAP + timer_int1 interrupt configuration register + 0x8C0 + 0x20 + 0x00000010 + + + TIMER_INT1_MAP + this register used to map timer_int1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TIMER_INT2_MAP + timer_int2 interrupt configuration register + 0x8C4 + 0x20 + 0x00000010 + + + TIMER_INT2_MAP + this register used to map timer_int2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TG_T0_INT_MAP + tg_t0 interrupt configuration register + 0x8C8 + 0x20 + 0x00000010 + + + TG_T0_INT_MAP + this register used to map tg_t0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TG_T1_INT_MAP + tg_t1 interrupt configuration register + 0x8CC + 0x20 + 0x00000010 + + + TG_T1_INT_MAP + this register used to map tg_t1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TG_WDT_INT_MAP + tg_wdt interrupt configuration register + 0x8D0 + 0x20 + 0x00000010 + + + TG_WDT_INT_MAP + this register used to map rg_wdt interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TG1_T0_INT_MAP + tg1_t0 interrupt configuration register + 0x8D4 + 0x20 + 0x00000010 + + + TG1_T0_INT_MAP + this register used to map tg1_t0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TG1_T1_INT_MAP + tg1_t1 interrupt configuration register + 0x8D8 + 0x20 + 0x00000010 + + + TG1_T1_INT_MAP + this register used to map tg1_t1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + TG1_WDT_INT_MAP + tg1_wdt interrupt configuration register + 0x8DC + 0x20 + 0x00000010 + + + TG1_WDT_INT_MAP + this register used to map tg1_wdt interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CACHE_IA_INT_MAP + cache_ia interrupt configuration register + 0x8E0 + 0x20 + 0x00000010 + + + CACHE_IA_INT_MAP + this register used to map cache_ia interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SYSTIMER_TARGET0_INT_MAP + systimer_target0 interrupt configuration register + 0x8E4 + 0x20 + 0x00000010 + + + SYSTIMER_TARGET0_INT_MAP + this register used to map systimer_target0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SYSTIMER_TARGET1_INT_MAP + systimer_target1 interrupt configuration register + 0x8E8 + 0x20 + 0x00000010 + + + SYSTIMER_TARGET1_INT_MAP + this register used to map systimer_target1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SYSTIMER_TARGET2_INT_MAP + systimer_target2 interrupt configuration register + 0x8EC + 0x20 + 0x00000010 + + + SYSTIMER_TARGET2_INT_MAP + this register used to map systimer_target2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SPI_MEM_REJECT_INTR_MAP + spi_mem_reject interrupt configuration register + 0x8F0 + 0x20 + 0x00000010 + + + SPI_MEM_REJECT_INTR_MAP + this register used to map spi_mem_reject interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DCACHE_PRELOAD_INT_MAP + dcache_prelaod interrupt configuration register + 0x8F4 + 0x20 + 0x00000010 + + + DCACHE_PRELOAD_INT_MAP + this register used to map dcache_prelaod interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + ICACHE_PRELOAD_INT_MAP + icache_preload interrupt configuration register + 0x8F8 + 0x20 + 0x00000010 + + + ICACHE_PRELOAD_INT_MAP + this register used to map icache_preload interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DCACHE_SYNC_INT_MAP + dcache_sync interrupt configuration register + 0x8FC + 0x20 + 0x00000010 + + + DCACHE_SYNC_INT_MAP + this register used to map dcache_sync interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + ICACHE_SYNC_INT_MAP + icache_sync interrupt configuration register + 0x900 + 0x20 + 0x00000010 + + + ICACHE_SYNC_INT_MAP + this register used to map icache_sync interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + APB_ADC_INT_MAP + apb_adc interrupt configuration register + 0x904 + 0x20 + 0x00000010 + + + APB_ADC_INT_MAP + this register used to map apb_adc interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH0_INT_MAP + dma_in_ch0 interrupt configuration register + 0x908 + 0x20 + 0x00000010 + + + DMA_IN_CH0_INT_MAP + this register used to map dma_in_ch0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH1_INT_MAP + dma_in_ch1 interrupt configuration register + 0x90C + 0x20 + 0x00000010 + + + DMA_IN_CH1_INT_MAP + this register used to map dma_in_ch1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH2_INT_MAP + dma_in_ch2 interrupt configuration register + 0x910 + 0x20 + 0x00000010 + + + DMA_IN_CH2_INT_MAP + this register used to map dma_in_ch2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH3_INT_MAP + dma_in_ch3 interrupt configuration register + 0x914 + 0x20 + 0x00000010 + + + DMA_IN_CH3_INT_MAP + this register used to map dma_in_ch3 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_IN_CH4_INT_MAP + dma_in_ch4 interrupt configuration register + 0x918 + 0x20 + 0x00000010 + + + DMA_IN_CH4_INT_MAP + this register used to map dma_in_ch4 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH0_INT_MAP + dma_out_ch0 interrupt configuration register + 0x91C + 0x20 + 0x00000010 + + + DMA_OUT_CH0_INT_MAP + this register used to map dma_out_ch0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH1_INT_MAP + dma_out_ch1 interrupt configuration register + 0x920 + 0x20 + 0x00000010 + + + DMA_OUT_CH1_INT_MAP + this register used to map dma_out_ch1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH2_INT_MAP + dma_out_ch2 interrupt configuration register + 0x924 + 0x20 + 0x00000010 + + + DMA_OUT_CH2_INT_MAP + this register used to map dma_out_ch2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH3_INT_MAP + dma_out_ch3 interrupt configuration register + 0x928 + 0x20 + 0x00000010 + + + DMA_OUT_CH3_INT_MAP + this register used to map dma_out_ch3 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_OUT_CH4_INT_MAP + dma_out_ch4 interrupt configuration register + 0x92C + 0x20 + 0x00000010 + + + DMA_OUT_CH4_INT_MAP + this register used to map dma_out_ch4 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + RSA_INT_MAP + rsa interrupt configuration register + 0x930 + 0x20 + 0x00000010 + + + RSA_INT_MAP + this register used to map rsa interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + AES_INT_MAP + aes interrupt configuration register + 0x934 + 0x20 + 0x00000010 + + + AES_INT_MAP + this register used to map aes interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + SHA_INT_MAP + sha interrupt configuration register + 0x938 + 0x20 + 0x00000010 + + + SHA_INT_MAP + this register used to map sha interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_0_MAP + cpu_intr_from_cpu_0 interrupt configuration register + 0x93C + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_0_MAP + this register used to map cpu_intr_from_cpu_0 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_1_MAP + cpu_intr_from_cpu_1 interrupt configuration register + 0x940 + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_1_MAP + this register used to map cpu_intr_from_cpu_1 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_2_MAP + cpu_intr_from_cpu_2 interrupt configuration register + 0x944 + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_2_MAP + this register used to map cpu_intr_from_cpu_2 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CPU_INTR_FROM_CPU_3_MAP + cpu_intr_from_cpu_3 interrupt configuration register + 0x948 + 0x20 + 0x00000010 + + + CPU_INTR_FROM_CPU_3_MAP + this register used to map cpu_intr_from_cpu_3 interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + ASSIST_DEBUG_INTR_MAP + assist_debug interrupt configuration register + 0x94C + 0x20 + 0x00000010 + + + ASSIST_DEBUG_INTR_MAP + this register used to map assist_debug interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_INTR_MAP + dma_pms_monitor_violatile interrupt configuration register + 0x950 + 0x20 + 0x00000010 + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map dma_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core0_IRam0_pms_monitor_violatile interrupt configuration register + 0x954 + 0x20 + 0x00000010 + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core0_IRam0_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core0_DRam0_pms_monitor_violatile interrupt configuration register + 0x958 + 0x20 + 0x00000010 + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core0_DRam0_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + core0_PIF_pms_monitor_violatile interrupt configuration register + 0x95C + 0x20 + 0x00000010 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core0_PIF_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + core0_PIF_pms_monitor_violatile_size interrupt configuration register + 0x960 + 0x20 + 0x00000010 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + this register used to map core0_PIF_pms_monitor_violatile_size interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core1_IRam0_pms_monitor_violatile interrupt configuration register + 0x964 + 0x20 + 0x00000010 + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core1_IRam0_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + core1_DRam0_pms_monitor_violatile interrupt configuration register + 0x968 + 0x20 + 0x00000010 + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core1_DRam0_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + core1_PIF_pms_monitor_violatile interrupt configuration register + 0x96C + 0x20 + 0x00000010 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_INTR_MAP + this register used to map core1_PIF_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + core1_PIF_pms_monitor_violatile_size interrupt configuration register + 0x970 + 0x20 + 0x00000010 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_SIZE_INTR_MAP + this register used to map core1_PIF_pms_monitor_violatile_size interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + BACKUP_PMS_VIOLATE_INTR_MAP + backup_pms_monitor_violatile interrupt configuration register + 0x974 + 0x20 + 0x00000010 + + + BACKUP_PMS_VIOLATE_INTR_MAP + this register used to map backup_pms_monitor_violatile interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CACHE_CORE0_ACS_INT_MAP + cache_core0_acs interrupt configuration register + 0x978 + 0x20 + 0x00000010 + + + CACHE_CORE0_ACS_INT_MAP + this register used to map cache_core0_acs interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + CACHE_CORE1_ACS_INT_MAP + cache_core1_acs interrupt configuration register + 0x97C + 0x20 + 0x00000010 + + + CACHE_CORE1_ACS_INT_MAP + this register used to map cache_core1_acs interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + USB_DEVICE_INT_MAP + usb_device interrupt configuration register + 0x980 + 0x20 + 0x00000010 + + + USB_DEVICE_INT_MAP + this register used to map usb_device interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + PERI_BACKUP_INT_MAP + peri_backup interrupt configuration register + 0x984 + 0x20 + 0x00000010 + + + PERI_BACKUP_INT_MAP + this register used to map peri_backup interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + DMA_EXTMEM_REJECT_INT_MAP + dma_extmem_reject interrupt configuration register + 0x988 + 0x20 + 0x00000010 + + + DMA_EXTMEM_REJECT_INT_MAP + this register used to map dma_extmem_reject interrupt to one of core1's external interrupt + 0 + 5 + read-write + + + + + APP_INTR_STATUS_0 + interrupt status register + 0x98C + 0x20 + + + INTR_STATUS_0 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + APP_INTR_STATUS_1 + interrupt status register + 0x990 + 0x20 + + + INTR_STATUS_1 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + APP_INTR_STATUS_2 + interrupt status register + 0x994 + 0x20 + + + INTR_STATUS_2 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + APP_INTR_STATUS_3 + interrupt status register + 0x998 + 0x20 + + + INTR_STATUS_3 + this register store the status of the first 32 interrupt source + 0 + 32 + read-only + + + + + CLOCK_GATE + clock gate register + 0x99C + 0x20 + 0x00000001 + + + REG_CLK_EN + this register uesd to control clock-gating interupt martrix + 0 + 1 + read-write + + + + + DATE + version register + 0xFFC + 0x20 + 0x02012300 + + + INTERRUPT_DATE + version register + 0 + 28 + read-write + + + + + + + IO_MUX + Input/Output Multiplexer + IO_MUX + 0x60009000 + + 0x0 + 0xCC + registers + + + + PIN_CTRL + Clock Output Configuration Register + 0x0 + 0x20 + 0x000007FF + + + CLK_OUT1 + If you want to output clock for I2S to CLK_OUT_out1, set this register to 0x0. CLK_OUT_out1 can be found in peripheral output signals. + 0 + 4 + read-write + + + CLK_OUT2 + If you want to output clock for I2S to CLK_OUT_out2, set this register to 0x0. CLK_OUT_out2 can be found in peripheral output signals. + 4 + 4 + read-write + + + CLK_OUT3 + If you want to output clock for I2S to CLK_OUT_out3, set this register to 0x0. CLK_OUT_out3 can be found in peripheral output signals. + 8 + 4 + read-write + + + + + 49 + 0x4 + GPIO%s + IO MUX Configure Register for pad GPIO0 + 0x4 + 0x20 + 0x00000B00 + + + MCU_OE + Output enable of the pad in sleep mode. 1: output enabled; 0: output disabled. + 0 + 1 + read-write + + + SLP_SEL + Sleep mode selection of this pad. Set to 1 to put the pad in pad mode. + 1 + 1 + read-write + + + MCU_WPD + Pull-down enable of the pad in sleep mode. 1: internal pull-down enabled; 0: internal pull-down disabled. + 2 + 1 + read-write + + + MCU_WPU + Pull-up enable of the pad during sleep mode. 1: internal pull-up enabled; 0: internal pull-up disabled. + 3 + 1 + read-write + + + MCU_IE + Input enable of the pad during sleep mode. 1: input enabled; 0: input disabled. + 4 + 1 + read-write + + + FUN_WPD + Pull-down enable of the pad. 1: internal pull-down enabled; 0: internal pull-down disabled. + 7 + 1 + read-write + + + FUN_WPU + Pull-up enable of the pad. 1: internal pull-up enabled; 0: internal pull-up disabled. + 8 + 1 + read-write + + + FUN_IE + Input enable of the pad. 1: input enabled; 0: input disabled. + 9 + 1 + read-write + + + FUN_DRV + Select the drive strength of the pad. 0: ~5 mA; 1: ~10mA; 2: ~20mA; 3: ~40mA. + 10 + 2 + read-write + + + MCU_SEL + Select IO MUX function for this signal. 0: Select Function 1; 1: Select Function 2; etc. + 12 + 3 + read-write + + + FILTER_EN + Enable filter for pin input signals. 1: Filter enabled; 2: Filter disabled. + 15 + 1 + read-write + + + + + DATE + IO MUX Version Control Register + 0xFC + 0x20 + 0x01907160 + + + REG_DATE + Version control register + 0 + 28 + read-write + + + + + + + LCD_CAM + Peripheral LCD_CAM + LCD_CAM + 0x60041000 + + 0x0 + 0x48 + registers + + + + LCD_CLOCK + LCD clock register + 0x0 + 0x20 + 0x00000843 + + + LCD_CLKCNT_N + f_LCD_PCLK = f_LCD_CLK / (reg_clkcnt_N + 1) when reg_clk_equ_sysclk is 0. + 0 + 6 + read-write + + + LCD_CLK_EQU_SYSCLK + 1: f_LCD_PCLK = f_LCD_CLK. 0: f_LCD_PCLK = f_LCD_CLK / (reg_clkcnt_N + 1). + 6 + 1 + read-write + + + LCD_CK_IDLE_EDGE + 1: LCD_PCLK line is high when idle 0: LCD_PCLK line is low when idle. + 7 + 1 + read-write + + + LCD_CK_OUT_EDGE + 1: LCD_PCLK high in first half clock cycle. 0: LCD_PCLK low in first half clock cycle. + 8 + 1 + read-write + + + LCD_CLKM_DIV_NUM + Integral LCD clock divider value + 9 + 8 + read-write + + + LCD_CLKM_DIV_B + Fractional clock divider numerator value + 17 + 6 + read-write + + + LCD_CLKM_DIV_A + Fractional clock divider denominator value + 23 + 6 + read-write + + + LCD_CLK_SEL + Select LCD module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock. + 29 + 2 + read-write + + + CLK_EN + Set this bit to enable clk gate + 31 + 1 + read-write + + + + + CAM_CTRL + Camera configuration register + 0x4 + 0x20 + 0x00000800 + + + CAM_STOP_EN + Camera stop enable signal, 1: camera stops when DMA Rx FIFO is full. 0: Not stop. + 0 + 1 + read-write + + + CAM_VSYNC_FILTER_THRES + Filter threshold value for CAM_VSYNC signal. + 1 + 3 + read-write + + + CAM_UPDATE + 1: Update Camera registers, will be cleared by hardware. 0 : Not care. + 4 + 1 + read-write + + + CAM_BYTE_ORDER + 1: Change data bit order, change CAM_DATA_in[7:0] to CAM_DATA_in[0:7] in one byte mode, and bits[15:0] to bits[0:15] in two byte mode. 0: Not change. + 5 + 1 + read-write + + + CAM_BIT_ORDER + 1: invert data byte order, only valid in 2 byte mode. 0: Not change. + 6 + 1 + read-write + + + CAM_LINE_INT_EN + 1: Enable to generate CAM_HS_INT. 0: Disable. + 7 + 1 + read-write + + + CAM_VS_EOF_EN + 1: CAM_VSYNC to generate in_suc_eof. 0: in_suc_eof is controlled by reg_cam_rec_data_cyclelen. + 8 + 1 + read-write + + + CAM_CLKM_DIV_NUM + Integral Camera clock divider value + 9 + 8 + read-write + + + CAM_CLKM_DIV_B + Fractional clock divider numerator value + 17 + 6 + read-write + + + CAM_CLKM_DIV_A + Fractional clock divider denominator value + 23 + 6 + read-write + + + CAM_CLK_SEL + Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock. + 29 + 2 + read-write + + + + + CAM_CTRL1 + Camera configuration register + 0x8 + 0x20 + + + CAM_REC_DATA_BYTELEN + Camera receive data byte length minus 1 to set DMA in_suc_eof_int. + 0 + 16 + read-write + + + CAM_LINE_INT_NUM + The line number minus 1 to generate cam_hs_int. + 16 + 6 + read-write + + + CAM_CLK_INV + 1: Invert the input signal CAM_PCLK. 0: Not invert. + 22 + 1 + read-write + + + CAM_VSYNC_FILTER_EN + 1: Enable CAM_VSYNC filter function. 0: bypass. + 23 + 1 + read-write + + + CAM_2BYTE_EN + 1: The bit number of input data is 9~16. 0: The bit number of input data is 0~8. + 24 + 1 + read-write + + + CAM_DE_INV + CAM_DE invert enable signal, valid in high level. + 25 + 1 + read-write + + + CAM_HSYNC_INV + CAM_HSYNC invert enable signal, valid in high level. + 26 + 1 + read-write + + + CAM_VSYNC_INV + CAM_VSYNC invert enable signal, valid in high level. + 27 + 1 + read-write + + + CAM_VH_DE_MODE_EN + 1: Input control signals are CAM_DE CAM_HSYNC and CAM_VSYNC is 1. 0: Input control signals are CAM_DE and CAM_VSYNC. CAM_HSYNC and CAM_DE are all 1 the the same time. + 28 + 1 + read-write + + + CAM_START + Camera module start signal. + 29 + 1 + read-write + + + CAM_RESET + Camera module reset signal. + 30 + 1 + write-only + + + CAM_AFIFO_RESET + Camera AFIFO reset signal. + 31 + 1 + write-only + + + + + CAM_RGB_YUV + Camera configuration register + 0xC + 0x20 + 0x00C00000 + + + CAM_CONV_8BITS_DATA_INV + 1:invert every two 8bits input data. 2. disabled. + 21 + 1 + read-write + + + CAM_CONV_YUV2YUV_MODE + 0: to yuv422. 1: to yuv420. 2: to yuv411. 3: disabled. To enable yuv2yuv mode, trans_mode must be set to 1. + 22 + 2 + read-write + + + CAM_CONV_YUV_MODE + 0: yuv422. 1: yuv420. 2: yuv411. When in yuv2yuv mode, yuv_mode decides the yuv mode of Data_in + 24 + 2 + read-write + + + CAM_CONV_PROTOCOL_MODE + 0:BT601. 1:BT709. + 26 + 1 + read-write + + + CAM_CONV_DATA_OUT_MODE + LIMIT or FULL mode of Data out. 0: limit. 1: full + 27 + 1 + read-write + + + CAM_CONV_DATA_IN_MODE + LIMIT or FULL mode of Data in. 0: limit. 1: full + 28 + 1 + read-write + + + CAM_CONV_MODE_8BITS_ON + 0: 16bits mode. 1: 8bits mode. + 29 + 1 + read-write + + + CAM_CONV_TRANS_MODE + 0: YUV to RGB. 1: RGB to YUV. + 30 + 1 + read-write + + + CAM_CONV_BYPASS + 0: Bypass converter. 1: Enable converter. + 31 + 1 + read-write + + + + + LCD_RGB_YUV + LCD configuration register + 0x10 + 0x20 + 0x00C00000 + + + LCD_CONV_8BITS_DATA_INV + 1:invert every two 8bits input data. 2. disabled. + 20 + 1 + read-write + + + LCD_CONV_TXTORX + 0: txtorx mode off. 1: txtorx mode on. + 21 + 1 + read-write + + + LCD_CONV_YUV2YUV_MODE + 0: to yuv422. 1: to yuv420. 2: to yuv411. 3: disabled. To enable yuv2yuv mode, trans_mode must be set to 1. + 22 + 2 + read-write + + + LCD_CONV_YUV_MODE + 0: yuv422. 1: yuv420. 2: yuv411. When in yuv2yuv mode, yuv_mode decides the yuv mode of Data_in + 24 + 2 + read-write + + + LCD_CONV_PROTOCOL_MODE + 0:BT601. 1:BT709. + 26 + 1 + read-write + + + LCD_CONV_DATA_OUT_MODE + LIMIT or FULL mode of Data out. 0: limit. 1: full + 27 + 1 + read-write + + + LCD_CONV_DATA_IN_MODE + LIMIT or FULL mode of Data in. 0: limit. 1: full + 28 + 1 + read-write + + + LCD_CONV_MODE_8BITS_ON + 0: 16bits mode. 1: 8bits mode. + 29 + 1 + read-write + + + LCD_CONV_TRANS_MODE + 0: YUV to RGB. 1: RGB to YUV. + 30 + 1 + read-write + + + LCD_CONV_BYPASS + 0: Bypass converter. 1: Enable converter. + 31 + 1 + read-write + + + + + LCD_USER + LCD configuration register + 0x14 + 0x20 + 0x00000001 + + + LCD_DOUT_CYCLELEN + The output data cycles minus 1 of LCD module. + 0 + 13 + read-write + + + LCD_ALWAYS_OUT_EN + LCD always output when LCD is in LCD_DOUT state, unless reg_lcd_start is cleared or reg_lcd_reset is set. + 13 + 1 + read-write + + + LCD_8BITS_ORDER + 1: invert every two data byte, valid in 1 byte mode. 0: Not change. + 19 + 1 + read-write + + + LCD_UPDATE + 1: Update LCD registers, will be cleared by hardware. 0 : Not care. + 20 + 1 + read-write + + + LCD_BIT_ORDER + 1: Change data bit order, change LCD_DATA_out[7:0] to LCD_DATA_out[0:7] in one byte mode, and bits[15:0] to bits[0:15] in two byte mode. 0: Not change. + 21 + 1 + read-write + + + LCD_BYTE_ORDER + 1: invert data byte order, only valid in 2 byte mode. 0: Not change. + 22 + 1 + read-write + + + LCD_2BYTE_EN + 1: The bit number of output LCD data is 9~16. 0: The bit number of output LCD data is 0~8. + 23 + 1 + read-write + + + LCD_DOUT + 1: Be able to send data out in LCD sequence when LCD starts. 0: Disable. + 24 + 1 + read-write + + + LCD_DUMMY + 1: Enable DUMMY phase in LCD sequence when LCD starts. 0: Disable. + 25 + 1 + read-write + + + LCD_CMD + 1: Be able to send command in LCD sequence when LCD starts. 0: Disable. + 26 + 1 + read-write + + + LCD_START + LCD start sending data enable signal, valid in high level. + 27 + 1 + read-write + + + LCD_RESET + The value of command. + 28 + 1 + write-only + + + LCD_DUMMY_CYCLELEN + The dummy cycle length minus 1. + 29 + 2 + read-write + + + LCD_CMD_2_CYCLE_EN + The cycle length of command phase. 1: 2 cycles. 0: 1 cycle. + 31 + 1 + read-write + + + + + LCD_MISC + LCD configuration register + 0x18 + 0x20 + 0x000000D6 + + + LCD_AFIFO_THRESHOLD_NUM + The awfull threshold number of lcd_afifo. + 1 + 5 + read-write + + + LCD_VFK_CYCLELEN + The setup cycle length minus 1 in LCD non-RGB mode. + 6 + 6 + read-write + + + LCD_VBK_CYCLELEN + The vertical back blank region cycle length minus 1 in LCD RGB mode, or the hold time cycle length in LCD non-RGB mode. + 12 + 13 + read-write + + + LCD_NEXT_FRAME_EN + 1: Send the next frame data when the current frame is sent out. 0: LCD stops when the current frame is sent out. + 25 + 1 + read-write + + + LCD_BK_EN + 1: Enable blank region when LCD sends data out. 0: No blank region. + 26 + 1 + read-write + + + LCD_AFIFO_RESET + LCD AFIFO reset signal. + 27 + 1 + write-only + + + LCD_CD_DATA_SET + 1: LCD_CD = !reg_cd_idle_edge when lcd_st[2:0] is in LCD_DOUT state. 0: LCD_CD = reg_cd_idle_edge. + 28 + 1 + read-write + + + LCD_CD_DUMMY_SET + 1: LCD_CD = !reg_cd_idle_edge when lcd_st[2:0] is in LCD_DUMMY state. 0: LCD_CD = reg_cd_idle_edge. + 29 + 1 + read-write + + + LCD_CD_CMD_SET + 1: LCD_CD = !reg_cd_idle_edge when lcd_st[2:0] is in LCD_CMD state. 0: LCD_CD = reg_cd_idle_edge. + 30 + 1 + read-write + + + LCD_CD_IDLE_EDGE + The default value of LCD_CD. + 31 + 1 + read-write + + + + + LCD_CTRL + LCD configuration register + 0x1C + 0x20 + + + LCD_HB_FRONT + It is the horizontal blank front porch of a frame. + 0 + 11 + read-write + + + LCD_VA_HEIGHT + It is the vertical active height of a frame. + 11 + 10 + read-write + + + LCD_VT_HEIGHT + It is the vertical total height of a frame. + 21 + 10 + read-write + + + LCD_RGB_MODE_EN + 1: Enable reg mode input vsync, hsync, de. 0: Disable. + 31 + 1 + read-write + + + + + LCD_CTRL1 + LCD configuration register + 0x20 + 0x20 + + + LCD_VB_FRONT + It is the vertical blank front porch of a frame. + 0 + 8 + read-write + + + LCD_HA_WIDTH + It is the horizontal active width of a frame. + 8 + 12 + read-write + + + LCD_HT_WIDTH + It is the horizontal total width of a frame. + 20 + 12 + read-write + + + + + LCD_CTRL2 + LCD configuration register + 0x24 + 0x20 + 0x00010001 + + + LCD_VSYNC_WIDTH + It is the position of LCD_VSYNC active pulse in a line. + 0 + 7 + read-write + + + LCD_VSYNC_IDLE_POL + It is the idle value of LCD_VSYNC. + 7 + 1 + read-write + + + LCD_DE_IDLE_POL + It is the idle value of LCD_DE. + 8 + 1 + read-write + + + LCD_HS_BLANK_EN + 1: The pulse of LCD_HSYNC is out in vertical blanking lines RGB mode. 0: LCD_HSYNC pulse is valid only in active region lines in RGB mode. + 9 + 1 + read-write + + + LCD_HSYNC_WIDTH + It is the position of LCD_HSYNC active pulse in a line. + 16 + 7 + read-write + + + LCD_HSYNC_IDLE_POL + It is the idle value of LCD_HSYNC. + 23 + 1 + read-write + + + LCD_HSYNC_POSITION + It is the position of LCD_HSYNC active pulse in a line. + 24 + 8 + read-write + + + + + LCD_CMD_VAL + LCD configuration register + 0x28 + 0x20 + + + LCD_CMD_VALUE + The LCD write command value. + 0 + 32 + read-write + + + + + LCD_DLY_MODE + LCD configuration register + 0x30 + 0x20 + + + LCD_CD_MODE + The output LCD_CD is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 0 + 2 + read-write + + + LCD_DE_MODE + The output LCD_DE is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 2 + 2 + read-write + + + LCD_HSYNC_MODE + The output LCD_HSYNC is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 4 + 2 + read-write + + + LCD_VSYNC_MODE + The output LCD_VSYNC is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 6 + 2 + read-write + + + + + LCD_DATA_DOUT_MODE + LCD configuration register + 0x38 + 0x20 + + + DOUT0_MODE + The output data bit 0 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 0 + 2 + read-write + + + DOUT1_MODE + The output data bit 2 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 2 + 2 + read-write + + + DOUT2_MODE + The output data bit 4 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 4 + 2 + read-write + + + DOUT3_MODE + The output data bit 6 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 6 + 2 + read-write + + + DOUT4_MODE + The output data bit 8 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 8 + 2 + read-write + + + DOUT5_MODE + The output data bit 10 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 10 + 2 + read-write + + + DOUT6_MODE + The output data bit 12 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 12 + 2 + read-write + + + DOUT7_MODE + The output data bit 14 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 14 + 2 + read-write + + + DOUT8_MODE + The output data bit 16 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 16 + 2 + read-write + + + DOUT9_MODE + The output data bit 18 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 18 + 2 + read-write + + + DOUT10_MODE + The output data bit 20 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 20 + 2 + read-write + + + DOUT11_MODE + The output data bit 22 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 22 + 2 + read-write + + + DOUT12_MODE + The output data bit 24 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 24 + 2 + read-write + + + DOUT13_MODE + The output data bit 26 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 26 + 2 + read-write + + + DOUT14_MODE + The output data bit 28 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 28 + 2 + read-write + + + DOUT15_MODE + The output data bit 30 is delayed by module clock LCD_CLK. 0: output without delayed. 1: delay by the positive edge of LCD_CLK. 2: delay by the negative edge of LCD_CLK. + 30 + 2 + read-write + + + + + LC_DMA_INT_ENA + LCD_camera DMA inturrupt enable register + 0x64 + 0x20 + + + LCD_VSYNC_INT_ENA + The enable bit for LCD frame end interrupt. + 0 + 1 + read-write + + + LCD_TRANS_DONE_INT_ENA + The enable bit for lcd transfer end interrupt. + 1 + 1 + read-write + + + CAM_VSYNC_INT_ENA + The enable bit for Camera frame end interrupt. + 2 + 1 + read-write + + + CAM_HS_INT_ENA + The enable bit for Camera line interrupt. + 3 + 1 + read-write + + + + + LC_DMA_INT_RAW + LCD_camera DMA raw inturrupt status register + 0x68 + 0x20 + + + LCD_VSYNC_INT_RAW + The raw bit for LCD frame end interrupt. + 0 + 1 + read-only + + + LCD_TRANS_DONE_INT_RAW + The raw bit for lcd transfer end interrupt. + 1 + 1 + read-only + + + CAM_VSYNC_INT_RAW + The raw bit for Camera frame end interrupt. + 2 + 1 + read-only + + + CAM_HS_INT_RAW + The raw bit for Camera line interrupt. + 3 + 1 + read-only + + + + + LC_DMA_INT_ST + LCD_camera DMA masked inturrupt status register + 0x6C + 0x20 + + + LCD_VSYNC_INT_ST + The status bit for LCD frame end interrupt. + 0 + 1 + read-only + + + LCD_TRANS_DONE_INT_ST + The status bit for lcd transfer end interrupt. + 1 + 1 + read-only + + + CAM_VSYNC_INT_ST + The status bit for Camera frame end interrupt. + 2 + 1 + read-only + + + CAM_HS_INT_ST + The status bit for Camera transfer end interrupt. + 3 + 1 + read-only + + + + + LC_DMA_INT_CLR + LCD_camera DMA inturrupt clear register + 0x70 + 0x20 + + + LCD_VSYNC_INT_CLR + The clear bit for LCD frame end interrupt. + 0 + 1 + write-only + + + LCD_TRANS_DONE_INT_CLR + The clear bit for lcd transfer end interrupt. + 1 + 1 + write-only + + + CAM_VSYNC_INT_CLR + The clear bit for Camera frame end interrupt. + 2 + 1 + write-only + + + CAM_HS_INT_CLR + The clear bit for Camera line interrupt. + 3 + 1 + write-only + + + + + LC_REG_DATE + Version register + 0xFC + 0x20 + 0x02003020 + + + LC_DATE + LCD_CAM version control register + 0 + 28 + read-write + + + + + + + LEDC + LED PWM (Pulse Width Modulation) Controller + LEDC + 0x60019000 + + 0x0 + 0xD8 + registers + + + LEDC + 35 + + + + 8 + 0x14 + CH%s_CONF0 + Configuration register 0 for channel %s + 0x0 + 0x20 + + + TIMER_SEL + This field is used to select one of timers for channel %s. + +0: select timer0 + +1: select timer1 + +2: select timer2 + +3: select timer3 + 0 + 2 + read-write + + + SIG_OUT_EN + Set this bit to enable signal output on channel %s. + 2 + 1 + read-write + + + IDLE_LV + This bit is used to control the output value when channel %s is inactive (when LEDC_SIG_OUT_EN_CH%s is 0). + 3 + 1 + read-write + + + PARA_UP + This bit is used to update LEDC_HPOINT_CH%s, LEDC_DUTY_START_CH%s, LEDC_SIG_OUT_EN_CH%s, LEDC_TIMER_SEL_CH%s, LEDC_DUTY_NUM_CH%s, LEDC_DUTY_CYCLE_CH%s, LEDC_DUTY_SCALE_CH%s, LEDC_DUTY_INC_CH%s, and LEDC_OVF_CNT_EN_CH%s fields for channel %s, and will be automatically cleared by hardware. + 4 + 1 + write-only + + + OVF_NUM + This register is used to configure the maximum times of overflow minus 1. + +The LEDC_OVF_CNT_CH%s_INT interrupt will be triggered when channel %s overflows for (LEDC_OVF_NUM_CH%s + 1) times. + 5 + 10 + read-write + + + OVF_CNT_EN + This bit is used to enable the ovf_cnt of channel %s. + 15 + 1 + read-write + + + OVF_CNT_RESET + Set this bit to reset the ovf_cnt of channel %s. + 16 + 1 + write-only + + + OVF_CNT_RESET_ST + This is the status bit of LEDC_OVF_CNT_RESET_CH%s. + 17 + 1 + read-only + + + + + 8 + 0x14 + CH%s_HPOINT + High point register for channel %s + 0x4 + 0x20 + + + HPOINT + The output value changes to high when the selected timers has reached the value specified by this register. + 0 + 14 + read-write + + + + + 8 + 0x14 + CH%s_DUTY + Initial duty cycle for channel %s + 0x8 + 0x20 + + + DUTY + This register is used to change the output duty by controlling the Lpoint. + +The output value turns to low when the selected timers has reached the Lpoint. + 0 + 19 + read-write + + + + + 8 + 0x14 + CH%s_CONF1 + Configuration register 1 for channel %s + 0xC + 0x20 + 0x40000000 + + + DUTY_SCALE + This register is used to configure the changing step scale of duty on channel %s. + 0 + 10 + read-write + + + DUTY_CYCLE + The duty will change every LEDC_DUTY_CYCLE_CH%s on channel %s. + 10 + 10 + read-write + + + DUTY_NUM + This register is used to control the number of times the duty cycle will be changed. + 20 + 10 + read-write + + + DUTY_INC + This register is used to increase or decrease the duty of output signal on channel %s. 1: Increase; 0: Decrease. + 30 + 1 + read-write + + + DUTY_START + Other configured fields in LEDC_CH%s_CONF1_REG will start to take effect when this bit is set to 1. + 31 + 1 + read-write + + + + + 8 + 0x14 + CH%s_DUTY_R + Current duty cycle for channel %s + 0x10 + 0x20 + + + DUTY_R + This register stores the current duty of output signal on channel %s. + 0 + 19 + read-only + + + + + 4 + 0x8 + TIMER%s_CONF + Timer %s configuration + 0xA0 + 0x20 + 0x00800000 + + + DUTY_RES + This register is used to control the range of the counter in timer %s. + 0 + 4 + read-write + + + CLK_DIV + This register is used to configure the divisor for the divider in timer %s. + +The least significant eight bits represent the fractional part. + 4 + 18 + read-write + + + PAUSE + This bit is used to suspend the counter in timer %s. + 22 + 1 + read-write + + + RST + This bit is used to reset timer %s. The counter will show 0 after reset. + 23 + 1 + read-write + + + TICK_SEL + This bit is used to select clock for timer %s. When this bit is set to 1 LEDC_APB_CLK_SEL[1:0] should be 1, otherwise the timer clock may be not accurate. + +1'h0: SLOW_CLK 1'h1: REF_TICK + 24 + 1 + read-write + + + PARA_UP + Set this bit to update LEDC_CLK_DIV_TIMER%s and LEDC_TIMER%s_DUTY_RES. + 25 + 1 + write-only + + + + + 4 + 0x8 + TIMER%s_VALUE + Timer %s current counter value + 0xA4 + 0x20 + + + CNT + This register stores the current counter value of timer %s. + 0 + 14 + read-only + + + + + INT_RAW + Raw interrupt status + 0xC0 + 0x20 + + + TIMER0_OVF_INT_RAW + Triggered when the timer0 has reached its maximum counter value. + 0 + 1 + read-only + + + TIMER1_OVF_INT_RAW + Triggered when the timer1 has reached its maximum counter value. + 1 + 1 + read-only + + + TIMER2_OVF_INT_RAW + Triggered when the timer2 has reached its maximum counter value. + 2 + 1 + read-only + + + TIMER3_OVF_INT_RAW + Triggered when the timer3 has reached its maximum counter value. + 3 + 1 + read-only + + + DUTY_CHNG_END_CH0_INT_RAW + Interrupt raw bit for channel 0. Triggered when the gradual change of duty has finished. + 4 + 1 + read-only + + + DUTY_CHNG_END_CH1_INT_RAW + Interrupt raw bit for channel 1. Triggered when the gradual change of duty has finished. + 5 + 1 + read-only + + + DUTY_CHNG_END_CH2_INT_RAW + Interrupt raw bit for channel 2. Triggered when the gradual change of duty has finished. + 6 + 1 + read-only + + + DUTY_CHNG_END_CH3_INT_RAW + Interrupt raw bit for channel 3. Triggered when the gradual change of duty has finished. + 7 + 1 + read-only + + + DUTY_CHNG_END_CH4_INT_RAW + Interrupt raw bit for channel 4. Triggered when the gradual change of duty has finished. + 8 + 1 + read-only + + + DUTY_CHNG_END_CH5_INT_RAW + Interrupt raw bit for channel 5. Triggered when the gradual change of duty has finished. + 9 + 1 + read-only + + + DUTY_CHNG_END_CH6_INT_RAW + Interrupt raw bit for channel 6. Triggered when the gradual change of duty has finished. + 10 + 1 + read-only + + + DUTY_CHNG_END_CH7_INT_RAW + Interrupt raw bit for channel 7. Triggered when the gradual change of duty has finished. + 11 + 1 + read-only + + + OVF_CNT_CH0_INT_RAW + Interrupt raw bit for channel 0. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH0. + 12 + 1 + read-only + + + OVF_CNT_CH1_INT_RAW + Interrupt raw bit for channel 1. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH1. + 13 + 1 + read-only + + + OVF_CNT_CH2_INT_RAW + Interrupt raw bit for channel 2. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH2. + 14 + 1 + read-only + + + OVF_CNT_CH3_INT_RAW + Interrupt raw bit for channel 3. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH3. + 15 + 1 + read-only + + + OVF_CNT_CH4_INT_RAW + Interrupt raw bit for channel 4. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH4. + 16 + 1 + read-only + + + OVF_CNT_CH5_INT_RAW + Interrupt raw bit for channel 5. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH5. + 17 + 1 + read-only + + + OVF_CNT_CH6_INT_RAW + Interrupt raw bit for channel 6. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH6. + 18 + 1 + read-only + + + OVF_CNT_CH7_INT_RAW + Interrupt raw bit for channel 7. Triggered when the ovf_cnt has reached the value specified by LEDC_OVF_NUM_CH7. + 19 + 1 + read-only + + + + + INT_ST + Masked interrupt status + 0xC4 + 0x20 + + + TIMER0_OVF_INT_ST + This is the masked interrupt status bit for the LEDC_TIMER0_OVF_INT interrupt when LEDC_TIMER0_OVF_INT_ENA is set to 1. + 0 + 1 + read-only + + + TIMER1_OVF_INT_ST + This is the masked interrupt status bit for the LEDC_TIMER1_OVF_INT interrupt when LEDC_TIMER1_OVF_INT_ENA is set to 1. + 1 + 1 + read-only + + + TIMER2_OVF_INT_ST + This is the masked interrupt status bit for the LEDC_TIMER2_OVF_INT interrupt when LEDC_TIMER2_OVF_INT_ENA is set to 1. + 2 + 1 + read-only + + + TIMER3_OVF_INT_ST + This is the masked interrupt status bit for the LEDC_TIMER3_OVF_INT interrupt when LEDC_TIMER3_OVF_INT_ENA is set to 1. + 3 + 1 + read-only + + + DUTY_CHNG_END_CH0_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH0_INT interrupt when LEDC_DUTY_CHNG_END_CH0_INT_ENAIS set to 1. + 4 + 1 + read-only + + + DUTY_CHNG_END_CH1_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH1_INT interrupt when LEDC_DUTY_CHNG_END_CH1_INT_ENAIS set to 1. + 5 + 1 + read-only + + + DUTY_CHNG_END_CH2_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH2_INT interrupt when LEDC_DUTY_CHNG_END_CH2_INT_ENAIS set to 1. + 6 + 1 + read-only + + + DUTY_CHNG_END_CH3_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH3_INT interrupt when LEDC_DUTY_CHNG_END_CH3_INT_ENAIS set to 1. + 7 + 1 + read-only + + + DUTY_CHNG_END_CH4_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH4_INT interrupt when LEDC_DUTY_CHNG_END_CH4_INT_ENAIS set to 1. + 8 + 1 + read-only + + + DUTY_CHNG_END_CH5_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH5_INT interrupt when LEDC_DUTY_CHNG_END_CH5_INT_ENAIS set to 1. + 9 + 1 + read-only + + + DUTY_CHNG_END_CH6_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH6_INT interrupt when LEDC_DUTY_CHNG_END_CH6_INT_ENAIS set to 1. + 10 + 1 + read-only + + + DUTY_CHNG_END_CH7_INT_ST + This is the masked interrupt status bit for the LEDC_DUTY_CHNG_END_CH7_INT interrupt when LEDC_DUTY_CHNG_END_CH7_INT_ENAIS set to 1. + 11 + 1 + read-only + + + OVF_CNT_CH0_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH0_INT interrupt when LEDC_OVF_CNT_CH0_INT_ENA is set to 1. + 12 + 1 + read-only + + + OVF_CNT_CH1_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH1_INT interrupt when LEDC_OVF_CNT_CH1_INT_ENA is set to 1. + 13 + 1 + read-only + + + OVF_CNT_CH2_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH2_INT interrupt when LEDC_OVF_CNT_CH2_INT_ENA is set to 1. + 14 + 1 + read-only + + + OVF_CNT_CH3_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH3_INT interrupt when LEDC_OVF_CNT_CH3_INT_ENA is set to 1. + 15 + 1 + read-only + + + OVF_CNT_CH4_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH4_INT interrupt when LEDC_OVF_CNT_CH4_INT_ENA is set to 1. + 16 + 1 + read-only + + + OVF_CNT_CH5_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH5_INT interrupt when LEDC_OVF_CNT_CH5_INT_ENA is set to 1. + 17 + 1 + read-only + + + OVF_CNT_CH6_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH6_INT interrupt when LEDC_OVF_CNT_CH6_INT_ENA is set to 1. + 18 + 1 + read-only + + + OVF_CNT_CH7_INT_ST + This is the masked interrupt status bit for the LEDC_OVF_CNT_CH7_INT interrupt when LEDC_OVF_CNT_CH7_INT_ENA is set to 1. + 19 + 1 + read-only + + + + + INT_ENA + Interrupt enable bits + 0xC8 + 0x20 + + + TIMER0_OVF_INT_ENA + The interrupt enable bit for the LEDC_TIMER0_OVF_INT interrupt. + 0 + 1 + read-write + + + TIMER1_OVF_INT_ENA + The interrupt enable bit for the LEDC_TIMER1_OVF_INT interrupt. + 1 + 1 + read-write + + + TIMER2_OVF_INT_ENA + The interrupt enable bit for the LEDC_TIMER2_OVF_INT interrupt. + 2 + 1 + read-write + + + TIMER3_OVF_INT_ENA + The interrupt enable bit for the LEDC_TIMER3_OVF_INT interrupt. + 3 + 1 + read-write + + + DUTY_CHNG_END_CH0_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH0_INT interrupt. + 4 + 1 + read-write + + + DUTY_CHNG_END_CH1_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH1_INT interrupt. + 5 + 1 + read-write + + + DUTY_CHNG_END_CH2_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH2_INT interrupt. + 6 + 1 + read-write + + + DUTY_CHNG_END_CH3_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH3_INT interrupt. + 7 + 1 + read-write + + + DUTY_CHNG_END_CH4_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH4_INT interrupt. + 8 + 1 + read-write + + + DUTY_CHNG_END_CH5_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH5_INT interrupt. + 9 + 1 + read-write + + + DUTY_CHNG_END_CH6_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH6_INT interrupt. + 10 + 1 + read-write + + + DUTY_CHNG_END_CH7_INT_ENA + The interrupt enable bit for the LEDC_DUTY_CHNG_END_CH7_INT interrupt. + 11 + 1 + read-write + + + OVF_CNT_CH0_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH0_INT interrupt. + 12 + 1 + read-write + + + OVF_CNT_CH1_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH1_INT interrupt. + 13 + 1 + read-write + + + OVF_CNT_CH2_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH2_INT interrupt. + 14 + 1 + read-write + + + OVF_CNT_CH3_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH3_INT interrupt. + 15 + 1 + read-write + + + OVF_CNT_CH4_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH4_INT interrupt. + 16 + 1 + read-write + + + OVF_CNT_CH5_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH5_INT interrupt. + 17 + 1 + read-write + + + OVF_CNT_CH6_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH6_INT interrupt. + 18 + 1 + read-write + + + OVF_CNT_CH7_INT_ENA + The interrupt enable bit for the LEDC_OVF_CNT_CH7_INT interrupt. + 19 + 1 + read-write + + + + + INT_CLR + Interrupt clear bits + 0xCC + 0x20 + + + TIMER0_OVF_INT_CLR + Set this bit to clear the LEDC_TIMER0_OVF_INT interrupt. + 0 + 1 + write-only + + + TIMER1_OVF_INT_CLR + Set this bit to clear the LEDC_TIMER1_OVF_INT interrupt. + 1 + 1 + write-only + + + TIMER2_OVF_INT_CLR + Set this bit to clear the LEDC_TIMER2_OVF_INT interrupt. + 2 + 1 + write-only + + + TIMER3_OVF_INT_CLR + Set this bit to clear the LEDC_TIMER3_OVF_INT interrupt. + 3 + 1 + write-only + + + DUTY_CHNG_END_CH0_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH0_INT interrupt. + 4 + 1 + write-only + + + DUTY_CHNG_END_CH1_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH1_INT interrupt. + 5 + 1 + write-only + + + DUTY_CHNG_END_CH2_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH2_INT interrupt. + 6 + 1 + write-only + + + DUTY_CHNG_END_CH3_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH3_INT interrupt. + 7 + 1 + write-only + + + DUTY_CHNG_END_CH4_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH4_INT interrupt. + 8 + 1 + write-only + + + DUTY_CHNG_END_CH5_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH5_INT interrupt. + 9 + 1 + write-only + + + DUTY_CHNG_END_CH6_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH6_INT interrupt. + 10 + 1 + write-only + + + DUTY_CHNG_END_CH7_INT_CLR + Set this bit to clear the LEDC_DUTY_CHNG_END_CH7_INT interrupt. + 11 + 1 + write-only + + + OVF_CNT_CH0_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH0_INT interrupt. + 12 + 1 + write-only + + + OVF_CNT_CH1_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH1_INT interrupt. + 13 + 1 + write-only + + + OVF_CNT_CH2_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH2_INT interrupt. + 14 + 1 + write-only + + + OVF_CNT_CH3_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH3_INT interrupt. + 15 + 1 + write-only + + + OVF_CNT_CH4_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH4_INT interrupt. + 16 + 1 + write-only + + + OVF_CNT_CH5_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH5_INT interrupt. + 17 + 1 + write-only + + + OVF_CNT_CH6_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH6_INT interrupt. + 18 + 1 + write-only + + + OVF_CNT_CH7_INT_CLR + Set this bit to clear the LEDC_OVF_CNT_CH7_INT interrupt. + 19 + 1 + write-only + + + + + CONF + Global ledc configuration register + 0xD0 + 0x20 + + + APB_CLK_SEL + This bit is used to select clock source for the 4 timers . + +2'd1: APB_CLK 2'd2: RTC8M_CLK 2'd3: XTAL_CLK + 0 + 2 + read-write + + + CLK_EN + This bit is used to control clock. + +1'b1: Force clock on for register. 1'h0: Support clock only when application writes registers. + 31 + 1 + read-write + + + + + DATE + Version control register + 0xFC + 0x20 + 0x19040200 + + + DATE + This is the version control register. + 0 + 32 + read-write + + + + + + + PCNT + Pulse Count Controller + PCNT + 0x60017000 + + 0x0 + 0x68 + registers + + + PCNT + 41 + + + + 4 + 0xC + U%s_CONF0 + Configuration register 0 for unit %s + 0x0 + 0x20 + 0x00003C10 + + + FILTER_THRES_U + This sets the maximum threshold, in APB_CLK cycles, for the filter. + +Any pulses with width less than this will be ignored when the filter is enabled. + 0 + 10 + read-write + + + FILTER_EN_U + This is the enable bit for unit %s's input filter. + 10 + 1 + read-write + + + THR_ZERO_EN_U + This is the enable bit for unit %s's zero comparator. + 11 + 1 + read-write + + + THR_H_LIM_EN_U + This is the enable bit for unit %s's thr_h_lim comparator. + 12 + 1 + read-write + + + THR_L_LIM_EN_U + This is the enable bit for unit %s's thr_l_lim comparator. + 13 + 1 + read-write + + + THR_THRES0_EN_U + This is the enable bit for unit %s's thres0 comparator. + 14 + 1 + read-write + + + THR_THRES1_EN_U + This is the enable bit for unit %s's thres1 comparator. + 15 + 1 + read-write + + + CH0_NEG_MODE_U + This register sets the behavior when the signal input of channel 0 detects a negative edge. + +1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + 16 + 2 + read-write + + + CH0_POS_MODE_U + This register sets the behavior when the signal input of channel 0 detects a positive edge. + +1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + 18 + 2 + read-write + + + CH0_HCTRL_MODE_U + This register configures how the CH%s_POS_MODE/CH%s_NEG_MODE settings will be modified when the control signal is high. + +0: No modification;1: Invert behavior (increase -> decrease, decrease -> increase);2, 3: Inhibit counter modification + 20 + 2 + read-write + + + CH0_LCTRL_MODE_U + This register configures how the CH%s_POS_MODE/CH%s_NEG_MODE settings will be modified when the control signal is low. + +0: No modification;1: Invert behavior (increase -> decrease, decrease -> increase);2, 3: Inhibit counter modification + 22 + 2 + read-write + + + CH1_NEG_MODE_U + This register sets the behavior when the signal input of channel 1 detects a negative edge. + +1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + 24 + 2 + read-write + + + CH1_POS_MODE_U + This register sets the behavior when the signal input of channel 1 detects a positive edge. + +1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + 26 + 2 + read-write + + + CH1_HCTRL_MODE_U + This register configures how the CH%s_POS_MODE/CH%s_NEG_MODE settings will be modified when the control signal is high. + +0: No modification;1: Invert behavior (increase -> decrease, decrease -> increase);2, 3: Inhibit counter modification + 28 + 2 + read-write + + + CH1_LCTRL_MODE_U + This register configures how the CH%s_POS_MODE/CH%s_NEG_MODE settings will be modified when the control signal is low. + +0: No modification;1: Invert behavior (increase -> decrease, decrease -> increase);2, 3: Inhibit counter modification + 30 + 2 + read-write + + + + + 4 + 0xC + U%s_CONF1 + Configuration register 1 for unit %s + 0x4 + 0x20 + + + CNT_THRES0_U + This register is used to configure the thres0 value for unit %s. + 0 + 16 + read-write + + + CNT_THRES1_U + This register is used to configure the thres1 value for unit %s. + 16 + 16 + read-write + + + + + 4 + 0xC + U%s_CONF2 + Configuration register 2 for unit %s + 0x8 + 0x20 + + + CNT_H_LIM_U + This register is used to configure the thr_h_lim value for unit %s. + 0 + 16 + read-write + + + CNT_L_LIM_U + This register is used to configure the thr_l_lim value for unit %s. + 16 + 16 + read-write + + + + + 4 + 0x4 + U%s_CNT + Counter value for unit %s + 0x30 + 0x20 + + + PULSE_CNT_U + This register stores the current pulse count value for unit %s. + 0 + 16 + read-only + + + + + INT_RAW + Interrupt raw status register + 0x40 + 0x20 + + + CNT_THR_EVENT_U0_INT_RAW + The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + 0 + 1 + read-only + + + CNT_THR_EVENT_U1_INT_RAW + The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + 1 + 1 + read-only + + + CNT_THR_EVENT_U2_INT_RAW + The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + 2 + 1 + read-only + + + CNT_THR_EVENT_U3_INT_RAW + The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + 3 + 1 + read-only + + + + + INT_ST + Interrupt status register + 0x44 + 0x20 + + + CNT_THR_EVENT_U0_INT_ST + The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + 0 + 1 + read-only + + + CNT_THR_EVENT_U1_INT_ST + The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + 1 + 1 + read-only + + + CNT_THR_EVENT_U2_INT_ST + The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + 2 + 1 + read-only + + + CNT_THR_EVENT_U3_INT_ST + The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + 3 + 1 + read-only + + + + + INT_ENA + Interrupt enable register + 0x48 + 0x20 + + + CNT_THR_EVENT_U0_INT_ENA + The interrupt enable bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + 0 + 1 + read-write + + + CNT_THR_EVENT_U1_INT_ENA + The interrupt enable bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + 1 + 1 + read-write + + + CNT_THR_EVENT_U2_INT_ENA + The interrupt enable bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + 2 + 1 + read-write + + + CNT_THR_EVENT_U3_INT_ENA + The interrupt enable bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + 3 + 1 + read-write + + + + + INT_CLR + Interrupt clear register + 0x4C + 0x20 + + + CNT_THR_EVENT_U0_INT_CLR + Set this bit to clear the PCNT_CNT_THR_EVENT_U0_INT interrupt. + 0 + 1 + write-only + + + CNT_THR_EVENT_U1_INT_CLR + Set this bit to clear the PCNT_CNT_THR_EVENT_U1_INT interrupt. + 1 + 1 + write-only + + + CNT_THR_EVENT_U2_INT_CLR + Set this bit to clear the PCNT_CNT_THR_EVENT_U2_INT interrupt. + 2 + 1 + write-only + + + CNT_THR_EVENT_U3_INT_CLR + Set this bit to clear the PCNT_CNT_THR_EVENT_U3_INT interrupt. + 3 + 1 + write-only + + + + + 4 + 0x4 + U%s_STATUS + PNCT UNIT%s status register + 0x50 + 0x20 + + + CNT_THR_ZERO_MODE_U + The pulse counter status of PCNT_U%s corresponding to 0. 0: pulse counter decreases from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter is negative. 3: pulse counter is positive. + 0 + 2 + read-only + + + CNT_THR_THRES1_LAT_U + The latched value of thres1 event of PCNT_U%s when threshold event interrupt is valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: others + 2 + 1 + read-only + + + CNT_THR_THRES0_LAT_U + The latched value of thres0 event of PCNT_U%s when threshold event interrupt is valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: others + 3 + 1 + read-only + + + CNT_THR_L_LIM_LAT_U + The latched value of low limit event of PCNT_U%s when threshold event interrupt is valid. 1: the current pulse counter equals to thr_l_lim and low limit event is valid. 0: others + 4 + 1 + read-only + + + CNT_THR_H_LIM_LAT_U + The latched value of high limit event of PCNT_U%s when threshold event interrupt is valid. 1: the current pulse counter equals to thr_h_lim and high limit event is valid. 0: others + 5 + 1 + read-only + + + CNT_THR_ZERO_LAT_U + The latched value of zero threshold event of PCNT_U%s when threshold event interrupt is valid. 1: the current pulse counter equals to 0 and zero threshold event is valid. 0: others + 6 + 1 + read-only + + + + + CTRL + Control register for all counters + 0x60 + 0x20 + 0x00000001 + + + PULSE_CNT_RST_U0 + Set this bit to clear unit 0's counter. + 0 + 1 + read-write + + + CNT_PAUSE_U0 + Set this bit to freeze unit 0's counter. + 1 + 1 + read-write + + + PULSE_CNT_RST_U1 + Set this bit to clear unit 1's counter. + 2 + 1 + read-write + + + CNT_PAUSE_U1 + Set this bit to freeze unit 1's counter. + 3 + 1 + read-write + + + PULSE_CNT_RST_U2 + Set this bit to clear unit 2's counter. + 4 + 1 + read-write + + + CNT_PAUSE_U2 + Set this bit to freeze unit 2's counter. + 5 + 1 + read-write + + + PULSE_CNT_RST_U3 + Set this bit to clear unit 3's counter. + 6 + 1 + read-write + + + CNT_PAUSE_U3 + Set this bit to freeze unit 3's counter. + 7 + 1 + read-write + + + CLK_EN + The registers clock gate enable signal of PCNT module. 1: the registers can be read and written by application. 0: the registers can not be read or written by application + 16 + 1 + read-write + + + + + DATE + PCNT version control register + 0xFC + 0x20 + 0x19072601 + + + DATE + This is the PCNT version control register. + 0 + 32 + read-write + + + + + + + PERI_BACKUP + Peripheral PERI_BACKUP + PERI_BACKUP + 0x6002A000 + + 0x0 + 0x30 + registers + + + PERI_BACKUP + 97 + + + + CONFIG + x + 0x0 + 0x20 + 0x00006480 + + + FLOW_ERR + x + 0 + 3 + read-only + + + ADDR_MAP_MODE + x + 3 + 1 + read-write + + + BURST_LIMIT + x + 4 + 5 + read-write + + + TOUT_THRES + x + 9 + 10 + read-write + + + SIZE + x + 19 + 10 + read-write + + + START + x + 29 + 1 + write-only + + + TO_MEM + x + 30 + 1 + read-write + + + ENA + x + 31 + 1 + read-write + + + + + APB_ADDR + x + 0x4 + 0x20 + + + APB_START_ADDR + x + 0 + 32 + read-write + + + + + MEM_ADDR + x + 0x8 + 0x20 + + + MEM_START_ADDR + x + 0 + 32 + read-write + + + + + REG_MAP0 + x + 0xC + 0x20 + + + MAP0 + x + 0 + 32 + read-write + + + + + REG_MAP1 + x + 0x10 + 0x20 + + + MAP1 + x + 0 + 32 + read-write + + + + + REG_MAP2 + x + 0x14 + 0x20 + + + MAP2 + x + 0 + 32 + read-write + + + + + REG_MAP3 + x + 0x18 + 0x20 + + + MAP3 + x + 0 + 32 + read-write + + + + + INT_RAW + x + 0x1C + 0x20 + + + DONE_INT_RAW + x + 0 + 1 + read-only + + + ERR_INT_RAW + x + 1 + 1 + read-only + + + + + INT_ST + x + 0x20 + 0x20 + + + DONE_INT_ST + x + 0 + 1 + read-only + + + ERR_INT_ST + x + 1 + 1 + read-only + + + + + INT_ENA + x + 0x24 + 0x20 + + + DONE_INT_ENA + x + 0 + 1 + read-write + + + ERR_INT_ENA + x + 1 + 1 + read-write + + + + + INT_CLR + x + 0x28 + 0x20 + + + DONE_INT_CLR + x + 0 + 1 + write-only + + + ERR_INT_CLR + x + 1 + 1 + write-only + + + + + DATE + x + 0xFC + 0x20 + 0x02012300 + + + DATE + x + 0 + 28 + read-write + + + CLK_EN + register file clk gating + 31 + 1 + read-write + + + + + + + PWM0 + Peripheral PWM0 + PWM + 0x6001E000 + + 0x0 + 0x128 + registers + + + PWM0 + 31 + + + + CLK_CFG + PWM clock prescaler register. + 0x0 + 0x20 + + + CLK_PRESCALE + Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + 0 + 8 + read-write + + + + + TIMER0_CFG0 + PWM timer0 period and update method configuration register. + 0x4 + 0x20 + 0x0000FF00 + + + TIMER0_PRESCALE + period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1) + 0 + 8 + read-write + + + TIMER0_PERIOD + period shadow register of PWM timer0 + 8 + 16 + read-write + + + TIMER0_PERIOD_UPMETHOD + Update method for active register of PWM timer0 period, 0: immediate, 1: TEZ, 2: sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + 24 + 2 + read-write + + + + + TIMER0_CFG1 + PWM timer0 working mode and start/stop control configuration register. + 0x8 + 0x20 + + + TIMER0_START + PWM timer0 start and stop control. 0: if PWM timer0 starts, then stops at TEZ, 1: if timer0 starts, then stops at TEP, 2: PWM timer0 starts and runs on, 3: timer0 starts and stops at the next TEZ, 4: timer0 starts and stops at the next TEP. TEP here and below means the event that happens when the timer equals to period + 0 + 3 + read-write + + + TIMER0_MOD + PWM timer0 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down mode + 3 + 2 + read-write + + + + + TIMER0_SYNC + PWM timer0 sync function configuration register. + 0xC + 0x20 + + + TIMER0_SYNCI_EN + When set, timer reloading with phase on sync input event is enabled. + 0 + 1 + read-write + + + SW + Toggling this bit will trigger a software sync. + 1 + 1 + read-write + + + TIMER0_SYNCO_SEL + PWM timer0 sync_out selection, 0: synci, 1: TEZ, 2: TEP, otherwise:sync out is software sync + 2 + 2 + read-write + + + TIMER0_PHASE + phase for timer reload on sync event + 4 + 17 + read-write + + + + + TIMER0_STATUS + PWM timer0 status register. + 0x10 + 0x20 + + + TIMER0_VALUE + current PWM timer0 counter value + 0 + 16 + read-only + + + TIMER0_DIRECTION + current PWM timer0 counter direction, 0: increment 1: decrement + 16 + 1 + read-only + + + + + TIMER1_CFG0 + PWM timer1 period and update method configuration register. + 0x14 + 0x20 + 0x0000FF00 + + + TIMER1_PRESCALE + period of PT0_clk = Period of PWM_clk * (PWM_timer1_PRESCALE + 1) + 0 + 8 + read-write + + + TIMER1_PERIOD + period shadow register of PWM timer1 + 8 + 16 + read-write + + + TIMER1_PERIOD_UPMETHOD + Update method for active register of PWM timer1 period, 0: immediate, 1: TEZ, 2: sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + 24 + 2 + read-write + + + + + TIMER1_CFG1 + PWM timer1 working mode and start/stop control configuration register. + 0x18 + 0x20 + + + TIMER1_START + PWM timer1 start and stop control. 0: if PWM timer1 starts, then stops at TEZ, 1: if timer1 starts, then stops at TEP, 2: PWM timer1 starts and runs on, 3: timer1 starts and stops at the next TEZ, 4: timer1 starts and stops at the next TEP. TEP here and below means the event that happens when the timer equals to period + 0 + 3 + read-write + + + TIMER1_MOD + PWM timer1 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down mode + 3 + 2 + read-write + + + + + TIMER1_SYNC + PWM timer1 sync function configuration register. + 0x1C + 0x20 + + + TIMER1_SYNCI_EN + When set, timer reloading with phase on sync input event is enabled. + 0 + 1 + read-write + + + SW + Toggling this bit will trigger a software sync. + 1 + 1 + read-write + + + TIMER1_SYNCO_SEL + PWM timer1 sync_out selection, 0: synci, 1: TEZ, 2: TEP, otherwise:sync out is software sync + 2 + 2 + read-write + + + TIMER1_PHASE + phase for timer reload on sync event + 4 + 17 + read-write + + + + + TIMER1_STATUS + PWM timer1 status register. + 0x20 + 0x20 + + + TIMER1_VALUE + current PWM timer1 counter value + 0 + 16 + read-only + + + TIMER1_DIRECTION + current PWM timer1 counter direction, 0: increment 1: decrement + 16 + 1 + read-only + + + + + TIMER2_CFG0 + PWM timer2 period and update method configuration register. + 0x24 + 0x20 + 0x0000FF00 + + + TIMER2_PRESCALE + period of PT0_clk = Period of PWM_clk * (PWM_timer2_PRESCALE + 1) + 0 + 8 + read-write + + + TIMER2_PERIOD + period shadow register of PWM timer2 + 8 + 16 + read-write + + + TIMER2_PERIOD_UPMETHOD + Update method for active register of PWM timer2 period, 0: immediate, 1: TEZ, 2: sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + 24 + 2 + read-write + + + + + TIMER2_CFG1 + PWM timer2 working mode and start/stop control configuration register. + 0x28 + 0x20 + + + TIMER2_START + PWM timer2 start and stop control. 0: if PWM timer2 starts, then stops at TEZ, 1: if timer2 starts, then stops at TEP, 2: PWM timer2 starts and runs on, 3: timer2 starts and stops at the next TEZ, 4: timer2 starts and stops at the next TEP. TEP here and below means the event that happens when the timer equals to period + 0 + 3 + read-write + + + TIMER2_MOD + PWM timer2 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down mode + 3 + 2 + read-write + + + + + TIMER2_SYNC + PWM timer2 sync function configuration register. + 0x2C + 0x20 + + + TIMER2_SYNCI_EN + When set, timer reloading with phase on sync input event is enabled. + 0 + 1 + read-write + + + SW + Toggling this bit will trigger a software sync. + 1 + 1 + read-write + + + TIMER2_SYNCO_SEL + PWM timer2 sync_out selection, 0: synci, 1: TEZ, 2: TEP, otherwise:sync out is software sync + 2 + 2 + read-write + + + TIMER2_PHASE + phase for timer reload on sync event + 4 + 17 + read-write + + + + + TIMER2_STATUS + PWM timer2 status register. + 0x30 + 0x20 + + + TIMER2_VALUE + current PWM timer2 counter value + 0 + 16 + read-only + + + TIMER2_DIRECTION + current PWM timer2 counter direction, 0: increment 1: decrement + 16 + 1 + read-only + + + + + TIMER_SYNCI_CFG + Synchronization input selection for three PWM timers. + 0x34 + 0x20 + + + TIMER0_SYNCISEL + select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: SYNC2 from GPIO matrix, other values: no sync input selected + 0 + 3 + read-write + + + TIMER1_SYNCISEL + select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: SYNC2 from GPIO matrix, other values: no sync input selected + 3 + 3 + read-write + + + TIMER2_SYNCISEL + select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: SYNC2 from GPIO matrix, other values: no sync input selected + 6 + 3 + read-write + + + EXTERNAL_SYNCI0_INVERT + invert SYNC0 from GPIO matrix + 9 + 1 + read-write + + + EXTERNAL_SYNCI1_INVERT + invert SYNC1 from GPIO matrix + 10 + 1 + read-write + + + EXTERNAL_SYNCI2_INVERT + invert SYNC2 from GPIO matrix + 11 + 1 + read-write + + + + + OPERATOR_TIMERSEL + Select specific timer for PWM operators. + 0x38 + 0x20 + + + OPERATOR0_TIMERSEL + Select which PWM timer's is the timing reference for PWM operator0, 0: timer0, 1: timer1, 2: timer2 + 0 + 2 + read-write + + + OPERATOR1_TIMERSEL + Select which PWM timer's is the timing reference for PWM operator1, 0: timer0, 1: timer1, 2: timer2 + 2 + 2 + read-write + + + OPERATOR2_TIMERSEL + Select which PWM timer's is the timing reference for PWM operator2, 0: timer0, 1: timer1, 2: timer2 + 4 + 2 + read-write + + + + + CMPR0_CFG + Transfer status and update method for time stamp registers A and B + 0x3C + 0x20 + + + CMPR0_A_UPMETHOD + Update method for PWM generator 0 time stamp A's active register. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + 0 + 4 + read-write + + + CMPR0_B_UPMETHOD + Update method for PWM generator 0 time stamp B's active register. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + 4 + 4 + read-write + + + CMPR0_A_SHDW_FULL + Set and reset by hardware. If set, PWM generator 0 time stamp A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared, A's active reg has been updated with shadow register latest value + 8 + 1 + read-only + + + CMPR0_B_SHDW_FULL + Set and reset by hardware. If set, PWM generator 0 time stamp B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared, B's active reg has been updated with shadow register latest value + 9 + 1 + read-only + + + + + CMPR0_VALUE0 + Shadow register for register A. + 0x40 + 0x20 + + + CMPR0_A + PWM generator 0 time stamp A's shadow register + 0 + 16 + read-write + + + + + CMPR0_VALUE1 + Shadow register for register B. + 0x44 + 0x20 + + + CMPR0_B + PWM generator 0 time stamp B's shadow register + 0 + 16 + read-write + + + + + GEN0_CFG0 + Fault event T0 and T1 handling + 0x48 + 0x20 + + + GEN0_CFG_UPMETHOD + Update method for PWM generator 0's active register of configuration. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: + 0 + 4 + read-write + + + GEN0_T0_SEL + Source selection for PWM generator 0 event_t0, take effect immediately, 0: fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + 4 + 3 + read-write + + + GEN0_T1_SEL + Source selection for PWM generator 0 event_t1, take effect immediately, 0: fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + 7 + 3 + read-write + + + + + GEN0_FORCE + Permissives to force PWM0A and PWM0B outputs by software + 0x4C + 0x20 + 0x00000020 + + + GEN0_CNTUFORCE_UPMETHOD + Updating method for continuous software force of PWM generator0. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, when bit5 is set to 1: disable update. (TEA/B here and below means an event generated when the timer's value equals to that of register A/B.) + 0 + 6 + read-write + + + GEN0_A_CNTUFORCE_MODE + Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + 6 + 2 + read-write + + + GEN0_B_CNTUFORCE_MODE + Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + 8 + 2 + read-write + + + GEN0_A_NCIFORCE + Trigger of non-continuous immediate software-force event for PWM0A, a toggle will trigger a force event. + 10 + 1 + read-write + + + GEN0_A_NCIFORCE_MODE + non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: high, 3: disabled + 11 + 2 + read-write + + + GEN0_B_NCIFORCE + Trigger of non-continuous immediate software-force event for PWM0B, a toggle will trigger a force event. + 13 + 1 + read-write + + + GEN0_B_NCIFORCE_MODE + non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: high, 3: disabled + 14 + 2 + read-write + + + + + GEN0_A + Actions triggered by events on PWM0A + 0x50 + 0x20 + + + UTEZ + Action on PWM0A triggered by event TEZ when timer increasing + 0 + 2 + read-write + + + UTEP + Action on PWM0A triggered by event TEP when timer increasing + 2 + 2 + read-write + + + UTEA + Action on PWM0A triggered by event TEA when timer increasing + 4 + 2 + read-write + + + UTEB + Action on PWM0A triggered by event TEB when timer increasing + 6 + 2 + read-write + + + UT0 + Action on PWM0A triggered by event_t0 when timer increasing + 8 + 2 + read-write + + + UT1 + Action on PWM0A triggered by event_t1 when timer increasing + 10 + 2 + read-write + + + DTEZ + Action on PWM0A triggered by event TEZ when timer decreasing + 12 + 2 + read-write + + + DTEP + Action on PWM0A triggered by event TEP when timer decreasing + 14 + 2 + read-write + + + DTEA + Action on PWM0A triggered by event TEA when timer decreasing + 16 + 2 + read-write + + + DTEB + Action on PWM0A triggered by event TEB when timer decreasing + 18 + 2 + read-write + + + DT0 + Action on PWM0A triggered by event_t0 when timer decreasing + 20 + 2 + read-write + + + DT1 + Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, 2: high, 3: toggle + 22 + 2 + read-write + + + + + GEN0_B + Actions triggered by events on PWM0B + 0x54 + 0x20 + + + UTEZ + Action on PWM0B triggered by event TEZ when timer increasing + 0 + 2 + read-write + + + UTEP + Action on PWM0B triggered by event TEP when timer increasing + 2 + 2 + read-write + + + UTEA + Action on PWM0B triggered by event TEA when timer increasing + 4 + 2 + read-write + + + UTEB + Action on PWM0B triggered by event TEB when timer increasing + 6 + 2 + read-write + + + UT0 + Action on PWM0B triggered by event_t0 when timer increasing + 8 + 2 + read-write + + + UT1 + Action on PWM0B triggered by event_t1 when timer increasing + 10 + 2 + read-write + + + DTEZ + Action on PWM0B triggered by event TEZ when timer decreasing + 12 + 2 + read-write + + + DTEP + Action on PWM0B triggered by event TEP when timer decreasing + 14 + 2 + read-write + + + DTEA + Action on PWM0B triggered by event TEA when timer decreasing + 16 + 2 + read-write + + + DTEB + Action on PWM0B triggered by event TEB when timer decreasing + 18 + 2 + read-write + + + DT0 + Action on PWM0B triggered by event_t0 when timer decreasing + 20 + 2 + read-write + + + DT1 + Action on PWM0B triggered by event_t1 when timer decreasing. 0: no change, 1: low, 2: high, 3: toggle + 22 + 2 + read-write + + + + + DB0_CFG + dead time type selection and configuration + 0x58 + 0x20 + 0x00018000 + + + DB0_FED_UPMETHOD + Update method for FED (falling edge delay) active register. 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze + 0 + 4 + read-write + + + DB0_RED_UPMETHOD + Update method for RED (rising edge delay) active register. 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze + 4 + 4 + read-write + + + DB0_DEB_MODE + S8 in documentation, dual-edge B mode, 0: fed/red take effect on different path separately, 1: fed/red take effect on B path, A out is in bypass or dulpB mode + 8 + 1 + read-write + + + DB0_A_OUTSWAP + S6 in documentation + 9 + 1 + read-write + + + DB0_B_OUTSWAP + S7 in documentation + 10 + 1 + read-write + + + DB0_RED_INSEL + S4 in documentation + 11 + 1 + read-write + + + DB0_FED_INSEL + S5 in documentation + 12 + 1 + read-write + + + DB0_RED_OUTINVERT + S2 in documentation + 13 + 1 + read-write + + + DB0_FED_OUTINVERT + S3 in documentation + 14 + 1 + read-write + + + DB0_A_OUTBYPASS + S1 in documentation + 15 + 1 + read-write + + + DB0_B_OUTBYPASS + S0 in documentation + 16 + 1 + read-write + + + DB0_CLK_SEL + Dead time generator 0 clock selection. 0: PWM_clk, 1: PT_clk + 17 + 1 + read-write + + + + + DB0_FED_CFG + Shadow register for falling edge delay (FED). + 0x5C + 0x20 + + + DB0_FED + Shadow register for FED + 0 + 16 + read-write + + + + + DB0_RED_CFG + Shadow register for rising edge delay (RED). + 0x60 + 0x20 + + + DB0_RED + Shadow register for RED + 0 + 16 + read-write + + + + + CHOPPER0_CFG + Carrier enable and configuratoin + 0x64 + 0x20 + + + CHOPPER0_EN + When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + 0 + 1 + read-write + + + CHOPPER0_PRESCALE + PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1) + 1 + 4 + read-write + + + CHOPPER0_DUTY + carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + 5 + 3 + read-write + + + CHOPPER0_OSHTWTH + width of the fist pulse in number of periods of the carrier + 8 + 4 + read-write + + + CHOPPER0_OUT_INVERT + when set, invert the output of PWM0A and PWM0B for this submodule + 12 + 1 + read-write + + + CHOPPER0_IN_INVERT + when set, invert the input of PWM0A and PWM0B for this submodule + 13 + 1 + read-write + + + + + TZ0_CFG0 + Actions on PWM0A and PWM0B trip events + 0x68 + 0x20 + + + TZ0_SW_CBC + Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + 0 + 1 + read-write + + + TZ0_F2_CBC + event_f2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 1 + 1 + read-write + + + TZ0_F1_CBC + event_f1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 2 + 1 + read-write + + + TZ0_F0_CBC + event_f0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 3 + 1 + read-write + + + TZ0_SW_OST + Enable register for software force one-shot mode action. 0: disable, 1: enable + 4 + 1 + read-write + + + TZ0_F2_OST + event_f2 will trigger one-shot mode action. 0: disable, 1: enable + 5 + 1 + read-write + + + TZ0_F1_OST + event_f1 will trigger one-shot mode action. 0: disable, 1: enable + 6 + 1 + read-write + + + TZ0_F0_OST + event_f0 will trigger one-shot mode action. 0: disable, 1: enable + 7 + 1 + read-write + + + TZ0_A_CBC_D + Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 8 + 2 + read-write + + + TZ0_A_CBC_U + Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 10 + 2 + read-write + + + TZ0_A_OST_D + One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 12 + 2 + read-write + + + TZ0_A_OST_U + One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 14 + 2 + read-write + + + TZ0_B_CBC_D + Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 16 + 2 + read-write + + + TZ0_B_CBC_U + Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 18 + 2 + read-write + + + TZ0_B_OST_D + One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 20 + 2 + read-write + + + TZ0_B_OST_U + One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 22 + 2 + read-write + + + + + TZ0_CFG1 + Software triggers for fault handler actions + 0x6C + 0x20 + + + TZ0_CLR_OST + a rising edge will clear on going one-shot mode action + 0 + 1 + read-write + + + TZ0_CBCPULSE + cycle-by-cycle mode action refresh moment selection. Bit0: TEZ, bit1:TEP + 1 + 2 + read-write + + + TZ0_FORCE_CBC + a toggle trigger a cycle-by-cycle mode action + 3 + 1 + read-write + + + TZ0_FORCE_OST + a toggle (software negate its value) triggers a one-shot mode action + 4 + 1 + read-write + + + + + TZ0_STATUS + Status of fault events. + 0x70 + 0x20 + + + TZ0_CBC_ON + Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + 0 + 1 + read-only + + + TZ0_OST_ON + Set and reset by hardware. If set, an one-shot mode action is on going + 1 + 1 + read-only + + + + + CMPR1_CFG + Transfer status and update method for time stamp registers A and B + 0x74 + 0x20 + + + CMPR1_A_UPMETHOD + Update method for PWM generator 1 time stamp A's active register. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + 0 + 4 + read-write + + + CMPR1_B_UPMETHOD + Update method for PWM generator 1 time stamp B's active register. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + 4 + 4 + read-write + + + CMPR1_A_SHDW_FULL + Set and reset by hardware. If set, PWM generator 1 time stamp A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared, A's active reg has been updated with shadow register latest value + 8 + 1 + read-only + + + CMPR1_B_SHDW_FULL + Set and reset by hardware. If set, PWM generator 1 time stamp B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared, B's active reg has been updated with shadow register latest value + 9 + 1 + read-only + + + + + CMPR1_VALUE0 + Shadow register for register A. + 0x78 + 0x20 + + + CMPR1_A + PWM generator 1 time stamp A's shadow register + 0 + 16 + read-write + + + + + CMPR1_VALUE1 + Shadow register for register B. + 0x7C + 0x20 + + + CMPR1_B + PWM generator 1 time stamp B's shadow register + 0 + 16 + read-write + + + + + GEN1_CFG0 + Fault event T0 and T1 handling + 0x80 + 0x20 + + + GEN1_CFG_UPMETHOD + Update method for PWM generator 1's active register of configuration. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: + 0 + 4 + read-write + + + GEN1_T0_SEL + Source selection for PWM generator 1 event_t0, take effect immediately, 0: fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + 4 + 3 + read-write + + + GEN1_T1_SEL + Source selection for PWM generator 1 event_t1, take effect immediately, 0: fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + 7 + 3 + read-write + + + + + GEN1_FORCE + Permissives to force PWM1A and PWM1B outputs by software + 0x84 + 0x20 + 0x00000020 + + + GEN1_CNTUFORCE_UPMETHOD + Updating method for continuous software force of PWM generator 1. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, when bit5 is set to 1: disable update. (TEA/B here and below means an event generated when the timer's value equals to that of register A/B.) + 0 + 6 + read-write + + + GEN1_A_CNTUFORCE_MODE + Continuous software force mode for PWM1A. 0: disabled, 1: low, 2: high, 3: disabled + 6 + 2 + read-write + + + GEN1_B_CNTUFORCE_MODE + Continuous software force mode for PWM1B. 0: disabled, 1: low, 2: high, 3: disabled + 8 + 2 + read-write + + + GEN1_A_NCIFORCE + Trigger of non-continuous immediate software-force event for PWM1A, a toggle will trigger a force event. + 10 + 1 + read-write + + + GEN1_A_NCIFORCE_MODE + non-continuous immediate software force mode for PWM1A, 0: disabled, 1: low, 2: high, 3: disabled + 11 + 2 + read-write + + + GEN1_B_NCIFORCE + Trigger of non-continuous immediate software-force event for PWM1B, a toggle will trigger a force event. + 13 + 1 + read-write + + + GEN1_B_NCIFORCE_MODE + non-continuous immediate software force mode for PWM1B, 0: disabled, 1: low, 2: high, 3: disabled + 14 + 2 + read-write + + + + + GEN1_A + Actions triggered by events on PWM1A + 0x88 + 0x20 + + + UTEZ + Action on PWM1A triggered by event TEZ when timer increasing + 0 + 2 + read-write + + + UTEP + Action on PWM1A triggered by event TEP when timer increasing + 2 + 2 + read-write + + + UTEA + Action on PWM1A triggered by event TEA when timer increasing + 4 + 2 + read-write + + + UTEB + Action on PWM1A triggered by event TEB when timer increasing + 6 + 2 + read-write + + + UT0 + Action on PWM1A triggered by event_t0 when timer increasing + 8 + 2 + read-write + + + UT1 + Action on PWM1A triggered by event_t1 when timer increasing + 10 + 2 + read-write + + + DTEZ + Action on PWM1A triggered by event TEZ when timer decreasing + 12 + 2 + read-write + + + DTEP + Action on PWM1A triggered by event TEP when timer decreasing + 14 + 2 + read-write + + + DTEA + Action on PWM1A triggered by event TEA when timer decreasing + 16 + 2 + read-write + + + DTEB + Action on PWM1A triggered by event TEB when timer decreasing + 18 + 2 + read-write + + + DT0 + Action on PWM1A triggered by event_t0 when timer decreasing + 20 + 2 + read-write + + + DT1 + Action on PWM1A triggered by event_t1 when timer decreasing. 0: no change, 1: low, 2: high, 3: toggle + 22 + 2 + read-write + + + + + GEN1_B + Actions triggered by events on PWM1B + 0x8C + 0x20 + + + UTEZ + Action on PWM1B triggered by event TEZ when timer increasing + 0 + 2 + read-write + + + UTEP + Action on PWM1B triggered by event TEP when timer increasing + 2 + 2 + read-write + + + UTEA + Action on PWM1B triggered by event TEA when timer increasing + 4 + 2 + read-write + + + UTEB + Action on PWM1B triggered by event TEB when timer increasing + 6 + 2 + read-write + + + UT0 + Action on PWM1B triggered by event_t0 when timer increasing + 8 + 2 + read-write + + + UT1 + Action on PWM1B triggered by event_t1 when timer increasing + 10 + 2 + read-write + + + DTEZ + Action on PWM1B triggered by event TEZ when timer decreasing + 12 + 2 + read-write + + + DTEP + Action on PWM1B triggered by event TEP when timer decreasing + 14 + 2 + read-write + + + DTEA + Action on PWM1B triggered by event TEA when timer decreasing + 16 + 2 + read-write + + + DTEB + Action on PWM1B triggered by event TEB when timer decreasing + 18 + 2 + read-write + + + DT0 + Action on PWM1B triggered by event_t0 when timer decreasing + 20 + 2 + read-write + + + DT1 + Action on PWM1B triggered by event_t1 when timer decreasing. 0: no change, 1: low, 2: high, 3: toggle + 22 + 2 + read-write + + + + + DB1_CFG + dead time type selection and configuration + 0x90 + 0x20 + 0x00018000 + + + DB1_FED_UPMETHOD + Update method for FED (falling edge delay) active register. 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze + 0 + 4 + read-write + + + DB1_RED_UPMETHOD + Update method for RED (rising edge delay) active register. 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze + 4 + 4 + read-write + + + DB1_DEB_MODE + S8 in documentation, dual-edge B mode, 0: fed/red take effect on different path separately, 1: fed/red take effect on B path, A out is in bypass or dulpB mode + 8 + 1 + read-write + + + DB1_A_OUTSWAP + S6 in documentation + 9 + 1 + read-write + + + DB1_B_OUTSWAP + S7 in documentation + 10 + 1 + read-write + + + DB1_RED_INSEL + S4 in documentation + 11 + 1 + read-write + + + DB1_FED_INSEL + S5 in documentation + 12 + 1 + read-write + + + DB1_RED_OUTINVERT + S2 in documentation + 13 + 1 + read-write + + + DB1_FED_OUTINVERT + S3 in documentation + 14 + 1 + read-write + + + DB1_A_OUTBYPASS + S1 in documentation + 15 + 1 + read-write + + + DB1_B_OUTBYPASS + S0 in documentation + 16 + 1 + read-write + + + DB1_CLK_SEL + Dead time generator 1 clock selection. 0: PWM_clk, 1: PT_clk + 17 + 1 + read-write + + + + + DB1_FED_CFG + Shadow register for falling edge delay (FED). + 0x94 + 0x20 + + + DB1_FED + Shadow register for FED + 0 + 16 + read-write + + + + + DB1_RED_CFG + Shadow register for rising edge delay (RED). + 0x98 + 0x20 + + + DB1_RED + Shadow register for RED + 0 + 16 + read-write + + + + + CHOPPER1_CFG + Carrier enable and configuratoin + 0x9C + 0x20 + + + CHOPPER1_EN + When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + 0 + 1 + read-write + + + CHOPPER1_PRESCALE + PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1) + 1 + 4 + read-write + + + CHOPPER1_DUTY + carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + 5 + 3 + read-write + + + CHOPPER1_OSHTWTH + width of the fist pulse in number of periods of the carrier + 8 + 4 + read-write + + + CHOPPER1_OUT_INVERT + when set, invert the output of PWM1A and PWM1B for this submodule + 12 + 1 + read-write + + + CHOPPER1_IN_INVERT + when set, invert the input of PWM1A and PWM1B for this submodule + 13 + 1 + read-write + + + + + TZ1_CFG0 + Actions on PWM1A and PWM1B trip events + 0xA0 + 0x20 + + + TZ1_SW_CBC + Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + 0 + 1 + read-write + + + TZ1_F2_CBC + event_f2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 1 + 1 + read-write + + + TZ1_F1_CBC + event_f1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 2 + 1 + read-write + + + TZ1_F0_CBC + event_f0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 3 + 1 + read-write + + + TZ1_SW_OST + Enable register for software force one-shot mode action. 0: disable, 1: enable + 4 + 1 + read-write + + + TZ1_F2_OST + event_f2 will trigger one-shot mode action. 0: disable, 1: enable + 5 + 1 + read-write + + + TZ1_F1_OST + event_f1 will trigger one-shot mode action. 0: disable, 1: enable + 6 + 1 + read-write + + + TZ1_F0_OST + event_f0 will trigger one-shot mode action. 0: disable, 1: enable + 7 + 1 + read-write + + + TZ1_A_CBC_D + Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 8 + 2 + read-write + + + TZ1_A_CBC_U + Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 10 + 2 + read-write + + + TZ1_A_OST_D + One-shot mode action on PWM1A when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 12 + 2 + read-write + + + TZ1_A_OST_U + One-shot mode action on PWM1A when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 14 + 2 + read-write + + + TZ1_B_CBC_D + Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 16 + 2 + read-write + + + TZ1_B_CBC_U + Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 18 + 2 + read-write + + + TZ1_B_OST_D + One-shot mode action on PWM1B when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 20 + 2 + read-write + + + TZ1_B_OST_U + One-shot mode action on PWM1B when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 22 + 2 + read-write + + + + + TZ1_CFG1 + Software triggers for fault handler actions + 0xA4 + 0x20 + + + TZ1_CLR_OST + a rising edge will clear on going one-shot mode action + 0 + 1 + read-write + + + TZ1_CBCPULSE + cycle-by-cycle mode action refresh moment selection. Bit0: TEZ, bit1:TEP + 1 + 2 + read-write + + + TZ1_FORCE_CBC + a toggle trigger a cycle-by-cycle mode action + 3 + 1 + read-write + + + TZ1_FORCE_OST + a toggle (software negate its value) triggers a one-shot mode action + 4 + 1 + read-write + + + + + TZ1_STATUS + Status of fault events. + 0xA8 + 0x20 + + + TZ1_CBC_ON + Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + 0 + 1 + read-only + + + TZ1_OST_ON + Set and reset by hardware. If set, an one-shot mode action is on going + 1 + 1 + read-only + + + + + CMPR2_CFG + Transfer status and update method for time stamp registers A and B + 0xAC + 0x20 + + + CMPR2_A_UPMETHOD + Update method for PWM generator 2 time stamp A's active register. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + 0 + 4 + read-write + + + CMPR2_B_UPMETHOD + Update method for PWM generator 2 time stamp B's active register. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + 4 + 4 + read-write + + + CMPR2_A_SHDW_FULL + Set and reset by hardware. If set, PWM generator 2 time stamp A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared, A's active reg has been updated with shadow register latest value + 8 + 1 + read-only + + + CMPR2_B_SHDW_FULL + Set and reset by hardware. If set, PWM generator 2 time stamp B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared, B's active reg has been updated with shadow register latest value + 9 + 1 + read-only + + + + + CMPR2_VALUE0 + Shadow register for register A. + 0xB0 + 0x20 + + + CMPR2_A + PWM generator 2 time stamp A's shadow register + 0 + 16 + read-write + + + + + CMPR2_VALUE1 + Shadow register for register B. + 0xB4 + 0x20 + + + CMPR2_B + PWM generator 2 time stamp B's shadow register + 0 + 16 + read-write + + + + + GEN2_CFG0 + Fault event T0 and T1 handling + 0xB8 + 0x20 + + + GEN2_CFG_UPMETHOD + Update method for PWM generator 2's active register of configuration. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: + 0 + 4 + read-write + + + GEN2_T0_SEL + Source selection for PWM generator 2 event_t0, take effect immediately, 0: fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + 4 + 3 + read-write + + + GEN2_T1_SEL + Source selection for PWM generator 2 event_t1, take effect immediately, 0: fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + 7 + 3 + read-write + + + + + GEN2_FORCE + Permissives to force PWM2A and PWM2B outputs by software + 0xBC + 0x20 + 0x00000020 + + + GEN2_CNTUFORCE_UPMETHOD + Updating method for continuous software force of PWM generator 2. When all bits are set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, when bit5 is set to 1: disable update. (TEA/B here and below means an event generated when the timer's value equals to that of register A/B.) + 0 + 6 + read-write + + + GEN2_A_CNTUFORCE_MODE + Continuous software force mode for PWM2A. 0: disabled, 1: low, 2: high, 3: disabled + 6 + 2 + read-write + + + GEN2_B_CNTUFORCE_MODE + Continuous software force mode for PWM2B. 0: disabled, 1: low, 2: high, 3: disabled + 8 + 2 + read-write + + + GEN2_A_NCIFORCE + Trigger of non-continuous immediate software-force event for PWM2A, a toggle will trigger a force event. + 10 + 1 + read-write + + + GEN2_A_NCIFORCE_MODE + non-continuous immediate software force mode for PWM2A, 0: disabled, 1: low, 2: high, 3: disabled + 11 + 2 + read-write + + + GEN2_B_NCIFORCE + Trigger of non-continuous immediate software-force event for PWM2B, a toggle will trigger a force event. + 13 + 1 + read-write + + + GEN2_B_NCIFORCE_MODE + non-continuous immediate software force mode for PWM2B, 0: disabled, 1: low, 2: high, 3: disabled + 14 + 2 + read-write + + + + + GEN2_A + Actions triggered by events on PWM2A + 0xC0 + 0x20 + + + UTEZ + Action on PWM2A triggered by event TEZ when timer increasing + 0 + 2 + read-write + + + UTEP + Action on PWM2A triggered by event TEP when timer increasing + 2 + 2 + read-write + + + UTEA + Action on PWM2A triggered by event TEA when timer increasing + 4 + 2 + read-write + + + UTEB + Action on PWM2A triggered by event TEB when timer increasing + 6 + 2 + read-write + + + UT0 + Action on PWM2A triggered by event_t0 when timer increasing + 8 + 2 + read-write + + + UT1 + Action on PWM2A triggered by event_t1 when timer increasing + 10 + 2 + read-write + + + DTEZ + Action on PWM2A triggered by event TEZ when timer decreasing + 12 + 2 + read-write + + + DTEP + Action on PWM2A triggered by event TEP when timer decreasing + 14 + 2 + read-write + + + DTEA + Action on PWM2A triggered by event TEA when timer decreasing + 16 + 2 + read-write + + + DTEB + Action on PWM2A triggered by event TEB when timer decreasing + 18 + 2 + read-write + + + DT0 + Action on PWM2A triggered by event_t0 when timer decreasing + 20 + 2 + read-write + + + DT1 + Action on PWM2A triggered by event_t1 when timer decreasing. 0: no change, 1: low, 2: high, 3: toggle + 22 + 2 + read-write + + + + + GEN2_B + Actions triggered by events on PWM2B + 0xC4 + 0x20 + + + UTEZ + Action on PWM2B triggered by event TEZ when timer increasing + 0 + 2 + read-write + + + UTEP + Action on PWM2B triggered by event TEP when timer increasing + 2 + 2 + read-write + + + UTEA + Action on PWM2B triggered by event TEA when timer increasing + 4 + 2 + read-write + + + UTEB + Action on PWM2B triggered by event TEB when timer increasing + 6 + 2 + read-write + + + UT0 + Action on PWM2B triggered by event_t0 when timer increasing + 8 + 2 + read-write + + + UT1 + Action on PWM2B triggered by event_t1 when timer increasing + 10 + 2 + read-write + + + DTEZ + Action on PWM2B triggered by event TEZ when timer decreasing + 12 + 2 + read-write + + + DTEP + Action on PWM2B triggered by event TEP when timer decreasing + 14 + 2 + read-write + + + DTEA + Action on PWM2B triggered by event TEA when timer decreasing + 16 + 2 + read-write + + + DTEB + Action on PWM2B triggered by event TEB when timer decreasing + 18 + 2 + read-write + + + DT0 + Action on PWM2B triggered by event_t0 when timer decreasing + 20 + 2 + read-write + + + DT1 + Action on PWM2B triggered by event_t1 when timer decreasing. 0: no change, 1: low, 2: high, 3: toggle + 22 + 2 + read-write + + + + + DB2_CFG + dead time type selection and configuration + 0xC8 + 0x20 + 0x00018000 + + + DB2_FED_UPMETHOD + Update method for FED (falling edge delay) active register. 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze + 0 + 4 + read-write + + + DB2_RED_UPMETHOD + Update method for RED (rising edge delay) active register. 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze + 4 + 4 + read-write + + + DB2_DEB_MODE + S8 in documentation, dual-edge B mode, 0: fed/red take effect on different path separately, 1: fed/red take effect on B path, A out is in bypass or dulpB mode + 8 + 1 + read-write + + + DB2_A_OUTSWAP + S6 in documentation + 9 + 1 + read-write + + + DB2_B_OUTSWAP + S7 in documentation + 10 + 1 + read-write + + + DB2_RED_INSEL + S4 in documentation + 11 + 1 + read-write + + + DB2_FED_INSEL + S5 in documentation + 12 + 1 + read-write + + + DB2_RED_OUTINVERT + S2 in documentation + 13 + 1 + read-write + + + DB2_FED_OUTINVERT + S3 in documentation + 14 + 1 + read-write + + + DB2_A_OUTBYPASS + S1 in documentation + 15 + 1 + read-write + + + DB2_B_OUTBYPASS + S0 in documentation + 16 + 1 + read-write + + + DB2_CLK_SEL + Dead time generator 2 clock selection. 0: PWM_clk, 1: PT_clk + 17 + 1 + read-write + + + + + DB2_FED_CFG + Shadow register for falling edge delay (FED). + 0xCC + 0x20 + + + DB2_FED + Shadow register for FED + 0 + 16 + read-write + + + + + DB2_RED_CFG + Shadow register for rising edge delay (RED). + 0xD0 + 0x20 + + + DB2_RED + Shadow register for RED + 0 + 16 + read-write + + + + + CHOPPER2_CFG + Carrier enable and configuratoin + 0xD4 + 0x20 + + + CHOPPER2_EN + When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + 0 + 1 + read-write + + + CHOPPER2_PRESCALE + PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1) + 1 + 4 + read-write + + + CHOPPER2_DUTY + carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + 5 + 3 + read-write + + + CHOPPER2_OSHTWTH + width of the fist pulse in number of periods of the carrier + 8 + 4 + read-write + + + CHOPPER2_OUT_INVERT + when set, invert the output of PWM2A and PWM2B for this submodule + 12 + 1 + read-write + + + CHOPPER2_IN_INVERT + when set, invert the input of PWM2A and PWM2B for this submodule + 13 + 1 + read-write + + + + + TZ2_CFG0 + Actions on PWM2A and PWM2B trip events + 0xD8 + 0x20 + + + TZ2_SW_CBC + Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + 0 + 1 + read-write + + + TZ2_F2_CBC + event_f2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 1 + 1 + read-write + + + TZ2_F1_CBC + event_f1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 2 + 1 + read-write + + + TZ2_F0_CBC + event_f0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + 3 + 1 + read-write + + + TZ2_SW_OST + Enable register for software force one-shot mode action. 0: disable, 1: enable + 4 + 1 + read-write + + + TZ2_F2_OST + event_f2 will trigger one-shot mode action. 0: disable, 1: enable + 5 + 1 + read-write + + + TZ2_F1_OST + event_f1 will trigger one-shot mode action. 0: disable, 1: enable + 6 + 1 + read-write + + + TZ2_F0_OST + event_f0 will trigger one-shot mode action. 0: disable, 1: enable + 7 + 1 + read-write + + + TZ2_A_CBC_D + Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 8 + 2 + read-write + + + TZ2_A_CBC_U + Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 10 + 2 + read-write + + + TZ2_A_OST_D + One-shot mode action on PWM2A when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 12 + 2 + read-write + + + TZ2_A_OST_U + One-shot mode action on PWM2A when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 14 + 2 + read-write + + + TZ2_B_CBC_D + Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 16 + 2 + read-write + + + TZ2_B_CBC_U + Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 18 + 2 + read-write + + + TZ2_B_OST_D + One-shot mode action on PWM2B when fault event occurs and timer is decreasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 20 + 2 + read-write + + + TZ2_B_OST_U + One-shot mode action on PWM2B when fault event occurs and timer is increasing. 0: do nothing, 1: force lo, 2: force hi, 3: toggle + 22 + 2 + read-write + + + + + TZ2_CFG1 + Software triggers for fault handler actions + 0xDC + 0x20 + + + TZ2_CLR_OST + a rising edge will clear on going one-shot mode action + 0 + 1 + read-write + + + TZ2_CBCPULSE + cycle-by-cycle mode action refresh moment selection. Bit0: TEZ, bit1:TEP + 1 + 2 + read-write + + + TZ2_FORCE_CBC + a toggle trigger a cycle-by-cycle mode action + 3 + 1 + read-write + + + TZ2_FORCE_OST + a toggle (software negate its value) triggers a one-shot mode action + 4 + 1 + read-write + + + + + TZ2_STATUS + Status of fault events. + 0xE0 + 0x20 + + + TZ2_CBC_ON + Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + 0 + 1 + read-only + + + TZ2_OST_ON + Set and reset by hardware. If set, an one-shot mode action is on going + 1 + 1 + read-only + + + + + FAULT_DETECT + Fault detection configuration and status + 0xE4 + 0x20 + + + F0_EN + When set, event_f0 generation is enabled + 0 + 1 + read-write + + + F1_EN + When set, event_f1 generation is enabled + 1 + 1 + read-write + + + F2_EN + When set, event_f2 generation is enabled + 2 + 1 + read-write + + + F0_POLE + Set event_f0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, 1: level high + 3 + 1 + read-write + + + F1_POLE + Set event_f1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, 1: level high + 4 + 1 + read-write + + + F2_POLE + Set event_f2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, 1: level high + 5 + 1 + read-write + + + EVENT_F0 + Set and reset by hardware. If set, event_f0 is on going + 6 + 1 + read-only + + + EVENT_F1 + Set and reset by hardware. If set, event_f1 is on going + 7 + 1 + read-only + + + EVENT_F2 + Set and reset by hardware. If set, event_f2 is on going + 8 + 1 + read-only + + + + + CAP_TIMER_CFG + Configure capture timer + 0xE8 + 0x20 + + + CAP_TIMER_EN + When set, capture timer incrementing under APB_clk is enabled. + 0 + 1 + read-write + + + CAP_SYNCI_EN + When set, capture timer sync is enabled. + 1 + 1 + read-write + + + CAP_SYNCI_SEL + capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: SYNC2 from GPIO matrix + 2 + 3 + read-write + + + CAP_SYNC_SW + Write 1 will force a capture timer sync, capture timer is loaded with value in phase register. + 5 + 1 + write-only + + + + + CAP_TIMER_PHASE + Phase for capture timer sync + 0xEC + 0x20 + + + CAP_PHASE + Phase value for capture timer sync operation. + 0 + 32 + read-write + + + + + CAP_CH0_CFG + Capture channel 0 configuration and enable + 0xF0 + 0x20 + + + CAP0_EN + When set, capture on channel 0 is enabled + 0 + 1 + read-write + + + CAP0_MODE + Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable capture on the negative edge, When bit1 is set to 1: enable capture on the positive edge. + 1 + 2 + read-write + + + CAP0_PRESCALE + Value of prescaling on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + 1 + 3 + 8 + read-write + + + CAP0_IN_INVERT + when set, CAP0 form GPIO matrix is inverted before prescale + 11 + 1 + read-write + + + CAP0_SW + Write 1 will trigger a software forced capture on channel 0 + 12 + 1 + write-only + + + + + CAP_CH1_CFG + Capture channel 1 configuration and enable + 0xF4 + 0x20 + + + CAP1_EN + When set, capture on channel 2 is enabled + 0 + 1 + read-write + + + CAP1_MODE + Edge of capture on channel 1 after prescaling. When bit0 is set to 1: enable capture on the negative edge, When bit1 is set to 1: enable capture on the positive edge. + 1 + 2 + read-write + + + CAP1_PRESCALE + Value of prescaling on possitive edge of CAP1. Prescale value = PWM_CAP1_PRESCALE + 1 + 3 + 8 + read-write + + + CAP1_IN_INVERT + when set, CAP1 form GPIO matrix is inverted before prescale + 11 + 1 + read-write + + + CAP1_SW + Write 1 will trigger a software forced capture on channel 1 + 12 + 1 + write-only + + + + + CAP_CH2_CFG + Capture channel 2 configuration and enable + 0xF8 + 0x20 + + + CAP2_EN + When set, capture on channel 2 is enabled + 0 + 1 + read-write + + + CAP2_MODE + Edge of capture on channel 2 after prescaling. When bit0 is set to 1: enable capture on the negative edge, When bit1 is set to 1: enable capture on the positive edge. + 1 + 2 + read-write + + + CAP2_PRESCALE + Value of prescaling on possitive edge of CAP2. Prescale value = PWM_CAP2_PRESCALE + 1 + 3 + 8 + read-write + + + CAP2_IN_INVERT + when set, CAP2 form GPIO matrix is inverted before prescale + 11 + 1 + read-write + + + CAP2_SW + Write 1 will trigger a software forced capture on channel 2 + 12 + 1 + write-only + + + + + CAP_CH0 + Value of last capture on channel 0 + 0xFC + 0x20 + + + CAP0_VALUE + Value of last capture on channel 0 + 0 + 32 + read-only + + + + + CAP_CH1 + Value of last capture on channel 1 + 0x100 + 0x20 + + + CAP1_VALUE + Value of last capture on channel 1 + 0 + 32 + read-only + + + + + CAP_CH2 + Value of last capture on channel 2 + 0x104 + 0x20 + + + CAP2_VALUE + Value of last capture on channel 2 + 0 + 32 + read-only + + + + + CAP_STATUS + Edge of last capture trigger + 0x108 + 0x20 + + + CAP0_EDGE + Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + 0 + 1 + read-only + + + CAP1_EDGE + Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + 1 + 1 + read-only + + + CAP2_EDGE + Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + 2 + 1 + read-only + + + + + UPDATE_CFG + Enable update. + 0x10C + 0x20 + 0x00000055 + + + GLOBAL_UP_EN + The global enable of update of all active registers in MCPWM module + 0 + 1 + read-write + + + GLOBAL_FORCE_UP + a toggle (software invert its value) will trigger a forced update of all active registers in MCPWM module + 1 + 1 + read-write + + + OP0_UP_EN + When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 are enabled + 2 + 1 + read-write + + + OP0_FORCE_UP + a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 0 + 3 + 1 + read-write + + + OP1_UP_EN + When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 are enabled + 4 + 1 + read-write + + + OP1_FORCE_UP + a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 1 + 5 + 1 + read-write + + + OP2_UP_EN + When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 are enabled + 6 + 1 + read-write + + + OP2_FORCE_UP + a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 2 + 7 + 1 + read-write + + + + + INT_ENA + Interrupt enable bits + 0x110 + 0x20 + + + TIMER0_STOP_INT_ENA + The enable bit for the interrupt triggered when the timer 0 stops. + 0 + 1 + read-write + + + TIMER1_STOP_INT_ENA + The enable bit for the interrupt triggered when the timer 1 stops. + 1 + 1 + read-write + + + TIMER2_STOP_INT_ENA + The enable bit for the interrupt triggered when the timer 2 stops. + 2 + 1 + read-write + + + TIMER0_TEZ_INT_ENA + The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + 3 + 1 + read-write + + + TIMER1_TEZ_INT_ENA + The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + 4 + 1 + read-write + + + TIMER2_TEZ_INT_ENA + The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + 5 + 1 + read-write + + + TIMER0_TEP_INT_ENA + The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + 6 + 1 + read-write + + + TIMER1_TEP_INT_ENA + The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + 7 + 1 + read-write + + + TIMER2_TEP_INT_ENA + The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + 8 + 1 + read-write + + + FAULT0_INT_ENA + The enable bit for the interrupt triggered when event_f0 starts. + 9 + 1 + read-write + + + FAULT1_INT_ENA + The enable bit for the interrupt triggered when event_f1 starts. + 10 + 1 + read-write + + + FAULT2_INT_ENA + The enable bit for the interrupt triggered when event_f2 starts. + 11 + 1 + read-write + + + FAULT0_CLR_INT_ENA + The enable bit for the interrupt triggered when event_f0 ends. + 12 + 1 + read-write + + + FAULT1_CLR_INT_ENA + The enable bit for the interrupt triggered when event_f1 ends. + 13 + 1 + read-write + + + FAULT2_CLR_INT_ENA + The enable bit for the interrupt triggered when event_f2 ends. + 14 + 1 + read-write + + + CMPR0_TEA_INT_ENA + The enable bit for the interrupt triggered by a PWM operator 0 TEA event + 15 + 1 + read-write + + + CMPR1_TEA_INT_ENA + The enable bit for the interrupt triggered by a PWM operator 1 TEA event + 16 + 1 + read-write + + + CMPR2_TEA_INT_ENA + The enable bit for the interrupt triggered by a PWM operator 2 TEA event + 17 + 1 + read-write + + + CMPR0_TEB_INT_ENA + The enable bit for the interrupt triggered by a PWM operator 0 TEB event + 18 + 1 + read-write + + + CMPR1_TEB_INT_ENA + The enable bit for the interrupt triggered by a PWM operator 1 TEB event + 19 + 1 + read-write + + + CMPR2_TEB_INT_ENA + The enable bit for the interrupt triggered by a PWM operator 2 TEB event + 20 + 1 + read-write + + + TZ0_CBC_INT_ENA + The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + 21 + 1 + read-write + + + TZ1_CBC_INT_ENA + The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + 22 + 1 + read-write + + + TZ2_CBC_INT_ENA + The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + 23 + 1 + read-write + + + TZ0_OST_INT_ENA + The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + 24 + 1 + read-write + + + TZ1_OST_INT_ENA + The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + 25 + 1 + read-write + + + TZ2_OST_INT_ENA + The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + 26 + 1 + read-write + + + CAP0_INT_ENA + The enable bit for the interrupt triggered by capture on channel 0. + 27 + 1 + read-write + + + CAP1_INT_ENA + The enable bit for the interrupt triggered by capture on channel 1. + 28 + 1 + read-write + + + CAP2_INT_ENA + The enable bit for the interrupt triggered by capture on channel 2. + 29 + 1 + read-write + + + + + INT_RAW + Raw interrupt status + 0x114 + 0x20 + + + TIMER0_STOP_INT_RAW + The raw status bit for the interrupt triggered when the timer 0 stops. + 0 + 1 + read-only + + + TIMER1_STOP_INT_RAW + The raw status bit for the interrupt triggered when the timer 1 stops. + 1 + 1 + read-only + + + TIMER2_STOP_INT_RAW + The raw status bit for the interrupt triggered when the timer 2 stops. + 2 + 1 + read-only + + + TIMER0_TEZ_INT_RAW + The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + 3 + 1 + read-only + + + TIMER1_TEZ_INT_RAW + The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + 4 + 1 + read-only + + + TIMER2_TEZ_INT_RAW + The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + 5 + 1 + read-only + + + TIMER0_TEP_INT_RAW + The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + 6 + 1 + read-only + + + TIMER1_TEP_INT_RAW + The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + 7 + 1 + read-only + + + TIMER2_TEP_INT_RAW + The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + 8 + 1 + read-only + + + FAULT0_INT_RAW + The raw status bit for the interrupt triggered when event_f0 starts. + 9 + 1 + read-only + + + FAULT1_INT_RAW + The raw status bit for the interrupt triggered when event_f1 starts. + 10 + 1 + read-only + + + FAULT2_INT_RAW + The raw status bit for the interrupt triggered when event_f2 starts. + 11 + 1 + read-only + + + FAULT0_CLR_INT_RAW + The raw status bit for the interrupt triggered when event_f0 ends. + 12 + 1 + read-only + + + FAULT1_CLR_INT_RAW + The raw status bit for the interrupt triggered when event_f1 ends. + 13 + 1 + read-only + + + FAULT2_CLR_INT_RAW + The raw status bit for the interrupt triggered when event_f2 ends. + 14 + 1 + read-only + + + CMPR0_TEA_INT_RAW + The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + 15 + 1 + read-only + + + CMPR1_TEA_INT_RAW + The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + 16 + 1 + read-only + + + CMPR2_TEA_INT_RAW + The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + 17 + 1 + read-only + + + CMPR0_TEB_INT_RAW + The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + 18 + 1 + read-only + + + CMPR1_TEB_INT_RAW + The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + 19 + 1 + read-only + + + CMPR2_TEB_INT_RAW + The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + 20 + 1 + read-only + + + TZ0_CBC_INT_RAW + The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + 21 + 1 + read-only + + + TZ1_CBC_INT_RAW + The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + 22 + 1 + read-only + + + TZ2_CBC_INT_RAW + The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + 23 + 1 + read-only + + + TZ0_OST_INT_RAW + The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + 24 + 1 + read-only + + + TZ1_OST_INT_RAW + The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + 25 + 1 + read-only + + + TZ2_OST_INT_RAW + The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + 26 + 1 + read-only + + + CAP0_INT_RAW + The raw status bit for the interrupt triggered by capture on channel 0. + 27 + 1 + read-only + + + CAP1_INT_RAW + The raw status bit for the interrupt triggered by capture on channel 1. + 28 + 1 + read-only + + + CAP2_INT_RAW + The raw status bit for the interrupt triggered by capture on channel 2. + 29 + 1 + read-only + + + + + INT_ST + Masked interrupt status + 0x118 + 0x20 + + + TIMER0_STOP_INT_ST + The masked status bit for the interrupt triggered when the timer 0 stops. + 0 + 1 + read-only + + + TIMER1_STOP_INT_ST + The masked status bit for the interrupt triggered when the timer 1 stops. + 1 + 1 + read-only + + + TIMER2_STOP_INT_ST + The masked status bit for the interrupt triggered when the timer 2 stops. + 2 + 1 + read-only + + + TIMER0_TEZ_INT_ST + The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + 3 + 1 + read-only + + + TIMER1_TEZ_INT_ST + The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + 4 + 1 + read-only + + + TIMER2_TEZ_INT_ST + The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + 5 + 1 + read-only + + + TIMER0_TEP_INT_ST + The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + 6 + 1 + read-only + + + TIMER1_TEP_INT_ST + The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + 7 + 1 + read-only + + + TIMER2_TEP_INT_ST + The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + 8 + 1 + read-only + + + FAULT0_INT_ST + The masked status bit for the interrupt triggered when event_f0 starts. + 9 + 1 + read-only + + + FAULT1_INT_ST + The masked status bit for the interrupt triggered when event_f1 starts. + 10 + 1 + read-only + + + FAULT2_INT_ST + The masked status bit for the interrupt triggered when event_f2 starts. + 11 + 1 + read-only + + + FAULT0_CLR_INT_ST + The masked status bit for the interrupt triggered when event_f0 ends. + 12 + 1 + read-only + + + FAULT1_CLR_INT_ST + The masked status bit for the interrupt triggered when event_f1 ends. + 13 + 1 + read-only + + + FAULT2_CLR_INT_ST + The masked status bit for the interrupt triggered when event_f2 ends. + 14 + 1 + read-only + + + CMPR0_TEA_INT_ST + The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + 15 + 1 + read-only + + + CMPR1_TEA_INT_ST + The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + 16 + 1 + read-only + + + CMPR2_TEA_INT_ST + The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + 17 + 1 + read-only + + + CMPR0_TEB_INT_ST + The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + 18 + 1 + read-only + + + CMPR1_TEB_INT_ST + The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + 19 + 1 + read-only + + + CMPR2_TEB_INT_ST + The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + 20 + 1 + read-only + + + TZ0_CBC_INT_ST + The masked status bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + 21 + 1 + read-only + + + TZ1_CBC_INT_ST + The masked status bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + 22 + 1 + read-only + + + TZ2_CBC_INT_ST + The masked status bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + 23 + 1 + read-only + + + TZ0_OST_INT_ST + The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + 24 + 1 + read-only + + + TZ1_OST_INT_ST + The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + 25 + 1 + read-only + + + TZ2_OST_INT_ST + The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + 26 + 1 + read-only + + + CAP0_INT_ST + The masked status bit for the interrupt triggered by capture on channel 0. + 27 + 1 + read-only + + + CAP1_INT_ST + The masked status bit for the interrupt triggered by capture on channel 1. + 28 + 1 + read-only + + + CAP2_INT_ST + The masked status bit for the interrupt triggered by capture on channel 2. + 29 + 1 + read-only + + + + + INT_CLR + Interrupt clear bits + 0x11C + 0x20 + + + TIMER0_STOP_INT_CLR + Set this bit to clear the interrupt triggered when the timer 0 stops. + 0 + 1 + write-only + + + TIMER1_STOP_INT_CLR + Set this bit to clear the interrupt triggered when the timer 1 stops. + 1 + 1 + write-only + + + TIMER2_STOP_INT_CLR + Set this bit to clear the interrupt triggered when the timer 2 stops. + 2 + 1 + write-only + + + TIMER0_TEZ_INT_CLR + Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + 3 + 1 + write-only + + + TIMER1_TEZ_INT_CLR + Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + 4 + 1 + write-only + + + TIMER2_TEZ_INT_CLR + Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + 5 + 1 + write-only + + + TIMER0_TEP_INT_CLR + Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + 6 + 1 + write-only + + + TIMER1_TEP_INT_CLR + Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + 7 + 1 + write-only + + + TIMER2_TEP_INT_CLR + Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + 8 + 1 + write-only + + + FAULT0_INT_CLR + Set this bit to clear the interrupt triggered when event_f0 starts. + 9 + 1 + write-only + + + FAULT1_INT_CLR + Set this bit to clear the interrupt triggered when event_f1 starts. + 10 + 1 + write-only + + + FAULT2_INT_CLR + Set this bit to clear the interrupt triggered when event_f2 starts. + 11 + 1 + write-only + + + FAULT0_CLR_INT_CLR + Set this bit to clear the interrupt triggered when event_f0 ends. + 12 + 1 + write-only + + + FAULT1_CLR_INT_CLR + Set this bit to clear the interrupt triggered when event_f1 ends. + 13 + 1 + write-only + + + FAULT2_CLR_INT_CLR + Set this bit to clear the interrupt triggered when event_f2 ends. + 14 + 1 + write-only + + + CMPR0_TEA_INT_CLR + Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + 15 + 1 + write-only + + + CMPR1_TEA_INT_CLR + Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + 16 + 1 + write-only + + + CMPR2_TEA_INT_CLR + Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + 17 + 1 + write-only + + + CMPR0_TEB_INT_CLR + Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + 18 + 1 + write-only + + + CMPR1_TEB_INT_CLR + Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + 19 + 1 + write-only + + + CMPR2_TEB_INT_CLR + Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + 20 + 1 + write-only + + + TZ0_CBC_INT_CLR + Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on PWM0. + 21 + 1 + write-only + + + TZ1_CBC_INT_CLR + Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on PWM1. + 22 + 1 + write-only + + + TZ2_CBC_INT_CLR + Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on PWM2. + 23 + 1 + write-only + + + TZ0_OST_INT_CLR + Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + 24 + 1 + write-only + + + TZ1_OST_INT_CLR + Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + 25 + 1 + write-only + + + TZ2_OST_INT_CLR + Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + 26 + 1 + write-only + + + CAP0_INT_CLR + Set this bit to clear the interrupt triggered by capture on channel 0. + 27 + 1 + write-only + + + CAP1_INT_CLR + Set this bit to clear the interrupt triggered by capture on channel 1. + 28 + 1 + write-only + + + CAP2_INT_CLR + Set this bit to clear the interrupt triggered by capture on channel 2. + 29 + 1 + write-only + + + + + CLK + MCPWM APB configuration register + 0x120 + 0x20 + + + EN + Force clock on for this register file + 0 + 1 + read-write + + + + + VERSION + Version register. + 0x124 + 0x20 + 0x01509110 + + + DATE + Version of this register file + 0 + 28 + read-write + + + + + + + PWM1 + 0x6002C000 + + PWM1 + 32 + + + + RMT + Remote control + RMT + 0x60016000 + + 0x0 + 0xD0 + registers + + + RMT + 40 + + + + 4 + 0x4 + TX_CH%sDATA + The read and write data register for CHANNEL%s by apb fifo access. + 0x0 + 0x20 + + + CHDATA + Read and write data for channel %s via APB FIFO. + 0 + 32 + read-only + + + + + 4 + 0x4 + RX_CH%sDATA + The read and write data register for CHANNEL$n by apb fifo access. + 0x10 + 0x20 + + + CHDATA + Read and write data for channel 0 via APB FIFO. + 0 + 32 + read-only + + + + + 4 + 0x4 + CH%s_TX_CONF0 + Channel %s configure register 0 + 0x20 + 0x20 + 0x00710200 + + + TX_START + Set this bit to start sending data on CHANNEL%s. + 0 + 1 + write-only + + + MEM_RD_RST + Set this bit to reset read ram address for CHANNEL%s by accessing transmitter. + 1 + 1 + write-only + + + APB_MEM_RST + Set this bit to reset W/R ram address for CHANNEL%s by accessing apb fifo. + 2 + 1 + write-only + + + TX_CONTI_MODE + Set this bit to restart transmission from the first data to the last data in CHANNEL%s. + 3 + 1 + read-write + + + MEM_TX_WRAP_EN + This is the channel %s enable bit for wraparound mode: it will resume sending at the start when the data to be sent is more than its memory size. + 4 + 1 + read-write + + + IDLE_OUT_LV + This bit configures the level of output signal in CHANNEL%s when the latter is in IDLE state. + 5 + 1 + read-write + + + IDLE_OUT_EN + This is the output enable-control bit for CHANNEL%s in IDLE state. + 6 + 1 + read-write + + + TX_STOP + Set this bit to stop the transmitter of CHANNEL%s sending data out. + 7 + 1 + read-write + + + DIV_CNT + This register is used to configure the divider for clock of CHANNEL%s. + 8 + 8 + read-write + + + MEM_SIZE + This register is used to configure the maximum size of memory allocated to CHANNEL%s. + 16 + 4 + read-write + + + CARRIER_EFF_EN + 1: Add carrier modulation on the output signal only at the send data state for CHANNEL%s. 0: Add carrier modulation on the output signal at all state for CHANNEL%s. Only valid when RMT_CARRIER_EN_CH%s is 1. + 20 + 1 + read-write + + + CARRIER_EN + This is the carrier modulation enable-control bit for CHANNEL%s. 1: Add carrier modulation in the output signal. 0: No carrier modulation in sig_out. + 21 + 1 + read-write + + + CARRIER_OUT_LV + This bit is used to configure the position of carrier wave for CHANNEL%s. + +1'h0: add carrier wave on low level. + +1'h1: add carrier wave on high level. + 22 + 1 + read-write + + + AFIFO_RST + Reserved + 23 + 1 + write-only + + + CONF_UPDATE + synchronization bit for CHANNEL%s + 24 + 1 + write-only + + + + + 4 + 0x8 + CH%s_RX_CONF0 + Channel %s configure register 0 + 0x30 + 0x20 + 0x317FFF02 + + + DIV_CNT + This register is used to configure the divider for clock of CHANNEL%s. + 0 + 8 + read-write + + + IDLE_THRES + When no edge is detected on the input signal and continuous clock cycles is longer than this register value, received process is finished. + 8 + 15 + read-write + + + MEM_SIZE + This register is used to configure the maximum size of memory allocated to CHANNEL%s. + 24 + 4 + read-write + + + CARRIER_EN + This is the carrier modulation enable-control bit for CHANNEL%s. 1: Add carrier modulation in the output signal. 0: No carrier modulation in sig_out. + 28 + 1 + read-write + + + CARRIER_OUT_LV + This bit is used to configure the position of carrier wave for CHANNEL%s. + +1'h0: add carrier wave on low level. + +1'h1: add carrier wave on high level. + 29 + 1 + read-write + + + + + 4 + 0x8 + CH%s_RX_CONF1 + Channel %s configure register 1 + 0x34 + 0x20 + 0x000001E8 + + + RX_EN + Set this bit to enable receiver to receive data on CHANNEL%s. + 0 + 1 + read-write + + + MEM_WR_RST + Set this bit to reset write ram address for CHANNEL%s by accessing receiver. + 1 + 1 + write-only + + + APB_MEM_RST + Set this bit to reset W/R ram address for CHANNEL%s by accessing apb fifo. + 2 + 1 + write-only + + + MEM_OWNER + This register marks the ownership of CHANNEL%s's ram block. + +1'h1: Receiver is using the ram. + +1'h0: APB bus is using the ram. + 3 + 1 + read-write + + + RX_FILTER_EN + This is the receive filter's enable bit for CHANNEL%s. + 4 + 1 + read-write + + + RX_FILTER_THRES + Ignores the input pulse when its width is smaller than this register value in APB clock periods (in receive mode). + 5 + 8 + read-write + + + MEM_RX_WRAP_EN + This is the channel %s enable bit for wraparound mode: it will resume receiving at the start when the data to be received is more than its memory size. + 13 + 1 + read-write + + + AFIFO_RST + Reserved + 14 + 1 + write-only + + + CONF_UPDATE + synchronization bit for CHANNEL%s + 15 + 1 + write-only + + + + + 4 + 0x4 + CH%s_TX_STATUS + Channel %s status register + 0x50 + 0x20 + + + MEM_RADDR_EX + This register records the memory address offset when transmitter of CHANNEL%s is using the RAM. + 0 + 10 + read-only + + + APB_MEM_WADDR + This register records the memory address offset when writes RAM over APB bus. + 11 + 10 + read-only + + + STATE + This register records the FSM status of CHANNEL%s. + 22 + 3 + read-only + + + MEM_EMPTY + This status bit will be set when the data to be set is more than memory size and the wraparound mode is disabled. + 25 + 1 + read-only + + + APB_MEM_WR_ERR + This status bit will be set if the offset address out of memory size when writes via APB bus. + 26 + 1 + read-only + + + + + 4 + 0x4 + CH%s_RX_STATUS + Channel %s status register + 0x60 + 0x20 + 0x000600C0 + + + MEM_WADDR_EX + This register records the memory address offset when receiver of CHANNEL%s is using the RAM. + 0 + 10 + read-only + + + APB_MEM_RADDR + This register records the memory address offset when reads RAM over APB bus. + 11 + 10 + read-only + + + STATE + This register records the FSM status of CHANNEL%s. + 22 + 3 + read-only + + + MEM_OWNER_ERR + This status bit will be set when the ownership of memory block is wrong. + 25 + 1 + read-only + + + MEM_FULL + This status bit will be set if the receiver receives more data than the memory size. + 26 + 1 + read-only + + + APB_MEM_RD_ERR + This status bit will be set if the offset address out of memory size when reads via APB bus. + 27 + 1 + read-only + + + + + INT_RAW + Raw interrupt status + 0x70 + 0x20 + + + 4 + 0x1 + 0-3 + CH%s_TX_END_INT_RAW + The interrupt raw bit for CHANNEL%s. Triggered when transmission done. + 0 + 1 + read-only + + + 4 + 0x1 + 0-3 + CH%s_TX_ERR_INT_RAW + The interrupt raw bit for CHANNEL%s. Triggered when error occurs. + 4 + 1 + read-only + + + 4 + 0x1 + 0-3 + CH%s_TX_THR_EVENT_INT_RAW + The interrupt raw bit for CHANNEL%s. Triggered when transmitter sent more data than configured value. + 8 + 1 + read-only + + + 4 + 0x1 + 0-3 + CH%s_TX_LOOP_INT_RAW + The interrupt raw bit for CHANNEL%s. Triggered when the loop count reaches the configured threshold value. + 12 + 1 + read-only + + + 4 + 0x1 + 4-7 + CH%s_RX_END_INT_RAW + The interrupt raw bit for CHANNEL4. Triggered when reception done. + 16 + 1 + read-only + + + 4 + 0x1 + 4-7 + CH%s_RX_ERR_INT_RAW + The interrupt raw bit for CHANNEL4. Triggered when error occurs. + 20 + 1 + read-only + + + CH4_RX_THR_EVENT_INT_RAW + The interrupt raw bit for CHANNEL4. Triggered when receiver receive more data than configured value. + 24 + 1 + read-only + + + CH5_RX_THR_EVENT_INT_RAW + The interrupt raw bit for CHANNEL5. Triggered when receiver receive more data than configured value. + 25 + 1 + read-only + + + CH6_RX_THR_EVENT_INT_RAW + The interrupt raw bit for CHANNEL6. Triggered when receiver receive more data than configured value. + 26 + 1 + read-only + + + CH7_RX_THR_EVENT_INT_RAW + The interrupt raw bit for CHANNEL7. Triggered when receiver receive more data than configured value. + 27 + 1 + read-only + + + TX_CH3_DMA_ACCESS_FAIL_INT_RAW + The interrupt raw bit for CHANNEL3. Triggered when dma accessing CHANNEL3 fails. + 28 + 1 + read-only + + + RX_CH7_DMA_ACCESS_FAIL_INT_RAW + The interrupt raw bit for CHANNEL7. Triggered when dma accessing CHANNEL7 fails. + 29 + 1 + read-only + + + + + INT_ST + Masked interrupt status + 0x74 + 0x20 + + + 4 + 0x1 + 0-3 + CH%s_TX_END_INT_ST + The masked interrupt status bit for CH%s_TX_END_INT. + 0 + 1 + read-only + + + 4 + 0x1 + 0-3 + CH%s_TX_ERR_INT_ST + The masked interrupt status bit for CH%s_ERR_INT. + 4 + 1 + read-only + + + 4 + 0x1 + 0-3 + CH%s_TX_THR_EVENT_INT_ST + The masked interrupt status bit for CH%s_TX_THR_EVENT_INT. + 8 + 1 + read-only + + + 4 + 0x1 + 0-3 + CH%s_TX_LOOP_INT_ST + The masked interrupt status bit for CH%s_TX_LOOP_INT. + 12 + 1 + read-only + + + 4 + 0x1 + 4-7 + CH%s_RX_END_INT_ST + The masked interrupt status bit for CH4_RX_END_INT. + 16 + 1 + read-only + + + 4 + 0x1 + 4-7 + CH%s_RX_ERR_INT_ST + The masked interrupt status bit for CH4_ERR_INT. + 20 + 1 + read-only + + + CH4_RX_THR_EVENT_INT_ST + The masked interrupt status bit for CH4_RX_THR_EVENT_INT. + 24 + 1 + read-only + + + CH5_RX_THR_EVENT_INT_ST + The masked interrupt status bit for CH5_RX_THR_EVENT_INT. + 25 + 1 + read-only + + + CH6_RX_THR_EVENT_INT_ST + The masked interrupt status bit for CH6_RX_THR_EVENT_INT. + 26 + 1 + read-only + + + CH7_RX_THR_EVENT_INT_ST + The masked interrupt status bit for CH7_RX_THR_EVENT_INT. + 27 + 1 + read-only + + + TX_CH3_DMA_ACCESS_FAIL_INT_ST + The masked interrupt status bit for CH3_DMA_ACCESS_FAIL_INT. + 28 + 1 + read-only + + + RX_CH7_DMA_ACCESS_FAIL_INT_ST + The masked interrupt status bit for CH7_DMA_ACCESS_FAIL_INT. + 29 + 1 + read-only + + + + + INT_ENA + Interrupt enable bits + 0x78 + 0x20 + + + 4 + 0x1 + 0-3 + CH%s_TX_END_INT_ENA + The interrupt enable bit for CH%s_TX_END_INT. + 0 + 1 + read-write + + + 4 + 0x1 + 0-3 + CH%s_TX_ERR_INT_ENA + The interrupt enable bit for CH%s_ERR_INT. + 4 + 1 + read-write + + + 4 + 0x1 + 0-3 + CH%s_TX_THR_EVENT_INT_ENA + The interrupt enable bit for CH%s_TX_THR_EVENT_INT. + 8 + 1 + read-write + + + 4 + 0x1 + 0-3 + CH%s_TX_LOOP_INT_ENA + The interrupt enable bit for CH%s_TX_LOOP_INT. + 12 + 1 + read-write + + + 4 + 0x1 + 4-7 + CH%s_RX_END_INT_ENA + The interrupt enable bit for CH4_RX_END_INT. + 16 + 1 + read-write + + + 4 + 0x1 + 4-7 + CH%s_RX_ERR_INT_ENA + The interrupt enable bit for CH4_ERR_INT. + 20 + 1 + read-write + + + CH4_RX_THR_EVENT_INT_ENA + The interrupt enable bit for CH4_RX_THR_EVENT_INT. + 24 + 1 + read-write + + + CH5_RX_THR_EVENT_INT_ENA + The interrupt enable bit for CH5_RX_THR_EVENT_INT. + 25 + 1 + read-write + + + CH6_RX_THR_EVENT_INT_ENA + The interrupt enable bit for CH6_RX_THR_EVENT_INT. + 26 + 1 + read-write + + + CH7_RX_THR_EVENT_INT_ENA + The interrupt enable bit for CH7_RX_THR_EVENT_INT. + 27 + 1 + read-write + + + TX_CH3_DMA_ACCESS_FAIL_INT_ENA + The interrupt enable bit for CH3_DMA_ACCESS_FAIL_INT. + 28 + 1 + read-write + + + RX_CH7_DMA_ACCESS_FAIL_INT_ENA + The interrupt enable bit for CH7_DMA_ACCESS_FAIL_INT. + 29 + 1 + read-write + + + + + INT_CLR + Interrupt clear bits + 0x7C + 0x20 + + + 4 + 0x1 + 0-3 + CH%s_TX_END_INT_CLR + Set this bit to clear theCH%s_TX_END_INT interrupt. + 0 + 1 + write-only + + + 4 + 0x1 + 0-3 + CH%s_TX_ERR_INT_CLR + Set this bit to clear theCH%s_ERR_INT interrupt. + 4 + 1 + write-only + + + 4 + 0x1 + 0-3 + CH%s_TX_THR_EVENT_INT_CLR + Set this bit to clear theCH%s_TX_THR_EVENT_INT interrupt. + 8 + 1 + write-only + + + 4 + 0x1 + 0-3 + CH%s_TX_LOOP_INT_CLR + Set this bit to clear theCH%s_TX_LOOP_INT interrupt. + 12 + 1 + write-only + + + 4 + 0x1 + 4-7 + CH%s_RX_END_INT_CLR + Set this bit to clear theCH4_RX_END_INT interrupt. + 16 + 1 + write-only + + + 4 + 0x1 + RX_CH4,RX_CH5,RX_CH6,RX_CH7 + CH%s_RX_ERR_INT_CLR + Set this bit to clear theCH4_ERR_INT interrupt. + 20 + 1 + write-only + + + CH4_RX_THR_EVENT_INT_CLR + Set this bit to clear theCH4_RX_THR_EVENT_INT interrupt. + 24 + 1 + write-only + + + CH5_RX_THR_EVENT_INT_CLR + Set this bit to clear theCH5_RX_THR_EVENT_INT interrupt. + 25 + 1 + write-only + + + CH6_RX_THR_EVENT_INT_CLR + Set this bit to clear theCH6_RX_THR_EVENT_INT interrupt. + 26 + 1 + write-only + + + CH7_RX_THR_EVENT_INT_CLR + Set this bit to clear theCH7_RX_THR_EVENT_INT interrupt. + 27 + 1 + write-only + + + TX_CH3_DMA_ACCESS_FAIL_INT_CLR + Set this bit to clear the CH3_DMA_ACCESS_FAIL_INT interrupt. + 28 + 1 + write-only + + + RX_CH7_DMA_ACCESS_FAIL_INT_CLR + Set this bit to clear the CH7_DMA_ACCESS_FAIL_INT interrupt. + 29 + 1 + write-only + + + + + 4 + 0x4 + CH%sCARRIER_DUTY + Channel %s duty cycle configuration register + 0x80 + 0x20 + 0x00400040 + + + CARRIER_LOW + This register is used to configure carrier wave 's low level clock period for CHANNEL%s. + 0 + 16 + read-write + + + CARRIER_HIGH + This register is used to configure carrier wave 's high level clock period for CHANNEL%s. + 16 + 16 + read-write + + + + + 4 + 0x4 + CH%s_RX_CARRIER_RM + Channel %s carrier remove register + 0x90 + 0x20 + + + CARRIER_LOW_THRES + The low level period in a carrier modulation mode is (REG_RMT_REG_CARRIER_LOW_THRES_CH%s + 1) for channel %s. + 0 + 16 + read-write + + + CARRIER_HIGH_THRES + The high level period in a carrier modulation mode is (REG_RMT_REG_CARRIER_HIGH_THRES_CH%s + 1) for channel %s. + 16 + 16 + read-write + + + + + 4 + 0x4 + CH%s_TX_LIM + Channel %s Tx event configuration register + 0xA0 + 0x20 + 0x00000080 + + + TX_LIM + This register is used to configure the maximum entries that CHANNEL%s can send out. + 0 + 9 + read-write + + + TX_LOOP_NUM + This register is used to configure the maximum loop count when tx_conti_mode is valid. + 9 + 10 + read-write + + + TX_LOOP_CNT_EN + This register is the enabled bit for loop count. + 19 + 1 + read-write + + + LOOP_COUNT_RESET + This register is used to reset the loop count when tx_conti_mode is valid. + 20 + 1 + write-only + + + LOOP_STOP_EN + This bit is used to enable the loop send stop function after the loop counter counts to loop number for CHANNEL%s. + 21 + 1 + read-write + + + + + 4 + 0x4 + CH%s_RX_LIM + Channel %s Rx event configuration register + 0xB0 + 0x20 + 0x00000080 + + + RX_LIM + This register is used to configure the maximum entries that CHANNEL%s can receive. + 0 + 9 + read-write + + + + + SYS_CONF + RMT apb configuration register + 0xC0 + 0x20 + 0x05000010 + + + APB_FIFO_MASK + 1'h1: access memory directly. 1'h0: access memory by FIFO. + 0 + 1 + read-write + + + MEM_CLK_FORCE_ON + Set this bit to enable the clock for RMT memory. + 1 + 1 + read-write + + + MEM_FORCE_PD + Set this bit to power down RMT memory. + 2 + 1 + read-write + + + MEM_FORCE_PU + 1: Disable RMT memory light sleep power down function. 0: Power down RMT memory when RMT is in light sleep mode. + 3 + 1 + read-write + + + SCLK_DIV_NUM + the integral part of the fractional divisor + 4 + 8 + read-write + + + SCLK_DIV_A + the numerator of the fractional part of the fractional divisor + 12 + 6 + read-write + + + SCLK_DIV_B + the denominator of the fractional part of the fractional divisor + 18 + 6 + read-write + + + SCLK_SEL + choose the clock source of rmt_sclk. 1:CLK_80Mhz;2:CLK_8MHz; 2:XTAL + 24 + 2 + read-write + + + SCLK_ACTIVE + rmt_sclk switch + 26 + 1 + read-write + + + CLK_EN + RMT register clock gate enable signal. 1: Power up the drive clock of registers. 0: Power down the drive clock of registers + 31 + 1 + read-write + + + + + TX_SIM + RMT TX synchronous register + 0xC4 + 0x20 + + + CH0 + Set this bit to enable CHANNEL0 to start sending data synchronously with other enabled channels. + 0 + 1 + read-write + + + CH1 + Set this bit to enable CHANNEL1 to start sending data synchronously with other enabled channels. + 1 + 1 + read-write + + + CH2 + Set this bit to enable CHANNEL2 to start sending data synchronously with other enabled channels. + 2 + 1 + read-write + + + CH3 + Set this bit to enable CHANNEL3 to start sending data synchronously with other enabled channels. + 3 + 1 + read-write + + + EN + This register is used to enable multiple of channels to start sending data synchronously. + 4 + 1 + read-write + + + + + REF_CNT_RST + RMT clock divider reset register + 0xC8 + 0x20 + + + 8 + 0x1 + TX_REF_CNT_RST_CH0,TX_REF_CNT_RST_CH1,TX_REF_CNT_RST_CH2,TX_REF_CNT_RST_CH3,RX_REF_CNT_RST_CH4,RX_REF_CNT_RST_CH5,RX_REF_CNT_RST_CH6,RX_REF_CNT_RST_CH7 + CH%s + This register is used to reset the clock divider of CHANNEL0. + 0 + 1 + write-only + + + + + DATE + RMT version register + 0xCC + 0x20 + 0x02101181 + + + DATE + This is the version register. + 0 + 28 + read-write + + + + + + + RNG + Hardware random number generator + RNG + 0x60034F6C + + 0x0 + 0x4 + registers + + + + DATA + Random number data + 0x110 + 0x20 + + + + + RSA + RSA (Rivest Shamir Adleman) Accelerator + RSA + 0x6003C000 + + 0x0 + 0x834 + registers + + + RSA + 76 + + + + 512 + 0x1 + M_MEM[%s] + Memory M + 0x0 + 0x8 + + + 512 + 0x1 + Z_MEM[%s] + Memory Z + 0x200 + 0x8 + + + 512 + 0x1 + Y_MEM[%s] + Memory Y + 0x400 + 0x8 + + + 512 + 0x1 + X_MEM[%s] + Memory X + 0x600 + 0x8 + + + M_PRIME + RSA M' register + 0x800 + 0x20 + + + M_PRIME + Stores M' + 0 + 32 + read-write + + + + + MODE + RSA length mode register + 0x804 + 0x20 + + + MODE + Stores the RSA length mode + 0 + 7 + read-write + + + + + CLEAN + RSA clean register + 0x808 + 0x20 + + + CLEAN + The content of this bit is 1 when memories complete initialization. + 0 + 1 + read-only + + + + + MODEXP_START + Modular exponentiation trigger register. + 0x80C + 0x20 + + + MODEXP_START + Set this bit to 1 to start the modular exponentiation. + 0 + 1 + write-only + + + + + MODMULT_START + Modular multiplication trigger register. + 0x810 + 0x20 + + + MODMULT_START + Set this bit to 1 to start the modular multiplication + 0 + 1 + write-only + + + + + MULT_START + Normal multiplication trigger register. + 0x814 + 0x20 + + + MULT_START + Set this bit to 1 to start the multiplicaiton. + 0 + 1 + write-only + + + + + IDLE + RSA idle register + 0x818 + 0x20 + + + IDLE + The content of this bit is 1 when the RSA accelerator is idle. + 0 + 1 + read-only + + + + + CLEAR_INTERRUPT + RSA interrupt clear register + 0x81C + 0x20 + + + CLEAR_INTERRUPT + set this bit to 1 to clear the RSA interrupt. + 0 + 1 + write-only + + + + + CONSTANT_TIME + CONSTANT_TIME option control register + 0x820 + 0x20 + 0x00000001 + + + CONSTANT_TIME + Controls the CONSTANT_TIME option. 0: acceleration. 1: no acceleration(by default). + 0 + 1 + read-write + + + + + SEARCH_ENABLE + SEARCH option enable register + 0x824 + 0x20 + + + SEARCH_ENABLE + Controls the SEARCH option. 0: no acceleration(by default). 1: acceleration. + 0 + 1 + read-write + + + + + SEARCH_POS + RSA search position configure register + 0x828 + 0x20 + + + SEARCH_POS + This field is used to configure the starting search position when the acceleration option of SEARCH is used. + 0 + 12 + read-write + + + + + INTERRUPT_ENA + RSA interrupt enable register + 0x82C + 0x20 + + + INTERRUPT_ENA + Set this bit to 1 to enable the RSA interrupt. This option is enabled by default. + 0 + 1 + read-write + + + + + DATE + RSA version control register + 0x830 + 0x20 + 0x20191231 + + + DATE + rsa version information + 0 + 30 + read-write + + + + + + + RTC_CNTL + Real Time Controller + RTC_CNTL + 0x60008000 + + 0x0 + 0x15C + registers + + + RTC_CORE + 39 + + + + OPTIONS0 + RTC common configure register + 0x0 + 0x20 + 0x1C00A000 + + + SW_STALL_APPCPU_C0 + {reg_sw_stall_appcpu_c1[5:0], reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU + 0 + 2 + read-write + + + SW_STALL_PROCPU_C0 + {reg_sw_stall_procpu_c1[5:0], reg_sw_stall_procpu_c0[1:0]} == 0x86 will stall PRO CPU + 2 + 2 + read-write + + + SW_APPCPU_RST + APP CPU SW reset + 4 + 1 + write-only + + + SW_PROCPU_RST + PRO CPU SW reset + 5 + 1 + write-only + + + BB_I2C_FORCE_PD + BB_I2C force power down + 6 + 1 + read-write + + + BB_I2C_FORCE_PU + BB_I2C force power up + 7 + 1 + read-write + + + BBPLL_I2C_FORCE_PD + BB_PLL _I2C force power down + 8 + 1 + read-write + + + BBPLL_I2C_FORCE_PU + BB_PLL_I2C force power up + 9 + 1 + read-write + + + BBPLL_FORCE_PD + BB_PLL force power down + 10 + 1 + read-write + + + BBPLL_FORCE_PU + BB_PLL force power up + 11 + 1 + read-write + + + XTL_FORCE_PD + crystall force power down + 12 + 1 + read-write + + + XTL_FORCE_PU + crystall force power up + 13 + 1 + read-write + + + XTL_EN_WAIT + wait bias_sleep and current source wakeup + 14 + 4 + read-write + + + XTL_FORCE_ISO + No public + 23 + 1 + read-write + + + PLL_FORCE_ISO + No public + 24 + 1 + read-write + + + ANALOG_FORCE_ISO + No public + 25 + 1 + read-write + + + XTL_FORCE_NOISO + No public + 26 + 1 + read-write + + + PLL_FORCE_NOISO + No public + 27 + 1 + read-write + + + ANALOG_FORCE_NOISO + No public + 28 + 1 + read-write + + + DG_WRAP_FORCE_RST + digital wrap force reset in deep sleep + 29 + 1 + read-write + + + DG_WRAP_FORCE_NORST + digital core force no reset in deep sleep + 30 + 1 + read-write + + + SW_SYS_RST + SW system reset + 31 + 1 + write-only + + + + + SLP_TIMER0 + configure min sleep time + 0x4 + 0x20 + + + SLP_VAL_LO + RTC sleep timer low 32 bits + 0 + 32 + read-write + + + + + SLP_TIMER1 + configure sleep time hi + 0x8 + 0x20 + + + SLP_VAL_HI + RTC sleep timer high 16 bits + 0 + 16 + read-write + + + MAIN_TIMER_ALARM_EN + timer alarm enable bit + 16 + 1 + write-only + + + + + TIME_UPDATE + update rtc main timer + 0xC + 0x20 + + + TIMER_SYS_STALL + Enable to record system stall time + 27 + 1 + read-write + + + TIMER_XTL_OFF + Enable to record 40M XTAL OFF time + 28 + 1 + read-write + + + TIMER_SYS_RST + enable to record system reset time + 29 + 1 + read-write + + + TIME_UPDATE + Set 1: to update register with RTC timer + 31 + 1 + write-only + + + + + TIME_LOW0 + read rtc_main timer low bits + 0x10 + 0x20 + + + TIMER_VALUE0_LOW + RTC timer low 32 bits + 0 + 32 + read-only + + + + + TIME_HIGH0 + read rtc_main timer high bits + 0x14 + 0x20 + + + TIMER_VALUE0_HIGH + RTC timer high 16 bits + 0 + 16 + read-only + + + + + STATE0 + configure chip sleep + 0x18 + 0x20 + + + SW_CPU_INT + rtc software interrupt to main cpu + 0 + 1 + write-only + + + SLP_REJECT_CAUSE_CLR + clear rtc sleep reject cause + 1 + 1 + write-only + + + APB2RTC_BRIDGE_SEL + 1: APB to RTC using bridge, 0: APB to RTC using sync + 22 + 1 + read-write + + + SDIO_ACTIVE_IND + SDIO active indication + 28 + 1 + read-only + + + SLP_WAKEUP + leep wakeup bit + 29 + 1 + read-write + + + SLP_REJECT + leep reject bit + 30 + 1 + read-write + + + SLEEP_EN + sleep enable bit + 31 + 1 + read-write + + + + + TIMER1 + rtc state wait time + 0x1C + 0x20 + 0x28140403 + + + CPU_STALL_EN + CPU stall enable bit + 0 + 1 + read-write + + + CPU_STALL_WAIT + CPU stall wait cycles in fast_clk_rtc + 1 + 5 + read-write + + + CK8M_WAIT + CK8M wait cycles in slow_clk_rtc + 6 + 8 + read-write + + + XTL_BUF_WAIT + XTAL wait cycles in slow_clk_rtc + 14 + 10 + read-write + + + PLL_BUF_WAIT + PLL wait cycles in slow_clk_rtc + 24 + 8 + read-write + + + + + TIMER2 + rtc monitor state delay time + 0x20 + 0x20 + 0x01080000 + + + ULPCP_TOUCH_START_WAIT + wait cycles in slow_clk_rtc before ULP-coprocessor / touch controller start to work + 15 + 9 + read-write + + + MIN_TIME_CK8M_OFF + minimal cycles in slow_clk_rtc for CK8M in power down state + 24 + 8 + read-write + + + + + TIMER3 + No public + 0x24 + 0x20 + 0x14160A08 + + + WIFI_WAIT_TIMER + No public + 0 + 9 + read-write + + + WIFI_POWERUP_TIMER + No public + 9 + 7 + read-write + + + BT_WAIT_TIMER + No public + 16 + 9 + read-write + + + BT_POWERUP_TIMER + No public + 25 + 7 + read-write + + + + + TIMER4 + No public + 0x28 + 0x20 + 0x10200A08 + + + WAIT_TIMER + No public + 0 + 9 + read-write + + + POWERUP_TIMER + No public + 9 + 7 + read-write + + + DG_WRAP_WAIT_TIMER + No public + 16 + 9 + read-write + + + DG_WRAP_POWERUP_TIMER + No public + 25 + 7 + read-write + + + + + TIMER5 + configure min sleep time + 0x2C + 0x20 + 0x00008000 + + + MIN_SLP_VAL + minimal sleep cycles in slow_clk_rtc + 8 + 8 + read-write + + + + + TIMER6 + No public + 0x30 + 0x20 + 0x10200A08 + + + CPU_TOP_WAIT_TIMER + No public + 0 + 9 + read-write + + + CPU_TOP_POWERUP_TIMER + No public + 9 + 7 + read-write + + + DG_PERI_WAIT_TIMER + No public + 16 + 9 + read-write + + + DG_PERI_POWERUP_TIMER + No public + 25 + 7 + read-write + + + + + ANA_CONF + analog configure register + 0x34 + 0x20 + 0x00440000 + + + I2C_RESET_POR_FORCE_PD + force down I2C_RESET_POR + 18 + 1 + read-write + + + I2C_RESET_POR_FORCE_PU + force on I2C_RESET_POR + 19 + 1 + read-write + + + GLITCH_RST_EN + enable clk glitch + 20 + 1 + read-write + + + SAR_I2C_PU + PLLA force power up + 22 + 1 + read-write + + + ANALOG_TOP_ISO_SLEEP + PLLA force power down + 23 + 1 + read-write + + + ANALOG_TOP_ISO_MONITOR + PLLA force power up + 24 + 1 + read-write + + + BBPLL_CAL_SLP_START + start BBPLL calibration during sleep + 25 + 1 + read-write + + + PVTMON_PU + 1: PVTMON power up, otherwise power down + 26 + 1 + read-write + + + TXRF_I2C_PU + 1: TXRF_I2C power up, otherwise power down + 27 + 1 + read-write + + + RFRX_PBUS_PU + 1: RFRX_PBUS power up, otherwise power down + 28 + 1 + read-write + + + CKGEN_I2C_PU + 1: CKGEN_I2C power up, otherwise power down + 30 + 1 + read-write + + + PLL_I2C_PU + power on pll i2c + 31 + 1 + read-write + + + + + RESET_STATE + get reset state + 0x38 + 0x20 + 0x00003000 + + + RESET_CAUSE_PROCPU + reset cause of PRO CPU + 0 + 6 + read-only + + + RESET_CAUSE_APPCPU + reset cause of APP CPU + 6 + 6 + read-only + + + APPCPU_STAT_VECTOR_SEL + APP CPU state vector sel + 12 + 1 + read-write + + + PROCPU_STAT_VECTOR_SEL + PRO CPU state vector sel + 13 + 1 + read-write + + + RESET_FLAG_PROCPU + PRO CPU reset_flag + 14 + 1 + read-only + + + RESET_FLAG_APPCPU + APP CPU reset flag + 15 + 1 + read-only + + + RESET_FLAG_PROCPU_CLR + clear PRO CPU reset_flag + 16 + 1 + write-only + + + RESET_FLAG_APPCPU_CLR + clear APP CPU reset flag + 17 + 1 + write-only + + + APPCPU_OCD_HALT_ON_RESET + APPCPU OcdHaltOnReset + 18 + 1 + read-write + + + PROCPU_OCD_HALT_ON_RESET + PROCPU OcdHaltOnReset + 19 + 1 + read-write + + + RESET_FLAG_JTAG_PROCPU + jtag reset flag + 20 + 1 + read-only + + + RESET_FLAG_JTAG_APPCPU + jtag reset flag + 21 + 1 + read-only + + + RESET_FLAG_JTAG_PROCPU_CLR + clear jtag reset flag + 22 + 1 + write-only + + + RESET_FLAG_JTAG_APPCPU_CLR + clear jtag reset flag + 23 + 1 + write-only + + + APP_DRESET_MASK + bypass cpu1 dreset + 24 + 1 + read-write + + + PRO_DRESET_MASK + bypass cpu0 dreset + 25 + 1 + read-write + + + + + WAKEUP_STATE + configure wakeup state + 0x3C + 0x20 + 0x00060000 + + + WAKEUP_ENA + wakeup enable bitmap + 15 + 17 + read-write + + + + + INT_ENA_RTC + configure rtc interrupt register + 0x40 + 0x20 + + + SLP_WAKEUP_INT_ENA + enable sleep wakeup interrupt + 0 + 1 + read-write + + + SLP_REJECT_INT_ENA + enable sleep reject interrupt + 1 + 1 + read-write + + + SDIO_IDLE_INT_ENA + enable SDIO idle interrupt + 2 + 1 + read-write + + + WDT_INT_ENA + enable RTC WDT interrupt + 3 + 1 + read-write + + + TOUCH_SCAN_DONE_INT_ENA + enable touch scan done interrupt + 4 + 1 + read-write + + + ULP_CP_INT_ENA + enable ULP-coprocessor interrupt + 5 + 1 + read-write + + + TOUCH_DONE_INT_ENA + enable touch done interrupt + 6 + 1 + read-write + + + TOUCH_ACTIVE_INT_ENA + enable touch active interrupt + 7 + 1 + read-write + + + TOUCH_INACTIVE_INT_ENA + enable touch inactive interrupt + 8 + 1 + read-write + + + BROWN_OUT_INT_ENA + enable brown out interrupt + 9 + 1 + read-write + + + MAIN_TIMER_INT_ENA + enable RTC main timer interrupt + 10 + 1 + read-write + + + SARADC1_INT_ENA + enable saradc1 interrupt + 11 + 1 + read-write + + + TSENS_INT_ENA + enable tsens interrupt + 12 + 1 + read-write + + + COCPU_INT_ENA + enable riscV cocpu interrupt + 13 + 1 + read-write + + + SARADC2_INT_ENA + enable saradc2 interrupt + 14 + 1 + read-write + + + SWD_INT_ENA + enable super watch dog interrupt + 15 + 1 + read-write + + + XTAL32K_DEAD_INT_ENA + enable xtal32k_dead interrupt + 16 + 1 + read-write + + + COCPU_TRAP_INT_ENA + enable cocpu trap interrupt + 17 + 1 + read-write + + + TOUCH_TIMEOUT_INT_ENA + enable touch timeout interrupt + 18 + 1 + read-write + + + GLITCH_DET_INT_ENA + enbale gitch det interrupt + 19 + 1 + read-write + + + TOUCH_APPROACH_LOOP_DONE_INT_ENA + touch approach mode loop interrupt + 20 + 1 + read-write + + + + + INT_RAW_RTC + rtc interrupt register + 0x44 + 0x20 + + + SLP_WAKEUP_INT_RAW + sleep wakeup interrupt raw + 0 + 1 + read-only + + + SLP_REJECT_INT_RAW + sleep reject interrupt raw + 1 + 1 + read-only + + + SDIO_IDLE_INT_RAW + SDIO idle interrupt raw + 2 + 1 + read-only + + + WDT_INT_RAW + RTC WDT interrupt raw + 3 + 1 + read-only + + + TOUCH_SCAN_DONE_INT_RAW + enable touch scan done interrupt raw + 4 + 1 + read-only + + + ULP_CP_INT_RAW + ULP-coprocessor interrupt raw + 5 + 1 + read-only + + + TOUCH_DONE_INT_RAW + touch interrupt raw + 6 + 1 + read-only + + + TOUCH_ACTIVE_INT_RAW + touch active interrupt raw + 7 + 1 + read-only + + + TOUCH_INACTIVE_INT_RAW + touch inactive interrupt raw + 8 + 1 + read-only + + + BROWN_OUT_INT_RAW + brown out interrupt raw + 9 + 1 + read-only + + + MAIN_TIMER_INT_RAW + RTC main timer interrupt raw + 10 + 1 + read-only + + + SARADC1_INT_RAW + saradc1 interrupt raw + 11 + 1 + read-only + + + TSENS_INT_RAW + tsens interrupt raw + 12 + 1 + read-only + + + COCPU_INT_RAW + riscV cocpu interrupt raw + 13 + 1 + read-only + + + SARADC2_INT_RAW + saradc2 interrupt raw + 14 + 1 + read-only + + + SWD_INT_RAW + super watch dog interrupt raw + 15 + 1 + read-only + + + XTAL32K_DEAD_INT_RAW + xtal32k dead detection interrupt raw + 16 + 1 + read-only + + + COCPU_TRAP_INT_RAW + cocpu trap interrupt raw + 17 + 1 + read-only + + + TOUCH_TIMEOUT_INT_RAW + touch timeout interrupt raw + 18 + 1 + read-only + + + GLITCH_DET_INT_RAW + glitch_det_interrupt_raw + 19 + 1 + read-only + + + TOUCH_APPROACH_LOOP_DONE_INT_RAW + touch approach mode loop interrupt raw + 20 + 1 + read-write + + + + + INT_ST_RTC + rtc interrupt register + 0x48 + 0x20 + + + SLP_WAKEUP_INT_ST + sleep wakeup interrupt state + 0 + 1 + read-only + + + SLP_REJECT_INT_ST + sleep reject interrupt state + 1 + 1 + read-only + + + SDIO_IDLE_INT_ST + SDIO idle interrupt state + 2 + 1 + read-only + + + WDT_INT_ST + RTC WDT interrupt state + 3 + 1 + read-only + + + TOUCH_SCAN_DONE_INT_ST + enable touch scan done interrupt raw + 4 + 1 + read-only + + + ULP_CP_INT_ST + ULP-coprocessor interrupt state + 5 + 1 + read-only + + + TOUCH_DONE_INT_ST + touch done interrupt state + 6 + 1 + read-only + + + TOUCH_ACTIVE_INT_ST + touch active interrupt state + 7 + 1 + read-only + + + TOUCH_INACTIVE_INT_ST + touch inactive interrupt state + 8 + 1 + read-only + + + BROWN_OUT_INT_ST + brown out interrupt state + 9 + 1 + read-only + + + MAIN_TIMER_INT_ST + RTC main timer interrupt state + 10 + 1 + read-only + + + SARADC1_INT_ST + saradc1 interrupt state + 11 + 1 + read-only + + + TSENS_INT_ST + tsens interrupt state + 12 + 1 + read-only + + + COCPU_INT_ST + riscV cocpu interrupt state + 13 + 1 + read-only + + + SARADC2_INT_ST + saradc2 interrupt state + 14 + 1 + read-only + + + SWD_INT_ST + super watch dog interrupt state + 15 + 1 + read-only + + + XTAL32K_DEAD_INT_ST + xtal32k dead detection interrupt state + 16 + 1 + read-only + + + COCPU_TRAP_INT_ST + cocpu trap interrupt state + 17 + 1 + read-only + + + TOUCH_TIMEOUT_INT_ST + Touch timeout interrupt state + 18 + 1 + read-only + + + GLITCH_DET_INT_ST + glitch_det_interrupt state + 19 + 1 + read-only + + + TOUCH_APPROACH_LOOP_DONE_INT_ST + touch approach mode loop interrupt state + 20 + 1 + read-only + + + + + INT_CLR_RTC + rtc interrupt register + 0x4C + 0x20 + + + SLP_WAKEUP_INT_CLR + Clear sleep wakeup interrupt state + 0 + 1 + write-only + + + SLP_REJECT_INT_CLR + Clear sleep reject interrupt state + 1 + 1 + write-only + + + SDIO_IDLE_INT_CLR + Clear SDIO idle interrupt state + 2 + 1 + write-only + + + WDT_INT_CLR + Clear RTC WDT interrupt state + 3 + 1 + write-only + + + TOUCH_SCAN_DONE_INT_CLR + clear touch scan done interrupt raw + 4 + 1 + write-only + + + ULP_CP_INT_CLR + Clear ULP-coprocessor interrupt state + 5 + 1 + write-only + + + TOUCH_DONE_INT_CLR + Clear touch done interrupt state + 6 + 1 + write-only + + + TOUCH_ACTIVE_INT_CLR + Clear touch active interrupt state + 7 + 1 + write-only + + + TOUCH_INACTIVE_INT_CLR + Clear touch inactive interrupt state + 8 + 1 + write-only + + + BROWN_OUT_INT_CLR + Clear brown out interrupt state + 9 + 1 + write-only + + + MAIN_TIMER_INT_CLR + Clear RTC main timer interrupt state + 10 + 1 + write-only + + + SARADC1_INT_CLR + Clear saradc1 interrupt state + 11 + 1 + write-only + + + TSENS_INT_CLR + Clear tsens interrupt state + 12 + 1 + write-only + + + COCPU_INT_CLR + Clear riscV cocpu interrupt state + 13 + 1 + write-only + + + SARADC2_INT_CLR + Clear saradc2 interrupt state + 14 + 1 + write-only + + + SWD_INT_CLR + Clear super watch dog interrupt state + 15 + 1 + write-only + + + XTAL32K_DEAD_INT_CLR + Clear RTC WDT interrupt state + 16 + 1 + write-only + + + COCPU_TRAP_INT_CLR + Clear cocpu trap interrupt state + 17 + 1 + write-only + + + TOUCH_TIMEOUT_INT_CLR + Clear touch timeout interrupt state + 18 + 1 + write-only + + + GLITCH_DET_INT_CLR + Clear glitch det interrupt state + 19 + 1 + write-only + + + TOUCH_APPROACH_LOOP_DONE_INT_CLR + cleartouch approach mode loop interrupt state + 20 + 1 + write-only + + + + + STORE0 + Reserved register + 0x50 + 0x20 + + + SCRATCH0 + Reserved register + 0 + 32 + read-write + + + + + STORE1 + Reserved register + 0x54 + 0x20 + + + SCRATCH1 + Reserved register + 0 + 32 + read-write + + + + + STORE2 + Reserved register + 0x58 + 0x20 + + + SCRATCH2 + Reserved register + 0 + 32 + read-write + + + + + STORE3 + Reserved register + 0x5C + 0x20 + + + SCRATCH3 + Reserved register + 0 + 32 + read-write + + + + + EXT_XTL_CONF + Reserved register + 0x60 + 0x20 + 0x00066C80 + + + XTAL32K_WDT_EN + xtal 32k watch dog enable + 0 + 1 + read-write + + + XTAL32K_WDT_CLK_FO + xtal 32k watch dog clock force on + 1 + 1 + read-write + + + XTAL32K_WDT_RESET + xtal 32k watch dog sw reset + 2 + 1 + read-write + + + XTAL32K_EXT_CLK_FO + xtal 32k external xtal clock force on + 3 + 1 + read-write + + + XTAL32K_AUTO_BACKUP + xtal 32k switch to back up clock when xtal is dead + 4 + 1 + read-write + + + XTAL32K_AUTO_RESTART + xtal 32k restart xtal when xtal is dead + 5 + 1 + read-write + + + XTAL32K_AUTO_RETURN + xtal 32k switch back xtal when xtal is restarted + 6 + 1 + read-write + + + XTAL32K_XPD_FORCE + Xtal 32k xpd control by sw or fsm + 7 + 1 + read-write + + + ENCKINIT_XTAL_32K + apply an internal clock to help xtal 32k to start + 8 + 1 + read-write + + + DBUF_XTAL_32K + 0: single-end buffer 1: differential buffer + 9 + 1 + read-write + + + DGM_XTAL_32K + xtal_32k gm control + 10 + 3 + read-write + + + DRES_XTAL_32K + DRES_XTAL_32K + 13 + 3 + read-write + + + XPD_XTAL_32K + XPD_XTAL_32K + 16 + 1 + read-write + + + DAC_XTAL_32K + DAC_XTAL_32K + 17 + 3 + read-write + + + WDT_STATE + state of 32k_wdt + 20 + 3 + read-only + + + XTAL32K_GPIO_SEL + XTAL_32K sel. 0: external XTAL_32K, 1: CLK from RTC pad X32P_C + 23 + 1 + read-write + + + XTL_EXT_CTR_LV + 0: power down XTAL at high level, 1: power down XTAL at low level + 30 + 1 + read-write + + + XTL_EXT_CTR_EN + Reserved register + 31 + 1 + read-write + + + + + EXT_WAKEUP_CONF + ext wakeup configure + 0x64 + 0x20 + + + GPIO_WAKEUP_FILTER + enable filter for gpio wakeup event + 29 + 1 + read-write + + + EXT_WAKEUP0_LV + 0: external wakeup at low level, 1: external wakeup at high level + 30 + 1 + read-write + + + EXT_WAKEUP1_LV + 0: external wakeup at low level, 1: external wakeup at high level + 31 + 1 + read-write + + + + + SLP_REJECT_CONF + reject sleep register + 0x68 + 0x20 + + + SLEEP_REJECT_ENA + sleep reject enable + 12 + 18 + read-write + + + LIGHT_SLP_REJECT_EN + enable reject for light sleep + 30 + 1 + read-write + + + DEEP_SLP_REJECT_EN + enable reject for deep sleep + 31 + 1 + read-write + + + + + CPU_PERIOD_CONF + conigure cpu freq + 0x6C + 0x20 + + + CPUSEL_CONF + CPU sel option + 29 + 1 + read-write + + + CPUPERIOD_SEL + conigure cpu freq + 30 + 2 + read-write + + + + + SDIO_ACT_CONF + No public + 0x70 + 0x20 + + + SDIO_ACT_DNUM + No public + 22 + 10 + read-write + + + + + CLK_CONF + configure clock register + 0x74 + 0x20 + 0x1158321C + + + EFUSE_CLK_FORCE_GATING + force efuse clk gating + 1 + 1 + read-write + + + EFUSE_CLK_FORCE_NOGATING + force efuse clk nogating + 2 + 1 + read-write + + + CK8M_DIV_SEL_VLD + used to sync reg_ck8m_div_sel bus. Clear vld before set reg_ck8m_div_sel, then set vld to actually switch the clk + 3 + 1 + read-write + + + CK8M_DIV + CK8M_D256_OUT divider. 00: div128, 01: div256, 10: div512, 11: div1024. + 4 + 2 + read-write + + + ENB_CK8M + disable CK8M and CK8M_D256_OUT + 6 + 1 + read-write + + + ENB_CK8M_DIV + 1: CK8M_D256_OUT is actually CK8M, 0: CK8M_D256_OUT is CK8M divided by 256 + 7 + 1 + read-write + + + DIG_XTAL32K_EN + enable CK_XTAL_32K for digital core (no relationship with RTC core) + 8 + 1 + read-write + + + DIG_CLK8M_D256_EN + enable CK8M_D256_OUT for digital core (no relationship with RTC core) + 9 + 1 + read-write + + + DIG_CLK8M_EN + enable CK8M for digital core (no relationship with RTC core) + 10 + 1 + read-write + + + CK8M_DIV_SEL + divider = reg_ck8m_div_sel + 1 + 12 + 3 + read-write + + + XTAL_FORCE_NOGATING + XTAL force no gating during sleep + 15 + 1 + read-write + + + CK8M_FORCE_NOGATING + CK8M force no gating during sleep + 16 + 1 + read-write + + + CK8M_DFREQ + CK8M_DFREQ + 17 + 8 + read-write + + + CK8M_FORCE_PD + CK8M force power down + 25 + 1 + read-write + + + CK8M_FORCE_PU + CK8M force power up + 26 + 1 + read-write + + + XTAL_GLOBAL_FORCE_GATING + force global xtal gating + 27 + 1 + read-write + + + XTAL_GLOBAL_FORCE_NOGATING + force global xtal no gating + 28 + 1 + read-write + + + FAST_CLK_RTC_SEL + fast_clk_rtc sel. 0: XTAL div 4, 1: CK8M + 29 + 1 + read-write + + + ANA_CLK_RTC_SEL + select slow clock + 30 + 2 + read-write + + + + + SLOW_CLK_CONF + configure slow clk + 0x78 + 0x20 + 0x00400000 + + + ANA_CLK_DIV_VLD + used to sync div bus. clear vld before set reg_rtc_ana_clk_div, then set vld to actually switch the clk + 22 + 1 + read-write + + + ANA_CLK_DIV + rtc clk div + 23 + 8 + read-write + + + SLOW_CLK_NEXT_EDGE + No public + 31 + 1 + read-write + + + + + SDIO_CONF + configure flash power + 0x7C + 0x20 + 0x0AB0BE0A + + + SDIO_TIMER_TARGET + timer count to apply reg_sdio_dcap after sdio power on + 0 + 8 + read-write + + + SDIO_DTHDRV + Tieh = 1 mode drive ability. Initially set to 0 to limit charge current, set to 3 after several us. + 9 + 2 + read-write + + + SDIO_DCAP + ability to prevent LDO from overshoot + 11 + 2 + read-write + + + SDIO_INITI + add resistor from ldo output to ground. 0: no res, 1: 6k,2:4k,3:2k + 13 + 2 + read-write + + + SDIO_EN_INITI + 0 to set init[1:0]=0 + 15 + 1 + read-write + + + SDIO_DCURLIM + tune current limit threshold when tieh = 0. About 800mA/(8+d) + 16 + 3 + read-write + + + SDIO_MODECURLIM + select current limit mode + 19 + 1 + read-write + + + SDIO_ENCURLIM + enable current limit + 20 + 1 + read-write + + + SDIO_REG_PD_EN + power down SDIO_REG in sleep. Only active when reg_sdio_force = 0 + 21 + 1 + read-write + + + SDIO_FORCE + 1: use SW option to control SDIO_REG, 0: use state machine + 22 + 1 + read-write + + + SDIO_TIEH + SW option for SDIO_TIEH. Only active when reg_sdio_force = 1 + 23 + 1 + read-write + + + REG1P8_READY + read only register for REG1P8_READY + 24 + 1 + read-only + + + DREFL_SDIO + SW option for DREFL_SDIO. Only active when reg_sdio_force = 1 + 25 + 2 + read-write + + + DREFM_SDIO + SW option for DREFM_SDIO. Only active when reg_sdio_force = 1 + 27 + 2 + read-write + + + DREFH_SDIO + SW option for DREFH_SDIO. Only active when reg_sdio_force = 1 + 29 + 2 + read-write + + + XPD_SDIO + power on flash regulator + 31 + 1 + read-write + + + + + BIAS_CONF + No public + 0x80 + 0x20 + 0x00010800 + + + BIAS_BUF_IDLE + No public + 10 + 1 + read-write + + + BIAS_BUF_WAKE + No public + 11 + 1 + read-write + + + BIAS_BUF_DEEP_SLP + No public + 12 + 1 + read-write + + + BIAS_BUF_MONITOR + No public + 13 + 1 + read-write + + + PD_CUR_DEEP_SLP + xpd cur when rtc in sleep_state + 14 + 1 + read-write + + + PD_CUR_MONITOR + xpd cur when rtc in monitor state + 15 + 1 + read-write + + + BIAS_SLEEP_DEEP_SLP + bias_sleep when rtc in sleep_state + 16 + 1 + read-write + + + BIAS_SLEEP_MONITOR + bias_sleep when rtc in monitor state + 17 + 1 + read-write + + + DBG_ATTEN_DEEP_SLP + DBG_ATTEN when rtc in sleep state + 18 + 4 + read-write + + + DBG_ATTEN_MONITOR + DBG_ATTEN when rtc in monitor state + 22 + 4 + read-write + + + DBG_ATTEN_WAKEUP + No public + 26 + 4 + read-write + + + + + RTC + configure rtc regulator + 0x84 + 0x20 + 0xA0000000 + + + DIG_REG_CAL_EN + enable dig regulator cali + 7 + 1 + read-write + + + SCK_DCAP + SCK_DCAP + 14 + 8 + read-write + + + DBOOST_FORCE_PD + RTC_DBOOST force power down + 28 + 1 + read-write + + + DBOOST_FORCE_PU + RTC_DBOOST force power up + 29 + 1 + read-write + + + REGULATOR_FORCE_PD + RTC_REG force power down (for RTC_REG power down means decrease the voltage to 0.8v or lower ) + 30 + 1 + read-write + + + REGULATOR_FORCE_PU + RTC_REG force power on (for RTC_REG power down means decrease the voltage to 0.8v or lower ) + 31 + 1 + read-write + + + + + PWC + configure rtc power + 0x88 + 0x20 + 0x00000925 + + + FASTMEM_FORCE_NOISO + Fast RTC memory force no ISO + 0 + 1 + read-write + + + FASTMEM_FORCE_ISO + Fast RTC memory force ISO + 1 + 1 + read-write + + + SLOWMEM_FORCE_NOISO + RTC memory force no ISO + 2 + 1 + read-write + + + SLOWMEM_FORCE_ISO + RTC memory force ISO + 3 + 1 + read-write + + + FORCE_ISO + rtc_peri force ISO + 4 + 1 + read-write + + + FORCE_NOISO + rtc_peri force no ISO + 5 + 1 + read-write + + + FASTMEM_FOLW_CPU + 1: Fast RTC memory PD following CPU, 0: fast RTC memory PD following RTC state machine + 6 + 1 + read-write + + + FASTMEM_FORCE_LPD + Fast RTC memory force PD + 7 + 1 + read-write + + + FASTMEM_FORCE_LPU + Fast RTC memory force no PD + 8 + 1 + read-write + + + SLOWMEM_FOLW_CPU + 1: RTC memory PD following CPU, 0: RTC memory PD following RTC state machine + 9 + 1 + read-write + + + SLOWMEM_FORCE_LPD + RTC memory force PD + 10 + 1 + read-write + + + SLOWMEM_FORCE_LPU + RTC memory force no PD + 11 + 1 + read-write + + + FORCE_PD + rtc_peri force power down + 18 + 1 + read-write + + + FORCE_PU + rtc_peri force power up + 19 + 1 + read-write + + + PD_EN + enable power down rtc_peri in sleep + 20 + 1 + read-write + + + PAD_FORCE_HOLD + rtc pad force hold + 21 + 1 + read-write + + + + + REGULATOR_DRV_CTRL + No public + 0x8C + 0x20 + + + REGULATOR_DRV_B_MONITOR + No public + 0 + 6 + read-write + + + REGULATOR_DRV_B_SLP + No public + 6 + 6 + read-write + + + DG_VDD_DRV_B_SLP + No public + 12 + 8 + read-write + + + DG_VDD_DRV_B_MONITOR + No public + 20 + 8 + read-write + + + + + DIG_PWC + configure digital power + 0x90 + 0x20 + 0x00545010 + + + LSLP_MEM_FORCE_PD + memories in digital core force PD in sleep + 3 + 1 + read-write + + + LSLP_MEM_FORCE_PU + memories in digital core force no PD in sleep + 4 + 1 + read-write + + + BT_FORCE_PD + internal SRAM 2 force power down + 11 + 1 + read-write + + + BT_FORCE_PU + internal SRAM 2 force power up + 12 + 1 + read-write + + + DG_PERI_FORCE_PD + internal SRAM 3 force power down + 13 + 1 + read-write + + + DG_PERI_FORCE_PU + internal SRAM 3 force power up + 14 + 1 + read-write + + + WIFI_FORCE_PD + wifi force power down + 17 + 1 + read-write + + + WIFI_FORCE_PU + wifi force power up + 18 + 1 + read-write + + + DG_WRAP_FORCE_PD + digital core force power down + 19 + 1 + read-write + + + DG_WRAP_FORCE_PU + digital core force power up + 20 + 1 + read-write + + + CPU_TOP_FORCE_PD + digital dcdc force power down + 21 + 1 + read-write + + + CPU_TOP_FORCE_PU + digital dcdc force power up + 22 + 1 + read-write + + + BT_PD_EN + enable power down internal SRAM 2 in sleep + 27 + 1 + read-write + + + DG_PERI_PD_EN + enable power down internal SRAM 3 in sleep + 28 + 1 + read-write + + + CPU_TOP_PD_EN + enable power down internal SRAM 4 in sleep + 29 + 1 + read-write + + + WIFI_PD_EN + enable power down wifi in sleep + 30 + 1 + read-write + + + DG_WRAP_PD_EN + enable power down all digital logic + 31 + 1 + read-write + + + + + DIG_ISO + congigure digital power isolation + 0x94 + 0x20 + 0xAA805080 + + + FORCE_OFF + No public + 7 + 1 + read-write + + + FORCE_ON + No public + 8 + 1 + read-write + + + DG_PAD_AUTOHOLD + read only register to indicate digital pad auto-hold status + 9 + 1 + read-only + + + CLR_DG_PAD_AUTOHOLD + wtite only register to clear digital pad auto-hold + 10 + 1 + write-only + + + DG_PAD_AUTOHOLD_EN + digital pad enable auto-hold + 11 + 1 + read-write + + + DG_PAD_FORCE_NOISO + digital pad force no ISO + 12 + 1 + read-write + + + DG_PAD_FORCE_ISO + digital pad force ISO + 13 + 1 + read-write + + + DG_PAD_FORCE_UNHOLD + digital pad force un-hold + 14 + 1 + read-write + + + DG_PAD_FORCE_HOLD + digital pad force hold + 15 + 1 + read-write + + + BT_FORCE_ISO + internal SRAM 2 force ISO + 22 + 1 + read-write + + + BT_FORCE_NOISO + internal SRAM 2 force no ISO + 23 + 1 + read-write + + + DG_PERI_FORCE_ISO + internal SRAM 3 force ISO + 24 + 1 + read-write + + + DG_PERI_FORCE_NOISO + internal SRAM 3 force no ISO + 25 + 1 + read-write + + + CPU_TOP_FORCE_ISO + internal SRAM 4 force ISO + 26 + 1 + read-write + + + CPU_TOP_FORCE_NOISO + internal SRAM 4 force no ISO + 27 + 1 + read-write + + + WIFI_FORCE_ISO + wifi force ISO + 28 + 1 + read-write + + + WIFI_FORCE_NOISO + wifi force no ISO + 29 + 1 + read-write + + + DG_WRAP_FORCE_ISO + digital core force ISO + 30 + 1 + read-write + + + DG_WRAP_FORCE_NOISO + digita core force no ISO + 31 + 1 + read-write + + + + + WDTCONFIG0 + configure rtc watch dog + 0x98 + 0x20 + 0x00013214 + + + WDT_CHIP_RESET_WIDTH + chip reset siginal pulse width + 0 + 8 + read-write + + + WDT_CHIP_RESET_EN + wdt reset whole chip enable + 8 + 1 + read-write + + + WDT_PAUSE_IN_SLP + pause WDT in sleep + 9 + 1 + read-write + + + WDT_APPCPU_RESET_EN + enable WDT reset APP CPU + 10 + 1 + read-write + + + WDT_PROCPU_RESET_EN + enable WDT reset PRO CPU + 11 + 1 + read-write + + + WDT_FLASHBOOT_MOD_EN + enable WDT in flash boot + 12 + 1 + read-write + + + WDT_SYS_RESET_LENGTH + system reset counter length + 13 + 3 + read-write + + + WDT_CPU_RESET_LENGTH + CPU reset counter length + 16 + 3 + read-write + + + WDT_STG3 + 1: interrupt stage en 2: CPU reset stage en 3: system reset stage en 4: RTC reset stage en + 19 + 3 + read-write + + + WDT_STG2 + 1: interrupt stage en 2: CPU reset stage en 3: system reset stage en 4: RTC reset stage en + 22 + 3 + read-write + + + WDT_STG1 + 1: interrupt stage en 2: CPU reset stage en 3: system reset stage en 4: RTC reset stage en + 25 + 3 + read-write + + + WDT_STG0 + 1: interrupt stage en 2: CPU reset stage en 3: system reset stage en 4: RTC reset stage en + 28 + 3 + read-write + + + WDT_EN + enable rtc watch dog + 31 + 1 + read-write + + + + + WDTCONFIG1 + stage0 hold time + 0x9C + 0x20 + 0x00030D40 + + + WDT_STG0_HOLD + stage0 hold time + 0 + 32 + read-write + + + + + WDTCONFIG2 + stage1 hold time + 0xA0 + 0x20 + 0x00013880 + + + WDT_STG1_HOLD + stage1 hold time + 0 + 32 + read-write + + + + + WDTCONFIG3 + stage2 hold time + 0xA4 + 0x20 + 0x00000FFF + + + WDT_STG2_HOLD + stage2 hold time + 0 + 32 + read-write + + + + + WDTCONFIG4 + stage3 hold time + 0xA8 + 0x20 + 0x00000FFF + + + WDT_STG3_HOLD + stage3 hold time + 0 + 32 + read-write + + + + + WDTFEED + rtc wdt feed + 0xAC + 0x20 + + + WDT_FEED + rtc wdt feed + 31 + 1 + write-only + + + + + WDTWPROTECT + configure rtc watch dog + 0xB0 + 0x20 + 0x50D83AA1 + + + WDT_WKEY + rtc watch dog key + 0 + 32 + read-write + + + + + SWD_CONF + congfigure super watch dog + 0xB4 + 0x20 + 0x04B00000 + + + SWD_RESET_FLAG + swd reset flag + 0 + 1 + read-only + + + SWD_FEED_INT + swd interrupt for feeding + 1 + 1 + read-only + + + SWD_BYPASS_RST + bypass super watch dog reset + 17 + 1 + read-write + + + SWD_SIGNAL_WIDTH + adjust signal width send to swd + 18 + 10 + read-write + + + SWD_RST_FLAG_CLR + reset swd reset flag + 28 + 1 + write-only + + + SWD_FEED + Sw feed swd + 29 + 1 + write-only + + + SWD_DISABLE + disabel SWD + 30 + 1 + read-write + + + SWD_AUTO_FEED_EN + automatically feed swd when int comes + 31 + 1 + read-write + + + + + SWD_WPROTECT + super watch dog key + 0xB8 + 0x20 + 0x8F1D312A + + + SWD_WKEY + super watch dog key + 0 + 32 + read-write + + + + + SW_CPU_STALL + configure cpu stall by sw + 0xBC + 0x20 + + + SW_STALL_APPCPU_C1 + {reg_sw_stall_appcpu_c1[5:0], reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU + 20 + 6 + read-write + + + SW_STALL_PROCPU_C1 + {reg_sw_stall_appcpu_c1[5:0], reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU + 26 + 6 + read-write + + + + + STORE4 + reserved register + 0xC0 + 0x20 + + + SCRATCH4 + reserved register + 0 + 32 + read-write + + + + + STORE5 + reserved register + 0xC4 + 0x20 + + + SCRATCH5 + reserved register + 0 + 32 + read-write + + + + + STORE6 + reserved register + 0xC8 + 0x20 + + + SCRATCH6 + reserved register + 0 + 32 + read-write + + + + + STORE7 + reserved register + 0xCC + 0x20 + + + SCRATCH7 + reserved register + 0 + 32 + read-write + + + + + LOW_POWER_ST + reserved register + 0xD0 + 0x20 + + + XPD_ROM0 + rom0 power down + 0 + 1 + read-only + + + XPD_DIG_DCDC + External DCDC power down + 2 + 1 + read-only + + + PERI_ISO + rtc peripheral iso + 3 + 1 + read-only + + + XPD_RTC_PERI + rtc peripheral power down + 4 + 1 + read-only + + + WIFI_ISO + wifi iso + 5 + 1 + read-only + + + XPD_WIFI + wifi wrap power down + 6 + 1 + read-only + + + DIG_ISO + digital wrap iso + 7 + 1 + read-only + + + XPD_DIG + digital wrap power down + 8 + 1 + read-only + + + TOUCH_STATE_START + touch should start to work + 9 + 1 + read-only + + + TOUCH_STATE_SWITCH + touch is about to working. Switch rtc main state + 10 + 1 + read-only + + + TOUCH_STATE_SLP + touch is in sleep state + 11 + 1 + read-only + + + TOUCH_STATE_DONE + touch is done + 12 + 1 + read-only + + + COCPU_STATE_START + ulp/cocpu should start to work + 13 + 1 + read-only + + + COCPU_STATE_SWITCH + ulp/cocpu is about to working. Switch rtc main state + 14 + 1 + read-only + + + COCPU_STATE_SLP + ulp/cocpu is in sleep state + 15 + 1 + read-only + + + COCPU_STATE_DONE + ulp/cocpu is done + 16 + 1 + read-only + + + MAIN_STATE_XTAL_ISO + no use any more + 17 + 1 + read-only + + + MAIN_STATE_PLL_ON + rtc main state machine is in states that pll should be running + 18 + 1 + read-only + + + RDY_FOR_WAKEUP + rtc is ready to receive wake up trigger from wake up source + 19 + 1 + read-only + + + MAIN_STATE_WAIT_END + rtc main state machine has been waited for some cycles + 20 + 1 + read-only + + + IN_WAKEUP_STATE + rtc main state machine is in the states of wakeup process + 21 + 1 + read-only + + + IN_LOW_POWER_STATE + rtc main state machine is in the states of low power + 22 + 1 + read-only + + + MAIN_STATE_IN_WAIT_8M + rtc main state machine is in wait 8m state + 23 + 1 + read-only + + + MAIN_STATE_IN_WAIT_PLL + rtc main state machine is in wait pll state + 24 + 1 + read-only + + + MAIN_STATE_IN_WAIT_XTL + rtc main state machine is in wait xtal state + 25 + 1 + read-only + + + MAIN_STATE_IN_SLP + rtc main state machine is in sleep state + 26 + 1 + read-only + + + MAIN_STATE_IN_IDLE + rtc main state machine is in idle state + 27 + 1 + read-only + + + MAIN_STATE + rtc main state machine status + 28 + 4 + read-only + + + + + DIAG0 + No public + 0xD4 + 0x20 + + + LOW_POWER_DIAG1 + No public + 0 + 32 + read-only + + + + + PAD_HOLD + rtc pad hold configure + 0xD8 + 0x20 + + + TOUCH_PAD0_HOLD + hold rtc pad0 + 0 + 1 + read-write + + + TOUCH_PAD1_HOLD + hold rtc pad-1 + 1 + 1 + read-write + + + TOUCH_PAD2_HOLD + hold rtc pad-2 + 2 + 1 + read-write + + + TOUCH_PAD3_HOLD + hold rtc pad-3 + 3 + 1 + read-write + + + TOUCH_PAD4_HOLD + hold rtc pad-4 + 4 + 1 + read-write + + + TOUCH_PAD5_HOLD + hold rtc pad-5 + 5 + 1 + read-write + + + TOUCH_PAD6_HOLD + hold rtc pad-6 + 6 + 1 + read-write + + + TOUCH_PAD7_HOLD + hold rtc pad-7 + 7 + 1 + read-write + + + TOUCH_PAD8_HOLD + hold rtc pad-8 + 8 + 1 + read-write + + + TOUCH_PAD9_HOLD + hold rtc pad-9 + 9 + 1 + read-write + + + TOUCH_PAD10_HOLD + hold rtc pad-10 + 10 + 1 + read-write + + + TOUCH_PAD11_HOLD + hold rtc pad-11 + 11 + 1 + read-write + + + TOUCH_PAD12_HOLD + hold rtc pad-12 + 12 + 1 + read-write + + + TOUCH_PAD13_HOLD + hold rtc pad-13 + 13 + 1 + read-write + + + TOUCH_PAD14_HOLD + hold rtc pad-14 + 14 + 1 + read-write + + + X32P_HOLD + hold rtc pad-15 + 15 + 1 + read-write + + + X32N_HOLD + hold rtc pad-16 + 16 + 1 + read-write + + + PDAC1_HOLD + hold rtc pad-17 + 17 + 1 + read-write + + + PDAC2_HOLD + hold rtc pad-18 + 18 + 1 + read-write + + + PAD19_HOLD + hold rtc pad-19 + 19 + 1 + read-write + + + PAD20_HOLD + hold rtc pad-20 + 20 + 1 + read-write + + + PAD21_HOLD + hold rtc pad-21 + 21 + 1 + read-write + + + + + DIG_PAD_HOLD + configure digtal pad hold + 0xDC + 0x20 + + + DIG_PAD_HOLD + configure digtal pad hold + 0 + 32 + read-write + + + + + EXT_WAKEUP1 + configure ext1 wakeup + 0xE0 + 0x20 + + + EXT_WAKEUP1_SEL + Bitmap to select RTC pads for ext wakeup1 + 0 + 22 + read-write + + + EXT_WAKEUP1_STATUS_CLR + clear ext wakeup1 status + 22 + 1 + write-only + + + + + EXT_WAKEUP1_STATUS + check ext wakeup1 status + 0xE4 + 0x20 + + + EXT_WAKEUP1_STATUS + ext wakeup1 status + 0 + 22 + read-only + + + + + BROWN_OUT + congfigure brownout + 0xE8 + 0x20 + 0x43FF0010 + + + BROWN_OUT_INT_WAIT + brown out interrupt wait cycles + 4 + 10 + read-write + + + BROWN_OUT_CLOSE_FLASH_ENA + enable close flash when brown out happens + 14 + 1 + read-write + + + BROWN_OUT_PD_RF_ENA + enable power down RF when brown out happens + 15 + 1 + read-write + + + BROWN_OUT_RST_WAIT + brown out reset wait cycles + 16 + 10 + read-write + + + BROWN_OUT_RST_ENA + enable brown out reset + 26 + 1 + read-write + + + BROWN_OUT_RST_SEL + 1: 4-pos reset, 0: sys_reset + 27 + 1 + read-write + + + BROWN_OUT_ANA_RST_EN + enable brown out reset en + 28 + 1 + read-write + + + BROWN_OUT_CNT_CLR + clear brown out counter + 29 + 1 + write-only + + + BROWN_OUT_ENA + enable brown out + 30 + 1 + read-write + + + DET + get brown out detect + 31 + 1 + read-only + + + + + TIME_LOW1 + RTC timer low 32 bits + 0xEC + 0x20 + + + TIMER_VALUE1_LOW + RTC timer low 32 bits + 0 + 32 + read-only + + + + + TIME_HIGH1 + RTC timer high 16 bits + 0xF0 + 0x20 + + + TIMER_VALUE1_HIGH + RTC timer high 16 bits + 0 + 16 + read-only + + + + + XTAL32K_CLK_FACTOR + xtal 32k watch dog backup clock factor + 0xF4 + 0x20 + + + XTAL32K_CLK_FACTOR + xtal 32k watch dog backup clock factor + 0 + 32 + read-write + + + + + XTAL32K_CONF + configure xtal32k + 0xF8 + 0x20 + 0x0FF00000 + + + XTAL32K_RETURN_WAIT + cycles to wait to return noral xtal 32k + 0 + 4 + read-write + + + XTAL32K_RESTART_WAIT + cycles to wait to repower on xtal 32k + 4 + 16 + read-write + + + XTAL32K_WDT_TIMEOUT + If no clock detected for this amount of time 32k is regarded as dead + 20 + 8 + read-write + + + XTAL32K_STABLE_THRES + if restarted xtal32k period is smaller than this, it is regarded as stable + 28 + 4 + read-write + + + + + ULP_CP_TIMER + configure ulp + 0xFC + 0x20 + + + ULP_CP_PC_INIT + ULP-coprocessor PC initial address + 0 + 11 + read-write + + + ULP_CP_GPIO_WAKEUP_ENA + ULP-coprocessor wakeup by GPIO enable + 29 + 1 + read-write + + + ULP_CP_GPIO_WAKEUP_CLR + ULP-coprocessor wakeup by GPIO state clear + 30 + 1 + write-only + + + ULP_CP_SLP_TIMER_EN + ULP-coprocessor timer enable bit + 31 + 1 + read-write + + + + + ULP_CP_CTRL + configure ulp + 0x100 + 0x20 + 0x00100200 + + + ULP_CP_MEM_ADDR_INIT + No public + 0 + 11 + read-write + + + ULP_CP_MEM_ADDR_SIZE + No public + 11 + 11 + read-write + + + ULP_CP_MEM_OFFST_CLR + No public + 22 + 1 + write-only + + + ULP_CP_CLK_FO + ulp coprocessor clk force on + 28 + 1 + read-write + + + ULP_CP_RESET + ulp coprocessor clk software reset + 29 + 1 + read-write + + + ULP_CP_FORCE_START_TOP + 1: ULP-coprocessor is started by SW + 30 + 1 + read-write + + + ULP_CP_START_TOP + Write 1 to start ULP-coprocessor + 31 + 1 + read-write + + + + + COCPU_CTRL + configure ulp-riscv + 0x104 + 0x20 + 0x008A0810 + + + COCPU_CLK_FO + cocpu clk force on + 0 + 1 + read-write + + + COCPU_START_2_RESET_DIS + time from start cocpu to pull down reset + 1 + 6 + read-write + + + COCPU_START_2_INTR_EN + time from start cocpu to give start interrupt + 7 + 6 + read-write + + + COCPU_SHUT + to shut cocpu + 13 + 1 + read-write + + + COCPU_SHUT_2_CLK_DIS + time from shut cocpu to disable clk + 14 + 8 + read-write + + + COCPU_SHUT_RESET_EN + to reset cocpu + 22 + 1 + read-write + + + COCPU_SEL + 1: old ULP 0: new riscV + 23 + 1 + read-write + + + COCPU_DONE_FORCE + 1: select riscv done 0: select ulp done + 24 + 1 + read-write + + + COCPU_DONE + done signal used by riscv to control timer. + 25 + 1 + read-write + + + COCPU_SW_INT_TRIGGER + trigger cocpu register interrupt + 26 + 1 + write-only + + + COCPU_CLKGATE_EN + open ulp-riscv clk gate + 27 + 1 + read-write + + + + + TOUCH_CTRL1 + configure touch controller + 0x108 + 0x20 + 0x10000100 + + + TOUCH_SLEEP_CYCLES + sleep cycles for timer + 0 + 16 + read-write + + + TOUCH_MEAS_NUM + the meas length (in 8MHz) + 16 + 16 + read-write + + + + + TOUCH_CTRL2 + configure touch controller + 0x10C + 0x20 + 0x000840CC + + + TOUCH_DRANGE + TOUCH_DRANGE + 2 + 2 + read-write + + + TOUCH_DREFL + TOUCH_DREFL + 4 + 2 + read-write + + + TOUCH_DREFH + TOUCH_DREFH + 6 + 2 + read-write + + + TOUCH_XPD_BIAS + TOUCH_XPD_BIAS + 8 + 1 + read-write + + + TOUCH_REFC + TOUCH pad0 reference cap + 9 + 3 + read-write + + + TOUCH_DBIAS + 1:use self bias 0:use bandgap bias + 12 + 1 + read-write + + + TOUCH_SLP_TIMER_EN + touch timer enable bit + 13 + 1 + read-write + + + TOUCH_START_FSM_EN + 1: TOUCH_START & TOUCH_XPD is controlled by touch fsm + 14 + 1 + read-write + + + TOUCH_START_EN + 1: start touch fsm + 15 + 1 + read-write + + + TOUCH_START_FORCE + 1: to start touch fsm by SW + 16 + 1 + read-write + + + TOUCH_XPD_WAIT + the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD + 17 + 8 + read-write + + + TOUCH_SLP_CYC_DIV + when a touch pad is active sleep cycle could be divided by this number + 25 + 2 + read-write + + + TOUCH_TIMER_FORCE_DONE + force touch timer done + 27 + 2 + read-write + + + TOUCH_RESET + reset upgrade touch + 29 + 1 + read-write + + + TOUCH_CLK_FO + touch clock force on + 30 + 1 + read-write + + + TOUCH_CLKGATE_EN + touch clock enable + 31 + 1 + read-write + + + + + TOUCH_SCAN_CTRL + configure touch controller + 0x110 + 0x20 + 0xF0000102 + + + TOUCH_DENOISE_RES + De-noise resolution: 12/10/8/4 bit + 0 + 2 + read-write + + + TOUCH_DENOISE_EN + touch pad0 will be used to de-noise + 2 + 1 + read-write + + + TOUCH_INACTIVE_CONNECTION + inactive touch pads connect to 1: gnd 0: HighZ + 8 + 1 + read-write + + + TOUCH_SHIELD_PAD_EN + touch pad14 will be used as shield + 9 + 1 + read-write + + + TOUCH_SCAN_PAD_MAP + touch scan mode pad enable map + 10 + 15 + read-write + + + TOUCH_BUFDRV + touch7 buffer driver strength + 25 + 3 + read-write + + + TOUCH_OUT_RING + select out ring pad + 28 + 4 + read-write + + + + + TOUCH_SLP_THRES + configure touch controller + 0x114 + 0x20 + 0x78000000 + + + TOUCH_SLP_TH + the threshold for sleep touch pad + 0 + 22 + read-write + + + TOUCH_SLP_APPROACH_EN + sleep pad approach function enable + 26 + 1 + read-write + + + TOUCH_SLP_PAD + configure which pad as slp pad + 27 + 5 + read-write + + + + + TOUCH_APPROACH + configure touch controller + 0x118 + 0x20 + 0x50000000 + + + TOUCH_SLP_CHANNEL_CLR + clear touch slp channel + 23 + 1 + write-only + + + TOUCH_APPROACH_MEAS_TIME + approach pads total meas times + 24 + 8 + read-write + + + + + TOUCH_FILTER_CTRL + configure touch controller + 0x11C + 0x20 + 0x96AA8800 + + + TOUCH_BYPASS_NEG_NOISE_THRES + bypass neg noise thres + 7 + 1 + read-write + + + TOUCH_BYPASS_NOISE_THRES + bypaas noise thres + 8 + 1 + read-write + + + TOUCH_SMOOTH_LVL + smooth filter factor + 9 + 2 + read-write + + + TOUCH_JITTER_STEP + touch jitter step + 11 + 4 + read-write + + + TOUCH_NEG_NOISE_LIMIT + negative threshold counter limit + 15 + 4 + read-write + + + TOUCH_NEG_NOISE_THRES + neg noise thres + 19 + 2 + read-write + + + TOUCH_NOISE_THRES + noise thres + 21 + 2 + read-write + + + TOUCH_HYSTERESIS + hysteresis + 23 + 2 + read-write + + + TOUCH_DEBOUNCE + debounce counter + 25 + 3 + read-write + + + TOUCH_FILTER_MODE + 0: IIR ? 1: IIR ? 2: IIR 1/8 3: Jitter + 28 + 3 + read-write + + + TOUCH_FILTER_EN + touch filter enable + 31 + 1 + read-write + + + + + USB_CONF + usb configure + 0x120 + 0x20 + + + USB_VREFH + reg_usb_vrefh + 0 + 2 + read-write + + + USB_VREFL + reg_usb_vrefl + 2 + 2 + read-write + + + USB_VREF_OVERRIDE + reg_usb_vref_override + 4 + 1 + read-write + + + USB_PAD_PULL_OVERRIDE + reg_usb_pad_pull_override + 5 + 1 + read-write + + + USB_DP_PULLUP + reg_usb_dp_pullup + 6 + 1 + read-write + + + USB_DP_PULLDOWN + reg_usb_dp_pulldown + 7 + 1 + read-write + + + USB_DM_PULLUP + reg_usb_dm_pullup + 8 + 1 + read-write + + + USB_DM_PULLDOWN + reg_usb_dm_pulldown + 9 + 1 + read-write + + + USB_PULLUP_VALUE + reg_usb_pullup_value + 10 + 1 + read-write + + + USB_PAD_ENABLE_OVERRIDE + reg_usb_pad_enable_override + 11 + 1 + read-write + + + USB_PAD_ENABLE + reg_usb_pad_enable + 12 + 1 + read-write + + + USB_TXM + reg_usb_txm + 13 + 1 + read-write + + + USB_TXP + reg_usb_txp + 14 + 1 + read-write + + + USB_TX_EN + reg_usb_tx_en + 15 + 1 + read-write + + + USB_TX_EN_OVERRIDE + reg_usb_tx_en_override + 16 + 1 + read-write + + + USB_RESET_DISABLE + reg_usb_reset_disable + 17 + 1 + read-write + + + IO_MUX_RESET_DISABLE + reg_io_mux_reset_disable + 18 + 1 + read-write + + + SW_USB_PHY_SEL + reg_sw_usb_phy_sel + 19 + 1 + read-write + + + SW_HW_USB_PHY_SEL + reg_sw_hw_usb_phy_sel + 20 + 1 + read-write + + + + + TOUCH_TIMEOUT_CTRL + configure touch controller + 0x124 + 0x20 + 0x007FFFFF + + + TOUCH_TIMEOUT_NUM + configure touch timerout time + 0 + 22 + read-write + + + TOUCH_TIMEOUT_EN + enable touch timerout + 22 + 1 + read-write + + + + + SLP_REJECT_CAUSE + get reject casue + 0x128 + 0x20 + + + REJECT_CAUSE + sleep reject cause + 0 + 18 + read-only + + + + + OPTION1 + rtc common configure + 0x12C + 0x20 + + + FORCE_DOWNLOAD_BOOT + force chip entry download boot by sw + 0 + 1 + read-write + + + + + SLP_WAKEUP_CAUSE + get wakeup cause + 0x130 + 0x20 + + + WAKEUP_CAUSE + sleep wakeup cause + 0 + 17 + read-only + + + + + ULP_CP_TIMER_1 + configure ulp sleep time + 0x134 + 0x20 + 0x0000C800 + + + ULP_CP_TIMER_SLP_CYCLE + sleep cycles for ULP-coprocessor timer + 8 + 24 + read-write + + + + + INT_ENA_RTC_W1TS + oneset rtc interrupt + 0x138 + 0x20 + + + SLP_WAKEUP_INT_ENA_W1TS + enable sleep wakeup interrupt + 0 + 1 + write-only + + + SLP_REJECT_INT_ENA_W1TS + enable sleep reject interrupt + 1 + 1 + write-only + + + SDIO_IDLE_INT_ENA_W1TS + enable SDIO idle interrupt + 2 + 1 + write-only + + + WDT_INT_ENA_W1TS + enable RTC WDT interrupt + 3 + 1 + write-only + + + TOUCH_SCAN_DONE_INT_ENA_W1TS + enable touch scan done interrupt + 4 + 1 + write-only + + + ULP_CP_INT_ENA_W1TS + enable ULP-coprocessor interrupt + 5 + 1 + write-only + + + TOUCH_DONE_INT_ENA_W1TS + enable touch done interrupt + 6 + 1 + write-only + + + TOUCH_ACTIVE_INT_ENA_W1TS + enable touch active interrupt + 7 + 1 + write-only + + + TOUCH_INACTIVE_INT_ENA_W1TS + enable touch inactive interrupt + 8 + 1 + write-only + + + BROWN_OUT_INT_ENA_W1TS + enable brown out interrupt + 9 + 1 + write-only + + + MAIN_TIMER_INT_ENA_W1TS + enable RTC main timer interrupt + 10 + 1 + write-only + + + SARADC1_INT_ENA_W1TS + enable saradc1 interrupt + 11 + 1 + write-only + + + TSENS_INT_ENA_W1TS + enable tsens interrupt + 12 + 1 + write-only + + + COCPU_INT_ENA_W1TS + enable riscV cocpu interrupt + 13 + 1 + write-only + + + SARADC2_INT_ENA_W1TS + enable saradc2 interrupt + 14 + 1 + write-only + + + SWD_INT_ENA_W1TS + enable super watch dog interrupt + 15 + 1 + write-only + + + XTAL32K_DEAD_INT_ENA_W1TS + enable xtal32k_dead interrupt + 16 + 1 + write-only + + + COCPU_TRAP_INT_ENA_W1TS + enable cocpu trap interrupt + 17 + 1 + write-only + + + TOUCH_TIMEOUT_INT_ENA_W1TS + enable touch timeout interrupt + 18 + 1 + write-only + + + GLITCH_DET_INT_ENA_W1TS + enbale gitch det interrupt + 19 + 1 + write-only + + + TOUCH_APPROACH_LOOP_DONE_INT_ENA_W1TS + enbale touch approach_loop done interrupt + 20 + 1 + write-only + + + + + INT_ENA_RTC_W1TC + oneset clr rtc interrupt enable + 0x13C + 0x20 + + + SLP_WAKEUP_INT_ENA_W1TC + enable sleep wakeup interrupt + 0 + 1 + write-only + + + SLP_REJECT_INT_ENA_W1TC + enable sleep reject interrupt + 1 + 1 + write-only + + + SDIO_IDLE_INT_ENA_W1TC + enable SDIO idle interrupt + 2 + 1 + write-only + + + WDT_INT_ENA_W1TC + enable RTC WDT interrupt + 3 + 1 + write-only + + + TOUCH_SCAN_DONE_INT_ENA_W1TC + enable touch scan done interrupt + 4 + 1 + write-only + + + ULP_CP_INT_ENA_W1TC + enable ULP-coprocessor interrupt + 5 + 1 + write-only + + + TOUCH_DONE_INT_ENA_W1TC + enable touch done interrupt + 6 + 1 + write-only + + + TOUCH_ACTIVE_INT_ENA_W1TC + enable touch active interrupt + 7 + 1 + write-only + + + TOUCH_INACTIVE_INT_ENA_W1TC + enable touch inactive interrupt + 8 + 1 + write-only + + + BROWN_OUT_INT_ENA_W1TC + enable brown out interrupt + 9 + 1 + write-only + + + MAIN_TIMER_INT_ENA_W1TC + enable RTC main timer interrupt + 10 + 1 + write-only + + + SARADC1_INT_ENA_W1TC + enable saradc1 interrupt + 11 + 1 + write-only + + + TSENS_INT_ENA_W1TC + enable tsens interrupt + 12 + 1 + write-only + + + COCPU_INT_ENA_W1TC + enable riscV cocpu interrupt + 13 + 1 + write-only + + + SARADC2_INT_ENA_W1TC + enable saradc2 interrupt + 14 + 1 + write-only + + + SWD_INT_ENA_W1TC + enable super watch dog interrupt + 15 + 1 + write-only + + + XTAL32K_DEAD_INT_ENA_W1TC + enable xtal32k_dead interrupt + 16 + 1 + write-only + + + COCPU_TRAP_INT_ENA_W1TC + enable cocpu trap interrupt + 17 + 1 + write-only + + + TOUCH_TIMEOUT_INT_ENA_W1TC + enable touch timeout interrupt + 18 + 1 + write-only + + + GLITCH_DET_INT_ENA_W1TC + enbale gitch det interrupt + 19 + 1 + write-only + + + TOUCH_APPROACH_LOOP_DONE_INT_ENA_W1TC + enbale touch approach_loop done interrupt + 20 + 1 + write-only + + + + + RETENTION_CTRL + configure retention + 0x140 + 0x20 + 0x28340000 + + + RETENTION_TAG_MODE + No public + 10 + 4 + read-write + + + RETENTION_TARGET + congfigure retention target cpu and/or tag + 14 + 2 + read-write + + + RETENTION_CLK_SEL + No public + 16 + 1 + read-write + + + RETENTION_DONE_WAIT + wait retention done cycle + 17 + 3 + read-write + + + RETENTION_CLKOFF_WAIT + wait clk off cycle + 20 + 4 + read-write + + + RETENTION_EN + enable retention + 24 + 1 + read-write + + + RETENTION_WAIT + wait cycles for rention operation + 25 + 7 + read-write + + + + + PG_CTRL + configure power glitch + 0x144 + 0x20 + + + POWER_GLITCH_DSENSE + GLITCH_DSENSE + 26 + 2 + read-write + + + POWER_GLITCH_FORCE_PD + force power glitch disable + 28 + 1 + read-write + + + POWER_GLITCH_FORCE_PU + force power glitch enable + 29 + 1 + read-write + + + POWER_GLITCH_EFUSE_SEL + select use analog fib signal + 30 + 1 + read-write + + + POWER_GLITCH_EN + enable power glitch + 31 + 1 + read-write + + + + + FIB_SEL + No public + 0x148 + 0x20 + 0x00000007 + + + FIB_SEL + No public + 0 + 3 + read-write + + + + + TOUCH_DAC + configure touch dac + 0x14C + 0x20 + + + TOUCH_PAD9_DAC + configure touch pad dac9 + 2 + 3 + read-write + + + TOUCH_PAD8_DAC + configure touch pad dac8 + 5 + 3 + read-write + + + TOUCH_PAD7_DAC + configure touch pad dac7 + 8 + 3 + read-write + + + TOUCH_PAD6_DAC + configure touch pad dac6 + 11 + 3 + read-write + + + TOUCH_PAD5_DAC + configure touch pad dac5 + 14 + 3 + read-write + + + TOUCH_PAD4_DAC + configure touch pad dac4 + 17 + 3 + read-write + + + TOUCH_PAD3_DAC + configure touch pad dac3 + 20 + 3 + read-write + + + TOUCH_PAD2_DAC + configure touch pad dac2 + 23 + 3 + read-write + + + TOUCH_PAD1_DAC + configure touch pad dac1 + 26 + 3 + read-write + + + TOUCH_PAD0_DAC + configure touch pad dac0 + 29 + 3 + read-write + + + + + TOUCH_DAC1 + configure touch dac + 0x150 + 0x20 + + + TOUCH_PAD14_DAC + configure touch pad dac14 + 17 + 3 + read-write + + + TOUCH_PAD13_DAC + configure touch pad dac13 + 20 + 3 + read-write + + + TOUCH_PAD12_DAC + configure touch pad dac12 + 23 + 3 + read-write + + + TOUCH_PAD11_DAC + configure touch pad dac11 + 26 + 3 + read-write + + + TOUCH_PAD10_DAC + configure touch pad dac10 + 29 + 3 + read-write + + + + + COCPU_DISABLE + configure ulp diable + 0x154 + 0x20 + + + DISABLE_RTC_CPU + configure ulp diable + 31 + 1 + read-write + + + + + DATE + version register + 0x1FC + 0x20 + 0x02101271 + + + DATE + version register + 0 + 28 + read-write + + + + + + + RTC_I2C + Peripheral RTC_I2C + RTC_I2C + 0x60008C00 + + 0x0 + 0x7C + registers + + + + SCL_LOW + configure low scl period + 0x0 + 0x20 + 0x00000100 + + + PERIOD + time period that scl =0 + 0 + 20 + read-write + + + + + CTRL + configure i2c ctrl + 0x4 + 0x20 + + + SDA_FORCE_OUT + 1=push pull,0=open drain + 0 + 1 + read-write + + + SCL_FORCE_OUT + 1=push pull,0=open drain + 1 + 1 + read-write + + + MS_MODE + 1=master,0=slave + 2 + 1 + read-write + + + TRANS_START + force start + 3 + 1 + read-write + + + TX_LSB_FIRST + transit lsb first + 4 + 1 + read-write + + + RX_LSB_FIRST + receive lsb first + 5 + 1 + read-write + + + I2C_CTRL_CLK_GATE_EN + configure i2c ctrl clk enable + 29 + 1 + read-write + + + I2C_RESET + rtc i2c sw reset + 30 + 1 + read-write + + + I2CCLK_EN + rtc i2c reg clk gating + 31 + 1 + read-write + + + + + STATUS + get i2c status + 0x8 + 0x20 + + + ACK_REC + ack response + 0 + 1 + read-only + + + SLAVE_RW + slave read or write + 1 + 1 + read-only + + + ARB_LOST + arbitration is lost + 2 + 1 + read-only + + + BUS_BUSY + bus is busy + 3 + 1 + read-only + + + SLAVE_ADDRESSED + slave reg sub address + 4 + 1 + read-only + + + BYTE_TRANS + One byte transit done + 5 + 1 + read-only + + + OP_CNT + which operation is working + 6 + 2 + read-only + + + SHIFT + shifter content + 16 + 8 + read-only + + + SCL_MAIN_STATE_LAST + i2c last main status + 24 + 3 + read-only + + + SCL_STATE_LAST + scl last status + 28 + 3 + read-only + + + + + TO + configure time out + 0xC + 0x20 + 0x00010000 + + + TIME_OUT + time out threshold + 0 + 20 + read-write + + + + + SLAVE_ADDR + configure slave id + 0x10 + 0x20 + + + SLAVE_ADDR + slave address + 0 + 15 + read-write + + + ADDR_10BIT_EN + i2c 10bit mode enable + 31 + 1 + read-write + + + + + SCL_HIGH + configure high scl period + 0x14 + 0x20 + 0x00000100 + + + PERIOD + time period that scl = 1 + 0 + 20 + read-write + + + + + SDA_DUTY + configure sda duty + 0x18 + 0x20 + 0x00000010 + + + NUM + time period for SDA to toggle after SCL goes low + 0 + 20 + read-write + + + + + SCL_START_PERIOD + configure scl start period + 0x1C + 0x20 + 0x00000008 + + + SCL_START_PERIOD + time period for SCL to toggle after I2C start is triggered + 0 + 20 + read-write + + + + + SCL_STOP_PERIOD + configure scl stop period + 0x20 + 0x20 + 0x00000008 + + + SCL_STOP_PERIOD + time period for SCL to stop after I2C end is triggered + 0 + 20 + read-write + + + + + INT_CLR + interrupt clear register + 0x24 + 0x20 + + + SLAVE_TRAN_COMP_INT_CLR + clear slave transit complete interrupt + 0 + 1 + write-only + + + ARBITRATION_LOST_INT_CLR + clear arbitration lost interrupt + 1 + 1 + write-only + + + MASTER_TRAN_COMP_INT_CLR + clear master transit complete interrupt + 2 + 1 + write-only + + + TRANS_COMPLETE_INT_CLR + clear transit complete interrupt + 3 + 1 + write-only + + + TIME_OUT_INT_CLR + clear time out interrupt + 4 + 1 + write-only + + + ACK_ERR_INT_CLR + clear ack error interrupt + 5 + 1 + write-only + + + RX_DATA_INT_CLR + clear receive data interrupt + 6 + 1 + write-only + + + TX_DATA_INT_CLR + clear transit load data complete interrupt + 7 + 1 + write-only + + + DETECT_START_INT_CLR + clear detect start interrupt + 8 + 1 + write-only + + + + + INT_RAW + interrupt raw register + 0x28 + 0x20 + + + SLAVE_TRAN_COMP_INT_RAW + slave transit complete interrupt raw + 0 + 1 + read-only + + + ARBITRATION_LOST_INT_RAW + arbitration lost interrupt raw + 1 + 1 + read-only + + + MASTER_TRAN_COMP_INT_RAW + master transit complete interrupt raw + 2 + 1 + read-only + + + TRANS_COMPLETE_INT_RAW + transit complete interrupt raw + 3 + 1 + read-only + + + TIME_OUT_INT_RAW + time out interrupt raw + 4 + 1 + read-only + + + ACK_ERR_INT_RAW + ack error interrupt raw + 5 + 1 + read-only + + + RX_DATA_INT_RAW + receive data interrupt raw + 6 + 1 + read-only + + + TX_DATA_INT_RAW + transit data interrupt raw + 7 + 1 + read-only + + + DETECT_START_INT_RAW + detect start interrupt raw + 8 + 1 + read-only + + + + + INT_ST + interrupt state register + 0x2C + 0x20 + + + SLAVE_TRAN_COMP_INT_ST + slave transit complete interrupt state + 0 + 1 + read-only + + + ARBITRATION_LOST_INT_ST + arbitration lost interrupt state + 1 + 1 + read-only + + + MASTER_TRAN_COMP_INT_ST + master transit complete interrupt state + 2 + 1 + read-only + + + TRANS_COMPLETE_INT_ST + transit complete interrupt state + 3 + 1 + read-only + + + TIME_OUT_INT_ST + time out interrupt state + 4 + 1 + read-only + + + ACK_ERR_INT_ST + ack error interrupt state + 5 + 1 + read-only + + + RX_DATA_INT_ST + receive data interrupt state + 6 + 1 + read-only + + + TX_DATA_INT_ST + transit data interrupt state + 7 + 1 + read-only + + + DETECT_START_INT_ST + detect start interrupt state + 8 + 1 + read-only + + + + + INT_ENA + interrupt enable register + 0x30 + 0x20 + + + SLAVE_TRAN_COMP_INT_ENA + enable slave transit complete interrupt + 0 + 1 + read-write + + + ARBITRATION_LOST_INT_ENA + enable arbitration lost interrupt + 1 + 1 + read-write + + + MASTER_TRAN_COMP_INT_ENA + enable master transit complete interrupt + 2 + 1 + read-write + + + TRANS_COMPLETE_INT_ENA + enable transit complete interrupt + 3 + 1 + read-write + + + TIME_OUT_INT_ENA + enable time out interrupt + 4 + 1 + read-write + + + ACK_ERR_INT_ENA + enable eack error interrupt + 5 + 1 + read-write + + + RX_DATA_INT_ENA + enable receive data interrupt + 6 + 1 + read-write + + + TX_DATA_INT_ENA + enable transit data interrupt + 7 + 1 + read-write + + + DETECT_START_INT_ENA + enable detect start interrupt + 8 + 1 + read-write + + + + + DATA + get i2c data status + 0x34 + 0x20 + + + I2C_RDATA + data received + 0 + 8 + read-only + + + SLAVE_TX_DATA + data sent by slave + 8 + 8 + read-write + + + I2C_DONE + i2c done + 31 + 1 + read-only + + + + + CMD0 + i2c commond0 register + 0x38 + 0x20 + 0x00000903 + + + COMMAND0 + command0 + 0 + 14 + read-write + + + COMMAND0_DONE + command0_done + 31 + 1 + read-only + + + + + CMD1 + i2c commond1 register + 0x3C + 0x20 + 0x00001901 + + + COMMAND1 + command1 + 0 + 14 + read-write + + + COMMAND1_DONE + command1_done + 31 + 1 + read-only + + + + + CMD2 + i2c commond2 register + 0x40 + 0x20 + 0x00000902 + + + COMMAND2 + command2 + 0 + 14 + read-write + + + COMMAND2_DONE + command2_done + 31 + 1 + read-only + + + + + CMD3 + i2c commond3 register + 0x44 + 0x20 + 0x00000101 + + + COMMAND3 + command3 + 0 + 14 + read-write + + + COMMAND3_DONE + command3_done + 31 + 1 + read-only + + + + + CMD4 + i2c commond4 register + 0x48 + 0x20 + 0x00000901 + + + COMMAND4 + command4 + 0 + 14 + read-write + + + COMMAND4_DONE + command4_done + 31 + 1 + read-only + + + + + CMD5 + i2c commond5_register + 0x4C + 0x20 + 0x00001701 + + + COMMAND5 + command5 + 0 + 14 + read-write + + + COMMAND5_DONE + command5_done + 31 + 1 + read-only + + + + + CMD6 + i2c commond6 register + 0x50 + 0x20 + 0x00001901 + + + COMMAND6 + command6 + 0 + 14 + read-write + + + COMMAND6_DONE + command6_done + 31 + 1 + read-only + + + + + CMD7 + i2c commond7 register + 0x54 + 0x20 + 0x00000904 + + + COMMAND7 + command7 + 0 + 14 + read-write + + + COMMAND7_DONE + command7_done + 31 + 1 + read-only + + + + + CMD8 + i2c commond8 register + 0x58 + 0x20 + 0x00001901 + + + COMMAND8 + command8 + 0 + 14 + read-write + + + COMMAND8_DONE + command8_done + 31 + 1 + read-only + + + + + CMD9 + i2c commond9 register + 0x5C + 0x20 + 0x00000903 + + + COMMAND9 + command9 + 0 + 14 + read-write + + + COMMAND9_DONE + command9_done + 31 + 1 + read-only + + + + + CMD10 + i2c commond10 register + 0x60 + 0x20 + 0x00000101 + + + COMMAND10 + command10 + 0 + 14 + read-write + + + COMMAND10_DONE + command10_done + 31 + 1 + read-only + + + + + CMD11 + i2c commond11 register + 0x64 + 0x20 + 0x00000901 + + + COMMAND11 + command11 + 0 + 14 + read-write + + + COMMAND11_DONE + command11_done + 31 + 1 + read-only + + + + + CMD12 + i2c commond12 register + 0x68 + 0x20 + 0x00001701 + + + COMMAND12 + command12 + 0 + 14 + read-write + + + COMMAND12_DONE + command12_done + 31 + 1 + read-only + + + + + CMD13 + i2c commond13 register + 0x6C + 0x20 + 0x00001901 + + + COMMAND13 + command13 + 0 + 14 + read-write + + + COMMAND13_DONE + command13_done + 31 + 1 + read-only + + + + + CMD14 + i2c commond14 register + 0x70 + 0x20 + + + COMMAND14 + command14 + 0 + 14 + read-write + + + COMMAND14_DONE + command14_done + 31 + 1 + read-only + + + + + CMD15 + i2c commond15 register + 0x74 + 0x20 + + + COMMAND15 + command15 + 0 + 14 + read-write + + + COMMAND15_DONE + command15_done + 31 + 1 + read-only + + + + + DATE + version register + 0xFC + 0x20 + 0x01905310 + + + I2C_DATE + version + 0 + 28 + read-write + + + + + + + RTCIO + Peripheral RTC_IO + RTC_IO + 0x60008400 + + 0x0 + 0xF0 + registers + + + + RTC_GPIO_OUT + RTC GPIO 0 ~ 21 output data register + 0x0 + 0x20 + + + DATA + RTC GPIO 0 ~ 21 output data + 10 + 22 + read-write + + + + + RTC_GPIO_OUT_W1TS + one set RTC GPIO output data + 0x4 + 0x20 + + + RTC_GPIO_OUT_DATA_W1TS + RTC GPIO 0 ~ 21 output data write 1 to set + 10 + 22 + write-only + + + + + RTC_GPIO_OUT_W1TC + one clear RTC GPIO output data + 0x8 + 0x20 + + + RTC_GPIO_OUT_DATA_W1TC + RTC GPIO 0 ~ 21 output data write 1 to clear + 10 + 22 + write-only + + + + + RTC_GPIO_ENABLE + Configure RTC GPIO output enable + 0xC + 0x20 + + + RTC_GPIO_ENABLE + RTC GPIO 0 ~ 21 enable + 10 + 22 + read-write + + + + + RTC_GPIO_ENABLE_W1TS + one set RTC GPIO output enable + 0x10 + 0x20 + + + RTC_GPIO_ENABLE_W1TS + RTC GPIO 0 ~ 21 enable write 1 to set + 10 + 22 + write-only + + + + + ENABLE_W1TC + one clear RTC GPIO output enable + 0x14 + 0x20 + + + ENABLE_W1TC + RTC GPIO 0 ~ 21 enable write 1 to clear + 10 + 22 + write-only + + + + + RTC_GPIO_STATUS + RTC GPIO 0 ~ 21 interrupt status + 0x18 + 0x20 + + + INT + RTC GPIO 0 ~ 21 interrupt status + 10 + 22 + read-write + + + + + RTC_GPIO_STATUS_W1TS + One set RTC GPIO 0 ~ 21 interrupt status + 0x1C + 0x20 + + + RTC_GPIO_STATUS_INT_W1TS + RTC GPIO 0 ~ 21 interrupt status write 1 to set + 10 + 22 + write-only + + + + + RTC_GPIO_STATUS_W1TC + One clear RTC GPIO 0 ~ 21 interrupt status + 0x20 + 0x20 + + + RTC_GPIO_STATUS_INT_W1TC + RTC GPIO 0 ~ 21 interrupt status write 1 to clear + 10 + 22 + write-only + + + + + RTC_GPIO_IN + RTC GPIO input data + 0x24 + 0x20 + + + NEXT + RTC GPIO input data + 10 + 22 + read-only + + + + + 22 + 0x4 + 0-21 + PIN%s + configure RTC GPIO%s + 0x28 + 0x20 + + + PAD_DRIVER + if set to 0: normal output, if set to 1: open drain + 2 + 1 + read-write + + + INT_TYPE + if set to 0: GPIO interrupt disable, if set to 1: rising edge trigger, if set to 2: falling edge trigger, if set to 3: any edge trigger, if set to 4: low level trigger, if set to 5: high level trigger + 7 + 3 + read-write + + + WAKEUP_ENABLE + RTC GPIO wakeup enable bit + 10 + 1 + read-write + + + + + RTC_DEBUG_SEL + configure rtc debug + 0x80 + 0x20 + + + RTC_DEBUG_SEL0 + configure rtc debug + 0 + 5 + read-write + + + RTC_DEBUG_SEL1 + configure rtc debug + 5 + 5 + read-write + + + RTC_DEBUG_SEL2 + configure rtc debug + 10 + 5 + read-write + + + RTC_DEBUG_SEL3 + configure rtc debug + 15 + 5 + read-write + + + RTC_DEBUG_SEL4 + configure rtc debug + 20 + 5 + read-write + + + RTC_DEBUG_12M_NO_GATING + configure rtc debug + 25 + 1 + read-write + + + + + TOUCH_PAD0 + configure RTC PAD0 + 0x84 + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD1 + configure RTC PAD1 + 0x88 + 0x20 + 0x48000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD2 + configure RTC PAD2 + 0x8C + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD3 + configure RTC PAD3 + 0x90 + 0x20 + 0x48000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD4 + configure RTC PAD4 + 0x94 + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD5 + configure RTC PAD5 + 0x98 + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD6 + configure RTC PAD6 + 0x9C + 0x20 + 0x48000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD7 + configure RTC PAD7 + 0xA0 + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD8 + configure RTC PAD8 + 0xA4 + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD9 + configure RTC PAD9 + 0xA8 + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD10 + configure RTC PAD10 + 0xAC + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD11 + configure RTC PAD11 + 0xB0 + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD12 + configure RTC PAD12 + 0xB4 + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD13 + configure RTC PAD13 + 0xB8 + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + TOUCH_PAD14 + configure RTC PAD14 + 0xBC + 0x20 + 0x40000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + XPD + TOUCH_XPD + 20 + 1 + read-write + + + TIE_OPT + TOUCH_TIE_OPT + 21 + 1 + read-write + + + START + TOUCH_START + 22 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + XTAL_32P_PAD + configure RTC PAD15 + 0xC0 + 0x20 + 0x40000000 + + + X32P_FUN_IE + input enable in work mode + 13 + 1 + read-write + + + X32P_SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + X32P_SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + X32P_SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + X32P_FUN_SEL + function sel + 17 + 2 + read-write + + + X32P_MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + X32P_RUE + RUE + 27 + 1 + read-write + + + X32P_RDE + RDE + 28 + 1 + read-write + + + X32P_DRV + DRV + 29 + 2 + read-write + + + + + XTAL_32N_PAD + configure RTC PAD16 + 0xC4 + 0x20 + 0x40000000 + + + X32N_FUN_IE + input enable in work mode + 13 + 1 + read-write + + + X32N_SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + X32N_SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + X32N_SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + X32N_FUN_SEL + function sel + 17 + 2 + read-write + + + X32N_MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + X32N_RUE + RUE + 27 + 1 + read-write + + + X32N_RDE + RDE + 28 + 1 + read-write + + + X32N_DRV + DRV + 29 + 2 + read-write + + + + + PAD_DAC1 + configure RTC PAD17 + 0xC8 + 0x20 + 0x40000000 + + + PDAC1_DAC + PDAC1_DAC + 3 + 8 + read-write + + + PDAC1_XPD_DAC + PDAC1_XPD_DAC + 11 + 1 + read-write + + + PDAC1_DAC_XPD_FORCE + 1: use reg_pdac1_xpd_dac to control PDAC1_XPD_DAC,0: use SAR ADC FSM to control PDAC1_XPD_DAC + 12 + 1 + read-write + + + PDAC1_FUN_IE + input enable in work mode + 13 + 1 + read-write + + + PDAC1_SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + PDAC1_SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + PDAC1_SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + PDAC1_FUN_SEL + PDAC1 function sel + 17 + 2 + read-write + + + PDAC1_MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + PDAC1_RUE + PDAC1_RUE + 27 + 1 + read-write + + + PDAC1_RDE + PDAC1_RDE + 28 + 1 + read-write + + + PDAC1_DRV + PDAC1_DRV + 29 + 2 + read-write + + + + + PAD_DAC2 + configure RTC PAD18 + 0xCC + 0x20 + 0x40000000 + + + PDAC2_DAC + PDAC2_DAC + 3 + 8 + read-write + + + PDAC2_XPD_DAC + PDAC2_XPD_DAC + 11 + 1 + read-write + + + PDAC2_DAC_XPD_FORCE + 1: use reg_pdac2_xpd_dac to control PDAC2_XPD_DAC,0: use SAR ADC FSM to control PDAC2_XPD_DAC + 12 + 1 + read-write + + + PDAC2_FUN_IE + input enable in work mode + 13 + 1 + read-write + + + PDAC2_SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + PDAC2_SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + PDAC2_SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + PDAC2_FUN_SEL + PDAC1 function sel + 17 + 2 + read-write + + + PDAC2_MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + PDAC2_RUE + PDAC2_RUE + 27 + 1 + read-write + + + PDAC2_RDE + PDAC2_RDE + 28 + 1 + read-write + + + PDAC2_DRV + PDAC2_DRV + 29 + 2 + read-write + + + + + RTC_PAD19 + configure RTC PAD19 + 0xD0 + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + RTC_PAD20 + configure RTC PAD20 + 0xD4 + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + RTC_PAD21 + configure RTC PAD21 + 0xD8 + 0x20 + 0x50000000 + + + FUN_IE + input enable in work mode + 13 + 1 + read-write + + + SLP_OE + output enable in sleep mode + 14 + 1 + read-write + + + SLP_IE + input enable in sleep mode + 15 + 1 + read-write + + + SLP_SEL + 1: enable sleep mode during sleep,0: no sleep mode + 16 + 1 + read-write + + + FUN_SEL + function sel + 17 + 2 + read-write + + + MUX_SEL + 1: use RTC GPIO,0: use digital GPIO + 19 + 1 + read-write + + + RUE + RUE + 27 + 1 + read-write + + + RDE + RDE + 28 + 1 + read-write + + + DRV + DRV + 29 + 2 + read-write + + + + + EXT_WAKEUP0 + configure EXT0 wakeup + 0xDC + 0x20 + + + SEL + ******* Description configure*** + 27 + 5 + read-write + + + + + XTL_EXT_CTR + configure gpio pd XTAL + 0xE0 + 0x20 + + + SEL + select RTC GPIO 0 ~ 17 to control XTAL + 27 + 5 + read-write + + + + + SAR_I2C_IO + configure rtc i2c mux + 0xE4 + 0x20 + + + SAR_DEBUG_BIT_SEL + ******* Description configure*** + 23 + 5 + read-write + + + SAR_I2C_SCL_SEL + ******* Description configure*** + 28 + 2 + read-write + + + SAR_I2C_SDA_SEL + ******* Description configure*** + 30 + 2 + read-write + + + + + TOUCH_CTRL + configure touch pad bufmode + 0xE8 + 0x20 + + + IO_TOUCH_BUFSEL + BUF_SEL when touch work without fsm + 0 + 4 + read-write + + + IO_TOUCH_BUFMODE + BUF_MODE when touch work without fsm + 4 + 1 + read-write + + + + + DATE + version + 0x1FC + 0x20 + 0x02101180 + + + DATE + version + 0 + 28 + read-write + + + + + + + SENS + Peripheral SENS + SENS + 0x60008800 + + 0x0 + 0x11C + registers + + + + SAR_READER1_CTRL + configure saradc1 reader + 0x0 + 0x20 + 0x20040002 + + + SAR_SAR1_CLK_DIV + clock divider + 0 + 8 + read-write + + + SAR_SAR1_CLK_GATED + no public + 18 + 1 + read-write + + + SAR_SAR1_SAMPLE_NUM + no public + 19 + 8 + read-write + + + SAR_SAR1_DATA_INV + Invert SAR ADC1 data + 28 + 1 + read-write + + + SAR_SAR1_INT_EN + enable saradc1 to send out interrupt + 29 + 1 + read-write + + + + + SAR_READER1_STATUS + get saradc1 reader controller status + 0x4 + 0x20 + + + SAR_SAR1_READER_STATUS + get saradc1 reader controller status + 0 + 32 + read-only + + + + + SAR_MEAS1_CTRL1 + no public + 0x8 + 0x20 + + + SAR_FORCE_XPD_AMP + no public + 24 + 2 + read-write + + + SAR_AMP_RST_FB_FORCE + no public + 26 + 2 + read-write + + + SAR_AMP_SHORT_REF_FORCE + no public + 28 + 2 + read-write + + + SAR_AMP_SHORT_REF_GND_FORCE + no public + 30 + 2 + read-write + + + + + SAR_MEAS1_CTRL2 + configure saradc1 controller + 0xC + 0x20 + + + SAR_MEAS1_DATA_SAR + SAR ADC1 data + 0 + 16 + read-only + + + SAR_MEAS1_DONE_SAR + SAR ADC1 conversion done indication + 16 + 1 + read-only + + + SAR_MEAS1_START_SAR + SAR ADC1 controller (in RTC) starts conversion + 17 + 1 + read-write + + + SAR_MEAS1_START_FORCE + 1: SAR ADC1 controller (in RTC) is started by SW + 18 + 1 + read-write + + + SAR_SAR1_EN_PAD + SAR ADC1 pad enable bitmap + 19 + 12 + read-write + + + SAR_SAR1_EN_PAD_FORCE + 1: SAR ADC1 pad enable bitmap is controlled by SW + 31 + 1 + read-write + + + + + SAR_MEAS1_MUX + configure saradc1 controller + 0x10 + 0x20 + + + SAR_SAR1_DIG_FORCE + 1: SAR ADC1 controlled by DIG ADC1 CTRL + 31 + 1 + read-write + + + + + SAR_ATTEN1 + configure saradc1 controller + 0x14 + 0x20 + 0xFFFFFFFF + + + SAR_SAR1_ATTEN + 2-bit attenuation for each pad + 0 + 32 + read-write + + + + + SAR_AMP_CTRL1 + no public + 0x18 + 0x20 + 0x000A000A + + + SAR_AMP_WAIT1 + no public + 0 + 16 + read-write + + + SAR_AMP_WAIT2 + no public + 16 + 16 + read-write + + + + + SAR_AMP_CTRL2 + no public + 0x1C + 0x20 + 0x000A0000 + + + SAR_SAR1_DAC_XPD_FSM_IDLE + no public + 0 + 1 + read-write + + + SAR_XPD_SAR_AMP_FSM_IDLE + no public + 1 + 1 + read-write + + + SAR_AMP_RST_FB_FSM_IDLE + no public + 2 + 1 + read-write + + + SAR_AMP_SHORT_REF_FSM_IDLE + no public + 3 + 1 + read-write + + + SAR_AMP_SHORT_REF_GND_FSM_IDLE + no public + 4 + 1 + read-write + + + SAR_XPD_SAR_FSM_IDLE + no public + 5 + 1 + read-write + + + SAR_RSTB_FSM_IDLE + no public + 6 + 1 + read-write + + + SAR_AMP_WAIT3 + no public + 16 + 16 + read-write + + + + + SAR_AMP_CTRL3 + no public + 0x20 + 0x20 + 0x007338F3 + + + SAR_SAR1_DAC_XPD_FSM + no public + 0 + 4 + read-write + + + SAR_XPD_SAR_AMP_FSM + no public + 4 + 4 + read-write + + + SAR_AMP_RST_FB_FSM + no public + 8 + 4 + read-write + + + SAR_AMP_SHORT_REF_FSM + no public + 12 + 4 + read-write + + + SAR_AMP_SHORT_REF_GND_FSM + no public + 16 + 4 + read-write + + + SAR_XPD_SAR_FSM + no public + 20 + 4 + read-write + + + SAR_RSTB_FSM + no public + 24 + 4 + read-write + + + + + SAR_READER2_CTRL + configure saradc2 reader + 0x24 + 0x20 + 0x40050002 + + + SAR_SAR2_CLK_DIV + clock divider + 0 + 8 + read-write + + + SAR_SAR2_WAIT_ARB_CYCLE + wait arbit stable after sar_done + 16 + 2 + read-write + + + SAR_SAR2_CLK_GATED + ******* Description *********** + 18 + 1 + read-write + + + SAR_SAR2_SAMPLE_NUM + ******* Description *********** + 19 + 8 + read-write + + + SAR_SAR2_DATA_INV + Invert SAR ADC2 data + 29 + 1 + read-write + + + SAR_SAR2_INT_EN + enable saradc2 to send out interrupt + 30 + 1 + read-write + + + + + SAR_READER2_STATUS + get saradc1 reader controller status + 0x28 + 0x20 + + + SAR_SAR2_READER_STATUS + get saradc1 reader controller status + 0 + 32 + read-only + + + + + SAR_MEAS2_CTRL1 + configure saradc2 controller + 0x2C + 0x20 + 0x07020200 + + + SAR_SAR2_CNTL_STATE + saradc2_cntl_fsm + 0 + 3 + read-only + + + SAR_SAR2_PWDET_CAL_EN + rtc control pwdet enable + 3 + 1 + read-write + + + SAR_SAR2_PKDET_CAL_EN + rtc control pkdet enable + 4 + 1 + read-write + + + SAR_SAR2_EN_TEST + SAR2_EN_TEST + 5 + 1 + read-write + + + SAR_SAR2_RSTB_FORCE + no public + 6 + 2 + read-write + + + SAR_SAR2_STANDBY_WAIT + no public + 8 + 8 + read-write + + + SAR_SAR2_RSTB_WAIT + no public + 16 + 8 + read-write + + + SAR_SAR2_XPD_WAIT + no public + 24 + 8 + read-write + + + + + SAR_MEAS2_CTRL2 + configure saradc2 controller + 0x30 + 0x20 + + + SAR_MEAS2_DATA_SAR + SAR ADC2 data + 0 + 16 + read-only + + + SAR_MEAS2_DONE_SAR + SAR ADC2 conversion done indication + 16 + 1 + read-only + + + SAR_MEAS2_START_SAR + SAR ADC2 controller (in RTC) starts conversion + 17 + 1 + read-write + + + SAR_MEAS2_START_FORCE + 1: SAR ADC2 controller (in RTC) is started by SW + 18 + 1 + read-write + + + SAR_SAR2_EN_PAD + SAR ADC2 pad enable bitmap + 19 + 12 + read-write + + + SAR_SAR2_EN_PAD_FORCE + 1: SAR ADC2 pad enable bitmap is controlled by SW + 31 + 1 + read-write + + + + + SAR_MEAS2_MUX + configure saradc2 controller + 0x34 + 0x20 + + + SAR_SAR2_PWDET_CCT + SAR2_PWDET_CCT + 28 + 3 + read-write + + + SAR_SAR2_RTC_FORCE + in sleep, force to use rtc to control ADC + 31 + 1 + read-write + + + + + SAR_ATTEN2 + configure saradc2 controller + 0x38 + 0x20 + 0xFFFFFFFF + + + SAR_SAR2_ATTEN + 2-bit attenuation for each pad + 0 + 32 + read-write + + + + + SAR_POWER_XPD_SAR + configure power of saradc + 0x3C + 0x20 + + + SAR_FORCE_XPD_SAR + force power on/off saradc + 29 + 2 + read-write + + + SAR_SARCLK_EN + no public + 31 + 1 + read-write + + + + + SAR_SLAVE_ADDR1 + configure i2c slave address + 0x40 + 0x20 + + + SAR_I2C_SLAVE_ADDR1 + configure i2c slave address1 + 0 + 11 + read-write + + + SAR_I2C_SLAVE_ADDR0 + configure i2c slave address0 + 11 + 11 + read-write + + + SAR_SARADC_MEAS_STATUS + no public + 22 + 8 + read-only + + + + + SAR_SLAVE_ADDR2 + configure i2c slave address + 0x44 + 0x20 + + + SAR_I2C_SLAVE_ADDR3 + configure i2c slave address3 + 0 + 11 + read-write + + + SAR_I2C_SLAVE_ADDR2 + configure i2c slave address2 + 11 + 11 + read-write + + + + + SAR_SLAVE_ADDR3 + configure i2c slave address + 0x48 + 0x20 + + + SAR_I2C_SLAVE_ADDR5 + configure i2c slave address5 + 0 + 11 + read-write + + + SAR_I2C_SLAVE_ADDR4 + configure i2c slave address4 + 11 + 11 + read-write + + + + + SAR_SLAVE_ADDR4 + configure i2c slave address + 0x4C + 0x20 + + + SAR_I2C_SLAVE_ADDR7 + configure i2c slave address7 + 0 + 11 + read-write + + + SAR_I2C_SLAVE_ADDR6 + configure i2c slave address6 + 11 + 11 + read-write + + + + + SAR_TSENS_CTRL + configure tsens controller + 0x50 + 0x20 + 0x00019000 + + + SAR_TSENS_OUT + temperature sensor data out + 0 + 8 + read-only + + + SAR_TSENS_READY + indicate temperature sensor out ready + 8 + 1 + read-only + + + SAR_TSENS_INT_EN + enable temperature sensor to send out interrupt + 12 + 1 + read-write + + + SAR_TSENS_IN_INV + invert temperature sensor data + 13 + 1 + read-write + + + SAR_TSENS_CLK_DIV + temperature sensor clock divider + 14 + 8 + read-write + + + SAR_TSENS_POWER_UP + temperature sensor power up + 22 + 1 + read-write + + + SAR_TSENS_POWER_UP_FORCE + 1: dump out & power up controlled by SW 0: by FSM + 23 + 1 + read-write + + + SAR_TSENS_DUMP_OUT + temperature sensor dump out only active when reg_tsens_power_up_force = 1 + 24 + 1 + read-write + + + + + SAR_TSENS_CTRL2 + configure tsens controller + 0x54 + 0x20 + 0x00004002 + + + SAR_TSENS_XPD_WAIT + no public + 0 + 12 + read-write + + + SAR_TSENS_XPD_FORCE + no public + 12 + 2 + read-write + + + SAR_TSENS_CLK_INV + no public + 14 + 1 + read-write + + + + + SAR_I2C_CTRL + configure rtc i2c controller by sw + 0x58 + 0x20 + + + SAR_I2C_CTRL + I2C control data only active when reg_sar_i2c_start_force = 1 + 0 + 28 + read-write + + + SAR_I2C_START + start I2C only active when reg_sar_i2c_start_force = 1 + 28 + 1 + read-write + + + SAR_I2C_START_FORCE + 1: I2C started by SW 0: I2C started by FSM + 29 + 1 + read-write + + + + + SAR_TOUCH_CONF + configure touch controller + 0x5C + 0x20 + 0xFFF07FFF + + + SAR_TOUCH_OUTEN + touch controller output enable + 0 + 15 + read-write + + + SAR_TOUCH_STATUS_CLR + clear all touch active status + 15 + 1 + write-only + + + SAR_TOUCH_DATA_SEL + 3: smooth data 2: baseline 1,0: raw_data + 16 + 2 + read-write + + + SAR_TOUCH_DENOISE_END + touch_denoise_done + 18 + 1 + read-only + + + SAR_TOUCH_UNIT_END + touch_unit_done + 19 + 1 + read-only + + + SAR_TOUCH_APPROACH_PAD2 + indicate which pad is approach pad2 + 20 + 4 + read-write + + + SAR_TOUCH_APPROACH_PAD1 + indicate which pad is approach pad1 + 24 + 4 + read-write + + + SAR_TOUCH_APPROACH_PAD0 + indicate which pad is approach pad0 + 28 + 4 + read-write + + + + + SAR_TOUCH_DENOISE + configure touch controller + 0x60 + 0x20 + + + DATA + configure touch controller + 0 + 22 + read-only + + + + + SAR_TOUCH_THRES1 + configure touch thres of touch pad + 0x64 + 0x20 + + + SAR_TOUCH_OUT_TH1 + Finger threshold for touch pad 1 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES2 + configure touch thres of touch pad + 0x68 + 0x20 + + + SAR_TOUCH_OUT_TH2 + Finger threshold for touch pad 2 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES3 + configure touch thres of touch pad + 0x6C + 0x20 + + + SAR_TOUCH_OUT_TH3 + Finger threshold for touch pad 3 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES4 + configure touch thres of touch pad + 0x70 + 0x20 + + + SAR_TOUCH_OUT_TH4 + Finger threshold for touch pad 4 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES5 + configure touch thres of touch pad + 0x74 + 0x20 + + + SAR_TOUCH_OUT_TH5 + Finger threshold for touch pad 5 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES6 + configure touch thres of touch pad + 0x78 + 0x20 + + + SAR_TOUCH_OUT_TH6 + Finger threshold for touch pad 6 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES7 + configure touch thres of touch pad + 0x7C + 0x20 + + + SAR_TOUCH_OUT_TH7 + Finger threshold for touch pad 7 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES8 + configure touch thres of touch pad + 0x80 + 0x20 + + + SAR_TOUCH_OUT_TH8 + Finger threshold for touch pad 8 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES9 + configure touch thres of touch pad + 0x84 + 0x20 + + + SAR_TOUCH_OUT_TH9 + Finger threshold for touch pad 9 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES10 + configure touch thres of touch pad + 0x88 + 0x20 + + + SAR_TOUCH_OUT_TH10 + Finger threshold for touch pad 10 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES11 + configure touch thres of touch pad + 0x8C + 0x20 + + + SAR_TOUCH_OUT_TH11 + Finger threshold for touch pad 11 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES12 + configure touch thres of touch pad + 0x90 + 0x20 + + + SAR_TOUCH_OUT_TH12 + Finger threshold for touch pad 12 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES13 + configure touch thres of touch pad + 0x94 + 0x20 + + + SAR_TOUCH_OUT_TH13 + Finger threshold for touch pad 13 + 0 + 22 + read-write + + + + + SAR_TOUCH_THRES14 + configure touch thres of touch pad + 0x98 + 0x20 + + + SAR_TOUCH_OUT_TH14 + Finger threshold for touch pad 14 + 0 + 22 + read-write + + + + + SAR_TOUCH_CHN_ST + Get touch channel status + 0x9C + 0x20 + + + SAR_TOUCH_PAD_ACTIVE + touch active status + 0 + 15 + read-only + + + SAR_TOUCH_CHANNEL_CLR + Clear touch channel + 15 + 15 + write-only + + + SAR_TOUCH_MEAS_DONE + get touch meas done + 31 + 1 + read-only + + + + + SAR_TOUCH_STATUS0 + get touch scan status + 0xA0 + 0x20 + + + SAR_TOUCH_SCAN_CURR + current sample channel + 22 + 4 + read-only + + + + + SAR_TOUCH_STATUS1 + touch channel status of touch pad 1 + 0xA4 + 0x20 + + + SAR_TOUCH_PAD1_DATA + touch data debounce of touch pad 1 + 0 + 22 + read-only + + + SAR_TOUCH_PAD1_DEBOUNCE + touch current debounce of touch pad 1 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS2 + touch channel status of touch pad 2 + 0xA8 + 0x20 + + + SAR_TOUCH_PAD2_DATA + touch data debounce of touch pad 2 + 0 + 22 + read-only + + + SAR_TOUCH_PAD2_DEBOUNCE + touch current debounce of touch pad 2 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS3 + touch channel status of touch pad 3 + 0xAC + 0x20 + + + SAR_TOUCH_PAD3_DATA + touch data debounce of touch pad 3 + 0 + 22 + read-only + + + SAR_TOUCH_PAD3_DEBOUNCE + touch current debounce of touch pad 3 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS4 + touch channel status of touch pad 4 + 0xB0 + 0x20 + + + SAR_TOUCH_PAD4_DATA + touch data debounce of touch pad 4 + 0 + 22 + read-only + + + SAR_TOUCH_PAD4_DEBOUNCE + touch current debounce of touch pad 4 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS5 + touch channel status of touch pad 5 + 0xB4 + 0x20 + + + SAR_TOUCH_PAD5_DATA + touch data debounce of touch pad 5 + 0 + 22 + read-only + + + SAR_TOUCH_PAD5_DEBOUNCE + touch current debounce of touch pad 5 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS6 + touch channel status of touch pad 6 + 0xB8 + 0x20 + + + SAR_TOUCH_PAD6_DATA + touch data debounce of touch pad 6 + 0 + 22 + read-only + + + SAR_TOUCH_PAD6_DEBOUNCE + touch current debounce of touch pad 6 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS7 + touch channel status of touch pad 7 + 0xBC + 0x20 + + + SAR_TOUCH_PAD7_DATA + touch data debounce of touch pad 7 + 0 + 22 + read-only + + + SAR_TOUCH_PAD7_DEBOUNCE + touch current debounce of touch pad 7 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS8 + touch channel status of touch pad 8 + 0xC0 + 0x20 + + + SAR_TOUCH_PAD8_DATA + touch data debounce of touch pad 8 + 0 + 22 + read-only + + + SAR_TOUCH_PAD8_DEBOUNCE + touch current debounce of touch pad 8 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS9 + touch channel status of touch pad 9 + 0xC4 + 0x20 + + + SAR_TOUCH_PAD9_DATA + touch data debounce of touch pad 9 + 0 + 22 + read-only + + + SAR_TOUCH_PAD9_DEBOUNCE + touch current debounce of touch pad 9 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS10 + touch channel status of touch pad 10 + 0xC8 + 0x20 + + + SAR_TOUCH_PAD10_DATA + touch data debounce of touch pad 10 + 0 + 22 + read-only + + + SAR_TOUCH_PAD10_DEBOUNCE + touch current debounce of touch pad 10 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS11 + touch channel status of touch pad 11 + 0xCC + 0x20 + + + SAR_TOUCH_PAD11_DATA + touch data debounce of touch pad 11 + 0 + 22 + read-only + + + SAR_TOUCH_PAD11_DEBOUNCE + touch current debounce of touch pad 11 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS12 + touch channel status of touch pad 12 + 0xD0 + 0x20 + + + SAR_TOUCH_PAD12_DATA + touch data debounce of touch pad 12 + 0 + 22 + read-only + + + SAR_TOUCH_PAD12_DEBOUNCE + touch current debounce of touch pad 12 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS13 + touch channel status of touch pad 13 + 0xD4 + 0x20 + + + SAR_TOUCH_PAD13_DATA + touch data debounce of touch pad 13 + 0 + 22 + read-only + + + SAR_TOUCH_PAD13_DEBOUNCE + touch current debounce of touch pad 13 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS14 + touch channel status of touch pad 14 + 0xD8 + 0x20 + + + SAR_TOUCH_PAD14_DATA + touch data debounce of touch pad 14 + 0 + 22 + read-only + + + SAR_TOUCH_PAD14_DEBOUNCE + touch current debounce of touch pad 14 + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS15 + touch channel status of sleep pad + 0xDC + 0x20 + + + SAR_TOUCH_SLP_DATA + touch data debounce of sleep pad + 0 + 22 + read-only + + + SAR_TOUCH_SLP_DEBOUNCE + touch current debounce of sleep pad + 29 + 3 + read-only + + + + + SAR_TOUCH_STATUS16 + touch channel status of approach mode + 0xE0 + 0x20 + + + SAR_TOUCH_APPROACH_PAD2_CNT + touch current approach count of approach pad2 + 0 + 8 + read-only + + + SAR_TOUCH_APPROACH_PAD1_CNT + touch current approach count of approach pad1 + 8 + 8 + read-only + + + SAR_TOUCH_APPROACH_PAD0_CNT + touch current approach count of approach pad0 + 16 + 8 + read-only + + + SAR_TOUCH_SLP_APPROACH_CNT + touch current approach count of slp pad + 24 + 8 + read-only + + + + + SAR_COCPU_STATE + get cocpu status + 0xE4 + 0x20 + + + SAR_COCPU_DBG_TRIGGER + trigger cocpu debug registers + 25 + 1 + write-only + + + SAR_COCPU_CLK_EN_ST + check cocpu whether clk on + 26 + 1 + read-only + + + SAR_COCPU_RESET_N + check cocpu whether in reset state + 27 + 1 + read-only + + + SAR_COCPU_EOI + check cocpu whether in interrupt state + 28 + 1 + read-only + + + SAR_COCPU_TRAP + check cocpu whether in trap state + 29 + 1 + read-only + + + SAR_COCPU_EBREAK + check cocpu whether in ebreak + 30 + 1 + read-only + + + + + SAR_COCPU_INT_RAW + the interrupt raw of ulp + 0xE8 + 0x20 + + + SAR_COCPU_TOUCH_DONE_INT_RAW + int from touch done + 0 + 1 + read-only + + + SAR_COCPU_TOUCH_INACTIVE_INT_RAW + int from touch inactive + 1 + 1 + read-only + + + SAR_COCPU_TOUCH_ACTIVE_INT_RAW + int from touch active + 2 + 1 + read-only + + + SAR_COCPU_SARADC1_INT_RAW + int from saradc1 + 3 + 1 + read-only + + + SAR_COCPU_SARADC2_INT_RAW + int from saradc2 + 4 + 1 + read-only + + + SAR_COCPU_TSENS_INT_RAW + int from tsens + 5 + 1 + read-only + + + SAR_COCPU_START_INT_RAW + int from start + 6 + 1 + read-only + + + SAR_COCPU_SW_INT_RAW + int from software + 7 + 1 + read-only + + + SAR_COCPU_SWD_INT_RAW + int from super watch dog + 8 + 1 + read-only + + + SAR_COCPU_TOUCH_TIMEOUT_INT_RAW + int from timeout done + 9 + 1 + read-only + + + SAR_COCPU_TOUCH_APPROACH_LOOP_DONE_INT_RAW + int from approach loop done + 10 + 1 + read-only + + + SAR_COCPU_TOUCH_SCAN_DONE_INT_RAW + int from touch scan done + 11 + 1 + read-only + + + + + SAR_COCPU_INT_ENA + the interrupt enable of ulp + 0xEC + 0x20 + + + SAR_COCPU_TOUCH_DONE_INT_ENA + int enable of touch done + 0 + 1 + read-write + + + SAR_COCPU_TOUCH_INACTIVE_INT_ENA + int enable of from touch inactive + 1 + 1 + read-write + + + SAR_COCPU_TOUCH_ACTIVE_INT_ENA + int enable of touch active + 2 + 1 + read-write + + + SAR_COCPU_SARADC1_INT_ENA + int enable of from saradc1 + 3 + 1 + read-write + + + SAR_COCPU_SARADC2_INT_ENA + int enable of from saradc2 + 4 + 1 + read-write + + + SAR_COCPU_TSENS_INT_ENA + int enable of tsens + 5 + 1 + read-write + + + SAR_COCPU_START_INT_ENA + int enable of start + 6 + 1 + read-write + + + SAR_COCPU_SW_INT_ENA + int enable of software + 7 + 1 + read-write + + + SAR_COCPU_SWD_INT_ENA + int enable of super watch dog + 8 + 1 + read-write + + + SAR_COCPU_TOUCH_TIMEOUT_INT_ENA + int enable of timeout done + 9 + 1 + read-write + + + SAR_COCPU_TOUCH_APPROACH_LOOP_DONE_INT_ENA + int enable of approach loop done + 10 + 1 + read-write + + + SAR_COCPU_TOUCH_SCAN_DONE_INT_ENA + int enable of touch scan done + 11 + 1 + read-write + + + + + SAR_COCPU_INT_ST + the interrupt state of ulp + 0xF0 + 0x20 + + + SAR_COCPU_TOUCH_DONE_INT_ST + int state of touch done + 0 + 1 + read-only + + + SAR_COCPU_TOUCH_INACTIVE_INT_ST + int state of from touch inactive + 1 + 1 + read-only + + + SAR_COCPU_TOUCH_ACTIVE_INT_ST + int state of touch active + 2 + 1 + read-only + + + SAR_COCPU_SARADC1_INT_ST + int state of from saradc1 + 3 + 1 + read-only + + + SAR_COCPU_SARADC2_INT_ST + int state of from saradc2 + 4 + 1 + read-only + + + SAR_COCPU_TSENS_INT_ST + int state of tsens + 5 + 1 + read-only + + + SAR_COCPU_START_INT_ST + int state of start + 6 + 1 + read-only + + + SAR_COCPU_SW_INT_ST + int state of software + 7 + 1 + read-only + + + SAR_COCPU_SWD_INT_ST + int state of super watch dog + 8 + 1 + read-only + + + SAR_COCPU_TOUCH_TIMEOUT_INT_ST + int state of timeout done + 9 + 1 + read-only + + + SAR_COCPU_TOUCH_APPROACH_LOOP_DONE_INT_ST + int state of approach loop done + 10 + 1 + read-only + + + SAR_COCPU_TOUCH_SCAN_DONE_INT_ST + int state of touch scan done + 11 + 1 + read-only + + + + + SAR_COCPU_INT_CLR + the interrupt clear of ulp + 0xF4 + 0x20 + + + SAR_COCPU_TOUCH_DONE_INT_CLR + int clear of touch done + 0 + 1 + write-only + + + SAR_COCPU_TOUCH_INACTIVE_INT_CLR + int clear of from touch inactive + 1 + 1 + write-only + + + SAR_COCPU_TOUCH_ACTIVE_INT_CLR + int clear of touch active + 2 + 1 + write-only + + + SAR_COCPU_SARADC1_INT_CLR + int clear of from saradc1 + 3 + 1 + write-only + + + SAR_COCPU_SARADC2_INT_CLR + int clear of from saradc2 + 4 + 1 + write-only + + + SAR_COCPU_TSENS_INT_CLR + int clear of tsens + 5 + 1 + write-only + + + SAR_COCPU_START_INT_CLR + int clear of start + 6 + 1 + write-only + + + SAR_COCPU_SW_INT_CLR + int clear of software + 7 + 1 + write-only + + + SAR_COCPU_SWD_INT_CLR + int clear of super watch dog + 8 + 1 + write-only + + + SAR_COCPU_TOUCH_TIMEOUT_INT_CLR + int clear of timeout done + 9 + 1 + write-only + + + SAR_COCPU_TOUCH_APPROACH_LOOP_DONE_INT_CLR + int clear of approach loop done + 10 + 1 + write-only + + + SAR_COCPU_TOUCH_SCAN_DONE_INT_CLR + int clear of touch scan done + 11 + 1 + write-only + + + + + SAR_COCPU_DEBUG + Ulp-riscv debug signal + 0xF8 + 0x20 + + + SAR_COCPU_PC + cocpu Program counter + 0 + 13 + read-only + + + SAR_COCPU_MEM_VLD + cocpu mem valid output + 13 + 1 + read-only + + + SAR_COCPU_MEM_RDY + cocpu mem ready input + 14 + 1 + read-only + + + SAR_COCPU_MEM_WEN + cocpu mem write enable output + 15 + 4 + read-only + + + SAR_COCPU_MEM_ADDR + cocpu mem address output + 19 + 13 + read-only + + + + + SAR_HALL_CTRL + no public + 0xFC + 0x20 + 0xA0000000 + + + SAR_XPD_HALL + Power on hall sensor and connect to VP and VN + 28 + 1 + read-write + + + SAR_XPD_HALL_FORCE + 1: XPD HALL is controlled by SW. 0: XPD HALL is controlled by FSM in ULP-coprocessor + 29 + 1 + read-write + + + SAR_HALL_PHASE + Reverse phase of hall sensor + 30 + 1 + read-write + + + SAR_HALL_PHASE_FORCE + 1: HALL PHASE is controlled by SW 0: HALL PHASE is controlled by FSM in ULP-coprocessor + 31 + 1 + read-write + + + + + SAR_NOUSE + no public + 0x100 + 0x20 + + + SAR_NOUSE + no public + 0 + 32 + read-write + + + + + SAR_PERI_CLK_GATE_CONF + the peri clock gate of rtc peri + 0x104 + 0x20 + + + SAR_RTC_I2C_CLK_EN + enable rtc i2c clock + 27 + 1 + read-write + + + SAR_TSENS_CLK_EN + enable tsens clock + 29 + 1 + read-write + + + SAR_SARADC_CLK_EN + enbale saradc clock + 30 + 1 + read-write + + + SAR_IOMUX_CLK_EN + enable io_mux clock + 31 + 1 + read-write + + + + + SAR_PERI_RESET_CONF + the peri reset of rtc peri + 0x108 + 0x20 + + + SAR_COCPU_RESET + enable ulp-riscv reset + 25 + 1 + read-write + + + SAR_RTC_I2C_RESET + Reserved. + 27 + 1 + read-write + + + SAR_TSENS_RESET + enbale saradc reset + 29 + 1 + read-write + + + SAR_SARADC_RESET + enable io_mux reset + 30 + 1 + read-write + + + + + SAR_COCPU_INT_ENA_W1TS + the interrupt enable of ulp + 0x10C + 0x20 + + + SAR_COCPU_TOUCH_DONE_INT_ENA_W1TS + int enable of touch done + 0 + 1 + write-only + + + SAR_COCPU_TOUCH_INACTIVE_INT_ENA_W1TS + int enable of from touch inactive + 1 + 1 + write-only + + + SAR_COCPU_TOUCH_ACTIVE_INT_ENA_W1TS + int enable of touch active + 2 + 1 + write-only + + + SAR_COCPU_SARADC1_INT_ENA_W1TS + int enable of from saradc1 + 3 + 1 + write-only + + + SAR_COCPU_SARADC2_INT_ENA_W1TS + int enable of from saradc2 + 4 + 1 + write-only + + + SAR_COCPU_TSENS_INT_ENA_W1TS + int enable of tsens + 5 + 1 + write-only + + + SAR_COCPU_START_INT_ENA_W1TS + int enable of start + 6 + 1 + write-only + + + SAR_COCPU_SW_INT_ENA_W1TS + int enable of software + 7 + 1 + write-only + + + SAR_COCPU_SWD_INT_ENA_W1TS + int enable of super watch dog + 8 + 1 + write-only + + + SAR_COCPU_TOUCH_TIMEOUT_INT_ENA_W1TS + int enable of timeout done + 9 + 1 + write-only + + + SAR_COCPU_TOUCH_APPROACH_LOOP_DONE_INT_ENA_W1TS + int enable of approach loop done + 10 + 1 + write-only + + + SAR_COCPU_TOUCH_SCAN_DONE_INT_ENA_W1TS + int enable of touch scan done + 11 + 1 + write-only + + + + + SAR_COCPU_INT_ENA_W1TC + the interrupt enable clear of ulp + 0x110 + 0x20 + + + SAR_COCPU_TOUCH_DONE_INT_ENA_W1TC + Clear int enable of touch done + 0 + 1 + write-only + + + SAR_COCPU_TOUCH_INACTIVE_INT_ENA_W1TC + Clear int enable of from touch inactive + 1 + 1 + write-only + + + SAR_COCPU_TOUCH_ACTIVE_INT_ENA_W1TC + Clear int enable of touch active + 2 + 1 + write-only + + + SAR_COCPU_SARADC1_INT_ENA_W1TC + Clear int enable of from saradc1 + 3 + 1 + write-only + + + SAR_COCPU_SARADC2_INT_ENA_W1TC + Clear int enable of from saradc2 + 4 + 1 + write-only + + + SAR_COCPU_TSENS_INT_ENA_W1TC + Clear int enable of tsens + 5 + 1 + write-only + + + SAR_COCPU_START_INT_ENA_W1TC + Clear int enable of start + 6 + 1 + write-only + + + SAR_COCPU_SW_INT_ENA_W1TC + Clear int enable of software + 7 + 1 + write-only + + + SAR_COCPU_SWD_INT_ENA_W1TC + Clear int enable of super watch dog + 8 + 1 + write-only + + + SAR_COCPU_TOUCH_TIMEOUT_INT_ENA_W1TC + Clear int enable of timeout done + 9 + 1 + write-only + + + SAR_COCPU_TOUCH_APPROACH_LOOP_DONE_INT_ENA_W1TC + Clear int enable of approach loop done + 10 + 1 + write-only + + + SAR_COCPU_TOUCH_SCAN_DONE_INT_ENA_W1TC + Clear int enable of touch scan done + 11 + 1 + write-only + + + + + SAR_DEBUG_CONF + rtc peri debug configure + 0x114 + 0x20 + + + SAR_DEBUG_BIT_SEL + no public + 0 + 5 + read-write + + + + + SAR_SARDATE + version + 0x1FC + 0x20 + 0x02101180 + + + SAR_DATE + version + 0 + 28 + read-write + + + + + + + SENSITIVE + Peripheral SENSITIVE + SENSITIVE + 0x600C1000 + + 0x0 + 0x314 + registers + + + + CACHE_DATAARRAY_CONNECT_0 + Cache data array configuration register 0. + 0x0 + 0x20 + + + CACHE_DATAARRAY_CONNECT_LOCK + Set 1 to lock cache data array registers. + 0 + 1 + read-write + + + + + CACHE_DATAARRAY_CONNECT_1 + Cache data array configuration register 1. + 0x4 + 0x20 + 0x000000FF + + + CACHE_DATAARRAY_CONNECT_FLATTEN + Cache data array connection configuration. + 0 + 8 + read-write + + + + + APB_PERIPHERAL_ACCESS_0 + APB peripheral configuration register 0. + 0x8 + 0x20 + + + APB_PERIPHERAL_ACCESS_LOCK + Set 1 to lock APB peripheral Configuration Register. + 0 + 1 + read-write + + + + + APB_PERIPHERAL_ACCESS_1 + APB peripheral configuration register 1. + 0xC + 0x20 + 0x00000001 + + + APB_PERIPHERAL_ACCESS_SPLIT_BURST + Set 1 to support split function for AHB access to APB peripherals. + 0 + 1 + read-write + + + + + INTERNAL_SRAM_USAGE_0 + Internal SRAM configuration register 0. + 0x10 + 0x20 + + + INTERNAL_SRAM_USAGE_LOCK + Set 1 to lock internal SRAM Configuration Register. + 0 + 1 + read-write + + + + + INTERNAL_SRAM_USAGE_1 + Internal SRAM configuration register 1. + 0x14 + 0x20 + 0x000007FF + + + INTERNAL_SRAM_ICACHE_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by icache. + 0 + 2 + read-write + + + INTERNAL_SRAM_DCACHE_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by dcache. + 2 + 2 + read-write + + + INTERNAL_SRAM_CPU_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by cpu. + 4 + 7 + read-write + + + + + INTERNAL_SRAM_USAGE_2 + Internal SRAM configuration register 2. + 0x18 + 0x20 + + + INTERNAL_SRAM_CORE0_TRACE_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by core0 trace bus. + 0 + 7 + read-write + + + INTERNAL_SRAM_CORE1_TRACE_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by core1 trace bus. + 7 + 7 + read-write + + + INTERNAL_SRAM_CORE0_TRACE_ALLOC + Which internal SRAM bank (16KB) of 64KB can be accessed by core0 trace bus. + 14 + 2 + read-write + + + INTERNAL_SRAM_CORE1_TRACE_ALLOC + Which internal SRAM bank (16KB) of 64KB can be accessed by core1 trace bus. + 16 + 2 + read-write + + + + + INTERNAL_SRAM_USAGE_3 + Internal SRAM configuration register 3. + 0x1C + 0x20 + + + INTERNAL_SRAM_MAC_DUMP_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by mac dump. + 0 + 4 + read-write + + + + + INTERNAL_SRAM_USAGE_4 + Internal SRAM configuration register 4. + 0x20 + 0x20 + + + INTERNAL_SRAM_LOG_USAGE + Set 1 to someone bit means corresponding internal SRAM level can be accessed by log bus. + 0 + 7 + read-write + + + + + RETENTION_DISABLE + Retention configuration register. + 0x24 + 0x20 + + + RETENTION_DISABLE + Set 1 to disable retention function and lock disable state. + 0 + 1 + read-write + + + + + CACHE_TAG_ACCESS_0 + Cache tag configuration register 0. + 0x28 + 0x20 + + + CACHE_TAG_ACCESS_LOCK + Set 1 to lock cache tag Configuration Register. + 0 + 1 + read-write + + + + + CACHE_TAG_ACCESS_1 + Cache tag configuration register 1. + 0x2C + 0x20 + 0x0000000F + + + PRO_I_TAG_RD_ACS + Set 1 to enable Icache read access tag memory. + 0 + 1 + read-write + + + PRO_I_TAG_WR_ACS + Set 1 to enable Icache wrtie access tag memory. + 1 + 1 + read-write + + + PRO_D_TAG_RD_ACS + Set 1 to enable Dcache read access tag memory. + 2 + 1 + read-write + + + PRO_D_TAG_WR_ACS + Set 1 to enable Dcache wrtie access tag memory. + 3 + 1 + read-write + + + + + CACHE_MMU_ACCESS_0 + Cache MMU configuration register 0. + 0x30 + 0x20 + + + CACHE_MMU_ACCESS_LOCK + Set 1 to lock cache MMU registers. + 0 + 1 + read-write + + + + + CACHE_MMU_ACCESS_1 + Cache MMU configuration register 1. + 0x34 + 0x20 + 0x00000003 + + + PRO_MMU_RD_ACS + Set 1 to enable read access MMU memory. + 0 + 1 + read-write + + + PRO_MMU_WR_ACS + Set 1 to enable write access MMU memory. + 1 + 1 + read-write + + + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_0 + spi2 dma permission configuration register 0. + 0x38 + 0x20 + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_LOCK + Set 1 to lock spi2 dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_1 + spi2 dma permission configuration register 1. + 0x3C + 0x20 + 0x00000FFF + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_SRAM_PMS_0 + spi2's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_SRAM_PMS_1 + spi2's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_SRAM_PMS_2 + spi2's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_SRAM_PMS_3 + spi2's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + spi2's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_SPI2_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + spi2's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_0 + spi3 dma permission configuration register 0. + 0x40 + 0x20 + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_LOCK + Set 1 to lock spi3 dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_1 + spi3 dma permission configuration register 1. + 0x44 + 0x20 + 0x00000FFF + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_SRAM_PMS_0 + spi3's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_SRAM_PMS_1 + spi3's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_SRAM_PMS_2 + spi3's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_SRAM_PMS_3 + spi3's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + spi3's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_SPI3_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + spi3's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_0 + uhci0 dma permission configuration register 0. + 0x48 + 0x20 + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_LOCK + Set 1 to lock uhci0 dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_1 + uhci0 dma permission configuration register 1. + 0x4C + 0x20 + 0x00000FFF + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_SRAM_PMS_0 + uhci0's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_SRAM_PMS_1 + uhci0's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_SRAM_PMS_2 + uhci0's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_SRAM_PMS_3 + uhci0's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + uhci0's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_UHCI0_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + uhci0's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_0 + i2s0 dma permission configuration register 0. + 0x50 + 0x20 + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_LOCK + Set 1 to lock i2s0 dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_1 + i2s0 dma permission configuration register 1. + 0x54 + 0x20 + 0x00000FFF + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_SRAM_PMS_0 + i2s0's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_SRAM_PMS_1 + i2s0's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_SRAM_PMS_2 + i2s0's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_SRAM_PMS_3 + i2s0's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + i2s0's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_I2S0_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + i2s0's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_0 + i2s1 dma permission configuration register 0. + 0x58 + 0x20 + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_LOCK + Set 1 to lock i2s1 dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_1 + i2s1 dma permission configuration register 1. + 0x5C + 0x20 + 0x00000FFF + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_SRAM_PMS_0 + i2s1's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_SRAM_PMS_1 + i2s1's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_SRAM_PMS_2 + i2s1's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_SRAM_PMS_3 + i2s1's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + i2s1's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_I2S1_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + i2s1's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_0 + mac dma permission configuration register 0. + 0x60 + 0x20 + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_LOCK + Set 1 to lock mac dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_1 + mac dma permission configuration register 1. + 0x64 + 0x20 + 0x00000FFF + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_SRAM_PMS_0 + mac's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_SRAM_PMS_1 + mac's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_SRAM_PMS_2 + mac's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_SRAM_PMS_3 + mac's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + mac's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_MAC_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + mac's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_0 + backup dma permission configuration register 0. + 0x68 + 0x20 + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_LOCK + Set 1 to lock backup dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_1 + backup dma permission configuration register 1. + 0x6C + 0x20 + 0x00000FFF + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_SRAM_PMS_0 + backup's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_SRAM_PMS_1 + backup's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_SRAM_PMS_2 + backup's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_SRAM_PMS_3 + backup's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + backup's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_BACKUP_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + backup's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_AES_PMS_CONSTRAIN_0 + aes dma permission configuration register 0. + 0x70 + 0x20 + + + DMA_APBPERI_AES_PMS_CONSTRAIN_LOCK + Set 1 to lock aes dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_AES_PMS_CONSTRAIN_1 + aes dma permission configuration register 1. + 0x74 + 0x20 + 0x00000FFF + + + DMA_APBPERI_AES_PMS_CONSTRAIN_SRAM_PMS_0 + aes's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_AES_PMS_CONSTRAIN_SRAM_PMS_1 + aes's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_AES_PMS_CONSTRAIN_SRAM_PMS_2 + aes's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_AES_PMS_CONSTRAIN_SRAM_PMS_3 + aes's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_AES_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + aes's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_AES_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + aes's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_0 + sha dma permission configuration register 0. + 0x78 + 0x20 + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_LOCK + Set 1 to lock sha dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_1 + sha dma permission configuration register 1. + 0x7C + 0x20 + 0x00000FFF + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_SRAM_PMS_0 + sha's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_SRAM_PMS_1 + sha's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_SRAM_PMS_2 + sha's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_SRAM_PMS_3 + sha's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + sha's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_SHA_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + sha's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_0 + adc_dac dma permission configuration register 0. + 0x80 + 0x20 + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_LOCK + Set 1 to lock adc_dac dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_1 + adc_dac dma permission configuration register 1. + 0x84 + 0x20 + 0x00000FFF + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_SRAM_PMS_0 + adc_dac's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_SRAM_PMS_1 + adc_dac's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_SRAM_PMS_2 + adc_dac's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_SRAM_PMS_3 + adc_dac's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + adc_dac's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_ADC_DAC_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + adc_dac's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_0 + rmt dma permission configuration register 0. + 0x88 + 0x20 + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_LOCK + Set 1 to lock rmt dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_1 + rmt dma permission configuration register 1. + 0x8C + 0x20 + 0x00000FFF + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_SRAM_PMS_0 + rmt's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_SRAM_PMS_1 + rmt's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_SRAM_PMS_2 + rmt's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_SRAM_PMS_3 + rmt's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + rmt's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_RMT_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + rmt's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_0 + lcd_cam dma permission configuration register 0. + 0x90 + 0x20 + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_LOCK + Set 1 to lock lcd_cam dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_1 + lcd_cam dma permission configuration register 1. + 0x94 + 0x20 + 0x00000FFF + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_SRAM_PMS_0 + lcd_cam's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_SRAM_PMS_1 + lcd_cam's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_SRAM_PMS_2 + lcd_cam's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_SRAM_PMS_3 + lcd_cam's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + lcd_cam's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_LCD_CAM_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + lcd_cam's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_USB_PMS_CONSTRAIN_0 + usb dma permission configuration register 0. + 0x98 + 0x20 + + + DMA_APBPERI_USB_PMS_CONSTRAIN_LOCK + Set 1 to lock usb dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_USB_PMS_CONSTRAIN_1 + usb dma permission configuration register 1. + 0x9C + 0x20 + 0x00000FFF + + + DMA_APBPERI_USB_PMS_CONSTRAIN_SRAM_PMS_0 + usb's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_USB_PMS_CONSTRAIN_SRAM_PMS_1 + usb's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_USB_PMS_CONSTRAIN_SRAM_PMS_2 + usb's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_USB_PMS_CONSTRAIN_SRAM_PMS_3 + usb's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_USB_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + usb's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_USB_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + usb's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_LC_PMS_CONSTRAIN_0 + lc dma permission configuration register 0. + 0xA0 + 0x20 + + + DMA_APBPERI_LC_PMS_CONSTRAIN_LOCK + Set 1 to lock lc dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_LC_PMS_CONSTRAIN_1 + lc dma permission configuration register 1. + 0xA4 + 0x20 + 0x00000FFF + + + DMA_APBPERI_LC_PMS_CONSTRAIN_SRAM_PMS_0 + lc's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_LC_PMS_CONSTRAIN_SRAM_PMS_1 + lc's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_LC_PMS_CONSTRAIN_SRAM_PMS_2 + lc's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_LC_PMS_CONSTRAIN_SRAM_PMS_3 + lc's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_LC_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + lc's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_LC_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + lc's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_0 + sdio dma permission configuration register 0. + 0xA8 + 0x20 + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_LOCK + Set 1 to lock sdio dma permission Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_1 + sdio dma permission configuration register 1. + 0xAC + 0x20 + 0x00000FFF + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_SRAM_PMS_0 + sdio's permission(store,load) in data region0 of SRAM + 0 + 2 + read-write + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_SRAM_PMS_1 + sdio's permission(store,load) in data region1 of SRAM + 2 + 2 + read-write + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_SRAM_PMS_2 + sdio's permission(store,load) in data region2 of SRAM + 4 + 2 + read-write + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_SRAM_PMS_3 + sdio's permission(store,load) in data region3 of SRAM + 6 + 2 + read-write + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_0 + sdio's permission(store,load) in dcache data sram block0 + 8 + 2 + read-write + + + DMA_APBPERI_SDIO_PMS_CONSTRAIN_SRAM_CACHEDATAARRAY_PMS_1 + sdio's permission(store,load) in dcache data sram block1 + 10 + 2 + read-write + + + + + DMA_APBPERI_PMS_MONITOR_0 + dma permission monitor configuration register 0. + 0xB0 + 0x20 + + + DMA_APBPERI_PMS_MONITOR_LOCK + Set 1 to lock dma permission monitor Configuration Register. + 0 + 1 + read-write + + + + + DMA_APBPERI_PMS_MONITOR_1 + dma permission monitor configuration register 1. + 0xB4 + 0x20 + 0x00000003 + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear dma_pms_monitor_violate interrupt + 0 + 1 + read-write + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_EN + Set 1 to enable dma pms monitor, if dma access violated permission, will trigger interrupt. + 1 + 1 + read-write + + + + + DMA_APBPERI_PMS_MONITOR_2 + dma permission monitor configuration register 2. + 0xB8 + 0x20 + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_INTR + recorded dma's interrupt status when dma access violated permission + 0 + 1 + read-only + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_STATUS_WORLD + recorded dma's world status when dma access violated permission + 1 + 2 + read-only + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_STATUS_ADDR + recorded dma's address bit[25:4] status when dma access violated permission, real address is 0x3c00_0000+addr*16 + 3 + 22 + read-only + + + + + DMA_APBPERI_PMS_MONITOR_3 + dma permission monitor configuration register 3. + 0xBC + 0x20 + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_STATUS_WR + recorded dma's write status when dma access violated permission, 1(write), 0(read) + 0 + 1 + read-only + + + DMA_APBPERI_PMS_MONITOR_VIOLATE_STATUS_BYTEEN + recorded dma's byte enable status when dma access violated permission + 1 + 16 + read-only + + + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0 + sram split line configuration register 0 + 0xC0 + 0x20 + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_LOCK + Set 1 to lock sram split configuration register + 0 + 1 + read-write + + + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1 + sram split line configuration register 1 + 0xC4 + 0x20 + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_0 + category0 of core_x_iram0_dram_dma_line, if the splitaddress in block0 of SRAM, configured as 0x10, else if the splitaddress below block0 of SRAM, configured as 0x11, else if splitaddress higher than block0 of SRAM, configured as 0x00 + 0 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_1 + category1 of core_x_iram0_dram_dma_line, if the splitaddress in block1 of SRAM, configured as 0x10, else if the splitaddress below block1 of SRAM, configured as 0x11, else if splitaddress higher than block1 of SRAM, configured as 0x00 + 2 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2 + category2 of core_x_iram0_dram_dma_line, if the splitaddress in block2 of SRAM, configured as 0x10, else if the splitaddress below block2 of SRAM, configured as 0x11, else if splitaddress higher than block2 of SRAM, configured as 0x00 + 4 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_3 + category3 of core_x_iram0_dram_dma_line, if the splitaddress in block3 of SRAM, configured as 0x10, else if the splitaddress below block3 of SRAM, configured as 0x11, else if splitaddress higher than block3 of SRAM, configured as 0x00 + 6 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_4 + category4 of core_x_iram0_dram_dma_line, if the splitaddress in block4 of SRAM, configured as 0x10, else if the splitaddress below block4 of SRAM, configured as 0x11, else if splitaddress higher than block4 of SRAM, configured as 0x00 + 8 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_5 + category5 of core_x_iram0_dram_dma_line, if the splitaddress in block5 of SRAM, configured as 0x10, else if the splitaddress below block5 of SRAM, configured as 0x11, else if splitaddress higher than block5 of SRAM, configured as 0x00 + 10 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_6 + category6 of core_x_iram0_dram_dma_line, if the splitaddress in block6 of SRAM, configured as 0x10, else if the splitaddress below block6 of SRAM, configured as 0x11, else if splitaddress higher than block6 of SRAM, configured as 0x00 + 12 + 2 + read-write + + + CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR + splitaddr of core_x_iram0_dram_dma_line, configured as [15:8]bit of actual address + 14 + 8 + read-write + + + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2 + sram split line configuration register 1 + 0xC8 + 0x20 + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_0 + category0 of core_x_iram0_dram_dma_line, if the splitaddress in block0 of SRAM, configured as 0x10, else if the splitaddress below block0 of SRAM, configured as 0x11, else if splitaddress higher than block0 of SRAM, configured as 0x00 + 0 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_1 + category1 of core_x_iram0_dram_dma_line, if the splitaddress in block1 of SRAM, configured as 0x10, else if the splitaddress below block1 of SRAM, configured as 0x11, else if splitaddress higher than block1 of SRAM, configured as 0x00 + 2 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_2 + category2 of core_x_iram0_dram_dma_line, if the splitaddress in block2 of SRAM, configured as 0x10, else if the splitaddress below block2 of SRAM, configured as 0x11, else if splitaddress higher than block2 of SRAM, configured as 0x00 + 4 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_3 + category3 of core_x_iram0_dram_dma_line, if the splitaddress in block3 of SRAM, configured as 0x10, else if the splitaddress below block3 of SRAM, configured as 0x11, else if splitaddress higher than block3 of SRAM, configured as 0x00 + 6 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_4 + category4 of core_x_iram0_dram_dma_line, if the splitaddress in block4 of SRAM, configured as 0x10, else if the splitaddress below block4 of SRAM, configured as 0x11, else if splitaddress higher than block4 of SRAM, configured as 0x00 + 8 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_5 + category5 of core_x_iram0_dram_dma_line, if the splitaddress in block5 of SRAM, configured as 0x10, else if the splitaddress below block5 of SRAM, configured as 0x11, else if splitaddress higher than block5 of SRAM, configured as 0x00 + 10 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_CATEGORY_6 + category6 of core_x_iram0_dram_dma_line, if the splitaddress in block6 of SRAM, configured as 0x10, else if the splitaddress below block6 of SRAM, configured as 0x11, else if splitaddress higher than block6 of SRAM, configured as 0x00 + 12 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_0_SPLITADDR + splitaddr of core_x_iram0_dram_dma_line, configured as [15:8]bit of actual address + 14 + 8 + read-write + + + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3 + sram split line configuration register 1 + 0xCC + 0x20 + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_0 + category0 of core_x_iram0_dram_dma_line, if the splitaddress in block0 of SRAM, configured as 0x10, else if the splitaddress below block0 of SRAM, configured as 0x11, else if splitaddress higher than block0 of SRAM, configured as 0x00 + 0 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_1 + category1 of core_x_iram0_dram_dma_line, if the splitaddress in block1 of SRAM, configured as 0x10, else if the splitaddress below block1 of SRAM, configured as 0x11, else if splitaddress higher than block1 of SRAM, configured as 0x00 + 2 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_2 + category2 of core_x_iram0_dram_dma_line, if the splitaddress in block2 of SRAM, configured as 0x10, else if the splitaddress below block2 of SRAM, configured as 0x11, else if splitaddress higher than block2 of SRAM, configured as 0x00 + 4 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_3 + category3 of core_x_iram0_dram_dma_line, if the splitaddress in block3 of SRAM, configured as 0x10, else if the splitaddress below block3 of SRAM, configured as 0x11, else if splitaddress higher than block3 of SRAM, configured as 0x00 + 6 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_4 + category4 of core_x_iram0_dram_dma_line, if the splitaddress in block4 of SRAM, configured as 0x10, else if the splitaddress below block4 of SRAM, configured as 0x11, else if splitaddress higher than block4 of SRAM, configured as 0x00 + 8 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_5 + category5 of core_x_iram0_dram_dma_line, if the splitaddress in block5 of SRAM, configured as 0x10, else if the splitaddress below block5 of SRAM, configured as 0x11, else if splitaddress higher than block5 of SRAM, configured as 0x00 + 10 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_CATEGORY_6 + category6 of core_x_iram0_dram_dma_line, if the splitaddress in block6 of SRAM, configured as 0x10, else if the splitaddress below block6 of SRAM, configured as 0x11, else if splitaddress higher than block6 of SRAM, configured as 0x00 + 12 + 2 + read-write + + + CORE_X_IRAM0_SRAM_LINE_1_SPLITADDR + splitaddr of core_x_iram0_dram_dma_line, configured as [15:8]bit of actual address + 14 + 8 + read-write + + + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4 + sram split line configuration register 1 + 0xD0 + 0x20 + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_0 + category0 of core_x_iram0_dram_dma_line, if the splitaddress in block0 of SRAM, configured as 0x10, else if the splitaddress below block0 of SRAM, configured as 0x11, else if splitaddress higher than block0 of SRAM, configured as 0x00 + 0 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_1 + category1 of core_x_iram0_dram_dma_line, if the splitaddress in block1 of SRAM, configured as 0x10, else if the splitaddress below block1 of SRAM, configured as 0x11, else if splitaddress higher than block1 of SRAM, configured as 0x00 + 2 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_2 + category2 of core_x_iram0_dram_dma_line, if the splitaddress in block2 of SRAM, configured as 0x10, else if the splitaddress below block2 of SRAM, configured as 0x11, else if splitaddress higher than block2 of SRAM, configured as 0x00 + 4 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_3 + category3 of core_x_iram0_dram_dma_line, if the splitaddress in block3 of SRAM, configured as 0x10, else if the splitaddress below block3 of SRAM, configured as 0x11, else if splitaddress higher than block3 of SRAM, configured as 0x00 + 6 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_4 + category4 of core_x_iram0_dram_dma_line, if the splitaddress in block4 of SRAM, configured as 0x10, else if the splitaddress below block4 of SRAM, configured as 0x11, else if splitaddress higher than block4 of SRAM, configured as 0x00 + 8 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_5 + category5 of core_x_iram0_dram_dma_line, if the splitaddress in block5 of SRAM, configured as 0x10, else if the splitaddress below block5 of SRAM, configured as 0x11, else if splitaddress higher than block5 of SRAM, configured as 0x00 + 10 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_CATEGORY_6 + category6 of core_x_iram0_dram_dma_line, if the splitaddress in block6 of SRAM, configured as 0x10, else if the splitaddress below block6 of SRAM, configured as 0x11, else if splitaddress higher than block6 of SRAM, configured as 0x00 + 12 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_0_SPLITADDR + splitaddr of core_x_iram0_dram_dma_line, configured as [15:8]bit of actual address + 14 + 8 + read-write + + + + + CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5 + sram split line configuration register 1 + 0xD4 + 0x20 + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_0 + category0 of core_x_iram0_dram_dma_line, if the splitaddress in block0 of SRAM, configured as 0x10, else if the splitaddress below block0 of SRAM, configured as 0x11, else if splitaddress higher than block0 of SRAM, configured as 0x00 + 0 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_1 + category1 of core_x_iram0_dram_dma_line, if the splitaddress in block1 of SRAM, configured as 0x10, else if the splitaddress below block1 of SRAM, configured as 0x11, else if splitaddress higher than block1 of SRAM, configured as 0x00 + 2 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_2 + category2 of core_x_iram0_dram_dma_line, if the splitaddress in block2 of SRAM, configured as 0x10, else if the splitaddress below block2 of SRAM, configured as 0x11, else if splitaddress higher than block2 of SRAM, configured as 0x00 + 4 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_3 + category3 of core_x_iram0_dram_dma_line, if the splitaddress in block3 of SRAM, configured as 0x10, else if the splitaddress below block3 of SRAM, configured as 0x11, else if splitaddress higher than block3 of SRAM, configured as 0x00 + 6 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_4 + category4 of core_x_iram0_dram_dma_line, if the splitaddress in block4 of SRAM, configured as 0x10, else if the splitaddress below block4 of SRAM, configured as 0x11, else if splitaddress higher than block4 of SRAM, configured as 0x00 + 8 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_5 + category5 of core_x_iram0_dram_dma_line, if the splitaddress in block5 of SRAM, configured as 0x10, else if the splitaddress below block5 of SRAM, configured as 0x11, else if splitaddress higher than block5 of SRAM, configured as 0x00 + 10 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_CATEGORY_6 + category6 of core_x_iram0_dram_dma_line, if the splitaddress in block6 of SRAM, configured as 0x10, else if the splitaddress below block6 of SRAM, configured as 0x11, else if splitaddress higher than block6 of SRAM, configured as 0x00 + 12 + 2 + read-write + + + CORE_X_DRAM0_DMA_SRAM_LINE_1_SPLITADDR + splitaddr of core_x_iram0_dram_dma_line, configured as [15:8]bit of actual address + 14 + 8 + read-write + + + + + CORE_X_IRAM0_PMS_CONSTRAIN_0 + corex iram0 permission configuration register 0 + 0xD8 + 0x20 + + + CORE_X_IRAM0_PMS_CONSTRAIN_LOCK + Set 1 to lock corex iram0 permission configuration register + 0 + 1 + read-write + + + + + CORE_X_IRAM0_PMS_CONSTRAIN_1 + corex iram0 permission configuration register 0 + 0xDC + 0x20 + 0x001FFFFF + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_0 + core0/core1's permission of instruction region0 of SRAM in world1 + 0 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_1 + core0/core1's permission of instruction region1 of SRAM in world1 + 3 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_2 + core0/core1's permission of instruction region2 of SRAM in world1 + 6 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_3 + core0/core1's permission of instruction region3 of SRAM in world1 + 9 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_CACHEDATAARRAY_PMS_0 + core0/core1's permission of icache data sram block0 in world1 + 12 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_CACHEDATAARRAY_PMS_1 + core0/core1's permission of icache data sram block1 in world1 + 15 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_ROM_WORLD_1_PMS + core0/core1's permission of rom in world1 + 18 + 3 + read-write + + + + + CORE_X_IRAM0_PMS_CONSTRAIN_2 + corex iram0 permission configuration register 1 + 0xE0 + 0x20 + 0x001FFFFF + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0 + core0/core1's permission of instruction region0 of SRAM in world1 + 0 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1 + core0/core1's permission of instruction region1 of SRAM in world1 + 3 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2 + core0/core1's permission of instruction region2 of SRAM in world1 + 6 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3 + core0/core1's permission of instruction region3 of SRAM in world1 + 9 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_CACHEDATAARRAY_PMS_0 + core0/core1's permission of icache data sram block0 in world1 + 12 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_CACHEDATAARRAY_PMS_1 + core0/core1's permission of icache data sram block1 in world1 + 15 + 3 + read-write + + + CORE_X_IRAM0_PMS_CONSTRAIN_ROM_WORLD_0_PMS + core0/core1's permission of rom in world1 + 18 + 3 + read-write + + + + + CORE_0_IRAM0_PMS_MONITOR_0 + core0 iram0 permission monitor configuration register 0 + 0xE4 + 0x20 + + + CORE_0_IRAM0_PMS_MONITOR_LOCK + Set 1 to lock core0 iram0 permission monitor register + 0 + 1 + read-write + + + + + CORE_0_IRAM0_PMS_MONITOR_1 + core0 iram0 permission monitor configuration register 1 + 0xE8 + 0x20 + 0x00000003 + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear core0 iram0 permission violated interrupt + 0 + 1 + read-write + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN + Set 1 to enable core0 iram0 permission monitor, when core0_iram violated permission, will trigger interrupt + 1 + 1 + read-write + + + + + CORE_0_IRAM0_PMS_MONITOR_2 + core0 iram0 permission monitor configuration register 2 + 0xEC + 0x20 + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR + recorded core0 iram0 pms monitor interrupt status. + 0 + 1 + read-only + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR + recorded core0 iram0 wr status, only if loadstore is 1 have meaning, 1(store), 0(load). + 1 + 1 + read-only + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE + recorded core0 iram0 loadstore status, indicated the type of operation, 0(fetch), 1(load/store). + 2 + 1 + read-only + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD + recorded core0 iram0 world status, 0x01 means world0, 0x10 means world1. + 3 + 2 + read-only + + + CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR + recorded core0 iram0 address [25:2] status when core0 iram0 violated permission, the real address is 0x40000000+addr*4 + 5 + 24 + read-only + + + + + CORE_1_IRAM0_PMS_MONITOR_0 + core1 iram0 permission monitor configuration register 0 + 0xF0 + 0x20 + + + CORE_1_IRAM0_PMS_MONITOR_LOCK + Set 1 to lock core1 iram0 permission monitor register + 0 + 1 + read-write + + + + + CORE_1_IRAM0_PMS_MONITOR_1 + core1 iram0 permission monitor configuration register 1 + 0xF4 + 0x20 + 0x00000003 + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear core1 iram0 permission violated interrupt + 0 + 1 + read-write + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_EN + Set 1 to enable core1 iram0 permission monitor, when core1_iram violated permission, will trigger interrupt + 1 + 1 + read-write + + + + + CORE_1_IRAM0_PMS_MONITOR_2 + core1 iram0 permission monitor configuration register 2 + 0xF8 + 0x20 + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_INTR + recorded core1 iram0 pms monitor interrupt status. + 0 + 1 + read-only + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR + recorded core1 iram0 wr status, only if loadstore is 1 have meaning, 1(store), 0(load). + 1 + 1 + read-only + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE + recorded core1 iram0 loadstore status, indicated the type of operation, 0(fetch), 1(load/store). + 2 + 1 + read-only + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD + recorded core1 iram0 world status, 0x01 means world0, 0x10 means world1. + 3 + 2 + read-only + + + CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR + recorded core1 iram0 address [25:2] status when core1 iram0 violated permission, the real address is 0x40000000+addr*4 + 5 + 24 + read-only + + + + + CORE_X_DRAM0_PMS_CONSTRAIN_0 + corex dram0 permission configuration register 0 + 0xFC + 0x20 + + + CORE_X_DRAM0_PMS_CONSTRAIN_LOCK + Set 1 to lock corex dram0 permission configuration register + 0 + 1 + read-write + + + + + CORE_X_DRAM0_PMS_CONSTRAIN_1 + corex dram0 permission configuration register 1 + 0x100 + 0x20 + 0x0FFFFFFF + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0 + core0/core1's permission of data region0 of SRAM in world0. + 0 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1 + core0/core1's permission of data region1 of SRAM in world0. + 2 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2 + core0/core1's permission of data region2 of SRAM in world0. + 4 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3 + core0/core1's permission of data region3 of SRAM in world0. + 6 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_CACHEDATAARRAY_PMS_0 + core0/core1's permission of dcache data sram block0 in world0. + 8 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_CACHEDATAARRAY_PMS_1 + core0/core1's permission of dcache data sram block1 in world0. + 10 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_0 + core0/core1's permission of data region0 of SRAM in world1. + 12 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_1 + core0/core1's permission of data region1 of SRAM in world1. + 14 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_2 + core0/core1's permission of data region2 of SRAM in world1. + 16 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_PMS_3 + core0/core1's permission of data region3 of SRAM in world1. + 18 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_CACHEDATAARRAY_PMS_0 + core0/core1's permission of dcache data sram block0 in world1. + 20 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_1_CACHEDATAARRAY_PMS_1 + core0/core1's permission of dcache data sram block1 in world1. + 22 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_ROM_WORLD_0_PMS + core0/core1's permission(sotre,load) of rom in world0. + 24 + 2 + read-write + + + CORE_X_DRAM0_PMS_CONSTRAIN_ROM_WORLD_1_PMS + core0/core1's permission(sotre,load) of rom in world1. + 26 + 2 + read-write + + + + + CORE_0_DRAM0_PMS_MONITOR_0 + core0 dram0 permission monitor configuration register 0 + 0x104 + 0x20 + + + CORE_0_DRAM0_PMS_MONITOR_LOCK + Set 1 to lock core0 dram0 permission monitor configuration register. + 0 + 1 + read-write + + + + + CORE_0_DRAM0_PMS_MONITOR_1 + core0 dram0 permission monitor configuration register 1 + 0x108 + 0x20 + 0x00000003 + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear core0 dram0 permission monior interrupt. + 0 + 1 + read-write + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN + Set 1 to enable core0 dram0 permission monitor interrupt. + 1 + 1 + read-write + + + + + CORE_0_DRAM0_PMS_MONITOR_2 + core0 dram0 permission monitor configuration register 2. + 0x10C + 0x20 + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR + recorded core0 dram0 permission monitor interrupt status. + 0 + 1 + read-only + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK + recorded core0 dram0 lock status, 1 means s32c1i access. + 1 + 1 + read-only + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD + recorded core0 dram0 world status, 0x1 means world0, 0x2 means world1. + 2 + 2 + read-only + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR + recorded core0 dram0 address[25:4] status when core0 dram0 violated permission,the real address is 0x3c000000+addr*16 + 4 + 22 + read-only + + + + + CORE_0_DRAM0_PMS_MONITOR_3 + core0 dram0 permission monitor configuration register 3. + 0x110 + 0x20 + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR + recorded core0 dram0 wr status, 1 means store, 0 means load. + 0 + 1 + read-only + + + CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN + recorded core0 dram0 byteen status. + 1 + 16 + read-only + + + + + CORE_1_DRAM0_PMS_MONITOR_0 + core1 dram0 permission monitor configuration register 0 + 0x114 + 0x20 + + + CORE_1_DRAM0_PMS_MONITOR_LOCK + Set 1 to lock core1 dram0 permission monitor configuration register. + 0 + 1 + read-write + + + + + CORE_1_DRAM0_PMS_MONITOR_1 + core1 dram0 permission monitor configuration register 1 + 0x118 + 0x20 + 0x00000003 + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear core1 dram0 permission monior interrupt. + 0 + 1 + read-write + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_EN + Set 1 to enable core1 dram0 permission monitor interrupt. + 1 + 1 + read-write + + + + + CORE_1_DRAM0_PMS_MONITOR_2 + core1 dram0 permission monitor configuration register 2. + 0x11C + 0x20 + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_INTR + recorded core1 dram0 permission monitor interrupt status. + 0 + 1 + read-only + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK + recorded core1 dram0 lock status, 1 means s32c1i access. + 1 + 1 + read-only + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD + recorded core1 dram0 world status, 0x1 means world0, 0x2 means world1. + 2 + 2 + read-only + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR + recorded core1 dram0 address[25:4] status when core1 dram0 violated permission,the real address is 0x3c000000+addr*16 + 4 + 22 + read-only + + + + + CORE_1_DRAM0_PMS_MONITOR_3 + core1 dram0 permission monitor configuration register 3. + 0x120 + 0x20 + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR + recorded core1 dram0 wr status, 1 means store, 0 means load. + 0 + 1 + read-only + + + CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN + recorded core1 dram0 byteen status. + 1 + 16 + read-only + + + + + CORE_0_PIF_PMS_CONSTRAIN_0 + Core0 access peripherals permission configuration register 0. + 0x124 + 0x20 + + + CORE_0_PIF_PMS_CONSTRAIN_LOCK + Set 1 to lock core0 access peripherals permission Configuration Register. + 0 + 1 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_1 + Core0 access peripherals permission configuration register 1. + 0x128 + 0x20 + 0xFF33CFFF + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_UART + Core0 access uart permission in world0. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_G0SPI_1 + Core0 access g0spi_1 permission in world0. + 2 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_G0SPI_0 + Core0 access g0spi_0 permission in world0. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_GPIO + Core0 access gpio permission in world0. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_FE2 + Core0 access fe2 permission in world0. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_FE + Core0 access fe permission in world0. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RTC + Core0 access rtc permission in world0. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_IO_MUX + Core0 access io_mux permission in world0. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_HINF + Core0 access hinf permission in world0. + 20 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_MISC + Core0 access misc permission in world0. + 24 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2C + Core0 access i2c permission in world0. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S0 + Core0 access i2s0 permission in world0. + 28 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_UART1 + Core0 access uart1 permission in world0. + 30 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_2 + Core0 access peripherals permission configuration register 2. + 0x12C + 0x20 + 0xFFCFFFF3 + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_BT + Core0 access bt permission in world0. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2C_EXT0 + Core0 access i2c_ext0 permission in world0. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_UHCI0 + Core0 access uhci0 permission in world0. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SLCHOST + Core0 access slchost permission in world0. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RMT + Core0 access rmt permission in world0. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_PCNT + Core0 access pcnt permission in world0. + 12 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SLC + Core0 access slc permission in world0. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_LEDC + Core0 access ledc permission in world0. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_BACKUP + Core0 access backup permission in world0. + 18 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_BB + Core0 access bb permission in world0. + 22 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_PWM0 + Core0 access pwm0 permission in world0. + 24 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_TIMERGROUP + Core0 access timergroup permission in world0. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_TIMERGROUP1 + Core0 access timergroup1 permission in world0. + 28 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SYSTIMER + Core0 access systimer permission in world0. + 30 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_3 + Core0 access peripherals permission configuration register 3. + 0x130 + 0x20 + 0x3CC3FFFF + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SPI_2 + Core0 access spi_2 permission in world0. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SPI_3 + Core0 access spi_3 permission in world0. + 2 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_APB_CTRL + Core0 access apb_ctrl permission in world0. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2C_EXT1 + Core0 access i2c_ext1 permission in world0. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SDIO_HOST + Core0 access sdio_host permission in world0. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_CAN + Core0 access can permission in world0. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_PWM1 + Core0 access pwm1 permission in world0. + 12 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_I2S1 + Core0 access i2s1 permission in world0. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_UART2 + Core0 access uart2 permission in world0. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_RWBT + Core0 access rwbt permission in world0. + 22 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_WIFIMAC + Core0 access wifimac permission in world0. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_PWR + Core0 access pwr permission in world0. + 28 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_4 + Core0 access peripherals permission configuration register 4. + 0x134 + 0x20 + 0xFFFFFFFF + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_USB_DEVICE + Core0 access usb_device permission in world0. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_USB_WRAP + Core0 access usb_wrap permission in world0. + 2 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_CRYPTO_PERI + Core0 access crypto_peri permission in world0. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_CRYPTO_DMA + Core0 access crypto_dma permission in world0. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_APB_ADC + Core0 access apb_adc permission in world0. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_LCD_CAM + Core0 access lcd_cam permission in world0. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_BT_PWR + Core0 access bt_pwr permission in world0. + 12 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_USB + Core0 access usb permission in world0. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SYSTEM + Core0 access system permission in world0. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_SENSITIVE + Core0 access sensitive permission in world0. + 18 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_INTERRUPT + Core0 access interrupt permission in world0. + 20 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_DMA_COPY + Core0 access dma_copy permission in world0. + 22 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_CACHE_CONFIG + Core0 access cache_config permission in world0. + 24 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_AD + Core0 access ad permission in world0. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_DIO + Core0 access dio permission in world0. + 28 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_0_WORLD_CONTROLLER + Core0 access world_controller permission in world0. + 30 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_5 + Core0 access peripherals permission configuration register 5. + 0x138 + 0x20 + 0xFF33CFFF + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_UART + Core0 access uart permission in world1. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_G0SPI_1 + Core0 access g0spi_1 permission in world1. + 2 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_G0SPI_0 + Core0 access g0spi_0 permission in world1. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_GPIO + Core0 access gpio permission in world1. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_FE2 + Core0 access fe2 permission in world1. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_FE + Core0 access fe permission in world1. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RTC + Core0 access rtc permission in world1. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_IO_MUX + Core0 access io_mux permission in world1. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_HINF + Core0 access hinf permission in world1. + 20 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_MISC + Core0 access misc permission in world1. + 24 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2C + Core0 access i2c permission in world1. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S0 + Core0 access i2s0 permission in world1. + 28 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_UART1 + Core0 access uart1 permission in world1. + 30 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_6 + Core0 access peripherals permission configuration register 6. + 0x13C + 0x20 + 0xFFCFFFF3 + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_BT + Core0 access bt permission in world1. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2C_EXT0 + Core0 access i2c_ext0 permission in world1. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_UHCI0 + Core0 access uhci0 permission in world1. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SLCHOST + Core0 access slchost permission in world1. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RMT + Core0 access rmt permission in world1. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_PCNT + Core0 access pcnt permission in world1. + 12 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SLC + Core0 access slc permission in world1. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_LEDC + Core0 access ledc permission in world1. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_BACKUP + Core0 access backup permission in world1. + 18 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_BB + Core0 access bb permission in world1. + 22 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_PWM0 + Core0 access pwm0 permission in world1. + 24 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_TIMERGROUP + Core0 access timergroup permission in world1. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_TIMERGROUP1 + Core0 access timergroup1 permission in world1. + 28 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SYSTIMER + Core0 access systimer permission in world1. + 30 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_7 + Core0 access peripherals permission configuration register 7. + 0x140 + 0x20 + 0x3CC3FFFF + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SPI_2 + Core0 access spi_2 permission in world1. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SPI_3 + Core0 access spi_3 permission in world1. + 2 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_APB_CTRL + Core0 access apb_ctrl permission in world1. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2C_EXT1 + Core0 access i2c_ext1 permission in world1. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SDIO_HOST + Core0 access sdio_host permission in world1. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_CAN + Core0 access can permission in world1. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_PWM1 + Core0 access pwm1 permission in world1. + 12 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_I2S1 + Core0 access i2s1 permission in world1. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_UART2 + Core0 access uart2 permission in world1. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_RWBT + Core0 access rwbt permission in world1. + 22 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_WIFIMAC + Core0 access wifimac permission in world1. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_PWR + Core0 access pwr permission in world1. + 28 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_8 + Core0 access peripherals permission configuration register 8. + 0x144 + 0x20 + 0xFFFFFFFF + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_USB_DEVICE + Core0 access usb_device permission in world1. + 0 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_USB_WRAP + Core0 access usb_wrap permission in world1. + 2 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_CRYPTO_PERI + Core0 access crypto_peri permission in world1. + 4 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_CRYPTO_DMA + Core0 access crypto_dma permission in world1. + 6 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_APB_ADC + Core0 access apb_adc permission in world1. + 8 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_LCD_CAM + Core0 access lcd_cam permission in world1. + 10 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_BT_PWR + Core0 access bt_pwr permission in world1. + 12 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_USB + Core0 access usb permission in world1. + 14 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SYSTEM + Core0 access system permission in world1. + 16 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_SENSITIVE + Core0 access sensitive permission in world1. + 18 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_INTERRUPT + Core0 access interrupt permission in world1. + 20 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_DMA_COPY + Core0 access dma_copy permission in world1. + 22 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_CACHE_CONFIG + Core0 access cache_config permission in world1. + 24 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_AD + Core0 access ad permission in world1. + 26 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_DIO + Core0 access dio permission in world1. + 28 + 2 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_WORLD_1_WORLD_CONTROLLER + Core0 access world_controller permission in world1. + 30 + 2 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_9 + Core0 access peripherals permission configuration register 9. + 0x148 + 0x20 + 0x003FFFFF + + + CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0 + RTCFast memory split address in world 0 for core0. + 0 + 11 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1 + RTCFast memory split address in world 1 for core0. + 11 + 11 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_10 + Core0 access peripherals permission configuration register 10. + 0x14C + 0x20 + 0x00000FFF + + + CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L + RTCFast memory low region permission in world 0 for core0. + 0 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H + RTCFast memory high region permission in world 0 for core0. + 3 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L + RTCFast memory low region permission in world 1 for core0. + 6 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H + RTCFast memory high region permission in world 1 for core0. + 9 + 3 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_11 + Core0 access peripherals permission configuration register 11. + 0x150 + 0x20 + 0x003FFFFF + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_0_SPLTADDR_WORLD_0 + RTCSlow_0 memory split address in world 0 for core0. + 0 + 11 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_0_SPLTADDR_WORLD_1 + RTCSlow_0 memory split address in world 1 for core0. + 11 + 11 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_12 + Core0 access peripherals permission configuration register 12. + 0x154 + 0x20 + 0x00000FFF + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_0_L + RTCSlow_0 memory low region permission in world 0 for core0. + 0 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_0_H + RTCSlow_0 memory high region permission in world 0 for core0. + 3 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_1_L + RTCSlow_0 memory low region permission in world 1 for core0. + 6 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_1_H + RTCSlow_0 memory high region permission in world 1 for core0. + 9 + 3 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_13 + Core0 access peripherals permission configuration register 13. + 0x158 + 0x20 + 0x003FFFFF + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_1_SPLTADDR_WORLD_0 + RTCSlow_1 memory split address in world 0 for core0. + 0 + 11 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_1_SPLTADDR_WORLD_1 + RTCSlow_1 memory split address in world 1 for core0. + 11 + 11 + read-write + + + + + CORE_0_PIF_PMS_CONSTRAIN_14 + Core0 access peripherals permission configuration register 14. + 0x15C + 0x20 + 0x00000FFF + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_0_L + RTCSlow_1 memory low region permission in world 0 for core0. + 0 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_0_H + RTCSlow_1 memory high region permission in world 0 for core0. + 3 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_1_L + RTCSlow_1 memory low region permission in world 1 for core0. + 6 + 3 + read-write + + + CORE_0_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_1_H + RTCSlow_1 memory high region permission in world 1 for core0. + 9 + 3 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_0 + Core0 region permission register 0. + 0x160 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_LOCK + Set 1 to lock core0 region permission registers. + 0 + 1 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_1 + Core0 region permission register 1. + 0x164 + 0x20 + 0x003FFFFF + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_0 + Region 0 permission in world 0 for core0. + 0 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_1 + Region 1 permission in world 0 for core0. + 2 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_2 + Region 2 permission in world 0 for core0. + 4 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_3 + Region 3 permission in world 0 for core0. + 6 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_4 + Region 4 permission in world 0 for core0. + 8 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_5 + Region 5 permission in world 0 for core0. + 10 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_6 + Region 6 permission in world 0 for core0. + 12 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_7 + Region 7 permission in world 0 for core0. + 14 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_8 + Region 8 permission in world 0 for core0. + 16 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_9 + Region 9 permission in world 0 for core0. + 18 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_0_AREA_10 + Region 10 permission in world 0 for core0. + 20 + 2 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_2 + Core0 region permission register 2. + 0x168 + 0x20 + 0x003FFFFF + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_0 + Region 0 permission in world 1 for core0. + 0 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_1 + Region 1 permission in world 1 for core0. + 2 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_2 + Region 2 permission in world 1 for core0. + 4 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_3 + Region 3 permission in world 1 for core0. + 6 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_4 + Region 4 permission in world 1 for core0. + 8 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_5 + Region 5 permission in world 1 for core0. + 10 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_6 + Region 6 permission in world 1 for core0. + 12 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_7 + Region 7 permission in world 1 for core0. + 14 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_8 + Region 8 permission in world 1 for core0. + 16 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_9 + Region 9 permission in world 1 for core0. + 18 + 2 + read-write + + + CORE_0_REGION_PMS_CONSTRAIN_WORLD_1_AREA_10 + Region 10 permission in world 1 for core0. + 20 + 2 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_3 + Core0 region permission register 3. + 0x16C + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_0 + Region 0 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_4 + Core0 region permission register 4. + 0x170 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_1 + Region 0 end address and Region 1 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_5 + Core0 region permission register 5. + 0x174 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_2 + Region 1 end address and Region 2 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_6 + Core0 region permission register 6. + 0x178 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_3 + Region 2 end address and Region 3 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_7 + Core0 region permission register 7. + 0x17C + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_4 + Region 3 end address and Region 4 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_8 + Core0 region permission register 8. + 0x180 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_5 + Region 4 end address and Region 5 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_9 + Core0 region permission register 9. + 0x184 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_6 + Region 5 end address and Region 6 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_10 + Core0 region permission register 10. + 0x188 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_7 + Region 6 end address and Region 7 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_11 + Core0 region permission register 11. + 0x18C + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_8 + Region 7 end address and Region 8 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_12 + Core0 region permission register 12. + 0x190 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_9 + Region 8 end address and Region 9 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_13 + Core0 region permission register 13. + 0x194 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_10 + Region 9 end address and Region 10 start address for core0. + 0 + 30 + read-write + + + + + CORE_0_REGION_PMS_CONSTRAIN_14 + Core0 region permission register 14. + 0x198 + 0x20 + + + CORE_0_REGION_PMS_CONSTRAIN_ADDR_11 + Region 10 end address for core0. + 0 + 30 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_0 + Core0 permission report register 0. + 0x19C + 0x20 + + + CORE_0_PIF_PMS_MONITOR_LOCK + Set 1 to lock core0 permission report registers. + 0 + 1 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_1 + Core0 permission report register 1. + 0x1A0 + 0x20 + 0x00000003 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear interrupt that core0 initiate illegal PIF bus access. + 0 + 1 + read-write + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_EN + Set 1 to enable interrupt that core0 initiate illegal PIF bus access. + 1 + 1 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_2 + Core0 permission report register 2. + 0x1A4 + 0x20 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR + Record core0 illegal access interrupt state. + 0 + 1 + read-only + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0 + Record hport information when core0 initiate illegal access. + 1 + 1 + read-only + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HSIZE + Record access type when core0 initate illegal access. + 2 + 3 + read-only + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE + Record access direction when core0 initiate illegal access. + 5 + 1 + read-only + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD + Record world information when core0 initiate illegal access. + 6 + 2 + read-only + + + + + CORE_0_PIF_PMS_MONITOR_3 + Core0 permission report register 3. + 0x1A8 + 0x20 + + + CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HADDR + Record address information when core0 initiate illegal access. + 0 + 32 + read-only + + + + + CORE_0_PIF_PMS_MONITOR_4 + Core0 permission report register 4. + 0x1AC + 0x20 + 0x00000003 + + + CORE_0_PIF_PMS_MONITOR_NONWORD_VIOLATE_CLR + Set 1 to clear interrupt that core0 initiate unsupported access type. + 0 + 1 + read-write + + + CORE_0_PIF_PMS_MONITOR_NONWORD_VIOLATE_EN + Set 1 to enable interrupt that core0 initiate unsupported access type. + 1 + 1 + read-write + + + + + CORE_0_PIF_PMS_MONITOR_5 + Core0 permission report register 5. + 0x1B0 + 0x20 + + + CORE_0_PIF_PMS_MONITOR_NONWORD_VIOLATE_INTR + Record core0 unsupported access type interrupt state. + 0 + 1 + read-only + + + CORE_0_PIF_PMS_MONITOR_NONWORD_VIOLATE_STATUS_HSIZE + Record access type when core0 initiate unsupported access type. + 1 + 2 + read-only + + + CORE_0_PIF_PMS_MONITOR_NONWORD_VIOLATE_STATUS_HWORLD + Record world information when core0 initiate unsupported access type. + 3 + 2 + read-only + + + + + CORE_0_PIF_PMS_MONITOR_6 + Core0 permission report register 6. + 0x1B4 + 0x20 + + + CORE_0_PIF_PMS_MONITOR_NONWORD_VIOLATE_STATUS_HADDR + Record address information when core0 initiate unsupported access type. + 0 + 32 + read-only + + + + + CORE_0_VECBASE_OVERRIDE_LOCK + core0 vecbase override configuration register 0 + 0x1B8 + 0x20 + + + CORE_0_VECBASE_OVERRIDE_LOCK + Set 1 to lock core0 vecbase configuration register + 0 + 1 + read-write + + + + + CORE_0_VECBASE_OVERRIDE_0 + core0 vecbase override configuration register 0 + 0x1BC + 0x20 + 0x00000001 + + + CORE_0_VECBASE_WORLD_MASK + Set 1 to mask world, then only world0_value will work. + 0 + 1 + read-write + + + + + CORE_0_VECBASE_OVERRIDE_1 + core0 vecbase override configuration register 1 + 0x1C0 + 0x20 + + + CORE_0_VECBASE_OVERRIDE_WORLD0_VALUE + world0 vecbase_override register, when core0 in world0 use this register to override vecbase register. + 0 + 22 + read-write + + + CORE_0_VECBASE_OVERRIDE_SEL + Set 0x3 to sel vecbase_override to override vecbase register. + 22 + 2 + read-write + + + + + CORE_0_VECBASE_OVERRIDE_2 + core0 vecbase override configuration register 1 + 0x1C4 + 0x20 + + + CORE_0_VECBASE_OVERRIDE_WORLD1_VALUE + world1 vecbase_override register, when core0 in world1 use this register to override vecbase register. + 0 + 22 + read-write + + + + + CORE_0_TOOMANYEXCEPTIONS_M_OVERRIDE_0 + core0 toomanyexception override configuration register 0. + 0x1C8 + 0x20 + + + CORE_0_TOOMANYEXCEPTIONS_M_OVERRIDE_LOCK + Set 1 to lock core0 toomanyexception override configuration register + 0 + 1 + read-write + + + + + CORE_0_TOOMANYEXCEPTIONS_M_OVERRIDE_1 + core0 toomanyexception override configuration register 1. + 0x1CC + 0x20 + 0x00000001 + + + CORE_0_TOOMANYEXCEPTIONS_M_OVERRIDE + Set 1 to mask toomanyexception. + 0 + 1 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_0 + Core1 access peripherals permission configuration register 0. + 0x1D0 + 0x20 + + + CORE_1_PIF_PMS_CONSTRAIN_LOCK + Set 1 to lock core1 pif permission configuration register. + 0 + 1 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_1 + Core1 access peripherals permission configuration register 1. + 0x1D4 + 0x20 + 0xFF33CFFF + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_UART + Core1 access uart permission in world0. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_G0SPI_1 + Core1 access g0spi_1 permission in world0. + 2 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_G0SPI_0 + Core1 access g0spi_0 permission in world0. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_GPIO + Core1 access gpio permission in world0. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_FE2 + Core1 access fe2 permission in world0. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_FE + Core1 access fe permission in world0. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_RTC + Core1 access rtc permission in world0. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_IO_MUX + Core1 access io_mux permission in world0. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_HINF + Core1 access hinf permission in world0. + 20 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_MISC + Core1 access misc permission in world0. + 24 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_I2C + Core1 access i2c permission in world0. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_I2S0 + Core1 access i2s0 permission in world0. + 28 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_UART1 + Core1 access uart1 permission in world0. + 30 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_2 + Core1 access peripherals permission configuration register 2. + 0x1D8 + 0x20 + 0xFFCFFFF3 + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_BT + Core1 access bt permission in world0. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_I2C_EXT0 + Core1 access i2c_ext0 permission in world0. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_UHCI0 + Core1 access uhci0 permission in world0. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SLCHOST + Core1 access slchost permission in world0. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_RMT + Core1 access rmt permission in world0. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_PCNT + Core1 access pcnt permission in world0. + 12 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SLC + Core1 access slc permission in world0. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_LEDC + Core1 access ledc permission in world0. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_BACKUP + Core1 access backup permission in world0. + 18 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_BB + Core1 access bb permission in world0. + 22 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_PWM0 + Core1 access pwm0 permission in world0. + 24 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_TIMERGROUP + Core1 access timergroup permission in world0. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_TIMERGROUP1 + Core1 access timergroup1 permission in world0. + 28 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SYSTIMER + Core1 access systimer permission in world0. + 30 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_3 + Core1 access peripherals permission configuration register 3. + 0x1DC + 0x20 + 0x3CC3FFFF + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SPI_2 + Core1 access spi_2 permission in world0. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SPI_3 + Core1 access spi_3 permission in world0. + 2 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_APB_CTRL + Core1 access apb_ctrl permission in world0. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_I2C_EXT1 + Core1 access i2c_ext1 permission in world0. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SDIO_HOST + Core1 access sdio_host permission in world0. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_CAN + Core1 access can permission in world0. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_PWM1 + Core1 access pwm1 permission in world0. + 12 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_I2S1 + Core1 access i2s1 permission in world0. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_UART2 + Core1 access uart2 permission in world0. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_RWBT + Core1 access rwbt permission in world0. + 22 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_WIFIMAC + Core1 access wifimac permission in world0. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_PWR + Core1 access pwr permission in world0. + 28 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_4 + Core1 access peripherals permission configuration register 4. + 0x1E0 + 0x20 + 0xFFFFFFFF + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_USB_DEVICE + Core1 access usb_device permission in world0. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_USB_WRAP + Core1 access usb_wrap permission in world0. + 2 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_CRYPTO_PERI + Core1 access crypto_peri permission in world0. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_CRYPTO_DMA + Core1 access crypto_dma permission in world0. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_APB_ADC + Core1 access apb_adc permission in world0. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_LCD_CAM + Core1 access lcd_cam permission in world0. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_BT_PWR + Core1 access bt_pwr permission in world0. + 12 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_USB + Core1 access usb permission in world0. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SYSTEM + Core1 access system permission in world0. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_SENSITIVE + Core1 access sensitive permission in world0. + 18 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_INTERRUPT + Core1 access interrupt permission in world0. + 20 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_DMA_COPY + Core1 access dma_copy permission in world0. + 22 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_CACHE_CONFIG + Core1 access cache_config permission in world0. + 24 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_AD + Core1 access ad permission in world0. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_DIO + Core1 access dio permission in world0. + 28 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_0_WORLD_CONTROLLER + Core1 access world_controller permission in world0. + 30 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_5 + Core1 access peripherals permission configuration register 5. + 0x1E4 + 0x20 + 0xFF33CFFF + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_UART + Core1 access uart permission in world1. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_G0SPI_1 + Core1 access g0spi_1 permission in world1. + 2 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_G0SPI_0 + Core1 access g0spi_0 permission in world1. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_GPIO + Core1 access gpio permission in world1. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_FE2 + Core1 access fe2 permission in world1. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_FE + Core1 access fe permission in world1. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_RTC + Core1 access rtc permission in world1. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_IO_MUX + Core1 access io_mux permission in world1. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_HINF + Core1 access hinf permission in world1. + 20 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_MISC + Core1 access misc permission in world1. + 24 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_I2C + Core1 access i2c permission in world1. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_I2S0 + Core1 access i2s0 permission in world1. + 28 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_UART1 + Core1 access uart1 permission in world1. + 30 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_6 + Core1 access peripherals permission configuration register 6. + 0x1E8 + 0x20 + 0xFFCFFFF3 + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_BT + Core1 access bt permission in world1. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_I2C_EXT0 + Core1 access i2c_ext0 permission in world1. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_UHCI0 + Core1 access uhci0 permission in world1. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SLCHOST + Core1 access slchost permission in world1. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_RMT + Core1 access rmt permission in world1. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_PCNT + Core1 access pcnt permission in world1. + 12 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SLC + Core1 access slc permission in world1. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_LEDC + Core1 access ledc permission in world1. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_BACKUP + Core1 access backup permission in world1. + 18 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_BB + Core1 access bb permission in world1. + 22 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_PWM0 + Core1 access pwm0 permission in world1. + 24 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_TIMERGROUP + Core1 access timergroup permission in world1. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_TIMERGROUP1 + Core1 access timergroup1 permission in world1. + 28 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SYSTIMER + Core1 access systimer permission in world1. + 30 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_7 + Core1 access peripherals permission configuration register 7. + 0x1EC + 0x20 + 0x3CC3FFFF + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SPI_2 + Core1 access spi_2 permission in world1. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SPI_3 + Core1 access spi_3 permission in world1. + 2 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_APB_CTRL + Core1 access apb_ctrl permission in world1. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_I2C_EXT1 + Core1 access i2c_ext1 permission in world1. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SDIO_HOST + Core1 access sdio_host permission in world1. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_CAN + Core1 access can permission in world1. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_PWM1 + Core1 access pwm1 permission in world1. + 12 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_I2S1 + Core1 access i2s1 permission in world1. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_UART2 + Core1 access uart2 permission in world1. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_RWBT + Core1 access rwbt permission in world1. + 22 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_WIFIMAC + Core1 access wifimac permission in world1. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_PWR + Core1 access pwr permission in world1. + 28 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_8 + Core1 access peripherals permission configuration register 8. + 0x1F0 + 0x20 + 0xFFFFFFFF + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_USB_DEVICE + Core1 access usb_device permission in world1. + 0 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_USB_WRAP + Core1 access usb_wrap permission in world1. + 2 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_CRYPTO_PERI + Core1 access crypto_peri permission in world1. + 4 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_CRYPTO_DMA + Core1 access crypto_dma permission in world1. + 6 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_APB_ADC + Core1 access apb_adc permission in world1. + 8 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_LCD_CAM + Core1 access lcd_cam permission in world1. + 10 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_BT_PWR + Core1 access bt_pwr permission in world1. + 12 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_USB + Core1 access usb permission in world1. + 14 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SYSTEM + Core1 access system permission in world1. + 16 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_SENSITIVE + Core1 access sensitive permission in world1. + 18 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_INTERRUPT + Core1 access interrupt permission in world1. + 20 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_DMA_COPY + Core1 access dma_copy permission in world1. + 22 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_CACHE_CONFIG + Core1 access cache_config permission in world1. + 24 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_AD + Core1 access ad permission in world1. + 26 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_DIO + Core1 access dio permission in world1. + 28 + 2 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_WORLD_1_WORLD_CONTROLLER + Core1 access world_controller permission in world1. + 30 + 2 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_9 + Core1 access peripherals permission configuration register 9. + 0x1F4 + 0x20 + 0x003FFFFF + + + CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0 + RTCFast memory split address in world 0 for core1. + 0 + 11 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1 + RTCFast memory split address in world 1 for core1. + 11 + 11 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_10 + core1 access peripherals permission configuration register 10. + 0x1F8 + 0x20 + 0x00000FFF + + + CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L + RTCFast memory low region permission in world 0 for core1. + 0 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H + RTCFast memory high region permission in world 0 for core1. + 3 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L + RTCFast memory low region permission in world 1 for core1. + 6 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H + RTCFast memory high region permission in world 1 for core1. + 9 + 3 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_11 + core1 access peripherals permission configuration register 11. + 0x1FC + 0x20 + 0x003FFFFF + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_0_SPLTADDR_WORLD_0 + RTCSlow_0 memory split address in world 0 for core1. + 0 + 11 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_0_SPLTADDR_WORLD_1 + RTCSlow_0 memory split address in world 1 for core1. + 11 + 11 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_12 + core1 access peripherals permission configuration register 12. + 0x200 + 0x20 + 0x00000FFF + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_0_L + RTCSlow_0 memory low region permission in world 0 for core1. + 0 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_0_H + RTCSlow_0 memory high region permission in world 0 for core1. + 3 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_1_L + RTCSlow_0 memory low region permission in world 1 for core1. + 6 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_0_WORLD_1_H + RTCSlow_0 memory high region permission in world 1 for core1. + 9 + 3 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_13 + core1 access peripherals permission configuration register 13. + 0x204 + 0x20 + 0x003FFFFF + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_1_SPLTADDR_WORLD_0 + RTCSlow_1 memory split address in world 0 for core1. + 0 + 11 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_1_SPLTADDR_WORLD_1 + RTCSlow_1 memory split address in world 1 for core1. + 11 + 11 + read-write + + + + + CORE_1_PIF_PMS_CONSTRAIN_14 + core1 access peripherals permission configuration register 14. + 0x208 + 0x20 + 0x00000FFF + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_0_L + RTCSlow_1 memory low region permission in world 0 for core1. + 0 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_0_H + RTCSlow_1 memory high region permission in world 0 for core1. + 3 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_1_L + RTCSlow_1 memory low region permission in world 1 for core1. + 6 + 3 + read-write + + + CORE_1_PIF_PMS_CONSTRAIN_RTCSLOW_1_WORLD_1_H + RTCSlow_1 memory high region permission in world 1 for core1. + 9 + 3 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_0 + core1 region permission register 0. + 0x20C + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_LOCK + Set 1 to lock core1 region permission registers. + 0 + 1 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_1 + core1 region permission register 1. + 0x210 + 0x20 + 0x003FFFFF + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_0 + Region 0 permission in world 0 for core1. + 0 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_1 + Region 1 permission in world 0 for core1. + 2 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_2 + Region 2 permission in world 0 for core1. + 4 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_3 + Region 3 permission in world 0 for core1. + 6 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_4 + Region 4 permission in world 0 for core1. + 8 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_5 + Region 5 permission in world 0 for core1. + 10 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_6 + Region 6 permission in world 0 for core1. + 12 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_7 + Region 7 permission in world 0 for core1. + 14 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_8 + Region 8 permission in world 0 for core1. + 16 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_9 + Region 9 permission in world 0 for core1. + 18 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_0_AREA_10 + Region 10 permission in world 0 for core1. + 20 + 2 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_2 + core1 region permission register 2. + 0x214 + 0x20 + 0x003FFFFF + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_0 + Region 0 permission in world 1 for core1. + 0 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_1 + Region 1 permission in world 1 for core1. + 2 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_2 + Region 2 permission in world 1 for core1. + 4 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_3 + Region 3 permission in world 1 for core1. + 6 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_4 + Region 4 permission in world 1 for core1. + 8 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_5 + Region 5 permission in world 1 for core1. + 10 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_6 + Region 6 permission in world 1 for core1. + 12 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_7 + Region 7 permission in world 1 for core1. + 14 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_8 + Region 8 permission in world 1 for core1. + 16 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_9 + Region 9 permission in world 1 for core1. + 18 + 2 + read-write + + + CORE_1_REGION_PMS_CONSTRAIN_WORLD_1_AREA_10 + Region 10 permission in world 1 for core1. + 20 + 2 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_3 + core1 region permission register 3. + 0x218 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_0 + Region 0 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_4 + core1 region permission register 4. + 0x21C + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_1 + Region 0 end address and Region 1 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_5 + core1 region permission register 5. + 0x220 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_2 + Region 1 end address and Region 2 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_6 + core1 region permission register 6. + 0x224 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_3 + Region 2 end address and Region 3 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_7 + core1 region permission register 7. + 0x228 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_4 + Region 3 end address and Region 4 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_8 + core1 region permission register 8. + 0x22C + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_5 + Region 4 end address and Region 5 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_9 + core1 region permission register 9. + 0x230 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_6 + Region 5 end address and Region 6 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_10 + core1 region permission register 10. + 0x234 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_7 + Region 6 end address and Region 7 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_11 + core1 region permission register 11. + 0x238 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_8 + Region 7 end address and Region 8 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_12 + core1 region permission register 12. + 0x23C + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_9 + Region 8 end address and Region 9 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_13 + core1 region permission register 13. + 0x240 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_10 + Region 9 end address and Region 10 start address for core1. + 0 + 30 + read-write + + + + + CORE_1_REGION_PMS_CONSTRAIN_14 + core1 region permission register 14. + 0x244 + 0x20 + + + CORE_1_REGION_PMS_CONSTRAIN_ADDR_11 + Region 10 end address for core1. + 0 + 30 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_0 + core1 permission report register 0. + 0x248 + 0x20 + + + CORE_1_PIF_PMS_MONITOR_LOCK + Set 1 to lock core1 permission report registers. + 0 + 1 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_1 + core1 permission report register 1. + 0x24C + 0x20 + 0x00000003 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear interrupt that core1 initiate illegal PIF bus access. + 0 + 1 + read-write + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_EN + Set 1 to enable interrupt that core1 initiate illegal PIF bus access. + 1 + 1 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_2 + core1 permission report register 2. + 0x250 + 0x20 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_INTR + Record core1 illegal access interrupt state. + 0 + 1 + read-only + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0 + Record hport information when core1 initiate illegal access. + 1 + 1 + read-only + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HSIZE + Record access type when core1 initate illegal access. + 2 + 3 + read-only + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE + Record access direction when core1 initiate illegal access. + 5 + 1 + read-only + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD + Record world information when core1 initiate illegal access. + 6 + 2 + read-only + + + + + CORE_1_PIF_PMS_MONITOR_3 + core1 permission report register 3. + 0x254 + 0x20 + + + CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HADDR + Record address information when core1 initiate illegal access. + 0 + 32 + read-only + + + + + CORE_1_PIF_PMS_MONITOR_4 + core1 permission report register 4. + 0x258 + 0x20 + 0x00000003 + + + CORE_1_PIF_PMS_MONITOR_NONWORD_VIOLATE_CLR + Set 1 to clear interrupt that core1 initiate unsupported access type. + 0 + 1 + read-write + + + CORE_1_PIF_PMS_MONITOR_NONWORD_VIOLATE_EN + Set 1 to enable interrupt that core1 initiate unsupported access type. + 1 + 1 + read-write + + + + + CORE_1_PIF_PMS_MONITOR_5 + core1 permission report register 5. + 0x25C + 0x20 + + + CORE_1_PIF_PMS_MONITOR_NONWORD_VIOLATE_INTR + Record core1 unsupported access type interrupt state. + 0 + 1 + read-only + + + CORE_1_PIF_PMS_MONITOR_NONWORD_VIOLATE_STATUS_HSIZE + Record access type when core1 initiate unsupported access type. + 1 + 2 + read-only + + + CORE_1_PIF_PMS_MONITOR_NONWORD_VIOLATE_STATUS_HWORLD + Record world information when core1 initiate unsupported access type. + 3 + 2 + read-only + + + + + CORE_1_PIF_PMS_MONITOR_6 + core1 permission report register 6. + 0x260 + 0x20 + + + CORE_1_PIF_PMS_MONITOR_NONWORD_VIOLATE_STATUS_HADDR + Record address information when core1 initiate unsupported access type. + 0 + 32 + read-only + + + + + CORE_1_VECBASE_OVERRIDE_LOCK + core1 vecbase override configuration register 0 + 0x264 + 0x20 + + + CORE_1_VECBASE_OVERRIDE_LOCK + Set 1 to lock core1 vecbase configuration register + 0 + 1 + read-write + + + + + CORE_1_VECBASE_OVERRIDE_0 + core1 vecbase override configuration register 0 + 0x268 + 0x20 + 0x00000001 + + + CORE_1_VECBASE_WORLD_MASK + Set 1 to mask world, then only world0_value will work. + 0 + 1 + read-write + + + + + CORE_1_VECBASE_OVERRIDE_1 + core1 vecbase override configuration register 1 + 0x26C + 0x20 + + + CORE_1_VECBASE_OVERRIDE_WORLD0_VALUE + world0 vecbase_override register, when core1 in world0 use this register to override vecbase register. + 0 + 22 + read-write + + + CORE_1_VECBASE_OVERRIDE_SEL + Set 0x3 to sel vecbase_override to override vecbase register. + 22 + 2 + read-write + + + + + CORE_1_VECBASE_OVERRIDE_2 + core1 vecbase override configuration register 1 + 0x270 + 0x20 + + + CORE_1_VECBASE_OVERRIDE_WORLD1_VALUE + world1 vecbase_override register, when core1 in world1 use this register to override vecbase register. + 0 + 22 + read-write + + + + + CORE_1_TOOMANYEXCEPTIONS_M_OVERRIDE_0 + core1 toomanyexception override configuration register 0. + 0x274 + 0x20 + + + CORE_1_TOOMANYEXCEPTIONS_M_OVERRIDE_LOCK + Set 1 to lock core1 toomanyexception override configuration register + 0 + 1 + read-write + + + + + CORE_1_TOOMANYEXCEPTIONS_M_OVERRIDE_1 + core1 toomanyexception override configuration register 1. + 0x278 + 0x20 + 0x00000001 + + + CORE_1_TOOMANYEXCEPTIONS_M_OVERRIDE + Set 1 to mask toomanyexception. + 0 + 1 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_0 + BackUp access peripherals permission configuration register 0. + 0x27C + 0x20 + + + BACKUP_BUS_PMS_CONSTRAIN_LOCK + Set 1 to lock BackUp permission configuration registers. + 0 + 1 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_1 + BackUp access peripherals permission configuration register 1. + 0x280 + 0x20 + 0xFF33CFFF + + + BACKUP_BUS_PMS_CONSTRAIN_UART + BackUp access uart permission. + 0 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_G0SPI_1 + BackUp access g0spi_1 permission. + 2 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_G0SPI_0 + BackUp access g0spi_0 permission. + 4 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_GPIO + BackUp access gpio permission. + 6 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_FE2 + BackUp access fe2 permission. + 8 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_FE + BackUp access fe permission. + 10 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_RTC + BackUp access rtc permission. + 14 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_IO_MUX + BackUp access io_mux permission. + 16 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_HINF + BackUp access hinf permission. + 20 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_MISC + BackUp access misc permission. + 24 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_I2C + BackUp access i2c permission. + 26 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_I2S0 + BackUp access i2s0 permission. + 28 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_UART1 + BackUp access uart1 permission. + 30 + 2 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_2 + BackUp access peripherals permission configuration register 2. + 0x284 + 0x20 + 0xFFCFFFF3 + + + BACKUP_BUS_PMS_CONSTRAIN_BT + BackUp access bt permission. + 0 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_I2C_EXT0 + BackUp access i2c_ext0 permission. + 4 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_UHCI0 + BackUp access uhci0 permission. + 6 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SLCHOST + BackUp access slchost permission. + 8 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_RMT + BackUp access rmt permission. + 10 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_PCNT + BackUp access pcnt permission. + 12 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SLC + BackUp access slc permission. + 14 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_LEDC + BackUp access ledc permission. + 16 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_BACKUP + BackUp access backup permission. + 18 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_BB + BackUp access bb permission. + 22 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_PWM0 + BackUp access pwm0 permission. + 24 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_TIMERGROUP + BackUp access timergroup permission. + 26 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_TIMERGROUP1 + BackUp access timergroup1 permission. + 28 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SYSTIMER + BackUp access systimer permission. + 30 + 2 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_3 + BackUp access peripherals permission configuration register 3. + 0x288 + 0x20 + 0x3CC3FFFF + + + BACKUP_BUS_PMS_CONSTRAIN_SPI_2 + BackUp access spi_2 permission. + 0 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SPI_3 + BackUp access spi_3 permission. + 2 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_APB_CTRL + BackUp access apb_ctrl permission. + 4 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_I2C_EXT1 + BackUp access i2c_ext1 permission. + 6 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SDIO_HOST + BackUp access sdio_host permission. + 8 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_CAN + BackUp access can permission. + 10 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_PWM1 + BackUp access pwm1 permission. + 12 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_I2S1 + BackUp access i2s1 permission. + 14 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_UART2 + BackUp access uart2 permission. + 16 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_RWBT + BackUp access rwbt permission. + 22 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_WIFIMAC + BackUp access wifimac permission. + 26 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_PWR + BackUp access pwr permission. + 28 + 2 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_4 + BackUp access peripherals permission configuration register 4. + 0x28C + 0x20 + 0xFFFFFFFF + + + BACKUP_BUS_PMS_CONSTRAIN_USB_DEVICE + BackUp access usb_device permission. + 0 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_USB_WRAP + BackUp access usb_wrap permission. + 2 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_CRYPTO_PERI + BackUp access crypto_peri permission. + 4 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_CRYPTO_DMA + BackUp access crypto_dma permission. + 6 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_APB_ADC + BackUp access apb_adc permission. + 8 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_LCD_CAM + BackUp access lcd_cam permission. + 10 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_BT_PWR + BackUp access bt_pwr permission. + 12 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_USB + BackUp access usb permission. + 14 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SYSTEM + BackUp access system permission. + 16 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_SENSITIVE + BackUp access sensitive permission. + 18 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_INTERRUPT + BackUp access interrupt permission. + 20 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_DMA_COPY + BackUp access dma_copy permission. + 22 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_CACHE_CONFIG + BackUp access cache_config permission. + 24 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_AD + BackUp access ad permission. + 26 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_DIO + BackUp access dio permission. + 28 + 2 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_WORLD_CONTROLLER + BackUp access world_controller permission. + 30 + 2 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_5 + BackUp access peripherals permission configuration register 5. + 0x290 + 0x20 + 0x000007FF + + + BACKUP_BUS_PMS_CONSTRAIN_RTCFAST_SPLTADDR + BackUp access rtcfast_spltaddr permission. + 0 + 11 + read-write + + + + + BACKUP_BUS_PMS_CONSTRAIN_6 + BackUp access peripherals permission configuration register 6. + 0x294 + 0x20 + 0x0000003F + + + BACKUP_BUS_PMS_CONSTRAIN_RTCFAST_L + BackUp access rtcfast_l permission. + 0 + 3 + read-write + + + BACKUP_BUS_PMS_CONSTRAIN_RTCFAST_H + BackUp access rtcfast_h permission. + 3 + 3 + read-write + + + + + BACKUP_BUS_PMS_MONITOR_0 + BackUp permission report register 0. + 0x298 + 0x20 + + + BACKUP_BUS_PMS_MONITOR_LOCK + Set 1 to lock BackUp permission report registers. + 0 + 1 + read-write + + + + + BACKUP_BUS_PMS_MONITOR_1 + BackUp permission report register 1. + 0x29C + 0x20 + 0x00000003 + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_CLR + Set 1 to clear interrupt that BackUp initiate illegal access. + 0 + 1 + read-write + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_EN + Set 1 to enable interrupt that BackUp initiate illegal access. + 1 + 1 + read-write + + + + + BACKUP_BUS_PMS_MONITOR_2 + BackUp permission report register 2. + 0x2A0 + 0x20 + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_INTR + Record BackUp illegal access interrupt state. + 0 + 1 + read-only + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_STATUS_HTRANS + Record htrans when BackUp initate illegal access. + 1 + 2 + read-only + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_STATUS_HSIZE + Record access type when BackUp initate illegal access. + 3 + 3 + read-only + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_STATUS_HWRITE + Record access direction when BackUp initiate illegal access. + 6 + 1 + read-only + + + + + BACKUP_BUS_PMS_MONITOR_3 + BackUp permission report register 3. + 0x2A4 + 0x20 + + + BACKUP_BUS_PMS_MONITOR_VIOLATE_HADDR + Record address information when BackUp initiate illegal access. + 0 + 32 + read-only + + + + + EDMA_BOUNDARY_LOCK + EDMA boundary lock register. + 0x2A8 + 0x20 + + + EDMA_BOUNDARY_LOCK + Set 1 to lock EDMA boundary registers. + 0 + 1 + read-write + + + + + EDMA_BOUNDARY_0 + EDMA boundary 0 configuration + 0x2AC + 0x20 + + + EDMA_BOUNDARY_0 + This field is used to configure the boundary 0 of external RAM. The unit is 4K. For example, set this field to 0x80, then the address boundary 0 would be 0x3C080000 (0x3C000000 + 0x80 * 4K). + 0 + 14 + read-write + + + + + EDMA_BOUNDARY_1 + EDMA boundary 1 configuration + 0x2B0 + 0x20 + 0x00002000 + + + EDMA_BOUNDARY_1 + This field is used to configure the boundary 1 of external RAM. The unit is 4K. For example, set this field to 0x80, then the address boundary 0 would be 0x3C080000 (0x3C000000 + 0x80 * 4K). + 0 + 14 + read-write + + + + + EDMA_BOUNDARY_2 + EDMA boundary 2 configuration + 0x2B4 + 0x20 + 0x00002000 + + + EDMA_BOUNDARY_2 + This field is used to configure the boundary 2 of external RAM. The unit is 4K. For example, set this field to 0x80, then the address boundary 0 would be 0x3C080000 (0x3C000000 + 0x80 * 4K). + 0 + 14 + read-write + + + + + EDMA_PMS_SPI2_LOCK + EDMA-SPI2 permission lock register. + 0x2B8 + 0x20 + + + EDMA_PMS_SPI2_LOCK + Set 1 to lock EDMA-SPI2 permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_SPI2 + EDMA-SPI2 permission control register. + 0x2BC + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of SPI2 accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of SPI2 accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_SPI3_LOCK + EDMA-SPI3 permission lock register. + 0x2C0 + 0x20 + + + EDMA_PMS_SPI3_LOCK + Set 1 to lock EDMA-SPI3 permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_SPI3 + EDMA-SPI3 permission control register. + 0x2C4 + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of SPI3 accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of SPI3 accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_UHCI0_LOCK + EDMA-UHCI0 permission lock register. + 0x2C8 + 0x20 + + + EDMA_PMS_UHCI0_LOCK + Set 1 to lock EDMA-UHCI0 permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_UHCI0 + EDMA-UHCI0 permission control register. + 0x2CC + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of UHCI0 accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of UHCI0 accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_I2S0_LOCK + EDMA-I2S0 permission lock register. + 0x2D0 + 0x20 + + + EDMA_PMS_I2S0_LOCK + Set 1 to lock EDMA-I2S0 permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_I2S0 + EDMA-I2S0 permission control register. + 0x2D4 + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of I2S0 accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of I2S0 accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_I2S1_LOCK + EDMA-I2S1 permission lock register. + 0x2D8 + 0x20 + + + EDMA_PMS_I2S1_LOCK + Set 1 to lock EDMA-I2S1 permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_I2S1 + EDMA-I2S1 permission control register. + 0x2DC + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of I2S1 accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of I2S1 accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_LCD_CAM_LOCK + EDMA-LCD/CAM permission lock register. + 0x2E0 + 0x20 + + + EDMA_PMS_LCD_CAM_LOCK + Set 1 to lock EDMA-LCD/CAM permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_LCD_CAM + EDMA-LCD/CAM permission control register. + 0x2E4 + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of LCD/CAM accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of LCD/CAM accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_AES_LOCK + EDMA-AES permission lock register. + 0x2E8 + 0x20 + + + EDMA_PMS_AES_LOCK + Set 1 to lock EDMA-AES permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_AES + EDMA-AES permission control register. + 0x2EC + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of AES accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of AES accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_SHA_LOCK + EDMA-SHA permission lock register. + 0x2F0 + 0x20 + + + EDMA_PMS_SHA_LOCK + Set 1 to lock EDMA-SHA permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_SHA + EDMA-SHA permission control register. + 0x2F4 + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of SHA accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of SHA accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_ADC_DAC_LOCK + EDMA-ADC/DAC permission lock register. + 0x2F8 + 0x20 + + + EDMA_PMS_ADC_DAC_LOCK + Set 1 to lock EDMA-ADC/DAC permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_ADC_DAC + EDMA-ADC/DAC permission control register. + 0x2FC + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of ADC/DAC accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of ADC/DAC accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + EDMA_PMS_RMT_LOCK + EDMA-RMT permission lock register. + 0x300 + 0x20 + + + EDMA_PMS_RMT_LOCK + Set 1 to lock EDMA-RMT permission control registers. + 0 + 1 + read-write + + + + + EDMA_PMS_RMT + EDMA-RMT permission control register. + 0x304 + 0x20 + 0x0000000F + + + ATTR1 + This field is used to configure the permission of RMT accessing address, which is larger than boundary 0 and less than boundary 1, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 0 + 2 + read-write + + + ATTR2 + This field is used to configure the permission of RMT accessing address, which is larger than boundary 1 and less than boundary 2, through EDMA. Bit 0: set this bit to enable read permission. Bit 1: set this bit to enable write permission. + 2 + 2 + read-write + + + + + CLOCK_GATE_REG + Sensitive module clock gate configuration register. + 0x308 + 0x20 + 0x00000001 + + + REG_CLK_EN + Set 1 to enable clock gate function. + 0 + 1 + read-write + + + + + RTC_PMS + RTC coprocessor permission register. + 0x30C + 0x20 + + + DIS_RTC_CPU + Set 1 to disable rtc coprocessor. + 0 + 1 + read-write + + + + + DATE + Sensitive version register. + 0xFFC + 0x20 + 0x02101280 + + + DATE + Sensitive Date register. + 0 + 28 + read-write + + + + + + + SHA + SHA (Secure Hash Algorithm) Accelerator + SHA + 0x6003B000 + + 0x0 + 0xB0 + registers + + + SHA + 78 + + + + MODE + Initial configuration register. + 0x0 + 0x20 + + + MODE + sha mode + 0 + 3 + read-write + + + + + T_STRING + SHA 512/t configuration register 0. + 0x4 + 0x20 + + + T_STRING + sha t_string(used if and only if mode == sha_256/t) + 0 + 32 + read-write + + + + + T_LENGTH + SHA 512/t configuration register 1. + 0x8 + 0x20 + + + T_LENGTH + sha t_length(used if and only if mode == sha_256/t) + 0 + 6 + read-write + + + + + DMA_BLOCK_NUM + DMA configuration register 0. + 0xC + 0x20 + + + DMA_BLOCK_NUM + dma-sha block number + 0 + 6 + read-write + + + + + START + Typical SHA configuration register 0. + 0x10 + 0x20 + + + START + reserved. + 1 + 31 + read-only + + + + + CONTINUE + Typical SHA configuration register 1. + 0x14 + 0x20 + + + CONTINUE + reserved. + 1 + 31 + read-only + + + + + BUSY + Busy register. + 0x18 + 0x20 + + + STATE + sha busy state. 1'b0: idle 1'b1: busy + 0 + 1 + read-only + + + + + DMA_START + DMA configuration register 1. + 0x1C + 0x20 + + + DMA_START + start dma-sha + 0 + 1 + write-only + + + + + DMA_CONTINUE + DMA configuration register 2. + 0x20 + 0x20 + + + DMA_CONTINUE + continue dma-sha + 0 + 1 + write-only + + + + + CLEAR_IRQ + Interrupt clear register. + 0x24 + 0x20 + + + CLEAR_INTERRUPT + clear sha interrupt + 0 + 1 + write-only + + + + + IRQ_ENA + Interrupt enable register. + 0x28 + 0x20 + + + INTERRUPT_ENA + sha interrupt enable register. 1'b0: disable(default) 1'b1: enable + 0 + 1 + read-write + + + + + DATE + Date register. + 0x2C + 0x20 + 0x20190402 + + + DATE + sha date information/ sha version information + 0 + 30 + read-write + + + + + 64 + 0x1 + H_MEM[%s] + Sha H memory which contains intermediate hash or finial hash. + 0x40 + 0x8 + + + 64 + 0x1 + M_MEM[%s] + Sha M memory which contains message. + 0x80 + 0x8 + + + + + SPI0 + SPI (Serial Peripheral Interface) Controller + SPI0 + 0x60003000 + + 0x0 + 0x98 + registers + + + SPI_MEM_REJECT + 60 + + + + CTRL + SPI0 control register. + 0x8 + 0x20 + 0x002C2000 + + + FDUMMY_OUT + In the DUMMY phase the signal level of SPI bus is output by the SPI0 controller. + 3 + 1 + read-write + + + FDOUT_OCT + Set this bit to enable 8-bit-mode(8-bm) in DOUT phase. + 4 + 1 + read-write + + + FDIN_OCT + Set this bit to enable 8-bit-mode(8-bm) in DIN phase. + 5 + 1 + read-write + + + FADDR_OCT + Set this bit to enable 8-bit-mode(8-bm) in ADDR phase. + 6 + 1 + read-write + + + FCMD_DUAL + Set this bit to enable 2-bit-mode(2-bm) in CMD phase. + 7 + 1 + read-write + + + FCMD_QUAD + Set this bit to enable 4-bit-mode(4-bm) in CMD phase. + 8 + 1 + read-write + + + FCMD_OCT + Set this bit to enable 8-bit-mode(8-bm) in CMD phase. + 9 + 1 + read-write + + + FASTRD_MODE + This bit should be set when SPI_MEM_FREAD_QIO, SPI_MEM_FREAD_DIO, SPI_MEM_FREAD_QUAD or SPI_MEM_FREAD_DUAL is set. + 13 + 1 + read-write + + + FREAD_DUAL + In hardware 0x3B read operation, DIN phase apply 2 signals. 1: enable 0: disable. + 14 + 1 + read-write + + + Q_POL + The bit is used to set MISO line polarity, 1: high 0, low + 18 + 1 + read-write + + + D_POL + The bit is used to set MOSI line polarity, 1: high 0, low + 19 + 1 + read-write + + + FREAD_QUAD + In hardware 0x6B read operation, DIN phase apply 4 signals(4-bit-mode). 1: enable 0: disable. + 20 + 1 + read-write + + + WP + Write protect signal output when SPI is idle. 1: output high, 0: output low. + 21 + 1 + read-write + + + FREAD_DIO + In hardware 0xBB read operation, ADDR phase and DIN phase apply 2 signals(2-bit-mode). 1: enable 0: disable. + 23 + 1 + read-write + + + FREAD_QIO + In hardware 0xEB read operation, ADDR phase and DIN phase apply 4 signals(4-bit-mode). 1: enable 0: disable. + 24 + 1 + read-write + + + + + CTRL1 + SPI0 control 1 register. + 0xC + 0x20 + + + CLK_MODE + SPI Bus clock (SPI_CLK) mode bits. 0: SPI Bus clock (SPI_CLK) is off when CS inactive 1: SPI_CLK is delayed one cycle after SPI_CS inactive 2: SPI_CLK is delayed two cycles after SPI_CS inactive 3: SPI_CLK is always on. + 0 + 2 + read-write + + + RXFIFO_RST + SPI0 RX FIFO reset signal. Set this bit and clear it before SPI0 transfer starts. + 30 + 1 + read-write + + + + + CTRL2 + SPI0 control 2 register. + 0x10 + 0x20 + 0x00002C21 + + + CS_SETUP_TIME + (cycles-1) of PREP phase by SPI_CLK, which is the SPI_CS setup time. These bits are combined with SPI_MEM_CS_SETUP bit. + 0 + 5 + read-write + + + CS_HOLD_TIME + SPI Bus CS (SPI_CS) signal is delayed to inactive by SPI Bus clock (SPI_CLK), which is the SPI_CS hold time in non-ECC mode. These bits are combined with SPI_MEM_CS_HOLD bit. + 5 + 5 + read-write + + + ECC_CS_HOLD_TIME + SPI_MEM_CS_HOLD_TIME + SPI_MEM_ECC_CS_HOLD_TIME is the SPI_CS hold cycle in ECC mode when accessed flash. + 10 + 3 + read-write + + + ECC_SKIP_PAGE_CORNER + 1: MSPI skips page corner when accesses flash. 0: Not skip page corner when accesses flash. + 13 + 1 + read-write + + + ECC_16TO18_BYTE_EN + Set this bit to enable MSPI ECC 16 bytes data with 2 ECC bytes mode when accesses flash. + 14 + 1 + read-write + + + CS_HOLD_DELAY + These bits are used to set the minimum CS high time tSHSL between SPI burst transfer when accesses to flash. tSHSL is (SPI_MEM_CS_HOLD_DELAY[5:0] + 1) MSPI core clock cycles. + 25 + 6 + read-write + + + SYNC_RESET + The FSM will be reset. + 31 + 1 + read-write + + + + + CLOCK + SPI_CLK clock division register when SPI0 accesses to flash. + 0x14 + 0x20 + 0x00030103 + + + CLKCNT_L + It must equal to the value of SPI_MEM_CLKCNT_N. + 0 + 8 + read-write + + + CLKCNT_H + It must be a floor value of ((SPI_MEM_CLKCNT_N+1)/2-1). + 8 + 8 + read-write + + + CLKCNT_N + When SPI0 accesses flash, f_SPI_CLK = f_MSPI_CORE_CLK/(SPI_MEM_CLKCNT_N+1) + 16 + 8 + read-write + + + CLK_EQU_SYSCLK + When SPI0 accesses flash, set this bit in 1-division mode, f_SPI_CLK = f_MSPI_CORE_CLK. + 31 + 1 + read-write + + + + + USER + SPI0 user register. + 0x18 + 0x20 + + + CS_HOLD + Set this bit to keep SPI_CS low when MSPI is in DONE state. + 6 + 1 + read-write + + + CS_SETUP + Set this bit to keep SPI_CS low when MSPI is in PREP state. + 7 + 1 + read-write + + + CK_OUT_EDGE + This bit, combined with SPI_MEM_CK_IDLE_EDGE bit, is used to change the clock mode 0~3 of SPI_CLK. + 9 + 1 + read-write + + + USR_DUMMY_IDLE + SPI_CLK is disabled(No clock edges) in DUMMY phase when the bit is enable. + 26 + 1 + read-write + + + USR_DUMMY + This bit enable the DUMMY phase of an SPI transfer. + 29 + 1 + read-write + + + + + USER1 + SPI0 user1 register. + 0x1C + 0x20 + 0x5C000007 + + + USR_DUMMY_CYCLELEN + The SPI_CLK cycle length minus 1 of DUMMY phase. + 0 + 6 + read-write + + + USR_ADDR_BITLEN + The length in bits of ADDR phase. The register value shall be (bit_num-1). + 26 + 6 + read-write + + + + + USER2 + SPI0 user2 register. + 0x20 + 0x20 + 0x70000000 + + + USR_COMMAND_VALUE + The value of user defined(USR) command. + 0 + 16 + read-write + + + USR_COMMAND_BITLEN + The length in bits of CMD phase. The register value shall be (bit_num-1) + 28 + 4 + read-write + + + + + RD_STATUS + SPI0 read control register. + 0x2C + 0x20 + + + WB_MODE + Mode bits in the flash fast read mode it is combined with SPI_MEM_FASTRD_MODE bit. + 16 + 8 + read-write + + + + + EXT_ADDR + SPI0 extended address register. + 0x30 + 0x20 + + + EXT_ADDR + The register are the higher 32bits in the 64 bits address mode. + 0 + 32 + read-write + + + + + MISC + SPI0 misc register + 0x34 + 0x20 + + + FSUB_PIN + Flash is connected to SPI SUBPIN bus. + 7 + 1 + read-write + + + SSUB_PIN + Ext_RAM is connected to SPI SUBPIN bus. + 8 + 1 + read-write + + + CK_IDLE_EDGE + 1: SPI_CLK line is high when idle. 0: SPI_CLK line is low when idle + 9 + 1 + read-write + + + CS_KEEP_ACTIVE + SPI_CS line keep low when the bit is set. + 10 + 1 + read-write + + + + + CACHE_FCTRL + SPI0 external RAM bit mode control register. + 0x3C + 0x20 + + + CACHE_REQ_EN + Set this bit to enable Cache's access and SPI0's transfer. + 0 + 1 + read-write + + + CACHE_USR_CMD_4BYTE + Set this bit to enable SPI0 read flash with 32 bits address. The value of SPI_MEM_USR_ADDR_BITLEN should be 31. + 1 + 1 + read-write + + + CACHE_FLASH_USR_CMD + 1: The command value of SPI0 reads flash is SPI_MEM_USR_COMMAND_VALUE. 0: Hardware read command value, controlled by SPI_MEM_FREAD_QIO, SPI_MEM_FREAD_DIO, SPI_MEM_FREAD_QUAD, SPI_MEM_FREAD_DUAL and SPI_MEM_FASTRD_MODE bits. + 2 + 1 + read-write + + + FDIN_DUAL + When SPI0 accesses to flash, set this bit to enable 2-bm in DIN phase. + 3 + 1 + read-write + + + FDOUT_DUAL + When SPI0 accesses to flash, set this bit to enable 2-bm in DOUT phase. + 4 + 1 + read-write + + + FADDR_DUAL + When SPI0 accesses to flash, set this bit to enable 2-bm in ADDR phase. + 5 + 1 + read-write + + + FDIN_QUAD + When SPI0 accesses to flash, set this bit to enable 4-bm in DIN phase. + 6 + 1 + read-write + + + FDOUT_QUAD + When SPI0 accesses to flash, set this bit to enable 4-bm in DOUT phase. + 7 + 1 + read-write + + + FADDR_QUAD + When SPI0 accesses to flash, set this bit to enable 4-bm in ADDR phase. + 8 + 1 + read-write + + + + + CACHE_SCTRL + SPI0 external RAM control register + 0x40 + 0x20 + 0x0055C070 + + + CACHE_USR_SCMD_4BYTE + Set this bit to enable SPI0 read Ext_RAM with 32 bits address. The value of SPI_MEM_SRAM_ADDR_BITLEN should be 31. + 0 + 1 + read-write + + + USR_SRAM_DIO + Set the bit to enable 2-bm in all the phases of SPI0 Ext_RAM transfer. + 1 + 1 + read-write + + + USR_SRAM_QIO + Set the bit to enable QPI mode in all SPI0 Ext_RAM transfer. + 2 + 1 + read-write + + + USR_WR_SRAM_DUMMY + When SPI0 accesses to Ext_RAM, set this bit to enable DUMMY phase in write operations. + 3 + 1 + read-write + + + USR_RD_SRAM_DUMMY + When SPI0 accesses to Ext_RAM, set this bit to enable DUMMY phase in read operations. + 4 + 1 + read-write + + + CACHE_SRAM_USR_RCMD + 1: The command value of SPI0 read Ext_RAM is SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE. 0: The value is 0x2. + 5 + 1 + read-write + + + SRAM_RDUMMY_CYCLELEN + When SPI0 accesses to Ext_RAM, it is the SPI_CLK cycles minus 1 of DUMMY phase in read data transfer. + 6 + 6 + read-write + + + SRAM_ADDR_BITLEN + When SPI0 accesses to Ext_RAM, it is the length in bits of ADDR phase. The register value shall be (bit_num-1). + 14 + 6 + read-write + + + CACHE_SRAM_USR_WCMD + 1: The command value of SPI0 write Ext_RAM is SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE. 0: The value is 0x3. + 20 + 1 + read-write + + + SRAM_OCT + Set the bit to enable OPI mode in all SPI0 Ext_RAM transfer. + 21 + 1 + read-write + + + SRAM_WDUMMY_CYCLELEN + When SPI0 accesses to Ext_RAM, it is the SPI_CLK cycles minus 1 of DUMMY phase in write data transfer. + 22 + 6 + read-write + + + + + SRAM_CMD + SPI0 external RAM mode control register + 0x44 + 0x20 + + + SCLK_MODE + SPI_CLK mode bits when SPI0 accesses to Ext_RAM. 0: SPI_CLK is off when CS inactive 1: SPI_CLK is delayed one cycle after CS inactive 2: SPI_CLK is delayed two cycles after CS inactive 3: SPI_CLK is always on. + 0 + 2 + read-write + + + SWB_MODE + Mode bits when SPI0 accesses to Ext_RAM. + 2 + 8 + read-write + + + SDIN_DUAL + When SPI0 accesses to Ext_RAM, set this bit to enable 2-bm in DIN phase. + 10 + 1 + read-write + + + SDOUT_DUAL + When SPI0 accesses to Ext_RAM, set this bit to enable 2-bm in DOUT phase. + 11 + 1 + read-write + + + SADDR_DUAL + When SPI0 accesses to Ext_RAM, set this bit to enable 2-bm in ADDR phase. + 12 + 1 + read-write + + + SCMD_DUAL + When SPI0 accesses to Ext_RAM, set this bit to enable 2-bm in CMD phase. + 13 + 1 + read-write + + + SDIN_QUAD + When SPI0 accesses to Ext_RAM, set this bit to enable 4-bm in DIN phase. + 14 + 1 + read-write + + + SDOUT_QUAD + When SPI0 accesses to Ext_RAM, set this bit to enable 4-bm in DOUT phase. + 15 + 1 + read-write + + + SADDR_QUAD + When SPI0 accesses to Ext_RAM, set this bit to enable 4-bm in ADDR phase. + 16 + 1 + read-write + + + SCMD_QUAD + When SPI0 accesses to Ext_RAM, set this bit to enable 4-bm in CMD phase. + 17 + 1 + read-write + + + SDIN_OCT + When SPI0 accesses to Ext_RAM, set this bit to enable 8-bm in DIN phase. + 18 + 1 + read-write + + + SDOUT_OCT + When SPI0 accesses to Ext_RAM, set this bit to enable 8-bm in DOUT phase. + 19 + 1 + read-write + + + SADDR_OCT + When SPI0 accesses to Ext_RAM, set this bit to enable 8-bm in ADDR phase. + 20 + 1 + read-write + + + SCMD_OCT + When SPI0 accesses to Ext_RAM, set this bit to enable 8-bm in CMD phase. + 21 + 1 + read-write + + + SDUMMY_OUT + When SPI0 accesses to Ext_RAM, in the DUMMY phase the signal level of SPI bus is output by the SPI0 controller. + 22 + 1 + read-write + + + + + SRAM_DRD_CMD + SPI0 external RAM DDR read command control register + 0x48 + 0x20 + + + CACHE_SRAM_USR_RD_CMD_VALUE + When SPI0 reads Ext_RAM, it is the command value of CMD phase. + 0 + 16 + read-write + + + CACHE_SRAM_USR_RD_CMD_BITLEN + When SPI0 reads Ext_RAM, it is the length in bits of CMD phase. The register value shall be (bit_num-1). + 28 + 4 + read-write + + + + + SRAM_DWR_CMD + SPI0 external RAM DDR write command control register + 0x4C + 0x20 + + + CACHE_SRAM_USR_WR_CMD_VALUE + When SPI0 writes Ext_RAM, it is the command value of CMD phase. + 0 + 16 + read-write + + + CACHE_SRAM_USR_WR_CMD_BITLEN + When SPI0 writes Ext_RAM, it is the length in bits of CMD phase. The register value shall be (bit_num-1). + 28 + 4 + read-write + + + + + SRAM_CLK + SPI_CLK clock division register when SPI0 accesses to Ext_RAM. + 0x50 + 0x20 + 0x00030103 + + + SCLKCNT_L + It must equal to the value of SPI_MEM_SCLKCNT_N. + 0 + 8 + read-write + + + SCLKCNT_H + It must be a floor value of ((SPI_MEM_SCLKCNT_N+1)/2-1). + 8 + 8 + read-write + + + SCLKCNT_N + When SPI0 accesses to Ext_RAM, f_SPI_CLK = f_MSPI_CORE_CLK/(SPI_MEM_SCLKCNT_N+1) + 16 + 8 + read-write + + + SCLK_EQU_SYSCLK + When SPI0 accesses to Ext_RAM, set this bit in 1-division mode, f_SPI_CLK = f_MSPI_CORE_CLK. + 31 + 1 + read-write + + + + + FSM + SPI0 state machine(FSM) status register. + 0x54 + 0x20 + + + ST + The status of SPI0 state machine. 0: idle state(IDLE), 1: preparation state(PREP), 2: send command state(CMD), 3: send address state(ADDR), 4: red data state(DIN), 5:write data state(DOUT), 6: wait state(DUMMY), 7: done state(DONE). + 0 + 3 + read-only + + + + + TIMING_CALI + SPI0 timing compensation register when accesses to flash. + 0xA8 + 0x20 + + + TIMING_CLK_ENA + Set this bit to power on HCLK. When PLL is powered on, the frequency of HCLK equals to that of PLL. Otherwise, the frequency equals to that of XTAL. + 0 + 1 + read-write + + + TIMING_CALI + Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operations. + 1 + 1 + read-write + + + EXTRA_DUMMY_CYCLELEN + Extra SPI_CLK cycles added in DUMMY phase for timing compensation, when SPI0 accesses to flash. Active when SPI_MEM_TIMING_CALI bit is set. + 2 + 3 + read-write + + + + + DIN_MODE + MSPI input timing delay mode control register when accesses to flash. + 0xAC + 0x20 + + + DIN0_MODE + SPI_D input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN0_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN0_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN0_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN0_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN0_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 0 + 3 + read-write + + + DIN1_MODE + SPI_Q input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN3_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN3_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN3_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN3_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN3_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 3 + 3 + read-write + + + DIN2_MODE + SPI_WP input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN6_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN6_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN6_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN6_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN6_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 6 + 3 + read-write + + + DIN3_MODE + SPI_HD input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN9_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN9_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN9_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN9_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN9_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 9 + 3 + read-write + + + DIN4_MODE + SPI_IO4 input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN12_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN12_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN12_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN12_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN12_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 12 + 3 + read-write + + + DIN5_MODE + SPI_IO5 input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN15_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN15_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN15_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN15_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN15_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 15 + 3 + read-write + + + DIN6_MODE + SPI_IO6 input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN18_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN18_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN18_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN18_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN18_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 18 + 3 + read-write + + + DIN7_MODE + SPI_IO7 input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DIN21_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DIN21_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DIN21_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DIN21_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DIN21_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 21 + 3 + read-write + + + DINS_MODE + SPI_DQS input delay mode. 0: No delay. 1: Delay for (SPI_MEM_DINS_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_MEM_DINS_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_MEM_DINS_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_MEM_DINS_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_MEM_DINS_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 24 + 3 + read-write + + + + + DIN_NUM + MSPI input timing delay number control register when accesses to flash. + 0xB0 + 0x20 + + + DIN0_NUM + SPI_D input delay number. + 0 + 2 + read-write + + + DIN1_NUM + SPI_Q input delay number. + 2 + 2 + read-write + + + DIN2_NUM + SPI_WP input delay number. + 4 + 2 + read-write + + + DIN3_NUM + SPI_HD input delay number. + 6 + 2 + read-write + + + DIN4_NUM + SPI_IO4 input delay number. + 8 + 2 + read-write + + + DIN5_NUM + SPI_IO5 input delay number. + 10 + 2 + read-write + + + DIN6_NUM + SPI_IO6 input delay number. + 12 + 2 + read-write + + + DIN7_NUM + SPI_IO7 input delay number. + 14 + 2 + read-write + + + DINS_NUM + SPI_DQS input delay number. + 16 + 2 + read-write + + + + + DOUT_MODE + MSPI output timing delay mode control register when accesses to flash. + 0xB4 + 0x20 + + + DOUT0_MODE + SPI_D output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 0 + 1 + read-write + + + DOUT1_MODE + SPI_Q output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 1 + 1 + read-write + + + DOUT2_MODE + SPI_WP output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 2 + 1 + read-write + + + DOUT3_MODE + SPI_HD output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 3 + 1 + read-write + + + DOUT4_MODE + SPI_IO4 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 4 + 1 + read-write + + + DOUT5_MODE + SPI_IO5 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 5 + 1 + read-write + + + DOUT6_MODE + SPI_IO6 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 6 + 1 + read-write + + + DOUT7_MODE + SPI_IO7 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 7 + 1 + read-write + + + DOUTS_MODE + SPI_DQS output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 8 + 1 + read-write + + + + + SPI_SMEM_TIMING_CALI + SPI0 Ext_RAM timing compensation register. + 0xBC + 0x20 + + + SPI_SMEM_TIMING_CLK_ENA + Set this bit to power on HCLK. When PLL is powered on, the frequency of HCLK equals to that of PLL. Otherwise, the frequency equals to that of XTAL. + 0 + 1 + read-write + + + SPI_SMEM_TIMING_CALI + Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operations. + 1 + 1 + read-write + + + SPI_SMEM_EXTRA_DUMMY_CYCLELEN + Extra SPI_CLK cycles added in DUMMY phase for timing compensation, when SPI0 accesses to Ext_RAM. Active when SPI_SMEM_TIMING_CALI bit is set. + 2 + 3 + read-write + + + + + SPI_SMEM_DIN_MODE + MSPI input timing delay mode control register when accesses to Ext_RAM. + 0xC0 + 0x20 + + + SPI_SMEM_DIN0_MODE + SPI_D input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN0_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN0_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN0_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN0_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN0_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 0 + 3 + read-write + + + SPI_SMEM_DIN1_MODE + SPI_Q input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN3_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN3_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN3_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN3_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN3_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 3 + 3 + read-write + + + SPI_SMEM_DIN2_MODE + SPI_WP input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN6_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN6_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN6_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN6_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN6_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 6 + 3 + read-write + + + SPI_SMEM_DIN3_MODE + SPI_HD input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN9_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN9_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN9_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN9_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN9_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 9 + 3 + read-write + + + SPI_SMEM_DIN4_MODE + SPI_IO4 input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN12_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN12_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN12_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN12_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN12_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 12 + 3 + read-write + + + SPI_SMEM_DIN5_MODE + SPI_IO5 input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN15_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN15_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN15_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN15_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN15_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 15 + 3 + read-write + + + SPI_SMEM_DIN6_MODE + SPI_IO6 input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN18_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN18_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN18_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN18_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN18_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 18 + 3 + read-write + + + SPI_SMEM_DIN7_MODE + SPI_IO7 input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DIN21_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DIN21_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DIN21_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DIN21_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DIN21_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 21 + 3 + read-write + + + SPI_SMEM_DINS_MODE + SPI_DQS input delay mode. 0: No delay. 1: Delay for (SPI_SMEM_DINS_NUM+1) cycles at MSPI_CORE_CLK negative edge. 2: Delay for (SPI_SMEM_DINS_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK positive edge. 3: Delay for (SPI_SMEM_DINS_NUM+1) cycles at HCLK positive edge and one cycle at MSPI_CORE_CLK negative edge. 4: Delay for (SPI_SMEM_DINS_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK positive edge. 5: Delay for (SPI_SMEM_DINS_NUM+1) cycles at HCLK negative edge and one cycle at MSPI_CORE_CLK negative edge. + 24 + 3 + read-write + + + + + SPI_SMEM_DIN_NUM + MSPI input timing delay number control register when accesses to Ext_RAM. + 0xC4 + 0x20 + + + SPI_SMEM_DIN0_NUM + SPI_D input delay number. + 0 + 2 + read-write + + + SPI_SMEM_DIN1_NUM + SPI_Q input delay number. + 2 + 2 + read-write + + + SPI_SMEM_DIN2_NUM + SPI_WP input delay number. + 4 + 2 + read-write + + + SPI_SMEM_DIN3_NUM + SPI_HD input delay number. + 6 + 2 + read-write + + + SPI_SMEM_DIN4_NUM + SPI_IO4 input delay number. + 8 + 2 + read-write + + + SPI_SMEM_DIN5_NUM + SPI_IO5 input delay number. + 10 + 2 + read-write + + + SPI_SMEM_DIN6_NUM + SPI_IO6 input delay number. + 12 + 2 + read-write + + + SPI_SMEM_DIN7_NUM + SPI_IO7 input delay number. + 14 + 2 + read-write + + + SPI_SMEM_DINS_NUM + SPI_DQS input delay number. + 16 + 2 + read-write + + + + + SPI_SMEM_DOUT_MODE + MSPI output timing delay mode control register when accesses to Ext_RAM. + 0xC8 + 0x20 + + + SPI_SMEM_DOUT0_MODE + SPI_D output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 0 + 1 + read-write + + + SPI_SMEM_DOUT1_MODE + SPI_Q output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 1 + 1 + read-write + + + SPI_SMEM_DOUT2_MODE + SPI_WP output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 2 + 1 + read-write + + + SPI_SMEM_DOUT3_MODE + SPI_HD output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 3 + 1 + read-write + + + SPI_SMEM_DOUT4_MODE + SPI_IO4 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 4 + 1 + read-write + + + SPI_SMEM_DOUT5_MODE + SPI_IO5 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 5 + 1 + read-write + + + SPI_SMEM_DOUT6_MODE + SPI_IO6 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 6 + 1 + read-write + + + SPI_SMEM_DOUT7_MODE + SPI_IO7 output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 7 + 1 + read-write + + + SPI_SMEM_DOUTS_MODE + SPI_DQS output delay mode. 0: No delay. 1: Delay one cycle at MSPI_CORE_CLK negative edge. + 8 + 1 + read-write + + + + + ECC_CTRL + MSPI ECC control register + 0xCC + 0x20 + 0x0000000A + + + ECC_ERR_INT_NUM + Set the error times of MSPI ECC read to generate MSPI SPI_MEM_ECC_ERR_INT interrupt. + 0 + 8 + read-write + + + SPI_FMEM_ECC_ERR_INT_EN + Set this bit to calculate the error times of MSPI ECC read when accesses to flash. + 8 + 1 + read-write + + + + + ECC_ERR_ADDR + MSPI ECC error address register + 0xD0 + 0x20 + + + ECC_ERR_ADDR + These bits show the first MSPI ECC error address when SPI_FMEM_ECC_ERR_INT_EN/SPI_SMEM_ECC_ERR_INT_EN is set and accessed to flash/Ext_RAM, including ECC byte error and data error. It is cleared by when SPI_MEM_ECC_ERR_INT_CLR bit is set. + 0 + 32 + read-only + + + + + ECC_ERR_BIT + MSPI ECC error bits register + 0xD4 + 0x20 + + + ECC_DATA_ERR_BIT + It records the first ECC data error bit number when SPI_FMEM_ECC_ERR_INT_EN/SPI_SMEM_ECC_ERR_INT_EN is set and accessed to flash/Ext_RAM. The value ranges from 0~127, corresponding to the bit number in 16 data bytes. It is cleared by SPI_MEM_ECC_ERR_INT_CLR bit. + 6 + 7 + read-only + + + ECC_CHK_ERR_BIT + When SPI_MEM_ECC_BYTE_ERR is set, these bits show the error bit number of ECC byte. + 13 + 3 + read-only + + + ECC_BYTE_ERR + It records the first ECC byte error when SPI_FMEM_ECC_ERR_INT_EN/SPI_SMEM_ECC_ERR_INT_EN is set and accessed to flash/Ext_RAM. It is cleared by SPI_MEM_ECC_ERR_INT_CLR bit. + 16 + 1 + read-only + + + ECC_ERR_CNT + This bits show the error times of MSPI ECC read, including ECC byte error and data byte error. It is cleared by when SPI_MEM_ECC_ERR_INT_CLR bit is set. + 17 + 8 + read-only + + + + + SPI_SMEM_AC + MSPI external RAM ECC and SPI CS timing control register + 0xDC + 0x20 + 0x0000B084 + + + SPI_SMEM_CS_SETUP + Set this bit to keep SPI_CS low when MSPI is in PREP state. + 0 + 1 + read-write + + + SPI_SMEM_CS_HOLD + Set this bit to keep SPI_CS low when MSPI is in DONE state. + 1 + 1 + read-write + + + SPI_SMEM_CS_SETUP_TIME + (cycles-1) of PREP phase by SPI_CLK, which is the SPI_CS setup time. These bits are combined with SPI_MEM_CS_SETUP bit. + 2 + 5 + read-write + + + SPI_SMEM_CS_HOLD_TIME + SPI Bus CS (SPI_CS) signal is delayed to inactive by SPI Bus clock (SPI_CLK), which is the SPI_CS hold time in non-ECC mode. These bits are combined with SPI_MEM_CS_HOLD bit. + 7 + 5 + read-write + + + SPI_SMEM_ECC_CS_HOLD_TIME + SPI_SMEM_CS_HOLD_TIME + SPI_SMEM_ECC_CS_HOLD_TIME is the MSPI CS hold cycles in ECC mode when accesses to external RAM. + 12 + 3 + read-write + + + SPI_SMEM_ECC_SKIP_PAGE_CORNER + 1: MSPI skips page corner when accesses to external RAM. 0: Not skip page corner when accesses to external RAM. + 15 + 1 + read-write + + + SPI_SMEM_ECC_16TO18_BYTE_EN + Set this bit to enable MSPI ECC 16 bytes data with 2 ECC bytes mode when accesses to external RAM. + 16 + 1 + read-write + + + SPI_SMEM_ECC_ERR_INT_EN + Set this bit to calculate the error times of MSPI ECC read when accesses to external RAM. + 24 + 1 + read-write + + + SPI_SMEM_CS_HOLD_DELAY + These bits are used to set the minimum CS high time tSHSL between SPI burst transfer when accesses to external RAM. tSHSL is (SPI_SMEM_CS_HOLD_DELAY[5:0] + 1) MSPI core clock cycles. + 25 + 6 + read-write + + + + + DDR + SPI0 flash DDR mode control register + 0xE0 + 0x20 + 0x00003020 + + + SPI_FMEM_DDR_EN + 1: in ddr mode, 0 in sdr mode + 0 + 1 + read-write + + + SPI_FMEM_VAR_DUMMY + Set the bit to enable variable dummy cycle in DDR mode. + 1 + 1 + read-write + + + SPI_FMEM_DDR_RDAT_SWP + Set the bit to reorder RX data of the word in DDR mode. + 2 + 1 + read-write + + + SPI_FMEM_DDR_WDAT_SWP + Set the bit to swap TX data of a word in DDR mode. + 3 + 1 + read-write + + + SPI_FMEM_DDR_CMD_DIS + the bit is used to disable dual edge in CMD phase when ddr mode. + 4 + 1 + read-write + + + SPI_FMEM_OUTMINBYTELEN + It is the minimum output data length in the panda device. + 5 + 7 + read-write + + + SPI_FMEM_TX_DDR_MSK_EN + Set this bit to mask the first or the last byte in MSPI ECC DDR write mode, when accesses to flash. + 12 + 1 + read-write + + + SPI_FMEM_RX_DDR_MSK_EN + Set this bit to mask the first or the last byte in MSPI ECC DDR read mode, when accesses to flash. + 13 + 1 + read-write + + + SPI_FMEM_USR_DDR_DQS_THD + The delay number of data strobe which from memory based on SPI_CLK. + 14 + 7 + read-write + + + SPI_FMEM_DDR_DQS_LOOP + 1: Use internal signal as data strobe, the strobe can not be delayed by input timing module. 0: Use input SPI_DQS signal from PAD as data strobe, the strobe can be delayed by input timing module + 21 + 1 + read-write + + + SPI_FMEM_DDR_DQS_LOOP_MODE + When SPI_FMEM_DDR_DQS_LOOP and SPI_FMEM_DDR_EN are set, 1: Use internal SPI_CLK as data strobe. 0: Use internal ~SPI_CLK as data strobe. Otherwise this bit is not active. + 22 + 1 + read-write + + + SPI_FMEM_CLK_DIFF_EN + Set this bit to enable the differential SPI_CLK#. + 24 + 1 + read-write + + + SPI_FMEM_HYPERBUS_MODE + Set this bit to enable the SPI HyperBus mode. + 25 + 1 + read-write + + + SPI_FMEM_DQS_CA_IN + Set this bit to enable the input of SPI_DQS signal in SPI phases of CMD and ADDR. + 26 + 1 + read-write + + + SPI_FMEM_HYPERBUS_DUMMY_2X + Set this bit to enable the vary dummy function in SPI HyperBus mode, when SPI0 accesses to flash or SPI1 accesses flash or sram. + 27 + 1 + read-write + + + SPI_FMEM_CLK_DIFF_INV + Set this bit to invert SPI_DIFF when accesses to flash. . + 28 + 1 + read-write + + + SPI_FMEM_OCTA_RAM_ADDR + Set this bit to enable octa_ram address out when accesses to flash, which means ADDR_OUT[31:0] = {spi_usr_addr_value[25:4], 6'd0, spi_usr_addr_value[3:1], 1'b0}. + 29 + 1 + read-write + + + SPI_FMEM_HYPERBUS_CA + Set this bit to enable HyperRAM address out when accesses to flash, which means ADDR_OUT[31:0] = {spi_usr_addr_value[19:4], 13'd0, spi_usr_addr_value[3:1]}. + 30 + 1 + read-write + + + + + SPI_SMEM_DDR + SPI0 external RAM DDR mode control register + 0xE4 + 0x20 + 0x00003020 + + + EN + 1: in ddr mode, 0 in sdr mode + 0 + 1 + read-write + + + SPI_SMEM_VAR_DUMMY + Set the bit to enable variable dummy cycle in spi ddr mode. + 1 + 1 + read-write + + + RDAT_SWP + Set the bit to reorder rx data of the word in spi ddr mode. + 2 + 1 + read-write + + + WDAT_SWP + Set the bit to reorder tx data of the word in spi ddr mode. + 3 + 1 + read-write + + + CMD_DIS + the bit is used to disable dual edge in CMD phase when ddr mode. + 4 + 1 + read-write + + + SPI_SMEM_OUTMINBYTELEN + It is the minimum output data length in the ddr psram. + 5 + 7 + read-write + + + SPI_SMEM_TX_DDR_MSK_EN + Set this bit to mask the first or the last byte in MSPI ECC DDR write mode, when accesses to external RAM. + 12 + 1 + read-write + + + SPI_SMEM_RX_DDR_MSK_EN + Set this bit to mask the first or the last byte in MSPI ECC DDR read mode, when accesses to external RAM. + 13 + 1 + read-write + + + SPI_SMEM_USR_DDR_DQS_THD + The delay number of data strobe which from memory based on SPI_CLK. + 14 + 7 + read-write + + + DQS_LOOP + 1: Use internal signal as data strobe, the strobe can not be delayed by input timing module. 0: Use input SPI_DQS signal from PAD as data strobe, the strobe can be delayed by input timing module + 21 + 1 + read-write + + + DQS_LOOP_MODE + When SPI_SMEM_DDR_DQS_LOOP and SPI_SMEM_DDR_EN are set, 1: Use internal SPI_CLK as data strobe. 0: Use internal ~SPI_CLK as data strobe. Otherwise this bit is not active. + 22 + 1 + read-write + + + SPI_SMEM_CLK_DIFF_EN + Set this bit to enable the differential SPI_CLK#. + 24 + 1 + read-write + + + SPI_SMEM_HYPERBUS_MODE + Set this bit to enable the SPI HyperBus mode. + 25 + 1 + read-write + + + SPI_SMEM_DQS_CA_IN + Set this bit to enable the input of SPI_DQS signal in SPI phases of CMD and ADDR. + 26 + 1 + read-write + + + SPI_SMEM_HYPERBUS_DUMMY_2X + Set this bit to enable the vary dummy function in SPI HyperBus mode, when SPI0 accesses to flash or SPI1 accesses flash or sram. + 27 + 1 + read-write + + + SPI_SMEM_CLK_DIFF_INV + Set this bit to invert SPI_DIFF when accesses to external RAM. . + 28 + 1 + read-write + + + SPI_SMEM_OCTA_RAM_ADDR + Set this bit to enable octa_ram address out when accesses to external RAM, which means ADDR_OUT[31:0] = {spi_usr_addr_value[25:4], 6'd0, spi_usr_addr_value[3:1], 1'b0}. + 29 + 1 + read-write + + + SPI_SMEM_HYPERBUS_CA + Set this bit to enable HyperRAM address out when accesses to external RAM, which means ADDR_OUT[31:0] = {spi_usr_addr_value[19:4], 13'd0, spi_usr_addr_value[3:1]}. + 30 + 1 + read-write + + + + + CLOCK_GATE + SPI0 clk_gate register + 0xE8 + 0x20 + 0x00000001 + + + CLK_EN + Register clock gate enable signal. 1: Enable. 0: Disable. + 0 + 1 + read-write + + + + + CORE_CLK_SEL + SPI0 module clock select register + 0xEC + 0x20 + + + CORE_CLK_SEL + When the digital system clock selects PLL clock and the frequency of PLL clock is 480MHz, the value of SPI_MEM_CORE_CLK_SEL: 0: SPI0/1 module clock (MSPI_CORE_CLK) is 80MHz. 1: MSPI_CORE_CLK is 120MHz. 2: MSPI_CORE_CLK is 160MHz. 3: MSPI_CORE_CLK is 240MHz. When the digital system clock selects PLL clock and the frequency of PLL clock is 320MHz, the value of SPI_MEM_CORE_CLK_SEL: 0: MSPI_CORE_CLK is 80MHz. 1: MSPI_CORE_CLK is 80MHz. 2: MSPI_CORE_CLK 160MHz. 3: Not used. + 0 + 2 + read-write + + + + + INT_ENA + SPI1 interrupt enable register + 0xF0 + 0x20 + + + TOTAL_TRANS_END_INT_ENA + The enable bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. + 2 + 1 + read-write + + + ECC_ERR_INT_ENA + The enable bit for SPI_MEM_ECC_ERR_INT interrupt. + 4 + 1 + read-write + + + + + INT_CLR + SPI1 interrupt clear register + 0xF4 + 0x20 + + + TOTAL_TRANS_END_INT_CLR + The clear bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. + 2 + 1 + write-only + + + ECC_ERR_INT_CLR + The clear bit for SPI_MEM_ECC_ERR_INT interrupt. SPI_MEM_ECC_ERR_ADDR and SPI_MEM_ECC_ERR_CNT will be cleared by the pulse of this bit. + 4 + 1 + write-only + + + + + INT_RAW + SPI1 interrupt raw register + 0xF8 + 0x20 + + + TOTAL_TRANS_END_INT_RAW + The raw bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. 1: Triggered when SPI1 transfer is done and flash is already idle. When WRSR/PP/SE/BE/CE is sent and PES/PER command is sent, this bit is set when WRSR/PP/SE/BE/CE is success. 0: Others. + 2 + 1 + read-only + + + ECC_ERR_INT_RAW + The raw bit for SPI_MEM_ECC_ERR_INT interrupt. When APB_CTRL_FECC_ERR_INT_EN is set and APB_CTRL_SECC_ERR_INT_EN is cleared, this bit is triggered when the error times of SPI0/1 ECC read flash are equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN is cleared and APB_CTRL_SECC_ERR_INT_EN is set, this bit is triggered when the error times of SPI0/1 ECC read external RAM are equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN and APB_CTRL_SECC_ERR_INT_EN are set, this bit is triggered when the total error times of SPI0/1 ECC read external RAM and flash are equal or bigger than APB_CTRL_ECC_ERR_INT_NUM. When APB_CTRL_FECC_ERR_INT_EN and APB_CTRL_SECC_ERR_INT_EN are cleared, this bit will not be triggered. + 4 + 1 + read-only + + + + + INT_ST + SPI1 interrupt status register + 0xFC + 0x20 + + + TOTAL_TRANS_END_INT_ST + The status bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. + 2 + 1 + read-only + + + ECC_ERR_INT_ST + The status bit for SPI_MEM_ECC_ERR_INT interrupt. + 4 + 1 + read-only + + + + + DATE + SPI0 version control register + 0x3FC + 0x20 + 0x02101040 + + + SPI_SMEM_SPICLK_FUN_DRV + The driver of SPI_CLK PAD is controlled by the bits SPI_SMEM_SPICLK_FUN_DRV[1:0] when the bit SPI_SPICLK_PAD_DRV_CTL_EN is set and MSPI accesses to external RAM. + 0 + 2 + read-write + + + SPI_FMEM_SPICLK_FUN_DRV + The driver of SPI_CLK PAD is controlled by the bits SPI_FMEM_SPICLK_FUN_DRV[1:0] when the bit SPI_SPICLK_PAD_DRV_CTL_EN is set and MSPI accesses to flash. + 2 + 2 + read-write + + + SPI_SPICLK_PAD_DRV_CTL_EN + SPI_CLK PAD driver control signal. 1: The driver of SPI_CLK PAD is controlled by the bits SPI_FMEM_SPICLK_FUN_DRV[1:0] and SPI_SMEM_SPICLK_FUN_DRV[1:0]. 0: The driver of SPI_CLK PAD is controlled by the bits IO_MUX_FUNC_DRV[1:0] of SPICLK PAD. + 4 + 1 + read-write + + + DATE + SPI register version. + 5 + 23 + read-write + + + + + + + SPI1 + SPI (Serial Peripheral Interface) Controller + SPI1 + 0x60002000 + + 0x0 + 0xB4 + registers + + + SPI1 + 20 + + + + CMD + SPI1 memory command register + 0x0 + 0x20 + + + FLASH_PE + In user mode, it is set to indicate that program/erase operation will be triggered. The bit is combined with SPI_MEM_USR bit. The bit will be cleared once the operation done.1: enable 0: disable. + 17 + 1 + read-write + + + USR + User define command enable. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 18 + 1 + read-write + + + FLASH_HPM + Drive Flash into high performance mode. The bit will be cleared once the operation done.1: enable 0: disable. + 19 + 1 + read-write + + + FLASH_RES + This bit combined with SPI_MEM_RESANDRES bit releases Flash from the power-down state or high performance mode and obtains the devices ID. The bit will be cleared once the operation done.1: enable 0: disable. + 20 + 1 + read-write + + + FLASH_DP + Drive Flash into power down. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 21 + 1 + read-write + + + FLASH_CE + Chip erase enable. Chip erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 22 + 1 + read-write + + + FLASH_BE + Block erase enable(32KB) . Block erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 23 + 1 + read-write + + + FLASH_SE + Sector erase enable(4KB). Sector erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 24 + 1 + read-write + + + FLASH_PP + Page program enable(1 byte ~64 bytes data to be programmed). Page program operation will be triggered when the bit is set. The bit will be cleared once the operation done .1: enable 0: disable. + 25 + 1 + read-write + + + FLASH_WRSR + Write status register enable. Write status operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 26 + 1 + read-write + + + FLASH_RDSR + Read status register-1. Read status operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 27 + 1 + read-write + + + FLASH_RDID + Read JEDEC ID . Read ID command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable. + 28 + 1 + read-write + + + FLASH_WRDI + Write flash disable. Write disable command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable. + 29 + 1 + read-write + + + FLASH_WREN + Write flash enable. Write enable command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable. + 30 + 1 + read-write + + + FLASH_READ + Read flash enable. Read flash operation will be triggered when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable. + 31 + 1 + read-write + + + + + ADDR + SPI1 address register + 0x4 + 0x20 + + + USR_ADDR_VALUE + In user mode, it is the memory address. other then the bit0-bit23 is the memory address, the bit24-bit31 are the byte length of a transfer. + 0 + 32 + read-write + + + + + CTRL + SPI1 control register + 0x8 + 0x20 + 0x002CA000 + + + FDUMMY_OUT + In the DUMMY phase the signal level of SPI bus is output by the SPI0 controller. + 3 + 1 + read-write + + + FDOUT_OCT + Set this bit to enable 8-bit-mode(8-bm) in DOUT phase. + 4 + 1 + read-write + + + FDIN_OCT + Set this bit to enable 8-bit-mode(8-bm) in DIN phase. + 5 + 1 + read-write + + + FADDR_OCT + Set this bit to enable 8-bit-mode(8-bm) in ADDR phase. + 6 + 1 + read-write + + + FCMD_DUAL + Set this bit to enable 2-bit-mode(2-bm) in CMD phase. + 7 + 1 + read-write + + + FCMD_QUAD + Set this bit to enable 4-bit-mode(4-bm) in CMD phase. + 8 + 1 + read-write + + + FCMD_OCT + Set this bit to enable 8-bit-mode(8-bm) in CMD phase. + 9 + 1 + read-write + + + FCS_CRC_EN + For SPI1, initialize crc32 module before writing encrypted data to flash. Active low. + 10 + 1 + read-write + + + TX_CRC_EN + For SPI1, enable crc32 when writing encrypted data to flash. 1: enable 0:disable + 11 + 1 + read-write + + + FASTRD_MODE + This bit should be set when SPI_MEM_FREAD_QIO, SPI_MEM_FREAD_DIO, SPI_MEM_FREAD_QUAD or SPI_MEM_FREAD_DUAL is set. + 13 + 1 + read-write + + + FREAD_DUAL + In hardware 0x3B read operation, DIN phase apply 2 signals. 1: enable 0: disable. + 14 + 1 + read-write + + + RESANDRES + The Device ID is read out to SPI_MEM_RD_STATUS register, this bit combine with spi_mem_flash_res bit. 1: enable 0: disable. + 15 + 1 + read-write + + + Q_POL + The bit is used to set MISO line polarity, 1: high 0, low + 18 + 1 + read-write + + + D_POL + The bit is used to set MOSI line polarity, 1: high 0, low + 19 + 1 + read-write + + + FREAD_QUAD + In hardware 0x6B read operation, DIN phase apply 4 signals(4-bit-mode). 1: enable 0: disable. + 20 + 1 + read-write + + + WP + Write protect signal output when SPI is idle. 1: output high, 0: output low. + 21 + 1 + read-write + + + WRSR_2B + Two bytes data will be written to status register when it is set. 1: enable 0: disable. + 22 + 1 + read-write + + + FREAD_DIO + In hardware 0xBB read operation, ADDR phase and DIN phase apply 2 signals(2-bit-mode). 1: enable 0: disable. + 23 + 1 + read-write + + + FREAD_QIO + In hardware 0xEB read operation, ADDR phase and DIN phase apply 4 signals(4-bit-mode). 1: enable 0: disable. + 24 + 1 + read-write + + + + + CTRL1 + SPI1 control1 register + 0xC + 0x20 + 0x00000FFC + + + CLK_MODE + SPI Bus clock (SPI_CLK) mode bits. 0: SPI Bus clock (SPI_CLK) is off when CS inactive 1: SPI_CLK is delayed one cycle after SPI_CS inactive 2: SPI_CLK is delayed two cycles after SPI_CS inactive 3: SPI_CLK is always on. + 0 + 2 + read-write + + + CS_HOLD_DLY_RES + After RES/DP/HPM/PES/PER command is sent, SPI1 may waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4 or * 256) SPI_CLK cycles. + 2 + 10 + read-write + + + + + CTRL2 + SPI1 control2 register + 0x10 + 0x20 + + + SYNC_RESET + The FSM will be reset. + 31 + 1 + read-write + + + + + CLOCK + SPI_CLK clock division register when SPI1 accesses to flash or Ext_RAM. + 0x14 + 0x20 + 0x00030103 + + + CLKCNT_L + It must equal to the value of SPI_MEM_CLKCNT_N. + 0 + 8 + read-write + + + CLKCNT_H + It must be a floor value of ((SPI_MEM_CLKCNT_N+1)/2-1). + 8 + 8 + read-write + + + CLKCNT_N + When SPI1 accesses to flash or Ext_RAM, f_SPI_CLK = f_MSPI_CORE_CLK/(SPI_MEM_CLKCNT_N+1) + 16 + 8 + read-write + + + CLK_EQU_SYSCLK + When SPI1 access to flash or Ext_RAM, set this bit in 1-division mode, f_SPI_CLK = f_MSPI_CORE_CLK. + 31 + 1 + read-write + + + + + USER + SPI1 user register. + 0x18 + 0x20 + 0x80000000 + + + CK_OUT_EDGE + This bit, combined with SPI_MEM_CK_IDLE_EDGE bit, is used to change the clock mode 0~3 of SPI_CLK. + 9 + 1 + read-write + + + FWRITE_DUAL + Set this bit to enable 2-bm in DOUT phase in SPI1 write operation. + 12 + 1 + read-write + + + FWRITE_QUAD + Set this bit to enable 4-bm in DOUT phase in SPI1 write operation. + 13 + 1 + read-write + + + FWRITE_DIO + Set this bit to enable 2-bm in ADDR and DOUT phase in SPI1 write operation. + 14 + 1 + read-write + + + FWRITE_QIO + Set this bit to enable 4-bit-mode(4-bm) in ADDR and DOUT phase in SPI1 write operation. + 15 + 1 + read-write + + + USR_MISO_HIGHPART + DIN phase only access to high-part of the buffer SPI_MEM_W8_REG~SPI_MEM_W15_REG. 1: enable 0: disable. + 24 + 1 + read-write + + + USR_MOSI_HIGHPART + DOUT phase only access to high-part of the buffer SPI_MEM_W8_REG~SPI_MEM_W15_REG. 1: enable 0: disable. + 25 + 1 + read-write + + + USR_DUMMY_IDLE + SPI_CLK is disabled(No clock edges) in DUMMY phase when the bit is enable. + 26 + 1 + read-write + + + USR_MOSI + Set this bit to enable the DOUT phase of an write-data operation. + 27 + 1 + read-write + + + USR_MISO + Set this bit to enable enable the DIN phase of a read-data operation. + 28 + 1 + read-write + + + USR_DUMMY + Set this bit to enable enable the DUMMY phase of an operation. + 29 + 1 + read-write + + + USR_ADDR + Set this bit to enable enable the ADDR phase of an operation. + 30 + 1 + read-write + + + USR_COMMAND + Set this bit to enable enable the CMD phase of an operation. + 31 + 1 + read-write + + + + + USER1 + SPI1 user1 register. + 0x1C + 0x20 + 0x5C000007 + + + USR_DUMMY_CYCLELEN + The SPI_CLK cycle length minus 1 of DUMMY phase. + 0 + 6 + read-write + + + USR_ADDR_BITLEN + The length in bits of ADDR phase. The register value shall be (bit_num-1). + 26 + 6 + read-write + + + + + USER2 + SPI1 user2 register. + 0x20 + 0x20 + 0x70000000 + + + USR_COMMAND_VALUE + The value of user defined(USR) command. + 0 + 16 + read-write + + + USR_COMMAND_BITLEN + The length in bits of CMD phase. The register value shall be (bit_num-1) + 28 + 4 + read-write + + + + + MOSI_DLEN + SPI1 write-data bit length register. + 0x24 + 0x20 + + + USR_MOSI_DBITLEN + The length in bits of DOUT phase. The register value shall be (bit_num-1). + 0 + 10 + read-write + + + + + MISO_DLEN + SPI1 read-data bit length register. + 0x28 + 0x20 + + + USR_MISO_DBITLEN + The length in bits of DIN phase. The register value shall be (bit_num-1). + 0 + 10 + read-write + + + + + RD_STATUS + SPI1 read control register. + 0x2C + 0x20 + + + STATUS + The value is stored when set SPI_MEM_FLASH_RDSR bit and SPI_MEM_FLASH_RES bit. + 0 + 16 + read-write + + + WB_MODE + Mode bits in the flash fast read mode it is combined with SPI_MEM_FASTRD_MODE bit. + 16 + 8 + read-write + + + + + EXT_ADDR + SPI1 extended address register. + 0x30 + 0x20 + + + EXT_ADDR + The register are the higher 32bits in the 64 bits address mode. + 0 + 32 + read-write + + + + + MISC + SPI1 misc register. + 0x34 + 0x20 + 0x00000002 + + + CS0_DIS + Set this bit to raise high SPI_CS pin, which means that the SPI device(flash) connected to SPI_CS is in low level when SPI1 transfer starts. + 0 + 1 + read-write + + + CS1_DIS + Set this bit to raise high SPI_CS1 pin, which means that the SPI device(Ext_RAM) connected to SPI_CS1 is in low level when SPI1 transfer starts. + 1 + 1 + read-write + + + CK_IDLE_EDGE + 1: SPI_CLK line is high when MSPI is idle. 0: SPI_CLK line is low when MSPI is idle. + 9 + 1 + read-write + + + CS_KEEP_ACTIVE + SPI_CS line keep low when the bit is set. + 10 + 1 + read-write + + + AUTO_PER + Set this bit to enable auto PER function. Hardware will sent out PER command if PES command is sent. + 11 + 1 + read-write + + + + + TX_CRC + SPI1 CRC data register. + 0x38 + 0x20 + 0xFFFFFFFF + + + DATA + For SPI1, the value of crc32. + 0 + 32 + read-only + + + + + CACHE_FCTRL + SPI1 bit mode control register. + 0x3C + 0x20 + + + CACHE_USR_CMD_4BYTE + Set this bit to enable SPI1 transfer with 32 bits address. The value of SPI_MEM_USR_ADDR_BITLEN should be 31. + 1 + 1 + read-write + + + FDIN_DUAL + When SPI1 accesses to flash or Ext_RAM, set this bit to enable 2-bm in DIN phase. + 3 + 1 + read-write + + + FDOUT_DUAL + When SPI1 accesses to flash or Ext_RAM, set this bit to enable 2-bm in DOUT phase. + 4 + 1 + read-write + + + FADDR_DUAL + When SPI1 accesses to flash or Ext_RAM, set this bit to enable 2-bm in ADDR phase. + 5 + 1 + read-write + + + FDIN_QUAD + When SPI1 accesses to flash or Ext_RAM, set this bit to enable 4-bm in DIN phase. + 6 + 1 + read-write + + + FDOUT_QUAD + When SPI1 accesses to flash or Ext_RAM, set this bit to enable 4-bm in DOUT phase. + 7 + 1 + read-write + + + FADDR_QUAD + When SPI1 accesses to flash or Ext_RAM, set this bit to enable 4-bm in ADDR phase. + 8 + 1 + read-write + + + + + FSM + SPI1 state machine(FSM) status register. + 0x54 + 0x20 + + + ST + The status of SPI1 state machine. 0: idle state(IDLE), 1: preparation state(PREP), 2: send command state(CMD), 3: send address state(ADDR), 4: red data state(DIN), 5:write data state(DOUT), 6: wait state(DUMMY), 7: done state(DONE). + 0 + 3 + read-only + + + + + W0 + SPI1 memory data buffer0 + 0x58 + 0x20 + + + BUF0 + data buffer + 0 + 32 + read-write + + + + + W1 + SPI1 memory data buffer1 + 0x5C + 0x20 + + + BUF1 + data buffer + 0 + 32 + read-write + + + + + W2 + SPI1 memory data buffer2 + 0x60 + 0x20 + + + BUF2 + data buffer + 0 + 32 + read-write + + + + + W3 + SPI1 memory data buffer3 + 0x64 + 0x20 + + + BUF3 + data buffer + 0 + 32 + read-write + + + + + W4 + SPI1 memory data buffer4 + 0x68 + 0x20 + + + BUF4 + data buffer + 0 + 32 + read-write + + + + + W5 + SPI1 memory data buffer5 + 0x6C + 0x20 + + + BUF5 + data buffer + 0 + 32 + read-write + + + + + W6 + SPI1 memory data buffer6 + 0x70 + 0x20 + + + BUF6 + data buffer + 0 + 32 + read-write + + + + + W7 + SPI1 memory data buffer7 + 0x74 + 0x20 + + + BUF7 + data buffer + 0 + 32 + read-write + + + + + W8 + SPI1 memory data buffer8 + 0x78 + 0x20 + + + BUF8 + data buffer + 0 + 32 + read-write + + + + + W9 + SPI1 memory data buffer9 + 0x7C + 0x20 + + + BUF9 + data buffer + 0 + 32 + read-write + + + + + W10 + SPI1 memory data buffer10 + 0x80 + 0x20 + + + BUF10 + data buffer + 0 + 32 + read-write + + + + + W11 + SPI1 memory data buffer11 + 0x84 + 0x20 + + + BUF11 + data buffer + 0 + 32 + read-write + + + + + W12 + SPI1 memory data buffer12 + 0x88 + 0x20 + + + BUF12 + data buffer + 0 + 32 + read-write + + + + + W13 + SPI1 memory data buffer13 + 0x8C + 0x20 + + + BUF13 + data buffer + 0 + 32 + read-write + + + + + W14 + SPI1 memory data buffer14 + 0x90 + 0x20 + + + BUF14 + data buffer + 0 + 32 + read-write + + + + + W15 + SPI1 memory data buffer15 + 0x94 + 0x20 + + + BUF15 + data buffer + 0 + 32 + read-write + + + + + FLASH_WAITI_CTRL + SPI1 wait idle control register + 0x98 + 0x20 + 0x00000014 + + + WAITI_EN + Set this bit to enable auto-waiting flash idle operation when PP/SE/BE/CE/WRSR/PES command is sent. + 0 + 1 + read-write + + + WAITI_DUMMY + Set this bit to enable DUMMY phase in auto wait flash idle transfer(RDSR). + 1 + 1 + read-write + + + WAITI_CMD + The command value of auto wait flash idle transfer(RDSR). + 2 + 8 + read-write + + + WAITI_DUMMY_CYCLELEN + The dummy cycle length when wait flash idle(RDSR). + 10 + 6 + read-write + + + + + FLASH_SUS_CMD + SPI1 flash suspend control register + 0x9C + 0x20 + + + FLASH_PER + program erase resume bit, program erase suspend operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 0 + 1 + read-write + + + FLASH_PES + program erase suspend bit, program erase suspend operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. + 1 + 1 + read-write + + + FLASH_PER_WAIT_EN + Set this bit to add delay time after program erase resume(PER) is sent. + 2 + 1 + read-write + + + FLASH_PES_WAIT_EN + Set this bit to add delay time after program erase suspend(PES) command is sent. + 3 + 1 + read-write + + + PES_PER_EN + Set this bit to enable PES transfer trigger PES transfer option. + 4 + 1 + read-write + + + PESR_IDLE_EN + 1: Separate PER flash wait idle and PES flash wait idle. 0: Not separate. + 5 + 1 + read-write + + + + + FLASH_SUS_CTRL + SPI1 flash suspend command register + 0xA0 + 0x20 + 0x0000EAF4 + + + FLASH_PES_EN + Set this bit to enable auto-suspend function. + 0 + 1 + read-write + + + FLASH_PER_COMMAND + Program/Erase resume command value. + 1 + 8 + read-write + + + FLASH_PES_COMMAND + Program/Erase suspend command value. + 9 + 8 + read-write + + + + + SUS_STATUS + SPI1 flash suspend status register + 0xA4 + 0x20 + + + FLASH_SUS + The status of flash suspend. This bit is set when PES command is sent, and cleared when PER is sent. Only used in SPI1. + 0 + 1 + read-write + + + FLASH_HPM_DLY_256 + 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 256) SPI_CLK cycles after HPM command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after HPM command is sent. + 2 + 1 + read-write + + + FLASH_RES_DLY_256 + 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 256) SPI_CLK cycles after RES command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after RES command is sent. + 3 + 1 + read-write + + + FLASH_DP_DLY_256 + 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 256) SPI_CLK cycles after DP command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after DP command is sent. + 4 + 1 + read-write + + + FLASH_PER_DLY_256 + Valid when SPI_MEM_FLASH_PER_WAIT_EN is 1. 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 256) SPI_CLK cycles after PER command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PER command is sent. + 5 + 1 + read-write + + + FLASH_PES_DLY_256 + Valid when SPI_MEM_FLASH_PES_WAIT_EN is 1. 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 256) SPI_CLK cycles after PES command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PES command is sent. + 6 + 1 + read-write + + + + + TIMING_CALI + SPI1 timing compensation register when accesses to flash or Ext_RAM. + 0xA8 + 0x20 + + + TIMING_CALI + Set this bit to add extra SPI_CLK cycles in DUMMY phase for all reading operations. + 1 + 1 + read-write + + + EXTRA_DUMMY_CYCLELEN + Extra SPI_CLK cycles added in DUMMY phase for timing compensation. Active when SPI_MEM_TIMING_CALI bit is set. + 2 + 3 + read-write + + + + + DDR + SPI1 DDR control register + 0xE0 + 0x20 + 0x00000020 + + + SPI_FMEM_DDR_EN + 1: in DDR mode, 0: in SDR mode. + 0 + 1 + read-write + + + SPI_FMEM_VAR_DUMMY + Set the bit to enable variable dummy cycle in DDRmode. + 1 + 1 + read-write + + + SPI_FMEM_DDR_RDAT_SWP + Set the bit to reorder RX data of the word in DDR mode. + 2 + 1 + read-write + + + SPI_FMEM_DDR_WDAT_SWP + Set the bit to reorder TX data of the word in DDR mode. + 3 + 1 + read-write + + + SPI_FMEM_DDR_CMD_DIS + the bit is used to disable dual edge in command phase when DDR mode. + 4 + 1 + read-write + + + SPI_FMEM_OUTMINBYTELEN + It is the minimum output data length in the panda device. + 5 + 7 + read-write + + + SPI_FMEM_USR_DDR_DQS_THD + The delay number of data strobe which from memory based on SPI_CLK. + 14 + 7 + read-write + + + SPI_FMEM_DDR_DQS_LOOP + 1: Use internal signal as data strobe, the strobe can not be delayed by input timing module. 0: Use input SPI_DQS signal from PAD as data strobe, the strobe can be delayed by input timing module + 21 + 1 + read-write + + + SPI_FMEM_DDR_DQS_LOOP_MODE + When SPI_FMEM_DDR_DQS_LOOP and SPI_FMEM_DDR_EN are set, 1: Use internal SPI_CLK as data strobe. 0: Use internal ~SPI_CLK as data strobe. Otherwise this bit is not active. + 22 + 1 + read-write + + + SPI_FMEM_CLK_DIFF_EN + Set this bit to enable the differential SPI_CLK#. + 24 + 1 + read-write + + + SPI_FMEM_HYPERBUS_MODE + Set this bit to enable the SPI HyperBus mode. + 25 + 1 + read-write + + + SPI_FMEM_DQS_CA_IN + Set this bit to enable the input of SPI_DQS signal in SPI phases of CMD and ADDR. + 26 + 1 + read-write + + + SPI_FMEM_HYPERBUS_DUMMY_2X + Set this bit to enable the vary dummy function in SPI HyperBus mode, when SPI0 accesses flash or SPI1 accesses flash or sram. + 27 + 1 + read-write + + + SPI_FMEM_CLK_DIFF_INV + Set this bit to invert SPI_DIFF when accesses to flash. . + 28 + 1 + read-write + + + SPI_FMEM_OCTA_RAM_ADDR + Set this bit to enable octa_ram address out when accesses to flash, which means ADDR_OUT[31:0] = {spi_usr_addr_value[25:4], 6'd0, spi_usr_addr_value[3:1], 1'b0}. + 29 + 1 + read-write + + + SPI_FMEM_HYPERBUS_CA + Set this bit to enable HyperRAM address out when accesses to flash, which means ADDR_OUT[31:0] = {spi_usr_addr_value[19:4], 13'd0, spi_usr_addr_value[3:1]}. + 30 + 1 + read-write + + + + + CLOCK_GATE + SPI1 clk_gate register + 0xE8 + 0x20 + 0x00000001 + + + CLK_EN + Register clock gate enable signal. 1: Enable. 0: Disable. + 0 + 1 + read-write + + + + + INT_ENA + SPI1 interrupt enable register + 0xF0 + 0x20 + + + PER_END_INT_ENA + The enable bit for SPI_MEM_PER_END_INT interrupt. + 0 + 1 + read-write + + + PES_END_INT_ENA + The enable bit for SPI_MEM_PES_END_INT interrupt. + 1 + 1 + read-write + + + TOTAL_TRANS_END_INT_ENA + The enable bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. + 2 + 1 + read-write + + + BROWN_OUT_INT_ENA + The enable bit for SPI_MEM_BROWN_OUT_INT interrupt. + 3 + 1 + read-write + + + + + INT_CLR + SPI1 interrupt clear register + 0xF4 + 0x20 + + + PER_END_INT_CLR + The clear bit for SPI_MEM_PER_END_INT interrupt. + 0 + 1 + write-only + + + PES_END_INT_CLR + The clear bit for SPI_MEM_PES_END_INT interrupt. + 1 + 1 + write-only + + + TOTAL_TRANS_END_INT_CLR + The clear bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. + 2 + 1 + write-only + + + BROWN_OUT_INT_CLR + The status bit for SPI_MEM_BROWN_OUT_INT interrupt. + 3 + 1 + write-only + + + + + INT_RAW + SPI1 interrupt raw register + 0xF8 + 0x20 + + + PER_END_INT_RAW + The raw bit for SPI_MEM_PER_END_INT interrupt. 1: Triggered when Auto Resume command (0x7A) is sent and flash is resumed successfully. 0: Others. + 0 + 1 + read-only + + + PES_END_INT_RAW + The raw bit for SPI_MEM_PES_END_INT interrupt.1: Triggered when Auto Suspend command (0x75) is sent and flash is suspended successfully. 0: Others. + 1 + 1 + read-only + + + TOTAL_TRANS_END_INT_RAW + The raw bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. 1: Triggered when SPI1 transfer is done and flash is already idle. When WRSR/PP/SE/BE/CE is sent and PES/PER command is sent, this bit is set when WRSR/PP/SE/BE/CE is success. 0: Others. + 2 + 1 + read-only + + + BROWN_OUT_INT_RAW + The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that chip is loosing power and RTC module sends out brown out close flash request to SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered and MSPI returns to idle state. 0: Others. + 3 + 1 + read-only + + + + + INT_ST + SPI1 interrupt status register + 0xFC + 0x20 + + + PER_END_INT_ST + The status bit for SPI_MEM_PER_END_INT interrupt. + 0 + 1 + read-only + + + PES_END_INT_ST + The status bit for SPI_MEM_PES_END_INT interrupt. + 1 + 1 + read-only + + + TOTAL_TRANS_END_INT_ST + The status bit for SPI_MEM_TOTAL_TRANS_END_INT interrupt. + 2 + 1 + read-only + + + BROWN_OUT_INT_ST + The status bit for SPI_MEM_BROWN_OUT_INT interrupt. + 3 + 1 + read-only + + + + + DATE + SPI0 version control register + 0x3FC + 0x20 + 0x02101040 + + + DATE + SPI register version. + 0 + 28 + read-write + + + + + + + SPI2 + SPI (Serial Peripheral Interface) Controller + SPI2 + 0x60024000 + + 0x0 + 0x98 + registers + + + SPI2 + 21 + + + + CMD + Command control register + 0x0 + 0x20 + + + CONF_BITLEN + Define the APB cycles of SPI_CONF state. Can be configured in CONF state. + 0 + 18 + read-write + + + UPDATE + Set this bit to synchronize SPI registers from APB clock domain into SPI module clock domain, which is only used in SPI master mode. + 23 + 1 + read-write + + + USR + User define command enable. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable. Can not be changed by CONF_buf. + 24 + 1 + read-write + + + + + ADDR + Address value register + 0x4 + 0x20 + + + USR_ADDR_VALUE + Address to slave. Can be configured in CONF state. + 0 + 32 + read-write + + + + + CTRL + SPI control register + 0x8 + 0x20 + 0x003C0000 + + + DUMMY_OUT + 0: In the dummy phase, the FSPI bus signals are not output. 1: In the dummy phase, the FSPI bus signals are output. Can be configured in CONF state. + 3 + 1 + read-write + + + FADDR_DUAL + Apply 2 signals during addr phase 1:enable 0: disable. Can be configured in CONF state. + 5 + 1 + read-write + + + FADDR_QUAD + Apply 4 signals during addr phase 1:enable 0: disable. Can be configured in CONF state. + 6 + 1 + read-write + + + FADDR_OCT + Apply 8 signals during addr phase 1:enable 0: disable. Can be configured in CONF state. + 7 + 1 + read-write + + + FCMD_DUAL + Apply 2 signals during command phase 1:enable 0: disable. Can be configured in CONF state. + 8 + 1 + read-write + + + FCMD_QUAD + Apply 4 signals during command phase 1:enable 0: disable. Can be configured in CONF state. + 9 + 1 + read-write + + + FCMD_OCT + Apply 8 signals during command phase 1:enable 0: disable. Can be configured in CONF state. + 10 + 1 + read-write + + + FREAD_DUAL + In the read operations, read-data phase apply 2 signals. 1: enable 0: disable. Can be configured in CONF state. + 14 + 1 + read-write + + + FREAD_QUAD + In the read operations read-data phase apply 4 signals. 1: enable 0: disable. Can be configured in CONF state. + 15 + 1 + read-write + + + FREAD_OCT + In the read operations read-data phase apply 8 signals. 1: enable 0: disable. Can be configured in CONF state. + 16 + 1 + read-write + + + Q_POL + The bit is used to set MISO line polarity, 1: high 0, low. Can be configured in CONF state. + 18 + 1 + read-write + + + D_POL + The bit is used to set MOSI line polarity, 1: high 0, low. Can be configured in CONF state. + 19 + 1 + read-write + + + HOLD_POL + SPI_HOLD output value when SPI is idle. 1: output high, 0: output low. Can be configured in CONF state. + 20 + 1 + read-write + + + WP_POL + Write protect signal output when SPI is idle. 1: output high, 0: output low. Can be configured in CONF state. + 21 + 1 + read-write + + + RD_BIT_ORDER + In read-data (MISO) phase 1: LSB first 0: MSB first. Can be configured in CONF state. + 23 + 2 + read-write + + + WR_BIT_ORDER + In command address write-data (MOSI) phases 1: LSB firs 0: MSB first. Can be configured in CONF state. + 25 + 2 + read-write + + + + + CLOCK + SPI clock control register + 0xC + 0x20 + 0x80003043 + + + CLKCNT_L + In the master mode it must be equal to spi_clkcnt_N. In the slave mode it must be 0. Can be configured in CONF state. + 0 + 6 + read-write + + + CLKCNT_H + In the master mode it must be floor((spi_clkcnt_N+1)/2-1). In the slave mode it must be 0. Can be configured in CONF state. + 6 + 6 + read-write + + + CLKCNT_N + In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1). Can be configured in CONF state. + 12 + 6 + read-write + + + CLKDIV_PRE + In the master mode it is pre-divider of spi_clk. Can be configured in CONF state. + 18 + 4 + read-write + + + CLK_EQU_SYSCLK + In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock. Can be configured in CONF state. + 31 + 1 + read-write + + + + + USER + SPI USER control register + 0x10 + 0x20 + 0x800000C0 + + + DOUTDIN + Set the bit to enable full duplex communication. 1: enable 0: disable. Can be configured in CONF state. + 0 + 1 + read-write + + + QPI_MODE + Both for master mode and slave mode. 1: spi controller is in QPI mode. 0: others. Can be configured in CONF state. + 3 + 1 + read-write + + + OPI_MODE + Just for master mode. 1: spi controller is in OPI mode (all in 8-b-m). 0: others. Can be configured in CONF state. + 4 + 1 + read-write + + + TSCK_I_EDGE + In the slave mode, this bit can be used to change the polarity of tsck. 0: tsck = spi_ck_i. 1:tsck = !spi_ck_i. + 5 + 1 + read-write + + + CS_HOLD + spi cs keep low when spi is in done phase. 1: enable 0: disable. Can be configured in CONF state. + 6 + 1 + read-write + + + CS_SETUP + spi cs is enable when spi is in prepare phase. 1: enable 0: disable. Can be configured in CONF state. + 7 + 1 + read-write + + + RSCK_I_EDGE + In the slave mode, this bit can be used to change the polarity of rsck. 0: rsck = !spi_ck_i. 1:rsck = spi_ck_i. + 8 + 1 + read-write + + + CK_OUT_EDGE + the bit combined with spi_mosi_delay_mode bits to set mosi signal delay mode. Can be configured in CONF state. + 9 + 1 + read-write + + + FWRITE_DUAL + In the write operations read-data phase apply 2 signals. Can be configured in CONF state. + 12 + 1 + read-write + + + FWRITE_QUAD + In the write operations read-data phase apply 4 signals. Can be configured in CONF state. + 13 + 1 + read-write + + + FWRITE_OCT + In the write operations read-data phase apply 8 signals. Can be configured in CONF state. + 14 + 1 + read-write + + + USR_CONF_NXT + 1: Enable the DMA CONF phase of next seg-trans operation, which means seg-trans will continue. 0: The seg-trans will end after the current SPI seg-trans or this is not seg-trans mode. Can be configured in CONF state. + 15 + 1 + read-write + + + SIO + Set the bit to enable 3-line half duplex communication mosi and miso signals share the same pin. 1: enable 0: disable. Can be configured in CONF state. + 17 + 1 + read-write + + + USR_MISO_HIGHPART + read-data phase only access to high-part of the buffer spi_w8~spi_w15. 1: enable 0: disable. Can be configured in CONF state. + 24 + 1 + read-write + + + USR_MOSI_HIGHPART + write-data phase only access to high-part of the buffer spi_w8~spi_w15. 1: enable 0: disable. Can be configured in CONF state. + 25 + 1 + read-write + + + USR_DUMMY_IDLE + spi clock is disable in dummy phase when the bit is enable. Can be configured in CONF state. + 26 + 1 + read-write + + + USR_MOSI + This bit enable the write-data phase of an operation. Can be configured in CONF state. + 27 + 1 + read-write + + + USR_MISO + This bit enable the read-data phase of an operation. Can be configured in CONF state. + 28 + 1 + read-write + + + USR_DUMMY + This bit enable the dummy phase of an operation. Can be configured in CONF state. + 29 + 1 + read-write + + + USR_ADDR + This bit enable the address phase of an operation. Can be configured in CONF state. + 30 + 1 + read-write + + + USR_COMMAND + This bit enable the command phase of an operation. Can be configured in CONF state. + 31 + 1 + read-write + + + + + USER1 + SPI USER control register 1 + 0x14 + 0x20 + 0xB8410007 + + + USR_DUMMY_CYCLELEN + The length in spi_clk cycles of dummy phase. The register value shall be (cycle_num-1). Can be configured in CONF state. + 0 + 8 + read-write + + + MST_WFULL_ERR_END_EN + 1: SPI transfer is ended when SPI RX AFIFO wfull error is valid in GP-SPI master FD/HD-mode. 0: SPI transfer is not ended when SPI RX AFIFO wfull error is valid in GP-SPI master FD/HD-mode. + 16 + 1 + read-write + + + CS_SETUP_TIME + (cycles+1) of prepare phase by spi clock this bits are combined with spi_cs_setup bit. Can be configured in CONF state. + 17 + 5 + read-write + + + CS_HOLD_TIME + delay cycles of cs pin by spi clock this bits are combined with spi_cs_hold bit. Can be configured in CONF state. + 22 + 5 + read-write + + + USR_ADDR_BITLEN + The length in bits of address phase. The register value shall be (bit_num-1). Can be configured in CONF state. + 27 + 5 + read-write + + + + + USER2 + SPI USER control register 2 + 0x18 + 0x20 + 0x78000000 + + + USR_COMMAND_VALUE + The value of command. Can be configured in CONF state. + 0 + 16 + read-write + + + MST_REMPTY_ERR_END_EN + 1: SPI transfer is ended when SPI TX AFIFO read empty error is valid in GP-SPI master FD/HD-mode. 0: SPI transfer is not ended when SPI TX AFIFO read empty error is valid in GP-SPI master FD/HD-mode. + 27 + 1 + read-write + + + USR_COMMAND_BITLEN + The length in bits of command phase. The register value shall be (bit_num-1). Can be configured in CONF state. + 28 + 4 + read-write + + + + + MS_DLEN + SPI data bit length control register + 0x1C + 0x20 + + + MS_DATA_BITLEN + The value of these bits is the configured SPI transmission data bit length in master mode DMA controlled transfer or CPU controlled transfer. The value is also the configured bit length in slave mode DMA RX controlled transfer. The register value shall be (bit_num-1). Can be configured in CONF state. + 0 + 18 + read-write + + + + + MISC + SPI misc register + 0x20 + 0x20 + 0x0000003E + + + CS0_DIS + SPI CS0 pin enable, 1: disable CS0, 0: spi_cs0 signal is from/to CS0 pin. Can be configured in CONF state. + 0 + 1 + read-write + + + CS1_DIS + SPI CS1 pin enable, 1: disable CS1, 0: spi_cs1 signal is from/to CS1 pin. Can be configured in CONF state. + 1 + 1 + read-write + + + CS2_DIS + SPI CS2 pin enable, 1: disable CS2, 0: spi_cs2 signal is from/to CS2 pin. Can be configured in CONF state. + 2 + 1 + read-write + + + CS3_DIS + SPI CS3 pin enable, 1: disable CS3, 0: spi_cs3 signal is from/to CS3 pin. Can be configured in CONF state. + 3 + 1 + read-write + + + CS4_DIS + SPI CS4 pin enable, 1: disable CS4, 0: spi_cs4 signal is from/to CS4 pin. Can be configured in CONF state. + 4 + 1 + read-write + + + CS5_DIS + SPI CS5 pin enable, 1: disable CS5, 0: spi_cs5 signal is from/to CS5 pin. Can be configured in CONF state. + 5 + 1 + read-write + + + CK_DIS + 1: spi clk out disable, 0: spi clk out enable. Can be configured in CONF state. + 6 + 1 + read-write + + + MASTER_CS_POL + In the master mode the bits are the polarity of spi cs line, the value is equivalent to spi_cs ^ spi_master_cs_pol. Can be configured in CONF state. + 7 + 6 + read-write + + + CLK_DATA_DTR_EN + 1: SPI master DTR mode is applied to SPI clk, data and spi_dqs. 0: SPI master DTR mode is only applied to spi_dqs. This bit should be used with bit 17/18/19. + 16 + 1 + read-write + + + DATA_DTR_EN + 1: SPI clk and data of SPI_DOUT and SPI_DIN state are in DTR mode, including master 1/2/4/8-bm. 0: SPI clk and data of SPI_DOUT and SPI_DIN state are in STR mode. Can be configured in CONF state. + 17 + 1 + read-write + + + ADDR_DTR_EN + 1: SPI clk and data of SPI_SEND_ADDR state are in DTR mode, including master 1/2/4/8-bm. 0: SPI clk and data of SPI_SEND_ADDR state are in STR mode. Can be configured in CONF state. + 18 + 1 + read-write + + + CMD_DTR_EN + 1: SPI clk and data of SPI_SEND_CMD state are in DTR mode, including master 1/2/4/8-bm. 0: SPI clk and data of SPI_SEND_CMD state are in STR mode. Can be configured in CONF state. + 19 + 1 + read-write + + + SLAVE_CS_POL + spi slave input cs polarity select. 1: inv 0: not change. Can be configured in CONF state. + 23 + 1 + read-write + + + DQS_IDLE_EDGE + The default value of spi_dqs. Can be configured in CONF state. + 24 + 1 + read-write + + + CK_IDLE_EDGE + 1: spi clk line is high when idle 0: spi clk line is low when idle. Can be configured in CONF state. + 29 + 1 + read-write + + + CS_KEEP_ACTIVE + spi cs line keep low when the bit is set. Can be configured in CONF state. + 30 + 1 + read-write + + + QUAD_DIN_PIN_SWAP + 1: SPI quad input swap enable, swap FSPID with FSPIQ, swap FSPIWP with FSPIHD. 0: spi quad input swap disable. Can be configured in CONF state. + 31 + 1 + read-write + + + + + DIN_MODE + SPI input delay mode configuration + 0x24 + 0x20 + + + DIN0_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 0 + 2 + read-write + + + DIN1_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 2 + 2 + read-write + + + DIN2_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 4 + 2 + read-write + + + DIN3_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 6 + 2 + read-write + + + DIN4_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 8 + 2 + read-write + + + DIN5_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 10 + 2 + read-write + + + DIN6_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 12 + 2 + read-write + + + DIN7_MODE + the input signals are delayed by SPI module clock cycles, 0: input without delayed, 1: input with the posedge of clk_apb,2 input with the negedge of clk_apb, 3: input with the spi_clk. Can be configured in CONF state. + 14 + 2 + read-write + + + TIMING_HCLK_ACTIVE + 1:enable hclk in SPI input timing module. 0: disable it. Can be configured in CONF state. + 16 + 1 + read-write + + + + + DIN_NUM + SPI input delay number configuration + 0x28 + 0x20 + + + DIN0_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 0 + 2 + read-write + + + DIN1_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 2 + 2 + read-write + + + DIN2_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 4 + 2 + read-write + + + DIN3_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 6 + 2 + read-write + + + DIN4_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 8 + 2 + read-write + + + DIN5_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 10 + 2 + read-write + + + DIN6_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 12 + 2 + read-write + + + DIN7_NUM + the input signals are delayed by SPI module clock cycles, 0: delayed by 1 cycle, 1: delayed by 2 cycles,... Can be configured in CONF state. + 14 + 2 + read-write + + + + + DOUT_MODE + SPI output delay mode configuration + 0x2C + 0x20 + + + DOUT0_MODE + The output signal 0 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 0 + 1 + read-write + + + DOUT1_MODE + The output signal 1 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 1 + 1 + read-write + + + DOUT2_MODE + The output signal 2 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 2 + 1 + read-write + + + DOUT3_MODE + The output signal 3 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 3 + 1 + read-write + + + DOUT4_MODE + The output signal 4 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 4 + 1 + read-write + + + DOUT5_MODE + The output signal 5 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 5 + 1 + read-write + + + DOUT6_MODE + The output signal 6 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 6 + 1 + read-write + + + DOUT7_MODE + The output signal 7 is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 7 + 1 + read-write + + + D_DQS_MODE + The output signal SPI_DQS is delayed by the SPI module clock, 0: output without delayed, 1: output delay for a SPI module clock cycle at its negative edge. Can be configured in CONF state. + 8 + 1 + read-write + + + + + DMA_CONF + SPI DMA control register + 0x30 + 0x20 + 0x00000003 + + + DMA_OUTFIFO_EMPTY + Records the status of DMA TX FIFO. 1: DMA TX FIFO is not ready for sending data. 0: DMA TX FIFO is ready for sending data. + 0 + 1 + read-only + + + DMA_INFIFO_FULL + Records the status of DMA RX FIFO. 1: DMA RX FIFO is not ready for receiving data. 0: DMA RX FIFO is ready for receiving data. + 1 + 1 + read-only + + + DMA_SLV_SEG_TRANS_EN + Enable dma segment transfer in spi dma half slave mode. 1: enable. 0: disable. + 18 + 1 + read-write + + + SLV_RX_SEG_TRANS_CLR_EN + 1: spi_dma_infifo_full_vld is cleared by spi slave cmd 5. 0: spi_dma_infifo_full_vld is cleared by spi_trans_done. + 19 + 1 + read-write + + + SLV_TX_SEG_TRANS_CLR_EN + 1: spi_dma_outfifo_empty_vld is cleared by spi slave cmd 6. 0: spi_dma_outfifo_empty_vld is cleared by spi_trans_done. + 20 + 1 + read-write + + + RX_EOF_EN + 1: spi_dma_inlink_eof is set when the number of dma pushed data bytes is equal to the value of spi_slv/mst_dma_rd_bytelen[19:0] in spi dma transition. 0: spi_dma_inlink_eof is set by spi_trans_done in non-seg-trans or spi_dma_seg_trans_done in seg-trans. + 21 + 1 + read-write + + + DMA_RX_ENA + Set this bit to enable SPI DMA controlled receive data mode. + 27 + 1 + read-write + + + DMA_TX_ENA + Set this bit to enable SPI DMA controlled send data mode. + 28 + 1 + read-write + + + RX_AFIFO_RST + Set this bit to reset RX AFIFO, which is used to receive data in SPI master and slave mode transfer. + 29 + 1 + write-only + + + BUF_AFIFO_RST + Set this bit to reset BUF TX AFIFO, which is used send data out in SPI slave CPU controlled mode transfer and master mode transfer. + 30 + 1 + write-only + + + DMA_AFIFO_RST + Set this bit to reset DMA TX AFIFO, which is used to send data out in SPI slave DMA controlled mode transfer. + 31 + 1 + write-only + + + + + DMA_INT_ENA + SPI interrupt enable register + 0x34 + 0x20 + + + DMA_INFIFO_FULL_ERR_INT_ENA + The enable bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. + 0 + 1 + read-write + + + DMA_OUTFIFO_EMPTY_ERR_INT_ENA + The enable bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt. + 1 + 1 + read-write + + + SLV_EX_QPI_INT_ENA + The enable bit for SPI slave Ex_QPI interrupt. + 2 + 1 + read-write + + + SLV_EN_QPI_INT_ENA + The enable bit for SPI slave En_QPI interrupt. + 3 + 1 + read-write + + + SLV_CMD7_INT_ENA + The enable bit for SPI slave CMD7 interrupt. + 4 + 1 + read-write + + + SLV_CMD8_INT_ENA + The enable bit for SPI slave CMD8 interrupt. + 5 + 1 + read-write + + + SLV_CMD9_INT_ENA + The enable bit for SPI slave CMD9 interrupt. + 6 + 1 + read-write + + + SLV_CMDA_INT_ENA + The enable bit for SPI slave CMDA interrupt. + 7 + 1 + read-write + + + SLV_RD_DMA_DONE_INT_ENA + The enable bit for SPI_SLV_RD_DMA_DONE_INT interrupt. + 8 + 1 + read-write + + + SLV_WR_DMA_DONE_INT_ENA + The enable bit for SPI_SLV_WR_DMA_DONE_INT interrupt. + 9 + 1 + read-write + + + SLV_RD_BUF_DONE_INT_ENA + The enable bit for SPI_SLV_RD_BUF_DONE_INT interrupt. + 10 + 1 + read-write + + + SLV_WR_BUF_DONE_INT_ENA + The enable bit for SPI_SLV_WR_BUF_DONE_INT interrupt. + 11 + 1 + read-write + + + TRANS_DONE_INT_ENA + The enable bit for SPI_TRANS_DONE_INT interrupt. + 12 + 1 + read-write + + + DMA_SEG_TRANS_DONE_INT_ENA + The enable bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. + 13 + 1 + read-write + + + SEG_MAGIC_ERR_INT_ENA + The enable bit for SPI_SEG_MAGIC_ERR_INT interrupt. + 14 + 1 + read-write + + + SLV_BUF_ADDR_ERR_INT_ENA + The enable bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. + 15 + 1 + read-write + + + SLV_CMD_ERR_INT_ENA + The enable bit for SPI_SLV_CMD_ERR_INT interrupt. + 16 + 1 + read-write + + + MST_RX_AFIFO_WFULL_ERR_INT_ENA + The enable bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. + 17 + 1 + read-write + + + MST_TX_AFIFO_REMPTY_ERR_INT_ENA + The enable bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. + 18 + 1 + read-write + + + APP2_INT_ENA + The enable bit for SPI_APP2_INT interrupt. + 19 + 1 + read-write + + + APP1_INT_ENA + The enable bit for SPI_APP1_INT interrupt. + 20 + 1 + read-write + + + + + DMA_INT_CLR + SPI interrupt clear register + 0x38 + 0x20 + + + DMA_INFIFO_FULL_ERR_INT_CLR + The clear bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. + 0 + 1 + write-only + + + DMA_OUTFIFO_EMPTY_ERR_INT_CLR + The clear bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt. + 1 + 1 + write-only + + + SLV_EX_QPI_INT_CLR + The clear bit for SPI slave Ex_QPI interrupt. + 2 + 1 + write-only + + + SLV_EN_QPI_INT_CLR + The clear bit for SPI slave En_QPI interrupt. + 3 + 1 + write-only + + + SLV_CMD7_INT_CLR + The clear bit for SPI slave CMD7 interrupt. + 4 + 1 + write-only + + + SLV_CMD8_INT_CLR + The clear bit for SPI slave CMD8 interrupt. + 5 + 1 + write-only + + + SLV_CMD9_INT_CLR + The clear bit for SPI slave CMD9 interrupt. + 6 + 1 + write-only + + + SLV_CMDA_INT_CLR + The clear bit for SPI slave CMDA interrupt. + 7 + 1 + write-only + + + SLV_RD_DMA_DONE_INT_CLR + The clear bit for SPI_SLV_RD_DMA_DONE_INT interrupt. + 8 + 1 + write-only + + + SLV_WR_DMA_DONE_INT_CLR + The clear bit for SPI_SLV_WR_DMA_DONE_INT interrupt. + 9 + 1 + write-only + + + SLV_RD_BUF_DONE_INT_CLR + The clear bit for SPI_SLV_RD_BUF_DONE_INT interrupt. + 10 + 1 + write-only + + + SLV_WR_BUF_DONE_INT_CLR + The clear bit for SPI_SLV_WR_BUF_DONE_INT interrupt. + 11 + 1 + write-only + + + TRANS_DONE_INT_CLR + The clear bit for SPI_TRANS_DONE_INT interrupt. + 12 + 1 + write-only + + + DMA_SEG_TRANS_DONE_INT_CLR + The clear bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. + 13 + 1 + write-only + + + SEG_MAGIC_ERR_INT_CLR + The clear bit for SPI_SEG_MAGIC_ERR_INT interrupt. + 14 + 1 + write-only + + + SLV_BUF_ADDR_ERR_INT_CLR + The clear bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. + 15 + 1 + write-only + + + SLV_CMD_ERR_INT_CLR + The clear bit for SPI_SLV_CMD_ERR_INT interrupt. + 16 + 1 + write-only + + + MST_RX_AFIFO_WFULL_ERR_INT_CLR + The clear bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. + 17 + 1 + write-only + + + MST_TX_AFIFO_REMPTY_ERR_INT_CLR + The clear bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. + 18 + 1 + write-only + + + APP2_INT_CLR + The clear bit for SPI_APP2_INT interrupt. + 19 + 1 + write-only + + + APP1_INT_CLR + The clear bit for SPI_APP1_INT interrupt. + 20 + 1 + write-only + + + + + DMA_INT_RAW + SPI interrupt raw register + 0x3C + 0x20 + + + DMA_INFIFO_FULL_ERR_INT_RAW + 1: The current data rate of DMA Rx is smaller than that of SPI, which will lose the receive data. 0: Others. + 0 + 1 + read-only + + + DMA_OUTFIFO_EMPTY_ERR_INT_RAW + 1: The current data rate of DMA TX is smaller than that of SPI. SPI will stop in master mode and send out all 0 in slave mode. 0: Others. + 1 + 1 + read-only + + + SLV_EX_QPI_INT_RAW + The raw bit for SPI slave Ex_QPI interrupt. 1: SPI slave mode Ex_QPI transmission is ended. 0: Others. + 2 + 1 + read-only + + + SLV_EN_QPI_INT_RAW + The raw bit for SPI slave En_QPI interrupt. 1: SPI slave mode En_QPI transmission is ended. 0: Others. + 3 + 1 + read-only + + + SLV_CMD7_INT_RAW + The raw bit for SPI slave CMD7 interrupt. 1: SPI slave mode CMD7 transmission is ended. 0: Others. + 4 + 1 + read-only + + + SLV_CMD8_INT_RAW + The raw bit for SPI slave CMD8 interrupt. 1: SPI slave mode CMD8 transmission is ended. 0: Others. + 5 + 1 + read-only + + + SLV_CMD9_INT_RAW + The raw bit for SPI slave CMD9 interrupt. 1: SPI slave mode CMD9 transmission is ended. 0: Others. + 6 + 1 + read-only + + + SLV_CMDA_INT_RAW + The raw bit for SPI slave CMDA interrupt. 1: SPI slave mode CMDA transmission is ended. 0: Others. + 7 + 1 + read-only + + + SLV_RD_DMA_DONE_INT_RAW + The raw bit for SPI_SLV_RD_DMA_DONE_INT interrupt. 1: SPI slave mode Rd_DMA transmission is ended. 0: Others. + 8 + 1 + read-only + + + SLV_WR_DMA_DONE_INT_RAW + The raw bit for SPI_SLV_WR_DMA_DONE_INT interrupt. 1: SPI slave mode Wr_DMA transmission is ended. 0: Others. + 9 + 1 + read-only + + + SLV_RD_BUF_DONE_INT_RAW + The raw bit for SPI_SLV_RD_BUF_DONE_INT interrupt. 1: SPI slave mode Rd_BUF transmission is ended. 0: Others. + 10 + 1 + read-only + + + SLV_WR_BUF_DONE_INT_RAW + The raw bit for SPI_SLV_WR_BUF_DONE_INT interrupt. 1: SPI slave mode Wr_BUF transmission is ended. 0: Others. + 11 + 1 + read-only + + + TRANS_DONE_INT_RAW + The raw bit for SPI_TRANS_DONE_INT interrupt. 1: SPI master mode transmission is ended. 0: others. + 12 + 1 + read-only + + + DMA_SEG_TRANS_DONE_INT_RAW + The raw bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. 1: spi master DMA full-duplex/half-duplex seg-conf-trans ends or slave half-duplex seg-trans ends. And data has been pushed to corresponding memory. 0: seg-conf-trans or seg-trans is not ended or not occurred. + 13 + 1 + read-only + + + SEG_MAGIC_ERR_INT_RAW + The raw bit for SPI_SEG_MAGIC_ERR_INT interrupt. 1: The magic value in CONF buffer is error in the DMA seg-conf-trans. 0: others. + 14 + 1 + read-only + + + SLV_BUF_ADDR_ERR_INT_RAW + The raw bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. 1: The accessing data address of the current SPI slave mode CPU controlled FD, Wr_BUF or Rd_BUF transmission is bigger than 63. 0: Others. + 15 + 1 + read-only + + + SLV_CMD_ERR_INT_RAW + The raw bit for SPI_SLV_CMD_ERR_INT interrupt. 1: The slave command value in the current SPI slave HD mode transmission is not supported. 0: Others. + 16 + 1 + read-only + + + MST_RX_AFIFO_WFULL_ERR_INT_RAW + The raw bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. 1: There is a RX AFIFO write-full error when SPI inputs data in master mode. 0: Others. + 17 + 1 + read-only + + + MST_TX_AFIFO_REMPTY_ERR_INT_RAW + The raw bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. 1: There is a TX BUF AFIFO read-empty error when SPI outputs data in master mode. 0: Others. + 18 + 1 + read-only + + + APP2_INT_RAW + The raw bit for SPI_APP2_INT interrupt. The value is only controlled by software. + 19 + 1 + read-only + + + APP1_INT_RAW + The raw bit for SPI_APP1_INT interrupt. The value is only controlled by software. + 20 + 1 + read-only + + + + + DMA_INT_ST + SPI interrupt status register + 0x40 + 0x20 + + + DMA_INFIFO_FULL_ERR_INT_ST + The status bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. + 0 + 1 + read-only + + + DMA_OUTFIFO_EMPTY_ERR_INT_ST + The status bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt. + 1 + 1 + read-only + + + SLV_EX_QPI_INT_ST + The status bit for SPI slave Ex_QPI interrupt. + 2 + 1 + read-only + + + SLV_EN_QPI_INT_ST + The status bit for SPI slave En_QPI interrupt. + 3 + 1 + read-only + + + SLV_CMD7_INT_ST + The status bit for SPI slave CMD7 interrupt. + 4 + 1 + read-only + + + SLV_CMD8_INT_ST + The status bit for SPI slave CMD8 interrupt. + 5 + 1 + read-only + + + SLV_CMD9_INT_ST + The status bit for SPI slave CMD9 interrupt. + 6 + 1 + read-only + + + SLV_CMDA_INT_ST + The status bit for SPI slave CMDA interrupt. + 7 + 1 + read-only + + + SLV_RD_DMA_DONE_INT_ST + The status bit for SPI_SLV_RD_DMA_DONE_INT interrupt. + 8 + 1 + read-only + + + SLV_WR_DMA_DONE_INT_ST + The status bit for SPI_SLV_WR_DMA_DONE_INT interrupt. + 9 + 1 + read-only + + + SLV_RD_BUF_DONE_INT_ST + The status bit for SPI_SLV_RD_BUF_DONE_INT interrupt. + 10 + 1 + read-only + + + SLV_WR_BUF_DONE_INT_ST + The status bit for SPI_SLV_WR_BUF_DONE_INT interrupt. + 11 + 1 + read-only + + + TRANS_DONE_INT_ST + The status bit for SPI_TRANS_DONE_INT interrupt. + 12 + 1 + read-only + + + DMA_SEG_TRANS_DONE_INT_ST + The status bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. + 13 + 1 + read-only + + + SEG_MAGIC_ERR_INT_ST + The status bit for SPI_SEG_MAGIC_ERR_INT interrupt. + 14 + 1 + read-only + + + SLV_BUF_ADDR_ERR_INT_ST + The status bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. + 15 + 1 + read-only + + + SLV_CMD_ERR_INT_ST + The status bit for SPI_SLV_CMD_ERR_INT interrupt. + 16 + 1 + read-only + + + MST_RX_AFIFO_WFULL_ERR_INT_ST + The status bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. + 17 + 1 + read-only + + + MST_TX_AFIFO_REMPTY_ERR_INT_ST + The status bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. + 18 + 1 + read-only + + + APP2_INT_ST + The status bit for SPI_APP2_INT interrupt. + 19 + 1 + read-only + + + APP1_INT_ST + The status bit for SPI_APP1_INT interrupt. + 20 + 1 + read-only + + + + + DMA_INT_SET + SPI interrupt software set register + 0x44 + 0x20 + + + DMA_INFIFO_FULL_ERR_INT_SET + The software set bit for SPI_DMA_INFIFO_FULL_ERR_INT interrupt. + 0 + 1 + write-only + + + DMA_OUTFIFO_EMPTY_ERR_INT_SET + The software set bit for SPI_DMA_OUTFIFO_EMPTY_ERR_INT interrupt. + 1 + 1 + write-only + + + SLV_EX_QPI_INT_SET + The software set bit for SPI slave Ex_QPI interrupt. + 2 + 1 + write-only + + + SLV_EN_QPI_INT_SET + The software set bit for SPI slave En_QPI interrupt. + 3 + 1 + write-only + + + SLV_CMD7_INT_SET + The software set bit for SPI slave CMD7 interrupt. + 4 + 1 + write-only + + + SLV_CMD8_INT_SET + The software set bit for SPI slave CMD8 interrupt. + 5 + 1 + write-only + + + SLV_CMD9_INT_SET + The software set bit for SPI slave CMD9 interrupt. + 6 + 1 + write-only + + + SLV_CMDA_INT_SET + The software set bit for SPI slave CMDA interrupt. + 7 + 1 + write-only + + + SLV_RD_DMA_DONE_INT_SET + The software set bit for SPI_SLV_RD_DMA_DONE_INT interrupt. + 8 + 1 + write-only + + + SLV_WR_DMA_DONE_INT_SET + The software set bit for SPI_SLV_WR_DMA_DONE_INT interrupt. + 9 + 1 + write-only + + + SLV_RD_BUF_DONE_INT_SET + The software set bit for SPI_SLV_RD_BUF_DONE_INT interrupt. + 10 + 1 + write-only + + + SLV_WR_BUF_DONE_INT_SET + The software set bit for SPI_SLV_WR_BUF_DONE_INT interrupt. + 11 + 1 + write-only + + + TRANS_DONE_INT_SET + The software set bit for SPI_TRANS_DONE_INT interrupt. + 12 + 1 + write-only + + + DMA_SEG_TRANS_DONE_INT_SET + The software set bit for SPI_DMA_SEG_TRANS_DONE_INT interrupt. + 13 + 1 + write-only + + + SEG_MAGIC_ERR_INT_SET + The software set bit for SPI_SEG_MAGIC_ERR_INT interrupt. + 14 + 1 + write-only + + + SLV_BUF_ADDR_ERR_INT_SET + The software set bit for SPI_SLV_BUF_ADDR_ERR_INT interrupt. + 15 + 1 + write-only + + + SLV_CMD_ERR_INT_SET + The software set bit for SPI_SLV_CMD_ERR_INT interrupt. + 16 + 1 + write-only + + + MST_RX_AFIFO_WFULL_ERR_INT_SET + The software set bit for SPI_MST_RX_AFIFO_WFULL_ERR_INT interrupt. + 17 + 1 + write-only + + + MST_TX_AFIFO_REMPTY_ERR_INT_SET + The software set bit for SPI_MST_TX_AFIFO_REMPTY_ERR_INT interrupt. + 18 + 1 + write-only + + + APP2_INT_SET + The software set bit for SPI_APP2_INT interrupt. + 19 + 1 + write-only + + + APP1_INT_SET + The software set bit for SPI_APP1_INT interrupt. + 20 + 1 + write-only + + + + + W0 + SPI CPU-controlled buffer0 + 0x98 + 0x20 + + + BUF0 + data buffer + 0 + 32 + read-write + + + + + W1 + SPI CPU-controlled buffer1 + 0x9C + 0x20 + + + BUF1 + data buffer + 0 + 32 + read-write + + + + + W2 + SPI CPU-controlled buffer2 + 0xA0 + 0x20 + + + BUF2 + data buffer + 0 + 32 + read-write + + + + + W3 + SPI CPU-controlled buffer3 + 0xA4 + 0x20 + + + BUF3 + data buffer + 0 + 32 + read-write + + + + + W4 + SPI CPU-controlled buffer4 + 0xA8 + 0x20 + + + BUF4 + data buffer + 0 + 32 + read-write + + + + + W5 + SPI CPU-controlled buffer5 + 0xAC + 0x20 + + + BUF5 + data buffer + 0 + 32 + read-write + + + + + W6 + SPI CPU-controlled buffer6 + 0xB0 + 0x20 + + + BUF6 + data buffer + 0 + 32 + read-write + + + + + W7 + SPI CPU-controlled buffer7 + 0xB4 + 0x20 + + + BUF7 + data buffer + 0 + 32 + read-write + + + + + W8 + SPI CPU-controlled buffer8 + 0xB8 + 0x20 + + + BUF8 + data buffer + 0 + 32 + read-write + + + + + W9 + SPI CPU-controlled buffer9 + 0xBC + 0x20 + + + BUF9 + data buffer + 0 + 32 + read-write + + + + + W10 + SPI CPU-controlled buffer10 + 0xC0 + 0x20 + + + BUF10 + data buffer + 0 + 32 + read-write + + + + + W11 + SPI CPU-controlled buffer11 + 0xC4 + 0x20 + + + BUF11 + data buffer + 0 + 32 + read-write + + + + + W12 + SPI CPU-controlled buffer12 + 0xC8 + 0x20 + + + BUF12 + data buffer + 0 + 32 + read-write + + + + + W13 + SPI CPU-controlled buffer13 + 0xCC + 0x20 + + + BUF13 + data buffer + 0 + 32 + read-write + + + + + W14 + SPI CPU-controlled buffer14 + 0xD0 + 0x20 + + + BUF14 + data buffer + 0 + 32 + read-write + + + + + W15 + SPI CPU-controlled buffer15 + 0xD4 + 0x20 + + + BUF15 + data buffer + 0 + 32 + read-write + + + + + SLAVE + SPI slave control register + 0xE0 + 0x20 + 0x02800000 + + + CLK_MODE + SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3: SPI clock is alwasy on. Can be configured in CONF state. + 0 + 2 + read-write + + + CLK_MODE_13 + {CPOL, CPHA},1: support spi clk mode 1 and 3, first edge output data B[0]/B[7]. 0: support spi clk mode 0 and 2, first edge output data B[1]/B[6]. + 2 + 1 + read-write + + + RSCK_DATA_OUT + It saves half a cycle when tsck is the same as rsck. 1: output data at rsck posedge 0: output data at tsck posedge + 3 + 1 + read-write + + + SLV_RDDMA_BITLEN_EN + 1: SPI_SLV_DATA_BITLEN stores data bit length of master-read-slave data length in DMA controlled mode(Rd_DMA). 0: others + 8 + 1 + read-write + + + SLV_WRDMA_BITLEN_EN + 1: SPI_SLV_DATA_BITLEN stores data bit length of master-write-to-slave data length in DMA controlled mode(Wr_DMA). 0: others + 9 + 1 + read-write + + + SLV_RDBUF_BITLEN_EN + 1: SPI_SLV_DATA_BITLEN stores data bit length of master-read-slave data length in CPU controlled mode(Rd_BUF). 0: others + 10 + 1 + read-write + + + SLV_WRBUF_BITLEN_EN + 1: SPI_SLV_DATA_BITLEN stores data bit length of master-write-to-slave data length in CPU controlled mode(Wr_BUF). 0: others + 11 + 1 + read-write + + + DMA_SEG_MAGIC_VALUE + The magic value of BM table in master DMA seg-trans. + 22 + 4 + read-write + + + MODE + Set SPI work mode. 1: slave mode 0: master mode. + 26 + 1 + read-write + + + SOFT_RESET + Software reset enable, reset the spi clock line cs line and data lines. Can be configured in CONF state. + 27 + 1 + write-only + + + USR_CONF + 1: Enable the DMA CONF phase of current seg-trans operation, which means seg-trans will start. 0: This is not seg-trans mode. + 28 + 1 + read-write + + + + + SLAVE1 + SPI slave control register 1 + 0xE4 + 0x20 + + + SLV_DATA_BITLEN + The transferred data bit length in SPI slave FD and HD mode. + 0 + 18 + read-write + + + SLV_LAST_COMMAND + In the slave mode it is the value of command. + 18 + 8 + read-write + + + SLV_LAST_ADDR + In the slave mode it is the value of address. + 26 + 6 + read-write + + + + + CLK_GATE + SPI module clock and register clock control + 0xE8 + 0x20 + + + CLK_EN + Set this bit to enable clk gate + 0 + 1 + read-write + + + MST_CLK_ACTIVE + Set this bit to power on the SPI module clock. + 1 + 1 + read-write + + + MST_CLK_SEL + This bit is used to select SPI module clock source in master mode. 1: PLL_CLK_80M. 0: XTAL CLK. + 2 + 1 + read-write + + + + + DATE + Version control + 0xF0 + 0x20 + 0x02101190 + + + DATE + SPI register version. + 0 + 28 + read-write + + + + + + + SPI3 + SPI (Serial Peripheral Interface) Controller + 0x60025000 + + SPI3 + 22 + + + + SYSTEM + System + SYSTEM + 0x600C0000 + + 0x0 + 0xA8 + registers + + + + CORE_1_CONTROL_0 + Core0 control regiter 0 + 0x0 + 0x20 + 0x00000004 + + + CONTROL_CORE_1_RUNSTALL + Set 1 to stall core1 + 0 + 1 + read-write + + + CONTROL_CORE_1_CLKGATE_EN + Set 1 to open core1 clock + 1 + 1 + read-write + + + CONTROL_CORE_1_RESETING + Set 1 to let core1 reset + 2 + 1 + read-write + + + + + CORE_1_CONTROL_1 + Core0 control regiter 1 + 0x4 + 0x20 + + + CONTROL_CORE_1_MESSAGE + it's only a R/W register, no function, software can write any value + 0 + 32 + read-write + + + + + CPU_PERI_CLK_EN + cpu_peripheral clock configuration register + 0x8 + 0x20 + + + CLK_EN_ASSIST_DEBUG + Set 1 to open assist_debug module clock + 6 + 1 + read-write + + + CLK_EN_DEDICATED_GPIO + Set 1 to open dedicated_gpio module clk + 7 + 1 + read-write + + + + + CPU_PERI_RST_EN + cpu_peripheral reset configuration regsiter + 0xC + 0x20 + 0x000000C0 + + + RST_EN_ASSIST_DEBUG + Set 1 to let assist_debug module reset + 6 + 1 + read-write + + + RST_EN_DEDICATED_GPIO + Set 1 to let dedicated_gpio module reset + 7 + 1 + read-write + + + + + CPU_PER_CONF + cpu peripheral clock configuration register + 0x10 + 0x20 + 0x0000000C + + + CPUPERIOD_SEL + This field used to sel cpu clock frequent. + 0 + 2 + read-write + + + PLL_FREQ_SEL + This field used to sel pll frequent. + 2 + 1 + read-write + + + CPU_WAIT_MODE_FORCE_ON + Set 1 to force cpu_waiti_clk enable. + 3 + 1 + read-write + + + CPU_WAITI_DELAY_NUM + This field used to set delay cycle when cpu enter waiti mode, after delay waiti_clk will close + 4 + 4 + read-write + + + + + MEM_PD_MASK + memory power down mask configuration register + 0x14 + 0x20 + 0x00000001 + + + LSLP_MEM_PD_MASK + Set 1 to mask memory power down. + 0 + 1 + read-write + + + + + PERIP_CLK_EN0 + peripheral clock configuration regsiter 0 + 0x18 + 0x20 + 0xF9C1E06F + + + TIMERS_CLK_EN + Set 1 to enable TIMERS clock + 0 + 1 + read-write + + + SPI01_CLK_EN + Set 1 to enable SPI01 clock + 1 + 1 + read-write + + + UART_CLK_EN + Set 1 to enable UART clock + 2 + 1 + read-write + + + WDG_CLK_EN + Set 1 to enable WDG clock + 3 + 1 + read-write + + + I2S0_CLK_EN + Set 1 to enable I2S0 clock + 4 + 1 + read-write + + + UART1_CLK_EN + Set 1 to enable UART1 clock + 5 + 1 + read-write + + + SPI2_CLK_EN + Set 1 to enable SPI2 clock + 6 + 1 + read-write + + + I2C_EXT0_CLK_EN + Set 1 to enable I2C_EXT0 clock + 7 + 1 + read-write + + + UHCI0_CLK_EN + Set 1 to enable UHCI0 clock + 8 + 1 + read-write + + + RMT_CLK_EN + Set 1 to enable RMT clock + 9 + 1 + read-write + + + PCNT_CLK_EN + Set 1 to enable PCNT clock + 10 + 1 + read-write + + + LEDC_CLK_EN + Set 1 to enable LEDC clock + 11 + 1 + read-write + + + UHCI1_CLK_EN + Set 1 to enable UHCI1 clock + 12 + 1 + read-write + + + TIMERGROUP_CLK_EN + Set 1 to enable TIMERGROUP clock + 13 + 1 + read-write + + + EFUSE_CLK_EN + Set 1 to enable EFUSE clock + 14 + 1 + read-write + + + TIMERGROUP1_CLK_EN + Set 1 to enable TIMERGROUP1 clock + 15 + 1 + read-write + + + SPI3_CLK_EN + Set 1 to enable SPI3 clock + 16 + 1 + read-write + + + PWM0_CLK_EN + Set 1 to enable PWM0 clock + 17 + 1 + read-write + + + I2C_EXT1_CLK_EN + Set 1 to enable I2C_EXT1 clock + 18 + 1 + read-write + + + CAN_CLK_EN + Set 1 to enable CAN clock + 19 + 1 + read-write + + + PWM1_CLK_EN + Set 1 to enable PWM1 clock + 20 + 1 + read-write + + + I2S1_CLK_EN + Set 1 to enable I2S1 clock + 21 + 1 + read-write + + + SPI2_DMA_CLK_EN + Set 1 to enable SPI2_DMA clock + 22 + 1 + read-write + + + USB_CLK_EN + Set 1 to enable USB clock + 23 + 1 + read-write + + + UART_MEM_CLK_EN + Set 1 to enable UART_MEM clock + 24 + 1 + read-write + + + PWM2_CLK_EN + Set 1 to enable PWM2 clock + 25 + 1 + read-write + + + PWM3_CLK_EN + Set 1 to enable PWM3 clock + 26 + 1 + read-write + + + SPI3_DMA_CLK_EN + Set 1 to enable SPI4 clock + 27 + 1 + read-write + + + APB_SARADC_CLK_EN + Set 1 to enable APB_SARADC clock + 28 + 1 + read-write + + + SYSTIMER_CLK_EN + Set 1 to enable SYSTEMTIMER clock + 29 + 1 + read-write + + + ADC2_ARB_CLK_EN + Set 1 to enable ADC2_ARB clock + 30 + 1 + read-write + + + SPI4_CLK_EN + Set 1 to enable SPI4 clock + 31 + 1 + read-write + + + + + PERIP_CLK_EN1 + peripheral clock configuration regsiter 1 + 0x1C + 0x20 + 0x00000600 + + + PERI_BACKUP_CLK_EN + Set 1 to enable BACKUP clock + 0 + 1 + read-write + + + CRYPTO_AES_CLK_EN + Set 1 to enable AES clock + 1 + 1 + read-write + + + CRYPTO_SHA_CLK_EN + Set 1 to enable SHA clock + 2 + 1 + read-write + + + CRYPTO_RSA_CLK_EN + Set 1 to enable RSA clock + 3 + 1 + read-write + + + CRYPTO_DS_CLK_EN + Set 1 to enable DS clock + 4 + 1 + read-write + + + CRYPTO_HMAC_CLK_EN + Set 1 to enable HMAC clock + 5 + 1 + read-write + + + DMA_CLK_EN + Set 1 to enable DMA clock + 6 + 1 + read-write + + + SDIO_HOST_CLK_EN + Set 1 to enable SDIO_HOST clock + 7 + 1 + read-write + + + LCD_CAM_CLK_EN + Set 1 to enable LCD_CAM clock + 8 + 1 + read-write + + + UART2_CLK_EN + Set 1 to enable UART2 clock + 9 + 1 + read-write + + + USB_DEVICE_CLK_EN + Set 1 to enable USB_DEVICE clock + 10 + 1 + read-write + + + + + PERIP_RST_EN0 + peripheral reset configuration register0 + 0x20 + 0x20 + + + TIMERS_RST + Set 1 to let TIMERS reset + 0 + 1 + read-write + + + SPI01_RST + Set 1 to let SPI01 reset + 1 + 1 + read-write + + + UART_RST + Set 1 to let UART reset + 2 + 1 + read-write + + + WDG_RST + Set 1 to let WDG reset + 3 + 1 + read-write + + + I2S0_RST + Set 1 to let I2S0 reset + 4 + 1 + read-write + + + UART1_RST + Set 1 to let UART1 reset + 5 + 1 + read-write + + + SPI2_RST + Set 1 to let SPI2 reset + 6 + 1 + read-write + + + I2C_EXT0_RST + Set 1 to let I2C_EXT0 reset + 7 + 1 + read-write + + + UHCI0_RST + Set 1 to let UHCI0 reset + 8 + 1 + read-write + + + RMT_RST + Set 1 to let RMT reset + 9 + 1 + read-write + + + PCNT_RST + Set 1 to let PCNT reset + 10 + 1 + read-write + + + LEDC_RST + Set 1 to let LEDC reset + 11 + 1 + read-write + + + UHCI1_RST + Set 1 to let UHCI1 reset + 12 + 1 + read-write + + + TIMERGROUP_RST + Set 1 to let TIMERGROUP reset + 13 + 1 + read-write + + + EFUSE_RST + Set 1 to let EFUSE reset + 14 + 1 + read-write + + + TIMERGROUP1_RST + Set 1 to let TIMERGROUP1 reset + 15 + 1 + read-write + + + SPI3_RST + Set 1 to let SPI3 reset + 16 + 1 + read-write + + + PWM0_RST + Set 1 to let PWM0 reset + 17 + 1 + read-write + + + I2C_EXT1_RST + Set 1 to let I2C_EXT1 reset + 18 + 1 + read-write + + + CAN_RST + Set 1 to let CAN reset + 19 + 1 + read-write + + + PWM1_RST + Set 1 to let PWM1 reset + 20 + 1 + read-write + + + I2S1_RST + Set 1 to let I2S1 reset + 21 + 1 + read-write + + + SPI2_DMA_RST + Set 1 to let SPI2 reset + 22 + 1 + read-write + + + USB_RST + Set 1 to let USB reset + 23 + 1 + read-write + + + UART_MEM_RST + Set 1 to let UART_MEM reset + 24 + 1 + read-write + + + PWM2_RST + Set 1 to let PWM2 reset + 25 + 1 + read-write + + + PWM3_RST + Set 1 to let PWM3 reset + 26 + 1 + read-write + + + SPI3_DMA_RST + Set 1 to let SPI3 reset + 27 + 1 + read-write + + + APB_SARADC_RST + Set 1 to let APB_SARADC reset + 28 + 1 + read-write + + + SYSTIMER_RST + Set 1 to let SYSTIMER reset + 29 + 1 + read-write + + + ADC2_ARB_RST + Set 1 to let ADC2_ARB reset + 30 + 1 + read-write + + + SPI4_RST + Set 1 to let SPI4 reset + 31 + 1 + read-write + + + + + PERIP_RST_EN1 + peripheral reset configuration regsiter 1 + 0x24 + 0x20 + 0x000001FE + + + PERI_BACKUP_RST + Set 1 to let BACKUP reset + 0 + 1 + read-write + + + CRYPTO_AES_RST + Set 1 to let CRYPTO_AES reset + 1 + 1 + read-write + + + CRYPTO_SHA_RST + Set 1 to let CRYPTO_SHA reset + 2 + 1 + read-write + + + CRYPTO_RSA_RST + Set 1 to let CRYPTO_RSA reset + 3 + 1 + read-write + + + CRYPTO_DS_RST + Set 1 to let CRYPTO_DS reset + 4 + 1 + read-write + + + CRYPTO_HMAC_RST + Set 1 to let CRYPTO_HMAC reset + 5 + 1 + read-write + + + DMA_RST + Set 1 to let DMA reset + 6 + 1 + read-write + + + SDIO_HOST_RST + Set 1 to let SDIO_HOST reset + 7 + 1 + read-write + + + LCD_CAM_RST + Set 1 to let LCD_CAM reset + 8 + 1 + read-write + + + UART2_RST + Set 1 to let UART2 reset + 9 + 1 + read-write + + + USB_DEVICE_RST + Set 1 to let USB_DEVICE reset + 10 + 1 + read-write + + + + + BT_LPCK_DIV_INT + low power clock frequent division factor configuration regsiter + 0x28 + 0x20 + 0x000000FF + + + BT_LPCK_DIV_NUM + This field is lower power clock frequent division factor + 0 + 12 + read-write + + + + + BT_LPCK_DIV_FRAC + low power clock configuration register + 0x2C + 0x20 + 0x02001001 + + + BT_LPCK_DIV_B + This field is lower power clock frequent division factor b + 0 + 12 + read-write + + + BT_LPCK_DIV_A + This field is lower power clock frequent division factor a + 12 + 12 + read-write + + + LPCLK_SEL_RTC_SLOW + Set 1 to select rtc-slow clock as rtc low power clock + 24 + 1 + read-write + + + LPCLK_SEL_8M + Set 1 to select 8m clock as rtc low power clock + 25 + 1 + read-write + + + LPCLK_SEL_XTAL + Set 1 to select xtal clock as rtc low power clock + 26 + 1 + read-write + + + LPCLK_SEL_XTAL32K + Set 1 to select xtal32k clock as low power clock + 27 + 1 + read-write + + + LPCLK_RTC_EN + Set 1 to enable RTC low power clock + 28 + 1 + read-write + + + + + CPU_INTR_FROM_CPU_0 + interrupt source register 0 + 0x30 + 0x20 + + + CPU_INTR_FROM_CPU_0 + Set 1 to generate cpu interrupt 0 + 0 + 1 + read-write + + + + + CPU_INTR_FROM_CPU_1 + interrupt source register 1 + 0x34 + 0x20 + + + CPU_INTR_FROM_CPU_1 + Set 1 to generate cpu interrupt 1 + 0 + 1 + read-write + + + + + CPU_INTR_FROM_CPU_2 + interrupt source register 2 + 0x38 + 0x20 + + + CPU_INTR_FROM_CPU_2 + Set 1 to generate cpu interrupt 2 + 0 + 1 + read-write + + + + + CPU_INTR_FROM_CPU_3 + interrupt source register 3 + 0x3C + 0x20 + + + CPU_INTR_FROM_CPU_3 + Set 1 to generate cpu interrupt 3 + 0 + 1 + read-write + + + + + RSA_PD_CTRL + rsa memory power control register + 0x40 + 0x20 + 0x00000001 + + + RSA_MEM_PD + Set 1 to power down RSA memory. This bit has the lowest priority.When Digital Signature occupies the RSA, this bit is invalid. + 0 + 1 + read-write + + + RSA_MEM_FORCE_PU + Set 1 to force power up RSA memory, this bit has the second highest priority. + 1 + 1 + read-write + + + RSA_MEM_FORCE_PD + Set 1 to force power down RSA memory,this bit has the highest priority. + 2 + 1 + read-write + + + + + EDMA_CTRL + EDMA control register + 0x44 + 0x20 + 0x00000001 + + + EDMA_CLK_ON + Set 1 to enable EDMA clock. + 0 + 1 + read-write + + + EDMA_RESET + Set 1 to let EDMA reset + 1 + 1 + read-write + + + + + CACHE_CONTROL + Cache control register + 0x48 + 0x20 + 0x00000005 + + + ICACHE_CLK_ON + Set 1 to enable icache clock + 0 + 1 + read-write + + + ICACHE_RESET + Set 1 to let icache reset + 1 + 1 + read-write + + + DCACHE_CLK_ON + Set 1 to enable dcache clock + 2 + 1 + read-write + + + DCACHE_RESET + Set 1 to let dcache reset + 3 + 1 + read-write + + + + + EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL + External memory encrypt and decrypt control register + 0x4C + 0x20 + + + ENABLE_SPI_MANUAL_ENCRYPT + Set 1 to enable the SPI manual encrypt. + 0 + 1 + read-write + + + ENABLE_DOWNLOAD_DB_ENCRYPT + Set 1 to enable download DB encrypt. + 1 + 1 + read-write + + + ENABLE_DOWNLOAD_G0CB_DECRYPT + Set 1 to enable download G0CB decrypt + 2 + 1 + read-write + + + ENABLE_DOWNLOAD_MANUAL_ENCRYPT + Set 1 to enable download manual encrypt + 3 + 1 + read-write + + + + + RTC_FASTMEM_CONFIG + RTC fast memory configuration register + 0x50 + 0x20 + 0x7FF00000 + + + RTC_MEM_CRC_START + Set 1 to start the CRC of RTC memory + 8 + 1 + read-write + + + RTC_MEM_CRC_ADDR + This field is used to set address of RTC memory for CRC. + 9 + 11 + read-write + + + RTC_MEM_CRC_LEN + This field is used to set length of RTC memory for CRC based on start address. + 20 + 11 + read-write + + + RTC_MEM_CRC_FINISH + This bit stores the status of RTC memory CRC.1 means finished. + 31 + 1 + read-only + + + + + RTC_FASTMEM_CRC + RTC fast memory CRC control register + 0x54 + 0x20 + + + RTC_MEM_CRC_RES + This field stores the CRC result of RTC memory. + 0 + 32 + read-only + + + + + REDUNDANT_ECO_CTRL + ******* Description *********** + 0x58 + 0x20 + + + REDUNDANT_ECO_DRIVE + ******* Description *********** + 0 + 1 + read-write + + + REDUNDANT_ECO_RESULT + ******* Description *********** + 1 + 1 + read-only + + + + + CLOCK_GATE + ******* Description *********** + 0x5C + 0x20 + 0x00000001 + + + CLK_EN + ******* Description *********** + 0 + 1 + read-write + + + + + SYSCLK_CONF + System clock configuration register. + 0x60 + 0x20 + 0x00000001 + + + PRE_DIV_CNT + This field is used to set the count of prescaler of XTAL_CLK. + 0 + 10 + read-write + + + SOC_CLK_SEL + This field is used to select soc clock. + 10 + 2 + read-write + + + CLK_XTAL_FREQ + This field is used to read xtal frequency in MHz. + 12 + 7 + read-only + + + CLK_DIV_EN + Reserved. + 19 + 1 + read-only + + + + + MEM_PVT + ******* Description *********** + 0x64 + 0x20 + 0x00000003 + + + MEM_PATH_LEN + ******* Description *********** + 0 + 4 + read-write + + + MEM_ERR_CNT_CLR + ******* Description *********** + 4 + 1 + write-only + + + MONITOR_EN + ******* Description *********** + 5 + 1 + read-write + + + MEM_TIMING_ERR_CNT + ******* Description *********** + 6 + 16 + read-only + + + MEM_VT_SEL + ******* Description *********** + 22 + 2 + read-write + + + + + COMB_PVT_LVT_CONF + ******* Description *********** + 0x68 + 0x20 + 0x00000003 + + + COMB_PATH_LEN_LVT + ******* Description *********** + 0 + 5 + read-write + + + COMB_ERR_CNT_CLR_LVT + ******* Description *********** + 5 + 1 + write-only + + + COMB_PVT_MONITOR_EN_LVT + ******* Description *********** + 6 + 1 + read-write + + + + + COMB_PVT_NVT_CONF + ******* Description *********** + 0x6C + 0x20 + 0x00000003 + + + COMB_PATH_LEN_NVT + ******* Description *********** + 0 + 5 + read-write + + + COMB_ERR_CNT_CLR_NVT + ******* Description *********** + 5 + 1 + write-only + + + COMB_PVT_MONITOR_EN_NVT + ******* Description *********** + 6 + 1 + read-write + + + + + COMB_PVT_HVT_CONF + ******* Description *********** + 0x70 + 0x20 + 0x00000003 + + + COMB_PATH_LEN_HVT + ******* Description *********** + 0 + 5 + read-write + + + COMB_ERR_CNT_CLR_HVT + ******* Description *********** + 5 + 1 + write-only + + + COMB_PVT_MONITOR_EN_HVT + ******* Description *********** + 6 + 1 + read-write + + + + + COMB_PVT_ERR_LVT_SITE0 + ******* Description *********** + 0x74 + 0x20 + + + COMB_TIMING_ERR_CNT_LVT_SITE0 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_NVT_SITE0 + ******* Description *********** + 0x78 + 0x20 + + + COMB_TIMING_ERR_CNT_NVT_SITE0 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_HVT_SITE0 + ******* Description *********** + 0x7C + 0x20 + + + COMB_TIMING_ERR_CNT_HVT_SITE0 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_LVT_SITE1 + ******* Description *********** + 0x80 + 0x20 + + + COMB_TIMING_ERR_CNT_LVT_SITE1 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_NVT_SITE1 + ******* Description *********** + 0x84 + 0x20 + + + COMB_TIMING_ERR_CNT_NVT_SITE1 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_HVT_SITE1 + ******* Description *********** + 0x88 + 0x20 + + + COMB_TIMING_ERR_CNT_HVT_SITE1 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_LVT_SITE2 + ******* Description *********** + 0x8C + 0x20 + + + COMB_TIMING_ERR_CNT_LVT_SITE2 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_NVT_SITE2 + ******* Description *********** + 0x90 + 0x20 + + + COMB_TIMING_ERR_CNT_NVT_SITE2 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_HVT_SITE2 + ******* Description *********** + 0x94 + 0x20 + + + COMB_TIMING_ERR_CNT_HVT_SITE2 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_LVT_SITE3 + ******* Description *********** + 0x98 + 0x20 + + + COMB_TIMING_ERR_CNT_LVT_SITE3 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_NVT_SITE3 + ******* Description *********** + 0x9C + 0x20 + + + COMB_TIMING_ERR_CNT_NVT_SITE3 + ******* Description *********** + 0 + 16 + read-only + + + + + COMB_PVT_ERR_HVT_SITE3 + ******* Description *********** + 0xA0 + 0x20 + + + COMB_TIMING_ERR_CNT_HVT_SITE3 + ******* Description *********** + 0 + 16 + read-only + + + + + DATE + version register + 0xFFC + 0x20 + 0x02101220 + + + DATE + version register + 0 + 28 + read-write + + + + + + + SYSTIMER + System Timer + SYSTIMER + 0x60023000 + + 0x0 + 0x90 + registers + + + SYSTIMER_TARGET0 + 57 + + + SYSTIMER_TARGET1 + 58 + + + SYSTIMER_TARGET2 + 59 + + + + CONF + Configure system timer clock + 0x0 + 0x20 + 0x46000000 + + + SYSTIMER_CLK_FO + systimer clock force on + 0 + 1 + read-write + + + TARGET2_WORK_EN + target2 work enable + 22 + 1 + read-write + + + TARGET1_WORK_EN + target1 work enable + 23 + 1 + read-write + + + TARGET0_WORK_EN + target0 work enable + 24 + 1 + read-write + + + TIMER_UNIT1_CORE1_STALL_EN + If timer unit1 is stalled when core1 stalled + 25 + 1 + read-write + + + TIMER_UNIT1_CORE0_STALL_EN + If timer unit1 is stalled when core0 stalled + 26 + 1 + read-write + + + TIMER_UNIT0_CORE1_STALL_EN + If timer unit0 is stalled when core1 stalled + 27 + 1 + read-write + + + TIMER_UNIT0_CORE0_STALL_EN + If timer unit0 is stalled when core0 stalled + 28 + 1 + read-write + + + TIMER_UNIT1_WORK_EN + timer unit1 work enable + 29 + 1 + read-write + + + TIMER_UNIT0_WORK_EN + timer unit0 work enable + 30 + 1 + read-write + + + CLK_EN + register file clk gating + 31 + 1 + read-write + + + + + UNIT0_OP + system timer unit0 value update register + 0x4 + 0x20 + + + TIMER_UNIT0_VALUE_VALID + timer value is sync and valid + 29 + 1 + read-only + + + TIMER_UNIT0_UPDATE + update timer_unit0 + 30 + 1 + write-only + + + + + UNIT1_OP + system timer unit1 value update register + 0x8 + 0x20 + + + TIMER_UNIT1_VALUE_VALID + timer value is sync and valid + 29 + 1 + read-only + + + TIMER_UNIT1_UPDATE + update timer unit1 + 30 + 1 + write-only + + + + + UNIT0_LOAD_HI + system timer unit0 value high load register + 0xC + 0x20 + + + TIMER_UNIT0_LOAD_HI + timer unit0 load high 20 bits + 0 + 20 + read-write + + + + + UNIT0_LOAD_LO + system timer unit0 value low load register + 0x10 + 0x20 + + + TIMER_UNIT0_LOAD_LO + timer unit0 load low 32 bits + 0 + 32 + read-write + + + + + UNIT1_LOAD_HI + system timer unit1 value high load register + 0x14 + 0x20 + + + TIMER_UNIT1_LOAD_HI + timer unit1 load high 20 bits + 0 + 20 + read-write + + + + + UNIT1_LOAD_LO + system timer unit1 value low load register + 0x18 + 0x20 + + + TIMER_UNIT1_LOAD_LO + timer unit1 load low 32 bits + 0 + 32 + read-write + + + + + TARGET0_HI + system timer comp0 value high register + 0x1C + 0x20 + + + TIMER_TARGET0_HI + timer taget0 high 20 bits + 0 + 20 + read-write + + + + + TARGET0_LO + system timer comp0 value low register + 0x20 + 0x20 + + + TIMER_TARGET0_LO + timer taget0 low 32 bits + 0 + 32 + read-write + + + + + TARGET1_HI + system timer comp1 value high register + 0x24 + 0x20 + + + TIMER_TARGET1_HI + timer taget1 high 20 bits + 0 + 20 + read-write + + + + + TARGET1_LO + system timer comp1 value low register + 0x28 + 0x20 + + + TIMER_TARGET1_LO + timer taget1 low 32 bits + 0 + 32 + read-write + + + + + TARGET2_HI + system timer comp2 value high register + 0x2C + 0x20 + + + TIMER_TARGET2_HI + timer taget2 high 20 bits + 0 + 20 + read-write + + + + + TARGET2_LO + system timer comp2 value low register + 0x30 + 0x20 + + + TIMER_TARGET2_LO + timer taget2 low 32 bits + 0 + 32 + read-write + + + + + TARGET0_CONF + system timer comp0 target mode register + 0x34 + 0x20 + + + TARGET0_PERIOD + target0 period + 0 + 26 + read-write + + + TARGET0_PERIOD_MODE + Set target0 to period mode + 30 + 1 + read-write + + + TARGET0_TIMER_UNIT_SEL + select which unit to compare + 31 + 1 + read-write + + + + + TARGET1_CONF + system timer comp1 target mode register + 0x38 + 0x20 + + + TARGET1_PERIOD + target1 period + 0 + 26 + read-write + + + TARGET1_PERIOD_MODE + Set target1 to period mode + 30 + 1 + read-write + + + TARGET1_TIMER_UNIT_SEL + select which unit to compare + 31 + 1 + read-write + + + + + TARGET2_CONF + system timer comp2 target mode register + 0x3C + 0x20 + + + TARGET2_PERIOD + target2 period + 0 + 26 + read-write + + + TARGET2_PERIOD_MODE + Set target2 to period mode + 30 + 1 + read-write + + + TARGET2_TIMER_UNIT_SEL + select which unit to compare + 31 + 1 + read-write + + + + + UNIT0_VALUE_HI + system timer unit0 value high register + 0x40 + 0x20 + + + TIMER_UNIT0_VALUE_HI + timer read value high 20bits + 0 + 20 + read-only + + + + + UNIT0_VALUE_LO + system timer unit0 value low register + 0x44 + 0x20 + + + TIMER_UNIT0_VALUE_LO + timer read value low 32bits + 0 + 32 + read-only + + + + + UNIT1_VALUE_HI + system timer unit1 value high register + 0x48 + 0x20 + + + TIMER_UNIT1_VALUE_HI + timer read value high 20bits + 0 + 20 + read-only + + + + + UNIT1_VALUE_LO + system timer unit1 value low register + 0x4C + 0x20 + + + TIMER_UNIT1_VALUE_LO + timer read value low 32bits + 0 + 32 + read-only + + + + + COMP0_LOAD + system timer comp0 conf sync register + 0x50 + 0x20 + + + TIMER_COMP0_LOAD + timer comp0 sync enable signal + 0 + 1 + write-only + + + + + COMP1_LOAD + system timer comp1 conf sync register + 0x54 + 0x20 + + + TIMER_COMP1_LOAD + timer comp1 sync enable signal + 0 + 1 + write-only + + + + + COMP2_LOAD + system timer comp2 conf sync register + 0x58 + 0x20 + + + TIMER_COMP2_LOAD + timer comp2 sync enable signal + 0 + 1 + write-only + + + + + UNIT0_LOAD + system timer unit0 conf sync register + 0x5C + 0x20 + + + TIMER_UNIT0_LOAD + timer unit0 sync enable signal + 0 + 1 + write-only + + + + + UNIT1_LOAD + system timer unit1 conf sync register + 0x60 + 0x20 + + + TIMER_UNIT1_LOAD + timer unit1 sync enable signal + 0 + 1 + write-only + + + + + INT_ENA + systimer interrupt enable register + 0x64 + 0x20 + + + TARGET0_INT_ENA + interupt0 enable + 0 + 1 + read-write + + + TARGET1_INT_ENA + interupt1 enable + 1 + 1 + read-write + + + TARGET2_INT_ENA + interupt2 enable + 2 + 1 + read-write + + + + + INT_RAW + systimer interrupt raw register + 0x68 + 0x20 + + + TARGET0_INT_RAW + interupt0 raw + 0 + 1 + read-only + + + TARGET1_INT_RAW + interupt1 raw + 1 + 1 + read-only + + + TARGET2_INT_RAW + interupt2 raw + 2 + 1 + read-only + + + + + INT_CLR + systimer interrupt clear register + 0x6C + 0x20 + + + TARGET0_INT_CLR + interupt0 clear + 0 + 1 + write-only + + + TARGET1_INT_CLR + interupt1 clear + 1 + 1 + write-only + + + TARGET2_INT_CLR + interupt2 clear + 2 + 1 + write-only + + + + + INT_ST + systimer interrupt status register + 0x70 + 0x20 + + + TARGET0_INT_ST + interupt0 status + 0 + 1 + read-only + + + TARGET1_INT_ST + interupt1 status + 1 + 1 + read-only + + + TARGET2_INT_ST + interupt2 status + 2 + 1 + read-only + + + + + REAL_TARGET0_LO + system timer comp0 actual target value low register + 0x74 + 0x20 + + + TARGET0_LO_RO + actual target value value low 32bits + 0 + 32 + read-only + + + + + REAL_TARGET0_HI + system timer comp0 actual target value high register + 0x78 + 0x20 + + + TARGET0_HI_RO + actual target value value high 20bits + 0 + 20 + read-only + + + + + REAL_TARGET1_LO + system timer comp1 actual target value low register + 0x7C + 0x20 + + + TARGET1_LO_RO + actual target value value low 32bits + 0 + 32 + read-only + + + + + REAL_TARGET1_HI + system timer comp1 actual target value high register + 0x80 + 0x20 + + + TARGET1_HI_RO + actual target value value high 20bits + 0 + 20 + read-only + + + + + REAL_TARGET2_LO + system timer comp2 actual target value low register + 0x84 + 0x20 + + + TARGET2_LO_RO + actual target value value low 32bits + 0 + 32 + read-only + + + + + REAL_TARGET2_HI + system timer comp2 actual target value high register + 0x88 + 0x20 + + + TARGET2_HI_RO + actual target value value high 20bits + 0 + 20 + read-only + + + + + DATE + system timer version control register + 0xFC + 0x20 + 0x02012251 + + + DATE + systimer register version + 0 + 32 + read-write + + + + + + + TIMG0 + Timer Group + TIMG + 0x6001F000 + + 0x0 + 0x8C + registers + + + TG0_T0_LEVEL + 50 + + + TG0_T1_LEVEL + 51 + + + TG0_WDT_LEVEL + 52 + + + + 2 + 0x24 + T%sCONFIG + Timer %s configuration register + 0x0 + 0x20 + 0x60002000 + + + USE_XTAL + 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source clock of timer group. + 9 + 1 + read-write + + + ALARM_EN + When set, the alarm is enabled. This bit is automatically cleared once an +alarm occurs. + 10 + 1 + read-write + + + DIVIDER + Timer %s clock (T%s_clk) prescaler value. + 13 + 16 + read-write + + + AUTORELOAD + When set, timer %s auto-reload at alarm is enabled. + 29 + 1 + read-write + + + INCREASE + When set, the timer %s time-base counter will increment every clock tick. When +cleared, the timer %s time-base counter will decrement. + 30 + 1 + read-write + + + EN + When set, the timer %s time-base counter is enabled. + 31 + 1 + read-write + + + + + 2 + 0x24 + T%sLO + Timer %s current value, low 32 bits + 0x4 + 0x20 + + + LO + After writing to TIMG_T%sUPDATE_REG, the low 32 bits of the time-base counter +of timer %s can be read here. + 0 + 32 + read-only + + + + + 2 + 0x24 + T%sHI + Timer %s current value, high 22 bits + 0x8 + 0x20 + + + HI + After writing to TIMG_T%sUPDATE_REG, the high 22 bits of the time-base counter +of timer %s can be read here. + 0 + 22 + read-only + + + + + 2 + 0x24 + T%sUPDATE + Write to copy current timer value to TIMGn_T%s_(LO/HI)_REG + 0xC + 0x20 + + + UPDATE + After writing 0 or 1 to TIMG_T%sUPDATE_REG, the counter value is latched. + 31 + 1 + read-write + + + + + 2 + 0x24 + T%sALARMLO + Timer %s alarm value, low 32 bits + 0x10 + 0x20 + + + ALARM_LO + Timer %s alarm trigger time-base counter value, low 32 bits. + 0 + 32 + read-write + + + + + 2 + 0x24 + T%sALARMHI + Timer %s alarm value, high bits + 0x14 + 0x20 + + + ALARM_HI + Timer %s alarm trigger time-base counter value, high 22 bits. + 0 + 22 + read-write + + + + + 2 + 0x24 + T%sLOADLO + Timer %s reload value, low 32 bits + 0x18 + 0x20 + + + LOAD_LO + Low 32 bits of the value that a reload will load onto timer %s time-base +Counter. + 0 + 32 + read-write + + + + + 2 + 0x24 + T%sLOADHI + Timer %s reload value, high 22 bits + 0x1C + 0x20 + + + LOAD_HI + High 22 bits of the value that a reload will load onto timer %s time-base +counter. + 0 + 22 + read-write + + + + + 2 + 0x24 + T%sLOAD + Write to reload timer from TIMG_T%s_(LOADLOLOADHI)_REG + 0x20 + 0x20 + + + LOAD + +Write any value to trigger a timer %s time-base counter reload. + 0 + 32 + write-only + + + + + WDTCONFIG0 + Watchdog timer configuration register + 0x48 + 0x20 + 0x0004C000 + + + WDT_APPCPU_RESET_EN + Reserved + 12 + 1 + read-write + + + WDT_PROCPU_RESET_EN + WDT reset CPU enable. + 13 + 1 + read-write + + + WDT_FLASHBOOT_MOD_EN + When set, Flash boot protection is enabled. + 14 + 1 + read-write + + + WDT_SYS_RESET_LENGTH + System reset signal length selection. 0: 100 ns, 1: 200 ns, +2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + 15 + 3 + read-write + + + WDT_CPU_RESET_LENGTH + CPU reset signal length selection. 0: 100 ns, 1: 200 ns, +2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + 18 + 3 + read-write + + + WDT_STG3 + Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + + 23 + 2 + read-write + + + WDT_STG2 + Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + + 25 + 2 + read-write + + + WDT_STG1 + Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + + 27 + 2 + read-write + + + WDT_STG0 + Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + + 29 + 2 + read-write + + + WDT_EN + When set, MWDT is enabled. + 31 + 1 + read-write + + + + + WDTCONFIG1 + Watchdog timer prescaler register + 0x4C + 0x20 + 0x00010000 + + + WDT_CLK_PRESCALE + MWDT clock prescaler value. MWDT clock period = 12.5 ns * +TIMG_WDT_CLK_PRESCALE. + 16 + 16 + read-write + + + + + WDTCONFIG2 + Watchdog timer stage 0 timeout value + 0x50 + 0x20 + 0x018CBA80 + + + WDT_STG0_HOLD + Stage 0 timeout value, in MWDT clock cycles. + 0 + 32 + read-write + + + + + WDTCONFIG3 + Watchdog timer stage 1 timeout value + 0x54 + 0x20 + 0x07FFFFFF + + + WDT_STG1_HOLD + Stage 1 timeout value, in MWDT clock cycles. + 0 + 32 + read-write + + + + + WDTCONFIG4 + Watchdog timer stage 2 timeout value + 0x58 + 0x20 + 0x000FFFFF + + + WDT_STG2_HOLD + Stage 2 timeout value, in MWDT clock cycles. + 0 + 32 + read-write + + + + + WDTCONFIG5 + Watchdog timer stage 3 timeout value + 0x5C + 0x20 + 0x000FFFFF + + + WDT_STG3_HOLD + Stage 3 timeout value, in MWDT clock cycles. + 0 + 32 + read-write + + + + + WDTFEED + Write to feed the watchdog timer + 0x60 + 0x20 + + + WDT_FEED + Write any value to feed the MWDT. (WO) + 0 + 32 + write-only + + + + + WDTWPROTECT + Watchdog write protect register + 0x64 + 0x20 + 0x50D83AA1 + + + WDT_WKEY + If the register contains a different value than its reset value, write +protection is enabled. + 0 + 32 + read-write + + + + + RTCCALICFG + RTC calibration configure register + 0x68 + 0x20 + 0x00013000 + + + RTC_CALI_START_CYCLING + Reserved + 12 + 1 + read-write + + + RTC_CALI_CLK_SEL + 0:rtc slow clock. 1:clk_80m. 2:xtal_32k. + 13 + 2 + read-write + + + RTC_CALI_RDY + Reserved + 15 + 1 + read-only + + + RTC_CALI_MAX + Reserved + 16 + 15 + read-write + + + RTC_CALI_START + Reserved + 31 + 1 + read-write + + + + + RTCCALICFG1 + RTC calibration configure1 register + 0x6C + 0x20 + + + RTC_CALI_CYCLING_DATA_VLD + Reserved + 0 + 1 + read-only + + + RTC_CALI_VALUE + Reserved + 7 + 25 + read-only + + + + + INT_ENA_TIMERS + Interrupt enable bits + 0x70 + 0x20 + + + T0_INT_ENA + The interrupt enable bit for the TIMG_T0_INT interrupt. + 0 + 1 + read-write + + + T1_INT_ENA + The interrupt enable bit for the TIMG_T1_INT interrupt. + 1 + 1 + read-write + + + WDT_INT_ENA + The interrupt enable bit for the TIMG_WDT_INT interrupt. + 2 + 1 + read-write + + + + + INT_RAW_TIMERS + Raw interrupt status + 0x74 + 0x20 + + + T0_INT_RAW + The raw interrupt status bit for the TIMG_T0_INT interrupt. + 0 + 1 + read-only + + + T1_INT_RAW + The raw interrupt status bit for the TIMG_T1_INT interrupt. + 1 + 1 + read-only + + + WDT_INT_RAW + The raw interrupt status bit for the TIMG_WDT_INT interrupt. + 2 + 1 + read-only + + + + + INT_ST_TIMERS + Masked interrupt status + 0x78 + 0x20 + + + T0_INT_ST + The masked interrupt status bit for the TIMG_T0_INT interrupt. + 0 + 1 + read-only + + + T1_INT_ST + The masked interrupt status bit for the TIMG_T1_INT interrupt. + 1 + 1 + read-only + + + WDT_INT_ST + The masked interrupt status bit for the TIMG_WDT_INT interrupt. + 2 + 1 + read-only + + + + + INT_CLR_TIMERS + Interrupt clear bits + 0x7C + 0x20 + + + T0_INT_CLR + Set this bit to clear the TIMG_T0_INT interrupt. + 0 + 1 + write-only + + + T1_INT_CLR + Set this bit to clear the TIMG_T1_INT interrupt. + 1 + 1 + write-only + + + WDT_INT_CLR + Set this bit to clear the TIMG_WDT_INT interrupt. + 2 + 1 + write-only + + + + + RTCCALICFG2 + Timer group calibration register + 0x80 + 0x20 + 0xFFFFFF98 + + + RTC_CALI_TIMEOUT + RTC calibration timeout indicator + 0 + 1 + read-only + + + RTC_CALI_TIMEOUT_RST_CNT + Cycles that release calibration timeout reset + 3 + 4 + read-write + + + RTC_CALI_TIMEOUT_THRES + Threshold value for the RTC calibration timer. If the calibration timer's value exceeds this threshold, a timeout is triggered. + 7 + 25 + read-write + + + + + NTIMERS_DATE + Timer version control register + 0xF8 + 0x20 + 0x02003071 + + + NTIMERS_DATE + Timer version control register + 0 + 28 + read-write + + + + + REGCLK + Timer group clock gate register + 0xFC + 0x20 + + + CLK_EN + Register clock gate signal. 1: The clock for software to read and write registers is always on. 0: The clock for software to read and write registers only exits when the operation happens. + 31 + 1 + read-write + + + + + + + TIMG1 + Timer Group + 0x60020000 + + TG1_T0_LEVEL + 53 + + + TG1_T1_LEVEL + 54 + + + TG1_WDT_LEVEL + 55 + + + + TWAI + Two-Wire Automotive Interface + TWAI + 0x6002B000 + + 0x0 + 0x6C + registers + + + TWAI + 45 + + + + MODE + Mode Register + 0x0 + 0x20 + 0x00000001 + + + RESET_MODE + This bit is used to configure the operating mode of the TWAI Controller. 1: Reset mode; 0: Operating mode. + 0 + 1 + read-write + + + LISTEN_ONLY_MODE + 1: Listen only mode. In this mode the nodes will only receive messages from the bus, without generating the acknowledge signal nor updating the RX error counter. + 1 + 1 + read-write + + + SELF_TEST_MODE + 1: Self test mode. In this mode the TX nodes can perform a successful transmission without receiving the acknowledge signal. This mode is often used to test a single node with the self reception request command. + 2 + 1 + read-write + + + RX_FILTER_MODE + This bit is used to configure the filter mode. 0: Dual filter mode; 1: Single filter mode. + 3 + 1 + read-write + + + + + CMD + Command Register + 0x4 + 0x20 + + + TX_REQ + Set the bit to 1 to allow the driving nodes start transmission. + 0 + 1 + write-only + + + ABORT_TX + Set the bit to 1 to cancel a pending transmission request. + 1 + 1 + write-only + + + RELEASE_BUF + Set the bit to 1 to release the RX buffer. + 2 + 1 + write-only + + + CLR_OVERRUN + Set the bit to 1 to clear the data overrun status bit. + 3 + 1 + write-only + + + SELF_RX_REQ + Self reception request command. Set the bit to 1 to allow a message be transmitted and received simultaneously. + 4 + 1 + write-only + + + + + STATUS + Status register + 0x8 + 0x20 + + + RX_BUF_ST + 1: The data in the RX buffer is not empty, with at least one received data packet. + 0 + 1 + read-only + + + OVERRUN_ST + 1: The RX FIFO is full and data overrun has occurred. + 1 + 1 + read-only + + + TX_BUF_ST + 1: The TX buffer is empty, the CPU may write a message into it. + 2 + 1 + read-only + + + TX_COMPLETE + 1: The TWAI controller has successfully received a packet from the bus. + 3 + 1 + read-only + + + RX_ST + 1: The TWAI Controller is receiving a message from the bus. + 4 + 1 + read-only + + + TX_ST + 1: The TWAI Controller is transmitting a message to the bus. + 5 + 1 + read-only + + + ERR_ST + 1: At least one of the RX/TX error counter has reached or exceeded the value set in register TWAI_ERR_WARNING_LIMIT_REG. + 6 + 1 + read-only + + + BUS_OFF_ST + 1: In bus-off status, the TWAI Controller is no longer involved in bus activities. + 7 + 1 + read-only + + + MISS_ST + This bit reflects whether the data packet in the RX FIFO is complete. 1: The current packet is missing; 0: The current packet is complete + 8 + 1 + read-only + + + + + INT_RAW + Interrupt Register + 0xC + 0x20 + + + RX_INT_ST + Receive interrupt. If this bit is set to 1, it indicates there are messages to be handled in the RX FIFO. + 0 + 1 + read-only + + + TX_INT_ST + Transmit interrupt. If this bit is set to 1, it indicates the message transmitting mis- sion is finished and a new transmission is able to execute. + 1 + 1 + read-only + + + ERR_WARN_INT_ST + Error warning interrupt. If this bit is set to 1, it indicates the error status signal and the bus-off status signal of Status register have changed (e.g., switched from 0 to 1 or from 1 to 0). + 2 + 1 + read-only + + + OVERRUN_INT_ST + Data overrun interrupt. If this bit is set to 1, it indicates a data overrun interrupt is generated in the RX FIFO. + 3 + 1 + read-only + + + ERR_PASSIVE_INT_ST + Error passive interrupt. If this bit is set to 1, it indicates the TWAI Controller is switched between error active status and error passive status due to the change of error counters. + 5 + 1 + read-only + + + ARB_LOST_INT_ST + Arbitration lost interrupt. If this bit is set to 1, it indicates an arbitration lost interrupt is generated. + 6 + 1 + read-only + + + BUS_ERR_INT_ST + Error interrupt. If this bit is set to 1, it indicates an error is detected on the bus. + 7 + 1 + read-only + + + + + INT_ENA + Interrupt Enable Register + 0x10 + 0x20 + + + RX_INT_ENA + Set this bit to 1 to enable receive interrupt. + 0 + 1 + read-write + + + TX_INT_ENA + Set this bit to 1 to enable transmit interrupt. + 1 + 1 + read-write + + + ERR_WARN_INT_ENA + Set this bit to 1 to enable error warning interrupt. + 2 + 1 + read-write + + + OVERRUN_INT_ENA + Set this bit to 1 to enable data overrun interrupt. + 3 + 1 + read-write + + + ERR_PASSIVE_INT_ENA + Set this bit to 1 to enable error passive interrupt. + 5 + 1 + read-write + + + ARB_LOST_INT_ENA + Set this bit to 1 to enable arbitration lost interrupt. + 6 + 1 + read-write + + + BUS_ERR_INT_ENA + Set this bit to 1 to enable error interrupt. + 7 + 1 + read-write + + + + + BUS_TIMING_0 + Bus Timing Register 0 + 0x18 + 0x20 + + + BAUD_PRESC + Baud Rate Prescaler, determines the frequency dividing ratio. + 0 + 14 + + + SYNC_JUMP_WIDTH + Synchronization Jump Width (SJW), 1 \verb+~+ 14 Tq wide. + 14 + 2 + + + + + BUS_TIMING_1 + Bus Timing Register 1 + 0x1C + 0x20 + + + TIME_SEG1 + The width of PBS1. + 0 + 4 + + + TIME_SEG2 + The width of PBS2. + 4 + 3 + + + TIME_SAMP + The number of sample points. 0: the bus is sampled once; 1: the bus is sampled three times + 7 + 1 + + + + + ARB_LOST_CAP + Arbitration Lost Capture Register + 0x2C + 0x20 + + + ARB_LOST_CAP + This register contains information about the bit position of lost arbitration. + 0 + 5 + read-only + + + + + ERR_CODE_CAP + Error Code Capture Register + 0x30 + 0x20 + + + ECC_SEGMENT + This register contains information about the location of errors, see Table 181 for details. + 0 + 5 + read-only + + + ECC_DIRECTION + This register contains information about transmission direction of the node when error occurs. 1: Error occurs when receiving a message; 0: Error occurs when transmitting a message + 5 + 1 + read-only + + + ECC_TYPE + This register contains information about error types: 00: bit error; 01: form error; 10: stuff error; 11: other type of error + 6 + 2 + read-only + + + + + ERR_WARNING_LIMIT + Error Warning Limit Register + 0x34 + 0x20 + 0x00000060 + + + ERR_WARNING_LIMIT + Error warning threshold. In the case when any of a error counter value exceeds the threshold, or all the error counter values are below the threshold, an error warning interrupt will be triggered (given the enable signal is valid). + 0 + 8 + + + + + RX_ERR_CNT + Receive Error Counter Register + 0x38 + 0x20 + + + RX_ERR_CNT + The RX error counter register, reflects value changes under reception status. + 0 + 8 + + + + + TX_ERR_CNT + Transmit Error Counter Register + 0x3C + 0x20 + + + TX_ERR_CNT + The TX error counter register, reflects value changes under transmission status. + 0 + 8 + + + + + DATA_0 + Data register 0 + 0x40 + 0x20 + + + TX_BYTE_0 + In reset mode, it is acceptance code register 0 with R/W Permission. In operation mode, it stores the 0th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_1 + Data register 1 + 0x44 + 0x20 + + + TX_BYTE_1 + In reset mode, it is acceptance code register 1 with R/W Permission. In operation mode, it stores the 1st byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_2 + Data register 2 + 0x48 + 0x20 + + + TX_BYTE_2 + In reset mode, it is acceptance code register 2 with R/W Permission. In operation mode, it stores the 2nd byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_3 + Data register 3 + 0x4C + 0x20 + + + TX_BYTE_3 + In reset mode, it is acceptance code register 3 with R/W Permission. In operation mode, it stores the 3rd byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_4 + Data register 4 + 0x50 + 0x20 + + + TX_BYTE_4 + In reset mode, it is acceptance mask register 0 with R/W Permission. In operation mode, it stores the 4th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_5 + Data register 5 + 0x54 + 0x20 + + + TX_BYTE_5 + In reset mode, it is acceptance mask register 1 with R/W Permission. In operation mode, it stores the 5th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_6 + Data register 6 + 0x58 + 0x20 + + + TX_BYTE_6 + In reset mode, it is acceptance mask register 2 with R/W Permission. In operation mode, it stores the 6th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_7 + Data register 7 + 0x5C + 0x20 + + + TX_BYTE_7 + In reset mode, it is acceptance mask register 3 with R/W Permission. In operation mode, it stores the 7th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_8 + Data register 8 + 0x60 + 0x20 + + + TX_BYTE_8 + Stored the 8th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_9 + Data register 9 + 0x64 + 0x20 + + + TX_BYTE_9 + Stored the 9th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_10 + Data register 10 + 0x68 + 0x20 + + + TX_BYTE_10 + Stored the 10th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_11 + Data register 11 + 0x6C + 0x20 + + + TX_BYTE_11 + Stored the 11th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + DATA_12 + Data register 12 + 0x70 + 0x20 + + + TX_BYTE_12 + Stored the 12th byte information of the data to be transmitted under operating mode. + 0 + 8 + write-only + + + + + RX_MESSAGE_CNT + Receive Message Counter Register + 0x74 + 0x20 + + + RX_MESSAGE_COUNTER + This register reflects the number of messages available within the RX FIFO. + 0 + 7 + read-only + + + + + CLOCK_DIVIDER + Clock Divider register + 0x7C + 0x20 + + + CD + These bits are used to configure frequency dividing coefficients of the external CLKOUT pin. + 0 + 8 + read-write + + + CLOCK_OFF + This bit can be configured under reset mode. 1: Disable the external CLKOUT pin; 0: Enable the external CLKOUT pin + 8 + 1 + + + + + + + UART0 + UART (Universal Asynchronous Receiver-Transmitter) Controller + UART + 0x60000000 + + 0x0 + 0x84 + registers + + + UART0 + 27 + + + + FIFO + FIFO data register + 0x0 + 0x20 + + + RXFIFO_RD_BYTE + UART 0 accesses FIFO via this register. + 0 + 8 + read-write + + + + + INT_RAW + Raw interrupt status + 0x4 + 0x20 + 0x00000002 + + + RXFIFO_FULL_INT_RAW + This interrupt raw bit turns to high level when receiver receives more data than what rxfifo_full_thrhd specifies. + 0 + 1 + read-only + + + TXFIFO_EMPTY_INT_RAW + This interrupt raw bit turns to high level when the amount of data in Tx-FIFO is less than what txfifo_empty_thrhd specifies . + 1 + 1 + read-only + + + PARITY_ERR_INT_RAW + This interrupt raw bit turns to high level when receiver detects a parity error in the data. + 2 + 1 + read-only + + + FRM_ERR_INT_RAW + This interrupt raw bit turns to high level when receiver detects a data frame error . + 3 + 1 + read-only + + + RXFIFO_OVF_INT_RAW + This interrupt raw bit turns to high level when receiver receives more data than the FIFO can store. + 4 + 1 + read-only + + + DSR_CHG_INT_RAW + This interrupt raw bit turns to high level when receiver detects the edge change of DSRn signal. + 5 + 1 + read-only + + + CTS_CHG_INT_RAW + This interrupt raw bit turns to high level when receiver detects the edge change of CTSn signal. + 6 + 1 + read-only + + + BRK_DET_INT_RAW + This interrupt raw bit turns to high level when receiver detects a 0 after the stop bit. + 7 + 1 + read-only + + + RXFIFO_TOUT_INT_RAW + This interrupt raw bit turns to high level when receiver takes more time than rx_tout_thrhd to receive a byte. + 8 + 1 + read-only + + + SW_XON_INT_RAW + This interrupt raw bit turns to high level when receiver recevies Xon char when uart_sw_flow_con_en is set to 1. + 9 + 1 + read-only + + + SW_XOFF_INT_RAW + This interrupt raw bit turns to high level when receiver receives Xoff char when uart_sw_flow_con_en is set to 1. + 10 + 1 + read-only + + + GLITCH_DET_INT_RAW + This interrupt raw bit turns to high level when receiver detects a glitch in the middle of a start bit. + 11 + 1 + read-only + + + TX_BRK_DONE_INT_RAW + This interrupt raw bit turns to high level when transmitter completes sending NULL characters, after all data in Tx-FIFO are sent. + 12 + 1 + read-only + + + TX_BRK_IDLE_DONE_INT_RAW + This interrupt raw bit turns to high level when transmitter has kept the shortest duration after sending the last data. + 13 + 1 + read-only + + + TX_DONE_INT_RAW + This interrupt raw bit turns to high level when transmitter has send out all data in FIFO. + 14 + 1 + read-only + + + RS485_PARITY_ERR_INT_RAW + This interrupt raw bit turns to high level when receiver detects a parity error from the echo of transmitter in rs485 mode. + 15 + 1 + read-only + + + RS485_FRM_ERR_INT_RAW + This interrupt raw bit turns to high level when receiver detects a data frame error from the echo of transmitter in rs485 mode. + 16 + 1 + read-only + + + RS485_CLASH_INT_RAW + This interrupt raw bit turns to high level when detects a clash between transmitter and receiver in rs485 mode. + 17 + 1 + read-only + + + AT_CMD_CHAR_DET_INT_RAW + This interrupt raw bit turns to high level when receiver detects the configured at_cmd char. + 18 + 1 + read-only + + + WAKEUP_INT_RAW + This interrupt raw bit turns to high level when input rxd edge changes more times than what reg_active_threshold specifies in light sleeping mode. + 19 + 1 + read-only + + + + + INT_ST + Masked interrupt status + 0x8 + 0x20 + + + RXFIFO_FULL_INT_ST + This is the status bit for rxfifo_full_int_raw when rxfifo_full_int_ena is set to 1. + 0 + 1 + read-only + + + TXFIFO_EMPTY_INT_ST + This is the status bit for txfifo_empty_int_raw when txfifo_empty_int_ena is set to 1. + 1 + 1 + read-only + + + PARITY_ERR_INT_ST + This is the status bit for parity_err_int_raw when parity_err_int_ena is set to 1. + 2 + 1 + read-only + + + FRM_ERR_INT_ST + This is the status bit for frm_err_int_raw when frm_err_int_ena is set to 1. + 3 + 1 + read-only + + + RXFIFO_OVF_INT_ST + This is the status bit for rxfifo_ovf_int_raw when rxfifo_ovf_int_ena is set to 1. + 4 + 1 + read-only + + + DSR_CHG_INT_ST + This is the status bit for dsr_chg_int_raw when dsr_chg_int_ena is set to 1. + 5 + 1 + read-only + + + CTS_CHG_INT_ST + This is the status bit for cts_chg_int_raw when cts_chg_int_ena is set to 1. + 6 + 1 + read-only + + + BRK_DET_INT_ST + This is the status bit for brk_det_int_raw when brk_det_int_ena is set to 1. + 7 + 1 + read-only + + + RXFIFO_TOUT_INT_ST + This is the status bit for rxfifo_tout_int_raw when rxfifo_tout_int_ena is set to 1. + 8 + 1 + read-only + + + SW_XON_INT_ST + This is the status bit for sw_xon_int_raw when sw_xon_int_ena is set to 1. + 9 + 1 + read-only + + + SW_XOFF_INT_ST + This is the status bit for sw_xoff_int_raw when sw_xoff_int_ena is set to 1. + 10 + 1 + read-only + + + GLITCH_DET_INT_ST + This is the status bit for glitch_det_int_raw when glitch_det_int_ena is set to 1. + 11 + 1 + read-only + + + TX_BRK_DONE_INT_ST + This is the status bit for tx_brk_done_int_raw when tx_brk_done_int_ena is set to 1. + 12 + 1 + read-only + + + TX_BRK_IDLE_DONE_INT_ST + This is the stauts bit for tx_brk_idle_done_int_raw when tx_brk_idle_done_int_ena is set to 1. + 13 + 1 + read-only + + + TX_DONE_INT_ST + This is the status bit for tx_done_int_raw when tx_done_int_ena is set to 1. + 14 + 1 + read-only + + + RS485_PARITY_ERR_INT_ST + This is the status bit for rs485_parity_err_int_raw when rs485_parity_int_ena is set to 1. + 15 + 1 + read-only + + + RS485_FRM_ERR_INT_ST + This is the status bit for rs485_frm_err_int_raw when rs485_fm_err_int_ena is set to 1. + 16 + 1 + read-only + + + RS485_CLASH_INT_ST + This is the status bit for rs485_clash_int_raw when rs485_clash_int_ena is set to 1. + 17 + 1 + read-only + + + AT_CMD_CHAR_DET_INT_ST + This is the status bit for at_cmd_det_int_raw when at_cmd_char_det_int_ena is set to 1. + 18 + 1 + read-only + + + WAKEUP_INT_ST + This is the status bit for uart_wakeup_int_raw when uart_wakeup_int_ena is set to 1. + 19 + 1 + read-only + + + + + INT_ENA + Interrupt enable bits + 0xC + 0x20 + + + RXFIFO_FULL_INT_ENA + This is the enable bit for rxfifo_full_int_st register. + 0 + 1 + read-write + + + TXFIFO_EMPTY_INT_ENA + This is the enable bit for txfifo_empty_int_st register. + 1 + 1 + read-write + + + PARITY_ERR_INT_ENA + This is the enable bit for parity_err_int_st register. + 2 + 1 + read-write + + + FRM_ERR_INT_ENA + This is the enable bit for frm_err_int_st register. + 3 + 1 + read-write + + + RXFIFO_OVF_INT_ENA + This is the enable bit for rxfifo_ovf_int_st register. + 4 + 1 + read-write + + + DSR_CHG_INT_ENA + This is the enable bit for dsr_chg_int_st register. + 5 + 1 + read-write + + + CTS_CHG_INT_ENA + This is the enable bit for cts_chg_int_st register. + 6 + 1 + read-write + + + BRK_DET_INT_ENA + This is the enable bit for brk_det_int_st register. + 7 + 1 + read-write + + + RXFIFO_TOUT_INT_ENA + This is the enable bit for rxfifo_tout_int_st register. + 8 + 1 + read-write + + + SW_XON_INT_ENA + This is the enable bit for sw_xon_int_st register. + 9 + 1 + read-write + + + SW_XOFF_INT_ENA + This is the enable bit for sw_xoff_int_st register. + 10 + 1 + read-write + + + GLITCH_DET_INT_ENA + This is the enable bit for glitch_det_int_st register. + 11 + 1 + read-write + + + TX_BRK_DONE_INT_ENA + This is the enable bit for tx_brk_done_int_st register. + 12 + 1 + read-write + + + TX_BRK_IDLE_DONE_INT_ENA + This is the enable bit for tx_brk_idle_done_int_st register. + 13 + 1 + read-write + + + TX_DONE_INT_ENA + This is the enable bit for tx_done_int_st register. + 14 + 1 + read-write + + + RS485_PARITY_ERR_INT_ENA + This is the enable bit for rs485_parity_err_int_st register. + 15 + 1 + read-write + + + RS485_FRM_ERR_INT_ENA + This is the enable bit for rs485_parity_err_int_st register. + 16 + 1 + read-write + + + RS485_CLASH_INT_ENA + This is the enable bit for rs485_clash_int_st register. + 17 + 1 + read-write + + + AT_CMD_CHAR_DET_INT_ENA + This is the enable bit for at_cmd_char_det_int_st register. + 18 + 1 + read-write + + + WAKEUP_INT_ENA + This is the enable bit for uart_wakeup_int_st register. + 19 + 1 + read-write + + + + + INT_CLR + Interrupt clear bits + 0x10 + 0x20 + + + RXFIFO_FULL_INT_CLR + Set this bit to clear the rxfifo_full_int_raw interrupt. + 0 + 1 + write-only + + + TXFIFO_EMPTY_INT_CLR + Set this bit to clear txfifo_empty_int_raw interrupt. + 1 + 1 + write-only + + + PARITY_ERR_INT_CLR + Set this bit to clear parity_err_int_raw interrupt. + 2 + 1 + write-only + + + FRM_ERR_INT_CLR + Set this bit to clear frm_err_int_raw interrupt. + 3 + 1 + write-only + + + RXFIFO_OVF_INT_CLR + Set this bit to clear rxfifo_ovf_int_raw interrupt. + 4 + 1 + write-only + + + DSR_CHG_INT_CLR + Set this bit to clear the dsr_chg_int_raw interrupt. + 5 + 1 + write-only + + + CTS_CHG_INT_CLR + Set this bit to clear the cts_chg_int_raw interrupt. + 6 + 1 + write-only + + + BRK_DET_INT_CLR + Set this bit to clear the brk_det_int_raw interrupt. + 7 + 1 + write-only + + + RXFIFO_TOUT_INT_CLR + Set this bit to clear the rxfifo_tout_int_raw interrupt. + 8 + 1 + write-only + + + SW_XON_INT_CLR + Set this bit to clear the sw_xon_int_raw interrupt. + 9 + 1 + write-only + + + SW_XOFF_INT_CLR + Set this bit to clear the sw_xoff_int_raw interrupt. + 10 + 1 + write-only + + + GLITCH_DET_INT_CLR + Set this bit to clear the glitch_det_int_raw interrupt. + 11 + 1 + write-only + + + TX_BRK_DONE_INT_CLR + Set this bit to clear the tx_brk_done_int_raw interrupt.. + 12 + 1 + write-only + + + TX_BRK_IDLE_DONE_INT_CLR + Set this bit to clear the tx_brk_idle_done_int_raw interrupt. + 13 + 1 + write-only + + + TX_DONE_INT_CLR + Set this bit to clear the tx_done_int_raw interrupt. + 14 + 1 + write-only + + + RS485_PARITY_ERR_INT_CLR + Set this bit to clear the rs485_parity_err_int_raw interrupt. + 15 + 1 + write-only + + + RS485_FRM_ERR_INT_CLR + Set this bit to clear the rs485_frm_err_int_raw interrupt. + 16 + 1 + write-only + + + RS485_CLASH_INT_CLR + Set this bit to clear the rs485_clash_int_raw interrupt. + 17 + 1 + write-only + + + AT_CMD_CHAR_DET_INT_CLR + Set this bit to clear the at_cmd_char_det_int_raw interrupt. + 18 + 1 + write-only + + + WAKEUP_INT_CLR + Set this bit to clear the uart_wakeup_int_raw interrupt. + 19 + 1 + write-only + + + + + CLKDIV + Clock divider configuration + 0x14 + 0x20 + 0x000002B6 + + + CLKDIV + The integral part of the frequency divider factor. + 0 + 12 + read-write + + + FRAG + The decimal part of the frequency divider factor. + 20 + 4 + read-write + + + + + RX_FILT + Rx Filter configuration + 0x18 + 0x20 + 0x00000008 + + + GLITCH_FILT + when input pulse width is lower than this value, the pulse is ignored. + 0 + 8 + read-write + + + GLITCH_FILT_EN + Set this bit to enable Rx signal filter. + 8 + 1 + read-write + + + + + STATUS + UART status register + 0x1C + 0x20 + 0xE000C000 + + + RXFIFO_CNT + Stores the byte number of valid data in Rx-FIFO. + 0 + 10 + read-only + + + DSRN + The register represent the level value of the internal uart dsr signal. + 13 + 1 + read-only + + + CTSN + This register represent the level value of the internal uart cts signal. + 14 + 1 + read-only + + + RXD + This register represent the level value of the internal uart rxd signal. + 15 + 1 + read-only + + + TXFIFO_CNT + Stores the byte number of data in Tx-FIFO. + 16 + 10 + read-only + + + DTRN + This bit represents the level of the internal uart dtr signal. + 29 + 1 + read-only + + + RTSN + This bit represents the level of the internal uart rts signal. + 30 + 1 + read-only + + + TXD + This bit represents the level of the internal uart txd signal. + 31 + 1 + read-only + + + + + CONF0 + a + 0x20 + 0x20 + 0x1000001C + + + PARITY + This register is used to configure the parity check mode. + 0 + 1 + read-write + + + PARITY_EN + Set this bit to enable uart parity check. + 1 + 1 + read-write + + + BIT_NUM + This register is used to set the length of data. + 2 + 2 + read-write + + + STOP_BIT_NUM + This register is used to set the length of stop bit. + 4 + 2 + read-write + + + SW_RTS + This register is used to configure the software rts signal which is used in software flow control. + 6 + 1 + read-write + + + SW_DTR + This register is used to configure the software dtr signal which is used in software flow control. + 7 + 1 + read-write + + + TXD_BRK + Set this bit to enbale transmitter to send NULL when the process of sending data is done. + 8 + 1 + read-write + + + IRDA_DPLX + Set this bit to enable IrDA loopback mode. + 9 + 1 + read-write + + + IRDA_TX_EN + This is the start enable bit for IrDA transmitter. + 10 + 1 + read-write + + + IRDA_WCTL + 1'h1: The IrDA transmitter's 11th bit is the same as 10th bit. 1'h0: Set IrDA transmitter's 11th bit to 0. + 11 + 1 + read-write + + + IRDA_TX_INV + Set this bit to invert the level of IrDA transmitter. + 12 + 1 + read-write + + + IRDA_RX_INV + Set this bit to invert the level of IrDA receiver. + 13 + 1 + read-write + + + LOOPBACK + Set this bit to enable uart loopback test mode. + 14 + 1 + read-write + + + TX_FLOW_EN + Set this bit to enable flow control function for transmitter. + 15 + 1 + read-write + + + IRDA_EN + Set this bit to enable IrDA protocol. + 16 + 1 + read-write + + + RXFIFO_RST + Set this bit to reset the uart receive-FIFO. + 17 + 1 + read-write + + + TXFIFO_RST + Set this bit to reset the uart transmit-FIFO. + 18 + 1 + read-write + + + RXD_INV + Set this bit to inverse the level value of uart rxd signal. + 19 + 1 + read-write + + + CTS_INV + Set this bit to inverse the level value of uart cts signal. + 20 + 1 + read-write + + + DSR_INV + Set this bit to inverse the level value of uart dsr signal. + 21 + 1 + read-write + + + TXD_INV + Set this bit to inverse the level value of uart txd signal. + 22 + 1 + read-write + + + RTS_INV + Set this bit to inverse the level value of uart rts signal. + 23 + 1 + read-write + + + DTR_INV + Set this bit to inverse the level value of uart dtr signal. + 24 + 1 + read-write + + + CLK_EN + 1'h1: Force clock on for register. 1'h0: Support clock only when application writes registers. + 25 + 1 + read-write + + + ERR_WR_MASK + 1'h1: Receiver stops storing data into FIFO when data is wrong. 1'h0: Receiver stores the data even if the received data is wrong. + 26 + 1 + read-write + + + AUTOBAUD_EN + This is the enable bit for detecting baudrate. + 27 + 1 + read-write + + + MEM_CLK_EN + UART memory clock gate enable signal. + 28 + 1 + read-write + + + + + CONF1 + Configuration register 1 + 0x24 + 0x20 + 0x00018060 + + + RXFIFO_FULL_THRHD + It will produce rxfifo_full_int interrupt when receiver receives more data than this register value. + 0 + 10 + read-write + + + TXFIFO_EMPTY_THRHD + It will produce txfifo_empty_int interrupt when the data amount in Tx-FIFO is less than this register value. + 10 + 10 + read-write + + + DIS_RX_DAT_OVF + Disable UART Rx data overflow detect. + 20 + 1 + read-write + + + RX_TOUT_FLOW_DIS + Set this bit to stop accumulating idle_cnt when hardware flow control works. + 21 + 1 + read-write + + + RX_FLOW_EN + This is the flow enable bit for UART receiver. + 22 + 1 + read-write + + + RX_TOUT_EN + This is the enble bit for uart receiver's timeout function. + 23 + 1 + read-write + + + + + LOWPULSE + Autobaud minimum low pulse duration register + 0x28 + 0x20 + 0x00000FFF + + + MIN_CNT + This register stores the value of the minimum duration time of the low level pulse. It is used in baud rate-detect process. + 0 + 12 + read-only + + + + + HIGHPULSE + Autobaud minimum high pulse duration register + 0x2C + 0x20 + 0x00000FFF + + + MIN_CNT + This register stores the value of the maxinum duration time for the high level pulse. It is used in baud rate-detect process. + 0 + 12 + read-only + + + + + RXD_CNT + Autobaud edge change count register + 0x30 + 0x20 + + + RXD_EDGE_CNT + This register stores the count of rxd edge change. It is used in baud rate-detect process. + 0 + 10 + read-only + + + + + FLOW_CONF + Software flow-control configuration + 0x34 + 0x20 + + + SW_FLOW_CON_EN + Set this bit to enable software flow control. It is used with register sw_xon or sw_xoff. + 0 + 1 + read-write + + + XONOFF_DEL + Set this bit to remove flow control char from the received data. + 1 + 1 + read-write + + + FORCE_XON + Set this bit to enable the transmitter to go on sending data. + 2 + 1 + read-write + + + FORCE_XOFF + Set this bit to stop the transmitter from sending data. + 3 + 1 + read-write + + + SEND_XON + Set this bit to send Xon char. It is cleared by hardware automatically. + 4 + 1 + read-write + + + SEND_XOFF + Set this bit to send Xoff char. It is cleared by hardware automatically. + 5 + 1 + read-write + + + + + SLEEP_CONF + Sleep-mode configuration + 0x38 + 0x20 + 0x000000F0 + + + ACTIVE_THRESHOLD + The uart is activated from light sleeping mode when the input rxd edge changes more times than this register value. + 0 + 10 + read-write + + + + + SWFC_CONF0 + Software flow-control character configuration + 0x3C + 0x20 + 0x00004CE0 + + + XOFF_THRESHOLD + When the data amount in Rx-FIFO is more than this register value with uart_sw_flow_con_en set to 1, it will send a Xoff char. + 0 + 10 + read-write + + + XOFF_CHAR + This register stores the Xoff flow control char. + 10 + 8 + read-write + + + + + SWFC_CONF1 + Software flow-control character configuration + 0x40 + 0x20 + 0x00004400 + + + XON_THRESHOLD + When the data amount in Rx-FIFO is less than this register value with uart_sw_flow_con_en set to 1, it will send a Xon char. + 0 + 10 + read-write + + + XON_CHAR + This register stores the Xon flow control char. + 10 + 8 + read-write + + + + + TXBRK_CONF + Tx Break character configuration + 0x44 + 0x20 + 0x0000000A + + + TX_BRK_NUM + This register is used to configure the number of 0 to be sent after the process of sending data is done. It is active when txd_brk is set to 1. + 0 + 8 + read-write + + + + + IDLE_CONF + Frame-end idle configuration + 0x48 + 0x20 + 0x00040100 + + + RX_IDLE_THRHD + It will produce frame end signal when receiver takes more time to receive one byte data than this register value. + 0 + 10 + read-write + + + TX_IDLE_NUM + This register is used to configure the duration time between transfers. + 10 + 10 + read-write + + + + + RS485_CONF + RS485 mode configuration + 0x4C + 0x20 + + + RS485_EN + Set this bit to choose the rs485 mode. + 0 + 1 + read-write + + + DL0_EN + Set this bit to delay the stop bit by 1 bit. + 1 + 1 + read-write + + + DL1_EN + Set this bit to delay the stop bit by 1 bit. + 2 + 1 + read-write + + + RS485TX_RX_EN + Set this bit to enable receiver could receive data when the transmitter is transmitting data in rs485 mode. + 3 + 1 + read-write + + + RS485RXBY_TX_EN + 1'h1: enable rs485 transmitter to send data when rs485 receiver line is busy. + 4 + 1 + read-write + + + RS485_RX_DLY_NUM + This register is used to delay the receiver's internal data signal. + 5 + 1 + read-write + + + RS485_TX_DLY_NUM + This register is used to delay the transmitter's internal data signal. + 6 + 4 + read-write + + + + + AT_CMD_PRECNT + Pre-sequence timing configuration + 0x50 + 0x20 + 0x00000901 + + + PRE_IDLE_NUM + This register is used to configure the idle duration time before the first at_cmd is received by receiver. + 0 + 16 + read-write + + + + + AT_CMD_POSTCNT + Post-sequence timing configuration + 0x54 + 0x20 + 0x00000901 + + + POST_IDLE_NUM + This register is used to configure the duration time between the last at_cmd and the next data. + 0 + 16 + read-write + + + + + AT_CMD_GAPTOUT + Timeout configuration + 0x58 + 0x20 + 0x0000000B + + + RX_GAP_TOUT + This register is used to configure the duration time between the at_cmd chars. + 0 + 16 + read-write + + + + + AT_CMD_CHAR + AT escape sequence detection configuration + 0x5C + 0x20 + 0x0000032B + + + AT_CMD_CHAR + This register is used to configure the content of at_cmd char. + 0 + 8 + read-write + + + CHAR_NUM + This register is used to configure the num of continuous at_cmd chars received by receiver. + 8 + 8 + read-write + + + + + MEM_CONF + UART threshold and allocation configuration + 0x60 + 0x20 + 0x00140012 + + + RX_SIZE + This register is used to configure the amount of mem allocated for receive-FIFO. The default number is 128 bytes. + 1 + 3 + read-write + + + TX_SIZE + This register is used to configure the amount of mem allocated for transmit-FIFO. The default number is 128 bytes. + 4 + 3 + read-write + + + RX_FLOW_THRHD + This register is used to configure the maximum amount of data that can be received when hardware flow control works. + 7 + 10 + read-write + + + RX_TOUT_THRHD + This register is used to configure the threshold time that receiver takes to receive one byte. The rxfifo_tout_int interrupt will be trigger when the receiver takes more time to receive one byte with rx_tout_en set to 1. + 17 + 10 + read-write + + + MEM_FORCE_PD + Set this bit to force power down UART memory. + 27 + 1 + read-write + + + MEM_FORCE_PU + Set this bit to force power up UART memory. + 28 + 1 + read-write + + + + + MEM_TX_STATUS + Tx-FIFO write and read offset address. + 0x64 + 0x20 + + + APB_TX_WADDR + This register stores the offset address in Tx-FIFO when software writes Tx-FIFO via APB. + 0 + 10 + read-only + + + TX_RADDR + This register stores the offset address in Tx-FIFO when Tx-FSM reads data via Tx-FIFO_Ctrl. + 11 + 10 + read-only + + + + + MEM_RX_STATUS + Rx-FIFO write and read offset address. + 0x68 + 0x20 + 0x00100200 + + + APB_RX_RADDR + This register stores the offset address in RX-FIFO when software reads data from Rx-FIFO via APB. UART0 is 10'h200. UART1 is 10'h280. UART2 is 10'h300. + 0 + 10 + read-only + + + RX_WADDR + This register stores the offset address in Rx-FIFO when Rx-FIFO_Ctrl writes Rx-FIFO. UART0 is 10'h200. UART1 is 10'h280. UART2 is 10'h300. + 11 + 10 + read-only + + + + + FSM_STATUS + UART transmit and receive status. + 0x6C + 0x20 + + + ST_URX_OUT + This is the status register of receiver. + 0 + 4 + read-only + + + ST_UTX_OUT + This is the status register of transmitter. + 4 + 4 + read-only + + + + + POSPULSE + Autobaud high pulse register + 0x70 + 0x20 + 0x00000FFF + + + POSEDGE_MIN_CNT + This register stores the minimal input clock count between two positive edges. It is used in boudrate-detect process. + 0 + 12 + read-only + + + + + NEGPULSE + Autobaud low pulse register + 0x74 + 0x20 + 0x00000FFF + + + NEGEDGE_MIN_CNT + This register stores the minimal input clock count between two negative edges. It is used in boudrate-detect process. + 0 + 12 + read-only + + + + + CLK_CONF + UART core clock configuration + 0x78 + 0x20 + 0x03701000 + + + SCLK_DIV_B + The denominator of the frequency divider factor. + 0 + 6 + read-write + + + SCLK_DIV_A + The numerator of the frequency divider factor. + 6 + 6 + read-write + + + SCLK_DIV_NUM + The integral part of the frequency divider factor. + 12 + 8 + read-write + + + SCLK_SEL + UART clock source select. 1: 80Mhz, 2: 8Mhz, 3: XTAL. + 20 + 2 + read-write + + + SCLK_EN + Set this bit to enable UART Tx/Rx clock. + 22 + 1 + read-write + + + RST_CORE + Write 1 then write 0 to this bit, reset UART Tx/Rx. + 23 + 1 + read-write + + + TX_SCLK_EN + Set this bit to enable UART Tx clock. + 24 + 1 + read-write + + + RX_SCLK_EN + Set this bit to enable UART Rx clock. + 25 + 1 + read-write + + + TX_RST_CORE + Write 1 then write 0 to this bit, reset UART Tx. + 26 + 1 + read-write + + + RX_RST_CORE + Write 1 then write 0 to this bit, reset UART Rx. + 27 + 1 + read-write + + + + + DATE + UART Version register + 0x7C + 0x20 + 0x02008270 + + + DATE + This is the version register. + 0 + 32 + read-write + + + + + ID + UART ID register + 0x80 + 0x20 + 0x40000500 + + + ID + This register is used to configure the uart_id. + 0 + 30 + read-write + + + HIGH_SPEED + This bit used to select synchronize mode. 1: Registers are auto synchronized into UART Core clock and UART core should be keep the same with APB clock. 0: After configure registers, software needs to write 1 to UART_REG_UPDATE to synchronize registers. + 30 + 1 + read-write + + + REG_UPDATE + Software write 1 would synchronize registers into UART Core clock domain and would be cleared by hardware after synchronization is done. + 31 + 1 + read-write + + + + + + + UART1 + UART (Universal Asynchronous Receiver-Transmitter) Controller + 0x60010000 + + UART1 + 28 + + + + UART2 + UART (Universal Asynchronous Receiver-Transmitter) Controller + 0x6002E000 + + UART2 + 29 + + + + UHCI0 + Universal Host Controller Interface + UHCI + 0x60014000 + + 0x0 + 0x88 + registers + + + UHCI0 + 14 + + + + CONF0 + UHCI configuration register + 0x0 + 0x20 + 0x000006E0 + + + TX_RST + Write 1, then write 0 to this bit to reset decode state machine. + 0 + 1 + read-write + + + RX_RST + Write 1, then write 0 to this bit to reset encode state machine. + 1 + 1 + read-write + + + UART0_CE + Set this bit to link up HCI and UART0. + 2 + 1 + read-write + + + UART1_CE + Set this bit to link up HCI and UART1. + 3 + 1 + read-write + + + UART2_CE + Set this bit to link up HCI and UART2. + 4 + 1 + read-write + + + SEPER_EN + Set this bit to separate the data frame using a special char. + 5 + 1 + read-write + + + HEAD_EN + Set this bit to encode the data packet with a formatting header. + 6 + 1 + read-write + + + CRC_REC_EN + Set this bit to enable UHCI to receive the 16 bit CRC. + 7 + 1 + read-write + + + UART_IDLE_EOF_EN + If this bit is set to 1, UHCI will end the payload receiving process when UART has been in idle state. + 8 + 1 + read-write + + + LEN_EOF_EN + If this bit is set to 1, UHCI decoder receiving payload data is end when the receiving byte count has reached the specified value. The value is payload length indicated by UHCI packet header when UHCI_HEAD_EN is 1 or the value is configuration value when UHCI_HEAD_EN is 0. If this bit is set to 0, UHCI decoder receiving payload data is end when 0xc0 is received. + 9 + 1 + read-write + + + ENCODE_CRC_EN + Set this bit to enable data integrity checking by appending a 16 bit CCITT-CRC to end of the payload. + 10 + 1 + read-write + + + CLK_EN + 1'b1: Force clock on for register. 1'b0: Support clock only when application writes registers. + 11 + 1 + read-write + + + UART_RX_BRK_EOF_EN + If this bit is set to 1, UHCI will end payload receive process when NULL frame is received by UART. + 12 + 1 + read-write + + + + + INT_RAW + Raw interrupt status + 0x4 + 0x20 + + + RX_START_INT_RAW + This is the interrupt raw bit. Triggered when a separator char has been sent. + 0 + 1 + read-only + + + TX_START_INT_RAW + This is the interrupt raw bit. Triggered when UHCI detects a separator char. + 1 + 1 + read-only + + + RX_HUNG_INT_RAW + This is the interrupt raw bit. Triggered when UHCI takes more time to receive data than configure value. + 2 + 1 + read-only + + + TX_HUNG_INT_RAW + This is the interrupt raw bit. Triggered when UHCI takes more time to read data from RAM than the configured value. + 3 + 1 + read-only + + + SEND_S_REG_Q_INT_RAW + This is the interrupt raw bit. Triggered when UHCI has sent out a short packet using single_send registers. + 4 + 1 + read-only + + + SEND_A_REG_Q_INT_RAW + This is the interrupt raw bit. Triggered when UHCI has sent out a short packet using always_send registers. + 5 + 1 + read-only + + + OUT_EOF_INT_RAW + This is the interrupt raw bit. Triggered when there are some errors in EOF in the transmit data. + 6 + 1 + read-only + + + APP_CTRL0_INT_RAW + This is the interrupt raw bit. Triggered when set UHCI_APP_CTRL0_IN_SET. + 7 + 1 + read-write + + + APP_CTRL1_INT_RAW + This is the interrupt raw bit. Triggered when set UHCI_APP_CTRL1_IN_SET. + 8 + 1 + read-write + + + + + INT_ST + Masked interrupt status + 0x8 + 0x20 + + + RX_START_INT_ST + This is the masked interrupt bit for UHCI_RX_START_INT interrupt when UHCI_RX_START_INT_ENA is set to 1. + 0 + 1 + read-only + + + TX_START_INT_ST + This is the masked interrupt bit for UHCI_TX_START_INT interrupt when UHCI_TX_START_INT_ENA is set to 1. + 1 + 1 + read-only + + + RX_HUNG_INT_ST + This is the masked interrupt bit for UHCI_RX_HUNG_INT interrupt when UHCI_RX_HUNG_INT_ENA is set to 1. + 2 + 1 + read-only + + + TX_HUNG_INT_ST + This is the masked interrupt bit for UHCI_TX_HUNG_INT interrupt when UHCI_TX_HUNG_INT_ENA is set to 1. + 3 + 1 + read-only + + + SEND_S_REG_Q_INT_ST + This is the masked interrupt bit for UHCI_SEND_S_REQ_Q_INT interrupt when UHCI_SEND_S_REQ_Q_INT_ENA is set to 1. + 4 + 1 + read-only + + + SEND_A_REG_Q_INT_ST + This is the masked interrupt bit for UHCI_SEND_A_REQ_Q_INT interrupt when UHCI_SEND_A_REQ_Q_INT_ENA is set to 1. + 5 + 1 + read-only + + + OUTLINK_EOF_ERR_INT_ST + This is the masked interrupt bit for UHCI_OUTLINK_EOF_ERR_INT interrupt when UHCI_OUTLINK_EOF_ERR_INT_ENA is set to 1. + 6 + 1 + read-only + + + APP_CTRL0_INT_ST + This is the masked interrupt bit for UHCI_APP_CTRL0_INT interrupt when UHCI_APP_CTRL0_INT_ENA is set to 1. + 7 + 1 + read-only + + + APP_CTRL1_INT_ST + This is the masked interrupt bit for UHCI_APP_CTRL1_INT interrupt when UHCI_APP_CTRL1_INT_ENA is set to 1. + 8 + 1 + read-only + + + + + INT_ENA + Interrupt enable bits + 0xC + 0x20 + + + RX_START_INT_ENA + This is the interrupt enable bit for UHCI_RX_START_INT interrupt. + 0 + 1 + read-write + + + TX_START_INT_ENA + This is the interrupt enable bit for UHCI_TX_START_INT interrupt. + 1 + 1 + read-write + + + RX_HUNG_INT_ENA + This is the interrupt enable bit for UHCI_RX_HUNG_INT interrupt. + 2 + 1 + read-write + + + TX_HUNG_INT_ENA + This is the interrupt enable bit for UHCI_TX_HUNG_INT interrupt. + 3 + 1 + read-write + + + SEND_S_REG_Q_INT_ENA + This is the interrupt enable bit for UHCI_SEND_S_REQ_Q_INT interrupt. + 4 + 1 + read-write + + + SEND_A_REG_Q_INT_ENA + This is the interrupt enable bit for UHCI_SEND_A_REQ_Q_INT interrupt. + 5 + 1 + read-write + + + OUTLINK_EOF_ERR_INT_ENA + This is the interrupt enable bit for UHCI_OUTLINK_EOF_ERR_INT interrupt. + 6 + 1 + read-write + + + APP_CTRL0_INT_ENA + This is the interrupt enable bit for UHCI_APP_CTRL0_INT interrupt. + 7 + 1 + read-write + + + APP_CTRL1_INT_ENA + This is the interrupt enable bit for UHCI_APP_CTRL1_INT interrupt. + 8 + 1 + read-write + + + + + INT_CLR + Interrupt clear bits + 0x10 + 0x20 + + + RX_START_INT_CLR + Set this bit to clear UHCI_RX_START_INT interrupt. + 0 + 1 + write-only + + + TX_START_INT_CLR + Set this bit to clear UHCI_TX_START_INT interrupt. + 1 + 1 + write-only + + + RX_HUNG_INT_CLR + Set this bit to clear UHCI_RX_HUNG_INT interrupt. + 2 + 1 + write-only + + + TX_HUNG_INT_CLR + Set this bit to clear UHCI_TX_HUNG_INT interrupt. + 3 + 1 + write-only + + + SEND_S_REG_Q_INT_CLR + Set this bit to clear UHCI_SEND_S_REQ_Q_INT interrupt. + 4 + 1 + write-only + + + SEND_A_REG_Q_INT_CLR + Set this bit to clear UHCI_SEND_A_REQ_Q_INT interrupt. + 5 + 1 + write-only + + + OUTLINK_EOF_ERR_INT_CLR + Set this bit to clear UHCI_OUTLINK_EOF_ERR_INT interrupt. + 6 + 1 + write-only + + + APP_CTRL0_INT_CLR + Set this bit to clear UHCI_APP_CTRL0_INT interrupt. + 7 + 1 + write-only + + + APP_CTRL1_INT_CLR + Set this bit to clear UHCI_APP_CTRL1_INT interrupt. + 8 + 1 + write-only + + + + + APP_INT_SET + Software interrupt trigger source + 0x14 + 0x20 + + + APP_CTRL0_INT_SET + This bit is software interrupt trigger source of UHCI_APP_CTRL0_INT. + 0 + 1 + write-only + + + APP_CTRL1_INT_SET + This bit is software interrupt trigger source of UHCI_APP_CTRL1_INT. + 1 + 1 + write-only + + + + + CONF1 + UHCI configuration register + 0x18 + 0x20 + 0x00000033 + + + CHECK_SUM_EN + This is the enable bit to check header checksum when UHCI receives a data packet. + 0 + 1 + read-write + + + CHECK_SEQ_EN + This is the enable bit to check sequence number when UHCI receives a data packet. + 1 + 1 + read-write + + + CRC_DISABLE + Set this bit to support CRC calculation. Data Integrity Check Present bit in UHCI packet frame should be 1. + 2 + 1 + read-write + + + SAVE_HEAD + Set this bit to save the packet header when HCI receives a data packet. + 3 + 1 + read-write + + + TX_CHECK_SUM_RE + Set this bit to encode the data packet with a checksum. + 4 + 1 + read-write + + + TX_ACK_NUM_RE + Set this bit to encode the data packet with an acknowledgment when a reliable packet is to be transmit. + 5 + 1 + read-write + + + WAIT_SW_START + The uhci-encoder will jump to ST_SW_WAIT status if this register is set to 1. + 7 + 1 + read-write + + + SW_START + If current UHCI_ENCODE_STATE is ST_SW_WAIT, the UHCI will start to send data packet out when this bit is set to 1. + 8 + 1 + read-write + + + + + STATE0 + UHCI receive status + 0x1C + 0x20 + + + RX_ERR_CAUSE + This register indicates the error type when DMA has received a packet with error. 3'b001: Checksum error in HCI packet. 3'b010: Sequence number error in HCI packet. 3'b011: CRC bit error in HCI packet. 3'b100: 0xc0 is found but received HCI packet is not end. 3'b101: 0xc0 is not found when receiving HCI packet is end. 3'b110: CRC check error. + 0 + 3 + read-only + + + DECODE_STATE + UHCI decoder status. + 3 + 3 + read-only + + + + + STATE1 + UHCI transmit status + 0x20 + 0x20 + + + ENCODE_STATE + UHCI encoder status. + 0 + 3 + read-only + + + + + ESCAPE_CONF + Escape character configuration + 0x24 + 0x20 + 0x00000033 + + + TX_C0_ESC_EN + Set this bit to enable decoding char 0xc0 when DMA receives data. + 0 + 1 + read-write + + + TX_DB_ESC_EN + Set this bit to enable decoding char 0xdb when DMA receives data. + 1 + 1 + read-write + + + TX_11_ESC_EN + Set this bit to enable decoding flow control char 0x11 when DMA receives data. + 2 + 1 + read-write + + + TX_13_ESC_EN + Set this bit to enable decoding flow control char 0x13 when DMA receives data. + 3 + 1 + read-write + + + RX_C0_ESC_EN + Set this bit to enable replacing 0xc0 by special char when DMA sends data. + 4 + 1 + read-write + + + RX_DB_ESC_EN + Set this bit to enable replacing 0xdb by special char when DMA sends data. + 5 + 1 + read-write + + + RX_11_ESC_EN + Set this bit to enable replacing flow control char 0x11 by special char when DMA sends data. + 6 + 1 + read-write + + + RX_13_ESC_EN + Set this bit to enable replacing flow control char 0x13 by special char when DMA sends data. + 7 + 1 + read-write + + + + + HUNG_CONF + Timeout configuration + 0x28 + 0x20 + 0x00810810 + + + TXFIFO_TIMEOUT + This register stores the timeout value. It will produce the UHCI_TX_HUNG_INT interrupt when DMA takes more time to receive data. + 0 + 8 + read-write + + + TXFIFO_TIMEOUT_SHIFT + This register is used to configure the tick count maximum value. + 8 + 3 + read-write + + + TXFIFO_TIMEOUT_ENA + This is the enable bit for Tx-FIFO receive-data timeout. + 11 + 1 + read-write + + + RXFIFO_TIMEOUT + This register stores the timeout value. It will produce the UHCI_RX_HUNG_INT interrupt when DMA takes more time to read data from RAM. + 12 + 8 + read-write + + + RXFIFO_TIMEOUT_SHIFT + This register is used to configure the tick count maximum value. + 20 + 3 + read-write + + + RXFIFO_TIMEOUT_ENA + This is the enable bit for DMA send-data timeout. + 23 + 1 + read-write + + + + + ACK_NUM + UHCI ACK number configuration + 0x2C + 0x20 + 0x00000008 + + + ACK_NUM + This ACK number used in software flow control. + 0 + 3 + read-write + + + LOAD + Set this bit to 1, the value configured by UHCI_ACK_NUM would be loaded. + 3 + 1 + write-only + + + + + RX_HEAD + UHCI packet header register + 0x30 + 0x20 + + + RX_HEAD + This register stores the header of the current received packet. + 0 + 32 + read-only + + + + + QUICK_SENT + UHCI quick send configuration register + 0x34 + 0x20 + + + SINGLE_SEND_NUM + This register is used to specify the single_send register. + 0 + 3 + read-write + + + SINGLE_SEND_EN + Set this bit to enable single_send mode to send short packet. + 3 + 1 + read-write + + + ALWAYS_SEND_NUM + This register is used to specify the always_send register. + 4 + 3 + read-write + + + ALWAYS_SEND_EN + Set this bit to enable always_send mode to send short packet. + 7 + 1 + read-write + + + + + REG_Q0_WORD0 + Q0_WORD0 quick_sent register + 0x38 + 0x20 + + + SEND_Q0_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q0_WORD1 + Q0_WORD1 quick_sent register + 0x3C + 0x20 + + + SEND_Q0_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q1_WORD0 + Q1_WORD0 quick_sent register + 0x40 + 0x20 + + + SEND_Q1_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q1_WORD1 + Q1_WORD1 quick_sent register + 0x44 + 0x20 + + + SEND_Q1_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q2_WORD0 + Q2_WORD0 quick_sent register + 0x48 + 0x20 + + + SEND_Q2_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q2_WORD1 + Q2_WORD1 quick_sent register + 0x4C + 0x20 + + + SEND_Q2_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q3_WORD0 + Q3_WORD0 quick_sent register + 0x50 + 0x20 + + + SEND_Q3_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q3_WORD1 + Q3_WORD1 quick_sent register + 0x54 + 0x20 + + + SEND_Q3_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q4_WORD0 + Q4_WORD0 quick_sent register + 0x58 + 0x20 + + + SEND_Q4_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q4_WORD1 + Q4_WORD1 quick_sent register + 0x5C + 0x20 + + + SEND_Q4_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q5_WORD0 + Q5_WORD0 quick_sent register + 0x60 + 0x20 + + + SEND_Q5_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q5_WORD1 + Q5_WORD1 quick_sent register + 0x64 + 0x20 + + + SEND_Q5_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q6_WORD0 + Q6_WORD0 quick_sent register + 0x68 + 0x20 + + + SEND_Q6_WORD0 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + REG_Q6_WORD1 + Q6_WORD1 quick_sent register + 0x6C + 0x20 + + + SEND_Q6_WORD1 + This register is used as a quick_sent register when specified by UHCI_ALWAYS_SEND_NUM or UHCI_SINGLE_SEND_NUM. + 0 + 32 + read-write + + + + + ESC_CONF0 + Escape sequence configuration register 0 + 0x70 + 0x20 + 0x00DCDBC0 + + + SEPER_CHAR + This register is used to define the separate char that need to be encoded, default is 0xc0. + 0 + 8 + read-write + + + SEPER_ESC_CHAR0 + This register is used to define the first char of slip escape sequence when encoding the separate char, default is 0xdb. + 8 + 8 + read-write + + + SEPER_ESC_CHAR1 + This register is used to define the second char of slip escape sequence when encoding the separate char, default is 0xdc. + 16 + 8 + read-write + + + + + ESC_CONF1 + Escape sequence configuration register 1 + 0x74 + 0x20 + 0x00DDDBDB + + + ESC_SEQ0 + This register is used to define a char that need to be encoded, default is 0xdb that used as the first char of slip escape sequence. + 0 + 8 + read-write + + + ESC_SEQ0_CHAR0 + This register is used to define the first char of slip escape sequence when encoding the UHCI_ESC_SEQ0, default is 0xdb. + 8 + 8 + read-write + + + ESC_SEQ0_CHAR1 + This register is used to define the second char of slip escape sequence when encoding the UHCI_ESC_SEQ0, default is 0xdd. + 16 + 8 + read-write + + + + + ESC_CONF2 + Escape sequence configuration register 2 + 0x78 + 0x20 + 0x00DEDB11 + + + ESC_SEQ1 + This register is used to define a char that need to be encoded, default is 0x11 that used as flow control char. + 0 + 8 + read-write + + + ESC_SEQ1_CHAR0 + This register is used to define the first char of slip escape sequence when encoding the UHCI_ESC_SEQ1, default is 0xdb. + 8 + 8 + read-write + + + ESC_SEQ1_CHAR1 + This register is used to define the second char of slip escape sequence when encoding the UHCI_ESC_SEQ1, default is 0xde. + 16 + 8 + read-write + + + + + ESC_CONF3 + Escape sequence configuration register 3 + 0x7C + 0x20 + 0x00DFDB13 + + + ESC_SEQ2 + This register is used to define a char that need to be decoded, default is 0x13 that used as flow control char. + 0 + 8 + read-write + + + ESC_SEQ2_CHAR0 + This register is used to define the first char of slip escape sequence when encoding the UHCI_ESC_SEQ2, default is 0xdb. + 8 + 8 + read-write + + + ESC_SEQ2_CHAR1 + This register is used to define the second char of slip escape sequence when encoding the UHCI_ESC_SEQ2, default is 0xdf. + 16 + 8 + read-write + + + + + PKT_THRES + Configure register for packet length + 0x80 + 0x20 + 0x00000080 + + + PKT_THRS + This register is used to configure the maximum value of the packet length when UHCI_HEAD_EN is 0. + 0 + 13 + read-write + + + + + DATE + UHCI version control register + 0x84 + 0x20 + 0x02010090 + + + DATE + This is the version control register. + 0 + 32 + read-write + + + + + + + UHCI1 + Universal Host Controller Interface + 0x6000C000 + + + USB_DEVICE + Peripheral USB_DEVICE + USB_DEVICE + 0x60038000 + + 0x0 + 0x50 + registers + + + USB_DEVICE + 96 + + + + EP1 + Endpoint 1 FIFO register + 0x0 + 0x20 + + + RDWR_BYTE + Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_DEVICE_SERIAL_IN_EMPTY_INT is set, then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_DEVICE_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_DEVICE_OUT_EP1_WR_ADDR USB_DEVICE_OUT_EP0_RD_ADDR to know how many data is received, then read data from UART Rx FIFO. + 0 + 8 + read-write + + + + + EP1_CONF + Endpoint 1 configure and status register + 0x4 + 0x20 + 0x00000002 + + + WR_DONE + Set this bit to indicate writing byte data to UART Tx FIFO is done. + 0 + 1 + write-only + + + SERIAL_IN_EP_DATA_FREE + 1'b1: Indicate UART Tx FIFO is not full and can write data into in. After writing USB_DEVICE_WR_DONE, this bit would be 0 until data in UART Tx FIFO is read by USB Host. + 1 + 1 + read-only + + + SERIAL_OUT_EP_DATA_AVAIL + 1'b1: Indicate there is data in UART Rx FIFO. + 2 + 1 + read-only + + + + + INT_RAW + Raw status interrupt + 0x8 + 0x20 + 0x00000008 + + + JTAG_IN_FLUSH_INT_RAW + The raw interrupt bit turns to high level when flush cmd is received for IN endpoint 2 of JTAG. + 0 + 1 + read-only + + + SOF_INT_RAW + The raw interrupt bit turns to high level when SOF frame is received. + 1 + 1 + read-only + + + SERIAL_OUT_RECV_PKT_INT_RAW + The raw interrupt bit turns to high level when Serial Port OUT Endpoint received one packet. + 2 + 1 + read-only + + + SERIAL_IN_EMPTY_INT_RAW + The raw interrupt bit turns to high level when Serial Port IN Endpoint is empty. + 3 + 1 + read-only + + + PID_ERR_INT_RAW + The raw interrupt bit turns to high level when pid error is detected. + 4 + 1 + read-only + + + CRC5_ERR_INT_RAW + The raw interrupt bit turns to high level when CRC5 error is detected. + 5 + 1 + read-only + + + CRC16_ERR_INT_RAW + The raw interrupt bit turns to high level when CRC16 error is detected. + 6 + 1 + read-only + + + STUFF_ERR_INT_RAW + The raw interrupt bit turns to high level when stuff error is detected. + 7 + 1 + read-only + + + IN_TOKEN_REC_IN_EP1_INT_RAW + The raw interrupt bit turns to high level when IN token for IN endpoint 1 is received. + 8 + 1 + read-only + + + USB_BUS_RESET_INT_RAW + The raw interrupt bit turns to high level when usb bus reset is detected. + 9 + 1 + read-only + + + OUT_EP1_ZERO_PAYLOAD_INT_RAW + The raw interrupt bit turns to high level when OUT endpoint 1 received packet with zero palyload. + 10 + 1 + read-only + + + OUT_EP2_ZERO_PAYLOAD_INT_RAW + The raw interrupt bit turns to high level when OUT endpoint 2 received packet with zero palyload. + 11 + 1 + read-only + + + + + INT_ST + Masked interrupt + 0xC + 0x20 + + + JTAG_IN_FLUSH_INT_ST + The raw interrupt status bit for the USB_DEVICE_JTAG_IN_FLUSH_INT interrupt. + 0 + 1 + read-only + + + SOF_INT_ST + The raw interrupt status bit for the USB_DEVICE_SOF_INT interrupt. + 1 + 1 + read-only + + + SERIAL_OUT_RECV_PKT_INT_ST + The raw interrupt status bit for the USB_DEVICE_SERIAL_OUT_RECV_PKT_INT interrupt. + 2 + 1 + read-only + + + SERIAL_IN_EMPTY_INT_ST + The raw interrupt status bit for the USB_DEVICE_SERIAL_IN_EMPTY_INT interrupt. + 3 + 1 + read-only + + + PID_ERR_INT_ST + The raw interrupt status bit for the USB_DEVICE_PID_ERR_INT interrupt. + 4 + 1 + read-only + + + CRC5_ERR_INT_ST + The raw interrupt status bit for the USB_DEVICE_CRC5_ERR_INT interrupt. + 5 + 1 + read-only + + + CRC16_ERR_INT_ST + The raw interrupt status bit for the USB_DEVICE_CRC16_ERR_INT interrupt. + 6 + 1 + read-only + + + STUFF_ERR_INT_ST + The raw interrupt status bit for the USB_DEVICE_STUFF_ERR_INT interrupt. + 7 + 1 + read-only + + + IN_TOKEN_REC_IN_EP1_INT_ST + The raw interrupt status bit for the USB_DEVICE_IN_TOKEN_REC_IN_EP1_INT interrupt. + 8 + 1 + read-only + + + USB_BUS_RESET_INT_ST + The raw interrupt status bit for the USB_DEVICE_USB_BUS_RESET_INT interrupt. + 9 + 1 + read-only + + + OUT_EP1_ZERO_PAYLOAD_INT_ST + The raw interrupt status bit for the USB_DEVICE_OUT_EP1_ZERO_PAYLOAD_INT interrupt. + 10 + 1 + read-only + + + OUT_EP2_ZERO_PAYLOAD_INT_ST + The raw interrupt status bit for the USB_DEVICE_OUT_EP2_ZERO_PAYLOAD_INT interrupt. + 11 + 1 + read-only + + + + + INT_ENA + Interrupt enable bits + 0x10 + 0x20 + + + JTAG_IN_FLUSH_INT_ENA + The interrupt enable bit for the USB_DEVICE_JTAG_IN_FLUSH_INT interrupt. + 0 + 1 + read-write + + + SOF_INT_ENA + The interrupt enable bit for the USB_DEVICE_SOF_INT interrupt. + 1 + 1 + read-write + + + SERIAL_OUT_RECV_PKT_INT_ENA + The interrupt enable bit for the USB_DEVICE_SERIAL_OUT_RECV_PKT_INT interrupt. + 2 + 1 + read-write + + + SERIAL_IN_EMPTY_INT_ENA + The interrupt enable bit for the USB_DEVICE_SERIAL_IN_EMPTY_INT interrupt. + 3 + 1 + read-write + + + PID_ERR_INT_ENA + The interrupt enable bit for the USB_DEVICE_PID_ERR_INT interrupt. + 4 + 1 + read-write + + + CRC5_ERR_INT_ENA + The interrupt enable bit for the USB_DEVICE_CRC5_ERR_INT interrupt. + 5 + 1 + read-write + + + CRC16_ERR_INT_ENA + The interrupt enable bit for the USB_DEVICE_CRC16_ERR_INT interrupt. + 6 + 1 + read-write + + + STUFF_ERR_INT_ENA + The interrupt enable bit for the USB_DEVICE_STUFF_ERR_INT interrupt. + 7 + 1 + read-write + + + IN_TOKEN_REC_IN_EP1_INT_ENA + The interrupt enable bit for the USB_DEVICE_IN_TOKEN_REC_IN_EP1_INT interrupt. + 8 + 1 + read-write + + + USB_BUS_RESET_INT_ENA + The interrupt enable bit for the USB_DEVICE_USB_BUS_RESET_INT interrupt. + 9 + 1 + read-write + + + OUT_EP1_ZERO_PAYLOAD_INT_ENA + The interrupt enable bit for the USB_DEVICE_OUT_EP1_ZERO_PAYLOAD_INT interrupt. + 10 + 1 + read-write + + + OUT_EP2_ZERO_PAYLOAD_INT_ENA + The interrupt enable bit for the USB_DEVICE_OUT_EP2_ZERO_PAYLOAD_INT interrupt. + 11 + 1 + read-write + + + + + INT_CLR + Interrupt clear bits + 0x14 + 0x20 + + + JTAG_IN_FLUSH_INT_CLR + Set this bit to clear the USB_DEVICE_JTAG_IN_FLUSH_INT interrupt. + 0 + 1 + write-only + + + SOF_INT_CLR + Set this bit to clear the USB_DEVICE_JTAG_SOF_INT interrupt. + 1 + 1 + write-only + + + SERIAL_OUT_RECV_PKT_INT_CLR + Set this bit to clear the USB_DEVICE_SERIAL_OUT_RECV_PKT_INT interrupt. + 2 + 1 + write-only + + + SERIAL_IN_EMPTY_INT_CLR + Set this bit to clear the USB_DEVICE_SERIAL_IN_EMPTY_INT interrupt. + 3 + 1 + write-only + + + PID_ERR_INT_CLR + Set this bit to clear the USB_DEVICE_PID_ERR_INT interrupt. + 4 + 1 + write-only + + + CRC5_ERR_INT_CLR + Set this bit to clear the USB_DEVICE_CRC5_ERR_INT interrupt. + 5 + 1 + write-only + + + CRC16_ERR_INT_CLR + Set this bit to clear the USB_DEVICE_CRC16_ERR_INT interrupt. + 6 + 1 + write-only + + + STUFF_ERR_INT_CLR + Set this bit to clear the USB_DEVICE_STUFF_ERR_INT interrupt. + 7 + 1 + write-only + + + IN_TOKEN_REC_IN_EP1_INT_CLR + Set this bit to clear the USB_DEVICE_IN_TOKEN_IN_EP1_INT interrupt. + 8 + 1 + write-only + + + USB_BUS_RESET_INT_CLR + Set this bit to clear the USB_DEVICE_USB_BUS_RESET_INT interrupt. + 9 + 1 + write-only + + + OUT_EP1_ZERO_PAYLOAD_INT_CLR + Set this bit to clear the USB_DEVICE_OUT_EP1_ZERO_PAYLOAD_INT interrupt. + 10 + 1 + write-only + + + OUT_EP2_ZERO_PAYLOAD_INT_CLR + Set this bit to clear the USB_DEVICE_OUT_EP2_ZERO_PAYLOAD_INT interrupt. + 11 + 1 + write-only + + + + + CONF0 + Configure 0 register + 0x18 + 0x20 + 0x00004200 + + + PHY_SEL + Select internal/external PHY + 0 + 1 + read-write + + + EXCHG_PINS_OVERRIDE + Enable software control USB D+ D- exchange + 1 + 1 + read-write + + + EXCHG_PINS + USB D+ D- exchange + 2 + 1 + read-write + + + VREFH + Control single-end input high threshold,1.76V to 2V, step 80mV + 3 + 2 + read-write + + + VREFL + Control single-end input low threshold,0.8V to 1.04V, step 80mV + 5 + 2 + read-write + + + VREF_OVERRIDE + Enable software control input threshold + 7 + 1 + read-write + + + PAD_PULL_OVERRIDE + Enable software control USB D+ D- pullup pulldown + 8 + 1 + read-write + + + DP_PULLUP + Control USB D+ pull up. + 9 + 1 + read-write + + + DP_PULLDOWN + Control USB D+ pull down. + 10 + 1 + read-write + + + DM_PULLUP + Control USB D- pull up. + 11 + 1 + read-write + + + DM_PULLDOWN + Control USB D- pull down. + 12 + 1 + read-write + + + PULLUP_VALUE + Control pull up value. + 13 + 1 + read-write + + + USB_PAD_ENABLE + Enable USB pad function. + 14 + 1 + read-write + + + PHY_TX_EDGE_SEL + 0: TX output at clock negedge. 1: Tx output at clock posedge. + 15 + 1 + read-write + + + USB_JTAG_BRIDGE_EN + Set this bit usb_jtag, the connection between usb_jtag and internal JTAG is disconnected, and MTMS, MTDI, MTCK are output through GPIO Matrix, MTDO is input through GPIO Matrix. + 16 + 1 + read-write + + + + + TEST + USB Internal PHY test register + 0x1C + 0x20 + + + ENABLE + Enable test of the USB pad + 0 + 1 + read-write + + + USB_OE + USB pad oen in test + 1 + 1 + read-write + + + TX_DP + USB D+ tx value in test + 2 + 1 + read-write + + + TX_DM + USB D- tx value in test + 3 + 1 + read-write + + + RX_RCV + USB differential rx value in test + 4 + 1 + read-only + + + RX_DP + USB D+ rx value in test + 5 + 1 + read-only + + + RX_DM + USB D- rx value in test + 6 + 1 + read-only + + + + + JFIFO_ST + USB-JTAG FIFO status + 0x20 + 0x20 + 0x00000044 + + + IN_FIFO_CNT + JTAT in fifo counter. + 0 + 2 + read-only + + + IN_FIFO_EMPTY + 1: JTAG in fifo is empty. + 2 + 1 + read-only + + + IN_FIFO_FULL + 1: JTAG in fifo is full. + 3 + 1 + read-only + + + OUT_FIFO_CNT + JTAT out fifo counter. + 4 + 2 + read-only + + + OUT_FIFO_EMPTY + 1: JTAG out fifo is empty. + 6 + 1 + read-only + + + OUT_FIFO_FULL + 1: JTAG out fifo is full. + 7 + 1 + read-only + + + IN_FIFO_RESET + Write 1 to reset JTAG in fifo. + 8 + 1 + read-write + + + OUT_FIFO_RESET + Write 1 to reset JTAG out fifo. + 9 + 1 + read-write + + + + + FRAM_NUM + SOF frame number + 0x24 + 0x20 + + + SOF_FRAME_INDEX + Frame index of received SOF frame. + 0 + 11 + read-only + + + + + IN_EP0_ST + IN Endpoint 0 status + 0x28 + 0x20 + 0x00000001 + + + IN_EP0_STATE + State of IN Endpoint 0. + 0 + 2 + read-only + + + IN_EP0_WR_ADDR + Write data address of IN endpoint 0. + 2 + 7 + read-only + + + IN_EP0_RD_ADDR + Read data address of IN endpoint 0. + 9 + 7 + read-only + + + + + IN_EP1_ST + IN Endpoint 1 status + 0x2C + 0x20 + 0x00000001 + + + IN_EP1_STATE + State of IN Endpoint 1. + 0 + 2 + read-only + + + IN_EP1_WR_ADDR + Write data address of IN endpoint 1. + 2 + 7 + read-only + + + IN_EP1_RD_ADDR + Read data address of IN endpoint 1. + 9 + 7 + read-only + + + + + IN_EP2_ST + IN Endpoint 2 status + 0x30 + 0x20 + 0x00000001 + + + IN_EP2_STATE + State of IN Endpoint 2. + 0 + 2 + read-only + + + IN_EP2_WR_ADDR + Write data address of IN endpoint 2. + 2 + 7 + read-only + + + IN_EP2_RD_ADDR + Read data address of IN endpoint 2. + 9 + 7 + read-only + + + + + IN_EP3_ST + IN Endpoint 3 status + 0x34 + 0x20 + 0x00000001 + + + IN_EP3_STATE + State of IN Endpoint 3. + 0 + 2 + read-only + + + IN_EP3_WR_ADDR + Write data address of IN endpoint 3. + 2 + 7 + read-only + + + IN_EP3_RD_ADDR + Read data address of IN endpoint 3. + 9 + 7 + read-only + + + + + OUT_EP0_ST + OUT Endpoint 0 status + 0x38 + 0x20 + + + OUT_EP0_STATE + State of OUT Endpoint 0. + 0 + 2 + read-only + + + OUT_EP0_WR_ADDR + Write data address of OUT endpoint 0. When USB_DEVICE_SERIAL_OUT_RECV_PKT_INT is detected, there are USB_DEVICE_OUT_EP0_WR_ADDR-2 bytes data in OUT EP0. + 2 + 7 + read-only + + + OUT_EP0_RD_ADDR + Read data address of OUT endpoint 0. + 9 + 7 + read-only + + + + + OUT_EP1_ST + OUT Endpoint 1 status + 0x3C + 0x20 + + + OUT_EP1_STATE + State of OUT Endpoint 1. + 0 + 2 + read-only + + + OUT_EP1_WR_ADDR + Write data address of OUT endpoint 1. When USB_DEVICE_SERIAL_OUT_RECV_PKT_INT is detected, there are USB_DEVICE_OUT_EP1_WR_ADDR-2 bytes data in OUT EP1. + 2 + 7 + read-only + + + OUT_EP1_RD_ADDR + Read data address of OUT endpoint 1. + 9 + 7 + read-only + + + OUT_EP1_REC_DATA_CNT + Data count in OUT endpoint 1 when one packet is received. + 16 + 7 + read-only + + + + + OUT_EP2_ST + OUT Endpoint 2 status + 0x40 + 0x20 + + + OUT_EP2_STATE + State of OUT Endpoint 2. + 0 + 2 + read-only + + + OUT_EP2_WR_ADDR + Write data address of OUT endpoint 2. When USB_DEVICE_SERIAL_OUT_RECV_PKT_INT is detected, there are USB_DEVICE_OUT_EP2_WR_ADDR-2 bytes data in OUT EP2. + 2 + 7 + read-only + + + OUT_EP2_RD_ADDR + Read data address of OUT endpoint 2. + 9 + 7 + read-only + + + + + MISC_CONF + MISC register + 0x44 + 0x20 + + + CLK_EN + 1'h1: Force clock on for register. 1'h0: Support clock only when application writes registers. + 0 + 1 + read-write + + + + + MEM_CONF + Power control + 0x48 + 0x20 + 0x00000002 + + + USB_MEM_PD + 1: power down usb memory. + 0 + 1 + read-write + + + USB_MEM_CLK_EN + 1: Force clock on for usb memory. + 1 + 1 + read-write + + + + + DATE + Version control register + 0x80 + 0x20 + 0x02101200 + + + DATE + register version. + 0 + 32 + read-write + + + + + + + USB_WRAP + Peripheral USB_WRAP + USB_WRAP + 0x60039000 + + 0x0 + 0xC + registers + + + + OTG_CONF + USB OTG Wrapper Configure Register + 0x0 + 0x20 + 0x001C0000 + + + SRP_SESSEND_OVERRIDE + This bit is used to enable the software over-ride of srp session end signal. 1'b0: the signal is controlled by the chip input. 1'b1: the signal is controlled by the software. + 0 + 1 + read-write + + + SRP_SESSEND_VALUE + Software over-ride value of srp session end signal. + 1 + 1 + read-write + + + PHY_SEL + Select internal external PHY. 1'b0: Select internal PHY. 1'b1: Select external PHY. + 2 + 1 + read-write + + + DFIFO_FORCE_PD + Force the dfifo to go into low power mode. The data in dfifo will not lost. + 3 + 1 + read-write + + + DBNCE_FLTR_BYPASS + Bypass Debounce filters for avalid,bvalid,vbusvalid,session end, id signals + 4 + 1 + read-write + + + EXCHG_PINS_OVERRIDE + Enable software controlle USB D+ D- exchange + 5 + 1 + read-write + + + EXCHG_PINS + USB D+ D- exchange. 1'b0: don't change. 1'b1: exchange D+ D- + 6 + 1 + read-write + + + VREFH + Control single-end input high threshold,1.76V to 2V, step 80mV + 7 + 2 + read-write + + + VREFL + Control single-end input low threshold,0.8V to 1.04V, step 80mV + 9 + 2 + read-write + + + VREF_OVERRIDE + Enable software controlle input threshold + 11 + 1 + read-write + + + PAD_PULL_OVERRIDE + Enable software controlle USB D+ D- pullup pulldown + 12 + 1 + read-write + + + DP_PULLUP + Controlle USB D+ pullup + 13 + 1 + read-write + + + DP_PULLDOWN + Controlle USB D+ pulldown + 14 + 1 + read-write + + + DM_PULLUP + Controlle USB D+ pullup + 15 + 1 + read-write + + + DM_PULLDOWN + Controlle USB D+ pulldown + 16 + 1 + read-write + + + PULLUP_VALUE + Controlle pullup value. 1'b0: typical value is 2.4K. 1'b1: typical value is 1.2K. + 17 + 1 + read-write + + + USB_PAD_ENABLE + Enable USB pad function + 18 + 1 + read-write + + + AHB_CLK_FORCE_ON + Force ahb clock always on + 19 + 1 + read-write + + + PHY_CLK_FORCE_ON + Force phy clock always on + 20 + 1 + read-write + + + PHY_TX_EDGE_SEL + Select phy tx signal output clock edge. 1'b0: negedge. 1'b1: posedge. + 21 + 1 + read-write + + + DFIFO_FORCE_PU + Disable the dfifo to go into low power mode. The data in dfifo will not lost. + 22 + 1 + read-write + + + CLK_EN + Disable auto clock gating of CSR registers + 31 + 1 + read-write + + + + + TEST_CONF + USB Internal PHY Testing Register + 0x4 + 0x20 + + + TEST_ENABLE + Enable test of the USB pad + 0 + 1 + read-write + + + TEST_USB_OE + USB pad oen in test + 1 + 1 + read-write + + + TEST_TX_DP + USB D+ tx value in test + 2 + 1 + read-write + + + TEST_TX_DM + USB D- tx value in test + 3 + 1 + read-write + + + TEST_RX_RCV + USB differential rx value in test + 4 + 1 + read-only + + + TEST_RX_DP + USB D+ rx value in test + 5 + 1 + read-only + + + TEST_RX_DM + USB D- rx value in test + 6 + 1 + read-only + + + + + DATE + Version Control Register + 0x3FC + 0x20 + 0x02102010 + + + USB_WRAP_DATE + Date register + 0 + 32 + read-write + + + + + + + WCL + Peripheral WCL + WCL + 0x600D0000 + + 0x0 + 0x160 + registers + + + + Core_0_ENTRY_1_ADDR + Core_0 Entry 1 address configuration Register + 0x0 + 0x20 + + + CORE_0_ENTRY_1_ADDR + Core_0 Entry 1 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_2_ADDR + Core_0 Entry 2 address configuration Register + 0x4 + 0x20 + + + CORE_0_ENTRY_2_ADDR + Core_0 Entry 2 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_3_ADDR + Core_0 Entry 3 address configuration Register + 0x8 + 0x20 + + + CORE_0_ENTRY_3_ADDR + Core_0 Entry 3 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_4_ADDR + Core_0 Entry 4 address configuration Register + 0xC + 0x20 + + + CORE_0_ENTRY_4_ADDR + Core_0 Entry 4 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_5_ADDR + Core_0 Entry 5 address configuration Register + 0x10 + 0x20 + + + CORE_0_ENTRY_5_ADDR + Core_0 Entry 5 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_6_ADDR + Core_0 Entry 6 address configuration Register + 0x14 + 0x20 + + + CORE_0_ENTRY_6_ADDR + Core_0 Entry 6 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_7_ADDR + Core_0 Entry 7 address configuration Register + 0x18 + 0x20 + + + CORE_0_ENTRY_7_ADDR + Core_0 Entry 7 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_8_ADDR + Core_0 Entry 8 address configuration Register + 0x1C + 0x20 + + + CORE_0_ENTRY_8_ADDR + Core_0 Entry 8 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_9_ADDR + Core_0 Entry 9 address configuration Register + 0x20 + 0x20 + + + CORE_0_ENTRY_9_ADDR + Core_0 Entry 9 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_10_ADDR + Core_0 Entry 10 address configuration Register + 0x24 + 0x20 + + + CORE_0_ENTRY_10_ADDR + Core_0 Entry 10 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_11_ADDR + Core_0 Entry 11 address configuration Register + 0x28 + 0x20 + + + CORE_0_ENTRY_11_ADDR + Core_0 Entry 11 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_12_ADDR + Core_0 Entry 12 address configuration Register + 0x2C + 0x20 + + + CORE_0_ENTRY_12_ADDR + Core_0 Entry 12 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_13_ADDR + Core_0 Entry 13 address configuration Register + 0x30 + 0x20 + + + CORE_0_ENTRY_13_ADDR + Core_0 Entry 13 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_0_ENTRY_CHECK + Core_0 Entry check configuration Register + 0x7C + 0x20 + 0x00000002 + + + CORE_0_ENTRY_CHECK + This filed is used to enable entry address check + 1 + 13 + read-write + + + + + Core_0_STATUSTABLE1 + Status register of world switch of entry 1 + 0x80 + 0x20 + + + CORE_0_FROM_WORLD_1 + This bit is used to confirm world before enter entry 1 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_1 + This filed is used to confirm in which entry before enter entry 1 + 1 + 4 + read-write + + + CORE_0_CURRENT_1 + This bit is used to confirm whether the current state is in entry 1 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE2 + Status register of world switch of entry 2 + 0x84 + 0x20 + + + CORE_0_FROM_WORLD_2 + This bit is used to confirm world before enter entry 2 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_2 + This filed is used to confirm in which entry before enter entry 2 + 1 + 4 + read-write + + + CORE_0_CURRENT_2 + This bit is used to confirm whether the current state is in entry 2 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE3 + Status register of world switch of entry 3 + 0x88 + 0x20 + + + CORE_0_FROM_WORLD_3 + This bit is used to confirm world before enter entry 3 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_3 + This filed is used to confirm in which entry before enter entry 3 + 1 + 4 + read-write + + + CORE_0_CURRENT_3 + This bit is used to confirm whether the current state is in entry 3 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE4 + Status register of world switch of entry 4 + 0x8C + 0x20 + + + CORE_0_FROM_WORLD_4 + This bit is used to confirm world before enter entry 4 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_4 + This filed is used to confirm in which entry before enter entry 4 + 1 + 4 + read-write + + + CORE_0_CURRENT_4 + This bit is used to confirm whether the current state is in entry 4 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE5 + Status register of world switch of entry 5 + 0x90 + 0x20 + + + CORE_0_FROM_WORLD_5 + This bit is used to confirm world before enter entry 5 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_5 + This filed is used to confirm in which entry before enter entry 5 + 1 + 4 + read-write + + + CORE_0_CURRENT_5 + This bit is used to confirm whether the current state is in entry 5 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE6 + Status register of world switch of entry 6 + 0x94 + 0x20 + + + CORE_0_FROM_WORLD_6 + This bit is used to confirm world before enter entry 6 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_6 + This filed is used to confirm in which entry before enter entry 6 + 1 + 4 + read-write + + + CORE_0_CURRENT_6 + This bit is used to confirm whether the current state is in entry 6 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE7 + Status register of world switch of entry 7 + 0x98 + 0x20 + + + CORE_0_FROM_WORLD_7 + This bit is used to confirm world before enter entry 7 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_7 + This filed is used to confirm in which entry before enter entry 7 + 1 + 4 + read-write + + + CORE_0_CURRENT_7 + This bit is used to confirm whether the current state is in entry 7 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE8 + Status register of world switch of entry 8 + 0x9C + 0x20 + + + CORE_0_FROM_WORLD_8 + This bit is used to confirm world before enter entry 8 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_8 + This filed is used to confirm in which entry before enter entry 8 + 1 + 4 + read-write + + + CORE_0_CURRENT_8 + This bit is used to confirm whether the current state is in entry 8 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE9 + Status register of world switch of entry 9 + 0xA0 + 0x20 + + + CORE_0_FROM_WORLD_9 + This bit is used to confirm world before enter entry 9 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_9 + This filed is used to confirm in which entry before enter entry 9 + 1 + 4 + read-write + + + CORE_0_CURRENT_9 + This bit is used to confirm whether the current state is in entry 9 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE10 + Status register of world switch of entry 10 + 0xA4 + 0x20 + + + CORE_0_FROM_WORLD_10 + This bit is used to confirm world before enter entry 10 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_10 + This filed is used to confirm in which entry before enter entry 10 + 1 + 4 + read-write + + + CORE_0_CURRENT_10 + This bit is used to confirm whether the current state is in entry 10 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE11 + Status register of world switch of entry 11 + 0xA8 + 0x20 + + + CORE_0_FROM_WORLD_11 + This bit is used to confirm world before enter entry 11 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_11 + This filed is used to confirm in which entry before enter entry 11 + 1 + 4 + read-write + + + CORE_0_CURRENT_11 + This bit is used to confirm whether the current state is in entry 11 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE12 + Status register of world switch of entry 12 + 0xAC + 0x20 + + + CORE_0_FROM_WORLD_12 + This bit is used to confirm world before enter entry 12 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_12 + This filed is used to confirm in which entry before enter entry 12 + 1 + 4 + read-write + + + CORE_0_CURRENT_12 + This bit is used to confirm whether the current state is in entry 12 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE13 + Status register of world switch of entry 13 + 0xB0 + 0x20 + + + CORE_0_FROM_WORLD_13 + This bit is used to confirm world before enter entry 13 + 0 + 1 + read-write + + + CORE_0_FROM_ENTRY_13 + This filed is used to confirm in which entry before enter entry 13 + 1 + 4 + read-write + + + CORE_0_CURRENT_13 + This bit is used to confirm whether the current state is in entry 13 + 5 + 1 + read-write + + + + + Core_0_STATUSTABLE_CURRENT + Status register of statustable current + 0xFC + 0x20 + + + CORE_0_STATUSTABLE_CURRENT + This field is used to quickly read and rewrite the current field of all STATUSTABLE registers,for example,bit 1 represents the current field of STATUSTABLE1,bit2 represents the current field of STATUSTABLE2 + 1 + 13 + read-write + + + + + Core_0_MESSAGE_ADDR + Clear writer_buffer write address configuration register + 0x100 + 0x20 + + + CORE_0_MESSAGE_ADDR + This field is used to set address that need to write when enter WORLD0 + 0 + 32 + read-write + + + + + Core_0_MESSAGE_MAX + Clear writer_buffer write number configuration register + 0x104 + 0x20 + + + CORE_0_MESSAGE_MAX + This filed is used to set the max value of clear write_buffer + 0 + 4 + read-write + + + + + Core_0_MESSAGE_PHASE + Clear writer_buffer status register + 0x108 + 0x20 + + + CORE_0_MESSAGE_MATCH + This bit indicates whether the check is successful + 0 + 1 + read-only + + + CORE_0_MESSAGE_EXPECT + This field indicates the data to be written next time + 1 + 4 + read-only + + + CORE_0_MESSAGE_DATAPHASE + If this bit is 1, it means that is checking clear write_buffer operation,and is checking data + 5 + 1 + read-only + + + CORE_0_MESSAGE_ADDRESSPHASE + If this bit is 1, it means that is checking clear write_buffer operation,and is checking address. + 6 + 1 + read-only + + + + + Core_0_World_TRIGGER_ADDR + Core_0 trigger address configuration Register + 0x140 + 0x20 + + + CORE_0_WORLD_TRIGGER_ADDR + This field is used to configure the entry address from WORLD0 to WORLD1,when the CPU executes to this address,switch to WORLD1 + 0 + 32 + read-write + + + + + Core_0_World_PREPARE + Core_0 prepare world configuration Register + 0x144 + 0x20 + + + CORE_0_WORLD_PREPARE + This field to used to set world to enter, 2'b01 means WORLD0, 2'b10 means WORLD1 + 0 + 2 + read-write + + + + + Core_0_World_UPDATE + Core_0 configuration update register + 0x148 + 0x20 + + + CORE_0_UPDATE + This field is used to update configuration completed, can write any value,the hardware only checks the write operation of this register and does not case about its value + 0 + 32 + write-only + + + + + Core_0_World_Cancel + Core_0 configuration cancel register + 0x14C + 0x20 + + + CORE_0_WORLD_CANCEL + This field is used to cancel switch world configuration,if the trigger address and update configuration complete,use this register to cancel world switch, jujst need write any value,the hardware only checks the write operation of this register and does not case about its value + 0 + 32 + write-only + + + + + Core_0_World_IRam0 + Core_0 Iram0 world register + 0x150 + 0x20 + + + CORE_0_WORLD_IRAM0 + this field is used to read current world of Iram0 bus + 0 + 2 + read-write + + + + + Core_0_World_DRam0_PIF + Core_0 dram0 and PIF world register + 0x154 + 0x20 + + + CORE_0_WORLD_DRAM0_PIF + this field is used to read current world of Dram0 bus and PIF bus + 0 + 2 + read-write + + + + + Core_0_World_Phase + Core_0 world status register + 0x158 + 0x20 + + + CORE_0_WORLD_PHASE + This bit indicates whether is preparing to switch to WORLD1, 1 means value. + 0 + 1 + read-only + + + + + Core_0_NMI_MASK_ENABLE + Core_0 NMI mask enable register + 0x180 + 0x20 + + + CORE_0_NMI_MASK_ENABLE + this field is used to set NMI mask,it can write any value,when write this register,the hardware start masking NMI interrupt + 0 + 32 + write-only + + + + + Core_0_NMI_MASK_TRIGGER_ADDR + Core_0 NMI mask trigger address register + 0x184 + 0x20 + + + CORE_0_NMI_MASK_TRIGGER_ADDR + this field to used to set trigger address, when CPU executes to this address,NMI mask automatically fails + 0 + 32 + read-write + + + + + Core_0_NMI_MASK_DISABLE + Core_0 NMI mask disable register + 0x188 + 0x20 + + + CORE_0_NMI_MASK_DISABLE + this field is used to disable NMI mask,it will not take effect immediately,only when the CPU executes to the trigger address will it start to cancel NMI mask + 0 + 32 + write-only + + + + + Core_0_NMI_MASK_CANCLE + Core_0 NMI mask disable register + 0x18C + 0x20 + + + CORE_0_NMI_MASK_CANCEL + this field is used to cancel NMI mask disable function. + 0 + 32 + write-only + + + + + Core_0_NMI_MASK + Core_0 NMI mask register + 0x190 + 0x20 + + + CORE_0_NMI_MASK + this bit is used to mask NMI interrupt,it can directly mask NMI interrupt + 0 + 1 + read-write + + + + + Core_0_NMI_MASK_PHASE + Core_0 NMI mask phase register + 0x194 + 0x20 + + + CORE_0_NMI_MASK_PHASE + this bit is used to indicates whether the NMI interrupt is being masked, 1 means NMI interrupt is being masked + 0 + 1 + read-only + + + + + Core_1_ENTRY_1_ADDR + Core_1 Entry 1 address configuration Register + 0x400 + 0x20 + + + CORE_1_ENTRY_1_ADDR + Core_1 Entry 1 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_2_ADDR + Core_1 Entry 2 address configuration Register + 0x404 + 0x20 + + + CORE_1_ENTRY_2_ADDR + Core_1 Entry 2 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_3_ADDR + Core_1 Entry 3 address configuration Register + 0x408 + 0x20 + + + CORE_1_ENTRY_3_ADDR + Core_1 Entry 3 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_4_ADDR + Core_1 Entry 4 address configuration Register + 0x40C + 0x20 + + + CORE_1_ENTRY_4_ADDR + Core_1 Entry 4 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_5_ADDR + Core_1 Entry 5 address configuration Register + 0x410 + 0x20 + + + CORE_1_ENTRY_5_ADDR + Core_1 Entry 5 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_6_ADDR + Core_1 Entry 6 address configuration Register + 0x414 + 0x20 + + + CORE_1_ENTRY_6_ADDR + Core_1 Entry 6 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_7_ADDR + Core_1 Entry 7 address configuration Register + 0x418 + 0x20 + + + CORE_1_ENTRY_7_ADDR + Core_1 Entry 7 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_8_ADDR + Core_1 Entry 8 address configuration Register + 0x41C + 0x20 + + + CORE_1_ENTRY_8_ADDR + Core_1 Entry 8 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_9_ADDR + Core_1 Entry 9 address configuration Register + 0x420 + 0x20 + + + CORE_1_ENTRY_9_ADDR + Core_1 Entry 9 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_10_ADDR + Core_1 Entry 10 address configuration Register + 0x424 + 0x20 + + + CORE_1_ENTRY_10_ADDR + Core_1 Entry 10 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_11_ADDR + Core_1 Entry 11 address configuration Register + 0x428 + 0x20 + + + CORE_1_ENTRY_11_ADDR + Core_1 Entry 11 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_12_ADDR + Core_1 Entry 12 address configuration Register + 0x42C + 0x20 + + + CORE_1_ENTRY_12_ADDR + Core_1 Entry 12 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_13_ADDR + Core_1 Entry 13 address configuration Register + 0x430 + 0x20 + + + CORE_1_ENTRY_13_ADDR + Core_1 Entry 13 address from WORLD1 to WORLD0 + 0 + 32 + read-write + + + + + Core_1_ENTRY_CHECK + Core_1 Entry check configuration Register + 0x47C + 0x20 + 0x00000002 + + + CORE_1_ENTRY_CHECK + This filed is used to enable entry address check + 1 + 13 + read-write + + + + + Core_1_STATUSTABLE1 + Status register of world switch of entry 1 + 0x480 + 0x20 + + + CORE_1_FROM_WORLD_1 + This bit is used to confirm world before enter entry 1 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_1 + This filed is used to confirm in which entry before enter entry 1 + 1 + 4 + read-write + + + CORE_1_CURRENT_1 + This bit is used to confirm whether the current state is in entry 1 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE2 + Status register of world switch of entry 2 + 0x484 + 0x20 + + + CORE_1_FROM_WORLD_2 + This bit is used to confirm world before enter entry 2 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_2 + This filed is used to confirm in which entry before enter entry 2 + 1 + 4 + read-write + + + CORE_1_CURRENT_2 + This bit is used to confirm whether the current state is in entry 2 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE3 + Status register of world switch of entry 3 + 0x488 + 0x20 + + + CORE_1_FROM_WORLD_3 + This bit is used to confirm world before enter entry 3 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_3 + This filed is used to confirm in which entry before enter entry 3 + 1 + 4 + read-write + + + CORE_1_CURRENT_3 + This bit is used to confirm whether the current state is in entry 3 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE4 + Status register of world switch of entry 4 + 0x48C + 0x20 + + + CORE_1_FROM_WORLD_4 + This bit is used to confirm world before enter entry 4 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_4 + This filed is used to confirm in which entry before enter entry 4 + 1 + 4 + read-write + + + CORE_1_CURRENT_4 + This bit is used to confirm whether the current state is in entry 4 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE5 + Status register of world switch of entry 5 + 0x490 + 0x20 + + + CORE_1_FROM_WORLD_5 + This bit is used to confirm world before enter entry 5 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_5 + This filed is used to confirm in which entry before enter entry 5 + 1 + 4 + read-write + + + CORE_1_CURRENT_5 + This bit is used to confirm whether the current state is in entry 5 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE6 + Status register of world switch of entry 6 + 0x494 + 0x20 + + + CORE_1_FROM_WORLD_6 + This bit is used to confirm world before enter entry 6 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_6 + This filed is used to confirm in which entry before enter entry 6 + 1 + 4 + read-write + + + CORE_1_CURRENT_6 + This bit is used to confirm whether the current state is in entry 6 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE7 + Status register of world switch of entry 7 + 0x498 + 0x20 + + + CORE_1_FROM_WORLD_7 + This bit is used to confirm world before enter entry 7 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_7 + This filed is used to confirm in which entry before enter entry 7 + 1 + 4 + read-write + + + CORE_1_CURRENT_7 + This bit is used to confirm whether the current state is in entry 7 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE8 + Status register of world switch of entry 8 + 0x49C + 0x20 + + + CORE_1_FROM_WORLD_8 + This bit is used to confirm world before enter entry 8 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_8 + This filed is used to confirm in which entry before enter entry 8 + 1 + 4 + read-write + + + CORE_1_CURRENT_8 + This bit is used to confirm whether the current state is in entry 8 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE9 + Status register of world switch of entry 9 + 0x4A0 + 0x20 + + + CORE_1_FROM_WORLD_9 + This bit is used to confirm world before enter entry 9 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_9 + This filed is used to confirm in which entry before enter entry 9 + 1 + 4 + read-write + + + CORE_1_CURRENT_9 + This bit is used to confirm whether the current state is in entry 9 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE10 + Status register of world switch of entry 10 + 0x4A4 + 0x20 + + + CORE_1_FROM_WORLD_10 + This bit is used to confirm world before enter entry 10 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_10 + This filed is used to confirm in which entry before enter entry 10 + 1 + 4 + read-write + + + CORE_1_CURRENT_10 + This bit is used to confirm whether the current state is in entry 10 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE11 + Status register of world switch of entry 11 + 0x4A8 + 0x20 + + + CORE_1_FROM_WORLD_11 + This bit is used to confirm world before enter entry 11 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_11 + This filed is used to confirm in which entry before enter entry 11 + 1 + 4 + read-write + + + CORE_1_CURRENT_11 + This bit is used to confirm whether the current state is in entry 11 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE12 + Status register of world switch of entry 12 + 0x4AC + 0x20 + + + CORE_1_FROM_WORLD_12 + This bit is used to confirm world before enter entry 12 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_12 + This filed is used to confirm in which entry before enter entry 12 + 1 + 4 + read-write + + + CORE_1_CURRENT_12 + This bit is used to confirm whether the current state is in entry 12 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE13 + Status register of world switch of entry 13 + 0x4B0 + 0x20 + + + CORE_1_FROM_WORLD_13 + This bit is used to confirm world before enter entry 13 + 0 + 1 + read-write + + + CORE_1_FROM_ENTRY_13 + This filed is used to confirm in which entry before enter entry 13 + 1 + 4 + read-write + + + CORE_1_CURRENT_13 + This bit is used to confirm whether the current state is in entry 13 + 5 + 1 + read-write + + + + + Core_1_STATUSTABLE_CURRENT + Status register of statustable current + 0x4FC + 0x20 + + + CORE_1_STATUSTABLE_CURRENT + This field is used to quickly read and rewrite the current field of all STATUSTABLE registers,for example,bit 1 represents the current field of STATUSTABLE1 + 1 + 13 + read-write + + + + + Core_1_MESSAGE_ADDR + Clear writer_buffer write address configuration register + 0x500 + 0x20 + + + CORE_1_MESSAGE_ADDR + This field is used to set address that need to write when enter WORLD0 + 0 + 32 + read-write + + + + + Core_1_MESSAGE_MAX + Clear writer_buffer write number configuration register + 0x504 + 0x20 + + + CORE_1_MESSAGE_MAX + This filed is used to set the max value of clear write_buffer + 0 + 4 + read-write + + + + + Core_1_MESSAGE_PHASE + Clear writer_buffer status register + 0x508 + 0x20 + + + CORE_1_MESSAGE_MATCH + This bit indicates whether the check is successful + 0 + 1 + read-only + + + CORE_1_MESSAGE_EXPECT + This field indicates the data to be written next time + 1 + 4 + read-only + + + CORE_1_MESSAGE_DATAPHASE + If this bit is 1, it means that is checking clear write_buffer operation, and is checking data + 5 + 1 + read-only + + + CORE_1_MESSAGE_ADDRESSPHASE + If this bit is 1, it means that is checking clear write_buffer operation, and is checking address. + 6 + 1 + read-only + + + + + Core_1_World_TRIGGER_ADDR + Core_1 trigger address configuration Register + 0x540 + 0x20 + + + CORE_1_WORLD_TRIGGER_ADDR + This field is used to configure the entry address from WORLD0 to WORLD1,when the CPU executes to this address,switch to WORLD1 + 0 + 32 + read-write + + + + + Core_1_World_PREPARE + Core_1 prepare world configuration Register + 0x544 + 0x20 + + + CORE_1_WORLD_PREPARE + This field to used to set world to enter,2'b01 means WORLD0, 2'b10 means WORLD1 + 0 + 2 + read-write + + + + + Core_1_World_UPDATE + Core_1 configuration update register + 0x548 + 0x20 + + + CORE_1_UPDATE + This field is used to update configuration completed, can write any value,the hardware only checks the write operation of this register and does not case about its value + 0 + 32 + write-only + + + + + Core_1_World_Cancel + Core_1 configuration cancel register + 0x54C + 0x20 + + + CORE_1_WORLD_CANCEL + This field is used to cancel switch world configuration,if the trigger address and update configuration complete,can use this register to cancel world switch. can write any value, the hardware only checks the write operation of this register and does not case about its value + 0 + 32 + write-only + + + + + Core_1_World_IRam0 + Core_1 Iram0 world register + 0x550 + 0x20 + + + CORE_1_WORLD_IRAM0 + this field is used to read current world of Iram0 bus + 0 + 2 + read-write + + + + + Core_1_World_DRam0_PIF + Core_1 dram0 and PIF world register + 0x554 + 0x20 + + + CORE_1_WORLD_DRAM0_PIF + this field is used to read current world of Dram0 bus and PIF bus + 0 + 2 + read-write + + + + + Core_1_World_Phase + Core_0 world status register + 0x558 + 0x20 + + + CORE_1_WORLD_PHASE + This bit indicates whether is preparing to switch to WORLD1,1 means value. + 0 + 1 + read-only + + + + + Core_1_NMI_MASK_ENABLE + Core_1 NMI mask enable register + 0x580 + 0x20 + + + CORE_1_NMI_MASK_ENABLE + this field is used to set NMI mask, it can write any value, when write this register,the hardware start masking NMI interrupt + 0 + 32 + write-only + + + + + Core_1_NMI_MASK_TRIGGER_ADDR + Core_1 NMI mask trigger addr register + 0x584 + 0x20 + + + CORE_1_NMI_MASK_TRIGGER_ADDR + this field to used to set trigger address + 0 + 32 + read-write + + + + + Core_1_NMI_MASK_DISABLE + Core_1 NMI mask disable register + 0x588 + 0x20 + + + CORE_1_NMI_MASK_DISABLE + this field is used to disable NMI mask, it will not take effect immediately,only when the CPU executes to the trigger address will it start to cancel NMI mask + 0 + 32 + write-only + + + + + Core_1_NMI_MASK_CANCLE + Core_1 NMI mask disable register + 0x58C + 0x20 + + + CORE_1_NMI_MASK_CANCEL + this field is used to cancel NMI mask disable function. + 0 + 32 + write-only + + + + + Core_1_NMI_MASK + Core_1 NMI mask register + 0x590 + 0x20 + + + CORE_1_NMI_MASK + this bit is used to mask NMI interrupt,it can directly mask NMI interrupt + 0 + 1 + read-write + + + + + Core_1_NMI_MASK_PHASE + Core_1 NMI mask phase register + 0x594 + 0x20 + + + CORE_1_NMI_MASK_PHASE + this bit is used to indicates whether the NMI interrupt is being masked, 1 means NMI interrupt is being masked + 0 + 1 + read-only + + + + + + + XTS_AES + XTS-AES-128 Flash Encryption + XTS_AES + 0x600CC000 + + 0x0 + 0x60 + registers + + + + 16 + 0x4 + PLAIN_%s + Plaintext register %s + 0x0 + 0x20 + + + PLAIN_0 + Stores the nth 32-bit piece of plaintext. + 0 + 32 + read-write + + + + + LINESIZE + XTS-AES line-size register + 0x40 + 0x20 + + + LINESIZE + Configures the data size of one encryption. + 0 + 1 + read-write + + + + + DESTINATION + XTS-AES destination register + 0x44 + 0x20 + + + DESTINATION + Configures the type of the external memory. Currently, it must be set to 0, as the Manual Encryption block only supports flash encryption. Errors may occurs if users write 1. 0:flash. 1: external RAM. + 0 + 1 + read-write + + + + + PHYSICAL_ADDRESS + physical address + 0x48 + 0x20 + + + PHYSICAL_ADDRESS + Those bits stores the physical address. If linesize is 16-byte, the physical address should be aligned of 16 bytes. If linesize is 32-byte, the physical address should be aligned of 32 bytes. If linesize is 64-byte, the physical address should be aligned of 64 bytes. + 0 + 30 + read-write + + + + + TRIGGER + XTS-AES trigger register + 0x4C + 0x20 + + + TRIGGER + Write 1 to activate manual encryption. + 0 + 1 + write-only + + + + + RELEASE + XTS-AES release control register + 0x50 + 0x20 + + + RELEASE + Write 1 to grant SPI1 access to encrypted result. + 0 + 1 + write-only + + + + + DESTROY + XTS-AES destroy control register + 0x54 + 0x20 + + + DESTROY + Write 1 to destroy encrypted result. + 0 + 1 + write-only + + + + + STATE + XTS-AES status register + 0x58 + 0x20 + + + STATE + Those bits indicates the status of the Manual Encryption block. 0X0 (XTS_AES_IDLE): idle. 0X1 (XTS_AES_BUSY): busy with encryption. 0X2 (XTS_AES_DONE): encryption is completed, but the encrypted result is not accessible to SPI. 0X3 (XTS_AES_AVAILABLE) encrypted result is accessible and available to SPI. + 0 + 2 + read-only + + + + + DATE + XTS-AES version control register + 0x5C + 0x20 + 0x20200111 + + + DATE + Manual Encryption block version information. + 0 + 30 + read-write + + + + + + + \ No newline at end of file diff --git a/Software/fab-reader2-c/gdbinit b/Software/fab-reader2-c/gdbinit new file mode 100644 index 0000000..11d978e --- /dev/null +++ b/Software/fab-reader2-c/gdbinit @@ -0,0 +1,6 @@ +target remote :3333 +set remote hardware-watchpoint-limit 2 +mon reset halt +flushregs +thb app_main +c diff --git a/Software/fab-reader2-c/main/CMakeLists.txt b/Software/fab-reader2-c/main/CMakeLists.txt new file mode 100644 index 0000000..7e585fa --- /dev/null +++ b/Software/fab-reader2-c/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "fab-reader2.c" "pollingtagdetect.c" + INCLUDE_DIRS "." + REQUIRES "rfal") diff --git a/Software/fab-reader2-c/main/fab-reader2.c b/Software/fab-reader2-c/main/fab-reader2.c new file mode 100644 index 0000000..2d0c591 --- /dev/null +++ b/Software/fab-reader2-c/main/fab-reader2.c @@ -0,0 +1,102 @@ +#include +#include +#include + +#include "platform.h" +#include "st25R3911_interrupt.h" + +#include "pollingtagdetect.h" + +#define SPI_CLK 5 +#define SPI_MOSI 6 +#define SPI_MISO 7 + +#define ESP_INTR_FLAG_DEFAULT 0 + +portMUX_TYPE CommProtectLock = portMUX_INITIALIZER_UNLOCKED; + +static void gpio_isr_handler(void *arg) { + st25r3911Isr(); +} + +esp_err_t init_gpio(void) { + gpio_config_t io_conf = {}; + //disable interrupt + io_conf.intr_type = GPIO_INTR_DISABLE; + //set as output mode + io_conf.mode = GPIO_MODE_INPUT_OUTPUT; + //bit mask of the pins that you want to set,e.g.GPIO18/19 + io_conf.pin_bit_mask = (1ULL << ST25R391X_SS_PIN); + //disable pull-down mode + io_conf.pull_down_en = 0; + //disable pull-up mode + io_conf.pull_up_en = 0; + //configure GPIO with the given settings + esp_err_t ret = gpio_config(&io_conf); + ESP_ERROR_CHECK(ret); + + + //interrupt of rising edge + io_conf.intr_type = GPIO_INTR_POSEDGE; + //bit mask of the pins, use GPIO4/5 here + io_conf.pin_bit_mask = (1ULL << ST25R391X_INT_PIN); + //set as input mode + io_conf.mode = GPIO_MODE_INPUT; + //enable pull-up mode +// io_conf.pull_up_en = 1; + ret = gpio_config(&io_conf); + ESP_ERROR_CHECK(ret); + + + ret = gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + ESP_ERROR_CHECK(ret); + //hook isr handler for specific gpio pin + ret = gpio_isr_handler_add(ST25R391X_INT_PIN, gpio_isr_handler, NULL); + ESP_ERROR_CHECK(ret); + + return ret; +} + +esp_err_t init_spi(void) { + spi_bus_config_t buscfg = { + .miso_io_num=SPI_MISO, + .mosi_io_num=SPI_MOSI, + .sclk_io_num=SPI_CLK, + .quadwp_io_num=-1, + .quadhd_io_num=-1, + }; + esp_err_t ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO); + ESP_ERROR_CHECK(ret); + + spi_device_interface_config_t devcfg = { + .clock_speed_hz=SPI_MASTER_FREQ_8M, //Clock out at 4 MHz + .mode=1, //SPI mode 1 + .spics_io_num=-1, //CS pin + .queue_size=1, //We want to be able to queue 7 transactions at a time + }; + + spi_device_handle_t spi; + ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi); + ESP_ERROR_CHECK(ret); + st25r3911_spi_init(spi); + + return ret; +} + +_Noreturn static void cycle_task(void *arg) { + while (1) { + TagDetectCycle(); +// ESP_LOGI("cycle_task", "running tag detect cycle_task"); + } +} + +void app_main(void) { + ESP_ERROR_CHECK(init_gpio()); + ESP_LOGI("main", "init_gpio done"); + ESP_ERROR_CHECK(init_spi()); + ESP_LOGI("main", "init_spi done"); + ESP_ERROR_CHECK(TagDetectInit()); + ESP_LOGI("main", "TagDetectInit done"); + xTaskCreate(cycle_task, "cycle_task", 4096, NULL, tskIDLE_PRIORITY, NULL); + ESP_LOGI("main", "cycle_task sheduled"); +} diff --git a/Software/fab-reader2-c/main/idf_component.yml b/Software/fab-reader2-c/main/idf_component.yml new file mode 100644 index 0000000..4af0b4c --- /dev/null +++ b/Software/fab-reader2-c/main/idf_component.yml @@ -0,0 +1,17 @@ +## IDF Component Manager Manifest File +dependencies: +# espressif/esp-idf-cxx: "^1.0.0-beta" + ## Required IDF version + idf: + version: ">=4.4.0" + # # Put list of dependencies here + # # For components maintained by Espressif: + # component: "~1.0.0" + # # For 3rd party components: + # username/component: ">=1.0.0,<2.0.0" + # username2/component2: + # version: "~1.0.0" + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect dependencies of the `main` component. + # # All dependencies of `main` are public by default. + # public: true diff --git a/Software/fab-reader2-c/main/pollingtagdetect.c b/Software/fab-reader2-c/main/pollingtagdetect.c new file mode 100644 index 0000000..73d1838 --- /dev/null +++ b/Software/fab-reader2-c/main/pollingtagdetect.c @@ -0,0 +1,264 @@ +// +// Created by Kai Jan Kriegel on 17.10.22. +// + +#include "pollingtagdetect.h" +#include "rfal_nfc.h" +#include "utils.h" + + +/* P2P communication data */ +static uint8_t NFCID3[] = {0x01, 0xFE, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}; +static uint8_t GB[] = {0x46, 0x66, 0x6d, 0x01, 0x01, 0x11, 0x02, 0x02, 0x07, 0x80, 0x03, 0x02, 0x00, 0x03, 0x04, 0x01, + 0x32, 0x07, 0x01, 0x03}; + +/* APDUs communication data */ +static uint8_t ndefSelectApp[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01, 0x00}; +static uint8_t ccSelectFile[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03}; +static uint8_t readBinary[] = {0x00, 0xB0, 0x00, 0x00, 0x0F}; + +typedef enum { + NOT_INIT = 0, /*!< Demo State: Not initialized */ + START_DISCOVERY = 1, /*!< Demo State: Start Discovery */ + DISCOVERY = 2 /*!< Demo State: Discovery */ +} TagDetectState; + + +static rfalNfcDiscoverParam discParam; +static TagDetectState state = NOT_INIT; + +void TagDetectAPDU(void); + +ReturnCode TagDetectTransceiveBlocking(uint8_t *txBuf, uint16_t txBufSize, uint8_t **rxData, uint16_t **rcvLen, uint32_t fwt); + +static void TagDetectNotify(rfalNfcState st) { + uint8_t devCnt; + rfalNfcDevice *dev; + + + if (st == RFAL_NFC_STATE_WAKEUP_MODE) { + platformLog("Wake Up mode started \r\n"); + } else if (st == RFAL_NFC_STATE_POLL_TECHDETECT) { + platformLog("Wake Up mode terminated. Polling for devices \r\n"); + } else if (st == RFAL_NFC_STATE_POLL_SELECT) { + /* Multiple devices were found, activate first of them */ + rfalNfcGetDevicesFound(&dev, &devCnt); + rfalNfcSelect(0); + + platformLog("Multiple Tags detected: %d \r\n", devCnt); + } +} + +esp_err_t TagDetectInit(void) { + ReturnCode err = rfalNfcInitialize(); + if (err == ERR_NONE) { + discParam.compMode = RFAL_COMPLIANCE_MODE_NFC; + discParam.devLimit = 1U; + + ST_MEMCPY(&discParam.nfcid3, NFCID3, sizeof(NFCID3)); + ST_MEMCPY(&discParam.GB, GB, sizeof(GB)); + discParam.GBLen = sizeof(GB); + + discParam.notifyCb = TagDetectNotify; + discParam.totalDuration = 1000U; + discParam.wakeupEnabled = false; + discParam.wakeupConfigDefault = true; + discParam.techs2Find = (RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B); + +#if defined(ST25R3911) || defined(ST25R3916) + discParam.techs2Find |= RFAL_NFC_POLL_TECH_AP2P; +#endif /* ST25R95 */ + state = START_DISCOVERY; + return ESP_OK; + } + return err; +} + + +/*! + ***************************************************************************** + * \brief Demo Cycle + * + * This function executes the demo state machine. + * It must be called periodically + ***************************************************************************** + */ +void TagDetectCycle(void) { + static rfalNfcDevice *nfcDevice; + + rfalNfcWorker(); /* Run RFAL worker periodically */ + + /*******************************************************************************/ + /* Check if USER button is pressed */ +// if (platformGpioIsLow(PLATFORM_USER_BUTTON_PORT, PLATFORM_USER_BUTTON_PIN)) { +// discParam.wakeupEnabled = !discParam.wakeupEnabled; /* enable/disable wakeup */ +// state = START_DISCOVERY; /* restart loop */ +// platformLog("Toggling Wake Up mode %s\r\n", discParam.wakeupEnabled ? "ON" : "OFF"); +// +// /* Debounce button */ +// while (platformGpioIsLow(PLATFORM_USER_BUTTON_PORT, PLATFORM_USER_BUTTON_PIN)); +// } + + + switch (state) { + /*******************************************************************************/ + case START_DISCOVERY: + +// platformLedOff(PLATFORM_LED_A_PORT, PLATFORM_LED_A_PIN); +// platformLedOff(PLATFORM_LED_B_PORT, PLATFORM_LED_B_PIN); +// platformLedOff(PLATFORM_LED_F_PORT, PLATFORM_LED_F_PIN); +// platformLedOff(PLATFORM_LED_V_PORT, PLATFORM_LED_V_PIN); +// platformLedOff(PLATFORM_LED_AP2P_PORT, PLATFORM_LED_AP2P_PIN); +// platformLedOff(PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN); + + rfalNfcDeactivate(false); + rfalNfcDiscover(&discParam); + platformLog("Discovery started \r\n"); + + state = DISCOVERY; + break; + + /*******************************************************************************/ + case DISCOVERY: + + if (rfalNfcIsDevActivated(rfalNfcGetState())) { + rfalNfcGetActiveDevice(&nfcDevice); + platformLog("Device activated. \r\n"); + switch (nfcDevice->type) { + /*******************************************************************************/ + case RFAL_NFC_LISTEN_TYPE_NFCA: + +// platformLedOn(PLATFORM_LED_A_PORT, PLATFORM_LED_A_PIN); + switch (nfcDevice->dev.nfca.type) { + case RFAL_NFCA_T1T: + platformLog("ISO14443A/Topaz (NFC-A T1T) TAG found. UID: %s\r\n", + hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); + break; + + case RFAL_NFCA_T4T: + platformLog("NFCA Passive ISO-DEP device found. UID: %s\r\n", + hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); + + TagDetectAPDU(); + break; + + case RFAL_NFCA_T4T_NFCDEP: + case RFAL_NFCA_NFCDEP: + platformLog("NFCA Passive P2P device found. NFCID: %s\r\n", + hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); + +// demoP2P(); + break; + + default: + platformLog("ISO14443A/NFC-A card found. UID: %s\r\n", + hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); + break; + } + break; + + /*******************************************************************************/ + case RFAL_NFC_LISTEN_TYPE_NFCB: + + platformLog("ISO14443B/NFC-B card found. UID: %s\r\n", + hex2Str(nfcDevice->nfcid, nfcDevice->nfcidLen)); +// platformLedOn(PLATFORM_LED_B_PORT, PLATFORM_LED_B_PIN); + + if (rfalNfcbIsIsoDepSupported(&nfcDevice->dev.nfcb)) { + TagDetectAPDU(); + } + break; + + /*******************************************************************************/ + default: + break; + } + + rfalNfcDeactivate(false); + platformLog("Device deactivated. \r\n"); + platformDelay(500); + state = START_DISCOVERY; + } + break; + + /*******************************************************************************/ + case NOT_INIT: + default: + platformLog("ERROR: Demo not initialized \r\n"); + break; + } +} + +/*! + ***************************************************************************** + * \brief Demo APDUs Exchange + * + * Example how to exchange a set of predefined APDUs with PICC. The NDEF + * application will be selected and then CC will be selected and read. + * + ***************************************************************************** + */ +void TagDetectAPDU(void) { + ReturnCode err; + uint16_t *rxLen; + uint8_t *rxData; + + + /* Exchange APDU: NDEF Tag Application Select command */ + err = TagDetectTransceiveBlocking(ndefSelectApp, sizeof(ndefSelectApp), &rxData, &rxLen, RFAL_FWT_NONE); + platformLog(" Select NDEF Application: %s Data: %s\r\n", (err != ERR_NONE) ? "FAIL" : "OK", + hex2Str(rxData, *rxLen)); + + if ((err == ERR_NONE) && rxData[0] == 0x90 && rxData[1] == 0x00) { + /* Exchange APDU: Select Capability Container File */ + err = TagDetectTransceiveBlocking(ccSelectFile, sizeof(ccSelectFile), &rxData, &rxLen, RFAL_FWT_NONE); + platformLog(" Select CC: %s Data: %s\r\n", (err != ERR_NONE) ? "FAIL" : "OK", hex2Str(rxData, *rxLen)); + + /* Exchange APDU: Read Capability Container File */ + err = TagDetectTransceiveBlocking(readBinary, sizeof(readBinary), &rxData, &rxLen, RFAL_FWT_NONE); + platformLog(" Read CC: %s Data: %s\r\n", (err != ERR_NONE) ? "FAIL" : "OK", hex2Str(rxData, *rxLen)); + } +} + + +/*! + ***************************************************************************** + * \brief Demo Blocking Transceive + * + * Helper function to send data in a blocking manner via the rfalNfc module + * + * \warning A protocol transceive handles long timeouts (several seconds), + * transmission errors and retransmissions which may lead to a long period of + * time where the MCU/CPU is blocked in this method. + * This is a demo implementation, for a non-blocking usage example please + * refer to the Examples available with RFAL + * + * \param[in] txBuf : data to be transmitted + * \param[in] txBufSize : size of the data to be transmited + * \param[out] rxData : location where the received data has been placed + * \param[out] rcvLen : number of data bytes received + * \param[in] fwt : FWT to be used (only for RF frame interface, + * otherwise use RFAL_FWT_NONE) + * + * + * \return ERR_PARAM : Invalid parameters + * \return ERR_TIMEOUT : Timeout error + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + * + ***************************************************************************** + */ +ReturnCode +TagDetectTransceiveBlocking(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 == ERR_NONE) { + do { + rfalNfcWorker(); + err = rfalNfcDataExchangeGetStatus(); + } while (err == ERR_BUSY); + } + return err; +} diff --git a/Software/fab-reader2-c/main/pollingtagdetect.h b/Software/fab-reader2-c/main/pollingtagdetect.h new file mode 100644 index 0000000..84cbe35 --- /dev/null +++ b/Software/fab-reader2-c/main/pollingtagdetect.h @@ -0,0 +1,21 @@ +// +// Created by Kai Jan Kriegel on 17.10.22. +// + +#ifndef FAB_READER2_C_POLLINGTAGDETECT_H +#define FAB_READER2_C_POLLINGTAGDETECT_H + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +esp_err_t TagDetectInit(void); +void TagDetectCycle(void); + +#ifdef __cplusplus +} +#endif + +#endif //FAB_READER2_C_POLLINGTAGDETECT_H diff --git a/Software/fab-reader2-c/sdkconfig b/Software/fab-reader2-c/sdkconfig new file mode 100644 index 0000000..8def02d --- /dev/null +++ b/Software/fab-reader2-c/sdkconfig @@ -0,0 +1,1401 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# SDK tool configuration +# +CONFIG_SDK_TOOLPREFIX="xtensa-esp32s3-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +# +# Bootloader config +# +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_SUPPORTS_RSA=y +CONFIG_SECURE_TARGET_HAS_SECURE_ROM_DL_MODE=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +# end of Bluetooth + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# MCPWM configuration +# +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# end of MCPWM configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ESP32S3-Specific +# +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160=y +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP is not set +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_WRAP is not set +# end of Cache config + +# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32S3_ULP_COPROC_ENABLED is not set +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +# CONFIG_ESP32S3_NO_BLOBS is not set +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of ESP32S3-Specific + +# +# ADC-Calibration +# +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB=y +# end of RTC Clock Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +CONFIG_ESP_PHY_ENABLE_USB=y +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +# CONFIG_FMB_PORT_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_FMB_PORT_TASK_AFFINITY_CPU0=y +# CONFIG_FMB_PORT_TASK_AFFINITY_CPU1 is not set +CONFIG_FMB_PORT_TASK_AFFINITY=0x0 +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_FMB_TIMER_PORT_ENABLED is not set +# CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD is not set +# end of Modbus configuration + +# +# FreeRTOS +# +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +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_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v2.28.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v2.28.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ERROR_STACK=y +# CONFIG_OPENSSL_ASSERT_DO_NOTHING is not set +CONFIG_OPENSSL_ASSERT_EXIT=y +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport + +# +# TinyUSB Stack +# +# CONFIG_TINYUSB is not set +# end of TinyUSB Stack + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_OTG_SUPPORTED=y +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32s3-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +# CONFIG_ESP_SYSTEM_PD_FLASH is not set +CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_GDBSTUB is not set +CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_MB_TIMER_PORT_ENABLED is not set +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +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_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +# CONFIG_USB_ENABLED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/Software/fab-reader2-c/sdkconfig.old b/Software/fab-reader2-c/sdkconfig.old new file mode 100644 index 0000000..ff98e11 --- /dev/null +++ b/Software/fab-reader2-c/sdkconfig.old @@ -0,0 +1,1602 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDE_NUM=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256=y +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_SIZE=64 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_GDMA_GROUPS=y +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GDMA_PSRAM_MIN_ALIGN=16 +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_GPIO_SUPPORT_SLP_SWITCH=y +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_SUPPORTS_PDM_CODEC=y +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_PCNT_GROUPS=y +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_SDM_GROUPS=y +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_MEMSPI_SRC_FREQ_120M=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_TOUCH_VERSION_2=y +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_PAD_THRESHOLD_MAX=0x1FFFFF +CONFIG_SOC_TOUCH_PAD_MEASURE_WAIT_MAX=0xFF +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_REQUIRE_CORE_RESET=y +CONFIG_SOC_USB_PERIPH_NUM=y +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIME_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_UART2 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +# end of Bluetooth + +# +# Driver Configurations +# + +# +# Legacy ADC Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Configuration + +# +# SPI Configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI Configuration + +# +# TWAI Configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# end of TWAI Configuration + +# +# Temperature sensor Configuration +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of Temperature sensor Configuration + +# +# UART Configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART Configuration + +# +# GPIO Configuration +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of GPIO Configuration + +# +# Sigma Delta Modulator Configuration +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of Sigma Delta Modulator Configuration + +# +# GPTimer Configuration +# +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of GPTimer Configuration + +# +# PCNT Configuration +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of PCNT Configuration + +# +# RMT Configuration +# +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# end of RMT Configuration + +# +# MCPWM Configuration +# +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of MCPWM Configuration + +# +# I2S Configuration +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of I2S Configuration +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# end of ADC and ADC Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB=y +# end of RTC Clock Config + +# +# Peripheral Control +# +# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set +# end of Peripheral Control + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config +# end of Hardware Settings + +# +# LCD and Touch Panel +# + +# +# LCD Touch Drivers are maintained in the IDF Component Registry +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +CONFIG_ESP_PHY_REDUCE_TX_POWER=y +CONFIG_ESP_PHY_ENABLE_USB=y +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# +# CONFIG_SPIRAM is not set +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=y +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=160 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +# end of Brownout Detector + +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1536 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=2 +# CONFIG_FATFS_SECTOR_512 is not set +# CONFIG_FATFS_SECTOR_1024 is not set +# CONFIG_FATFS_SECTOR_2048 is not set +CONFIG_FATFS_SECTOR_4096=y +CONFIG_FATFS_SECTORS_PER_CLUSTER_1=y +# CONFIG_FATFS_SECTORS_PER_CLUSTER_2 is not set +# CONFIG_FATFS_SECTORS_PER_CLUSTER_4 is not set +# CONFIG_FATFS_SECTORS_PER_CLUSTER_8 is not set +# CONFIG_FATFS_SECTORS_PER_CLUSTER_16 is not set +# CONFIG_FATFS_SECTORS_PER_CLUSTER_32 is not set +# CONFIG_FATFS_SECTORS_PER_CLUSTER_64 is not set +# CONFIG_FATFS_SECTORS_PER_CLUSTER_128 is not set +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_AUTO_TYPE=y +# CONFIG_FATFS_FAT12 is not set +# CONFIG_FATFS_FAT16 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=1000 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +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_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK 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_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# end of Port + +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +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_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y +# CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# Protocomm +# +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +# end of Protocomm + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_HAS_ROM_IMPL=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Ultra Low Power (ULP) Co-processor +# +# CONFIG_ULP_COPROC_ENABLED is not set +# end of Ultra Low Power (ULP) Co-processor + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_OTG_SUPPORTED=y +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# end of Supplicant +# end of Component config diff --git a/Software/fab-reader2/out.bin b/Software/fab-reader2/out.bin new file mode 100644 index 0000000000000000000000000000000000000000..185435947e204c422256707ea4aee3f8e204a2a5 GIT binary patch literal 490256 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 z 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

?`?}jZo%TvrV6d< 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 literal 0 HcmV?d00001 diff --git a/Software/fab-reader2/src/main.rs b/Software/fab-reader2/src/main.rs index d6c2834..8d2ebd2 100644 --- a/Software/fab-reader2/src/main.rs +++ b/Software/fab-reader2/src/main.rs @@ -8,22 +8,22 @@ use embedded_hal::digital::v2::OutputPin; use esp_idf_sys::esp_sleep_pd_domain_t_ESP_PD_DOMAIN_VDDSDIO; use esp_idf_sys::EspError; -use esp_idf_hal::{delay, gpio}; use esp_idf_hal::gpio::{GpioPin, Unknown}; use esp_idf_hal::prelude::*; use esp_idf_hal::spi; +use esp_idf_hal::{delay, gpio}; use anyhow::Result; -use embedded_graphics::{Drawable, mono_font}; use embedded_graphics::mono_font::iso_8859_15::FONT_10X20; use embedded_graphics::mono_font::MonoTextStyle; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::Point; use embedded_graphics::text::Text; +use embedded_graphics::{mono_font, Drawable}; -use pervasive_epd::E2266CS0Cx; use pervasive_epd::graphics::{Display, VarDisplay}; use pervasive_epd::prelude::*; +use pervasive_epd::E2266CS0Cx; fn main() -> Result<()> { // Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once, @@ -33,6 +33,10 @@ fn main() -> Result<()> { let peripherals = Peripherals::take().unwrap(); let pins = peripherals.pins; + // NFC related pins + let nfc_cs = pins.gpio4.into_output()?; + let nfc_irq = pins.gpio15.into_input()?; + // EPD related pins let epd_cs = pins.gpio38.into_output()?; let epd_busy = pins.gpio41.into_input()?; @@ -76,7 +80,7 @@ fn main() -> Result<()> { epd_rst, &mut delay::Ets, ) - .unwrap(); + .unwrap(); // Use display graphics from embedded-graphics let mut buffer = vec![ E2266CS0Cx::DEFAULT_BACKGROUND_COLOR.get_byte_value(); diff --git a/Software/fab-reader2/st25r3911b/Cargo.toml b/Software/fab-reader2/st25r3911b/Cargo.toml index 3246593..6430023 100644 --- a/Software/fab-reader2/st25r3911b/Cargo.toml +++ b/Software/fab-reader2/st25r3911b/Cargo.toml @@ -8,9 +8,8 @@ edition = "2021" [dependencies] embedded-hal = { version ="0.2.7", features = ["unproven"] } embedded-svc = "0.22.1" -esp-idf-svc = { version = "0.42.1", features = ["alloc" ] } -esp-idf-hal = "0.38.1" anyhow = "1.0.65" +array-concat = "0.5.1" [build-dependencies] anyhow = "1.0.65" diff --git a/Software/fab-reader2/st25r3911b/src/analogConfig.rs b/Software/fab-reader2/st25r3911b/src/analogConfig.rs deleted file mode 100644 index bbe3443..0000000 --- a/Software/fab-reader2/st25r3911b/src/analogConfig.rs +++ /dev/null @@ -1,143 +0,0 @@ -use crate::constants::*; -use crate::Register; - -/* Helpers */ -// Register Helpers for 1 to 13 sets -const fn MODE_ENTRY_1_REG(mode: u32, r0: u32, m0: u8, v0: u8) -> [u8; 7] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 1, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0] -} - -const fn MODE_ENTRY_2_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8) -> [u8; 11] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 2, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1] -} - -const fn MODE_ENTRY_3_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8) -> [u8; 15] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 3, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2] -} - -const fn MODE_ENTRY_4_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8) -> [u8; 19] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 4, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3] -} - -const fn MODE_ENTRY_5_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8) -> [u8; 23] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 5, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4] -} - -const fn MODE_ENTRY_6_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8) -> [u8; 27] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 6, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5] -} - -const fn MODE_ENTRY_7_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8) -> [u8; 31] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 7, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6] -} - -const fn MODE_ENTRY_8_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8) -> [u8; 35] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 8, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7] -} - -const fn MODE_ENTRY_9_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8) -> [u8; 39] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 9, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8] -} - -const fn MODE_ENTRY_10_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8) -> [u8; 43] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 10, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9] -} - -const fn MODE_ENTRY_11_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8, r10: u32, m10: u8, v10: u8) -> [u8; 47] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 11, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9, (r10 << 8) as u8, (r10 & 0xFF) as u8, m10, v10] -} - -const fn MODE_ENTRY_12_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8, r10: u32, m10: u8, v10: u8, r11: u32, m11: u8, v11: u8) -> [u8; 51] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 12, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9, (r10 << 8) as u8, (r10 & 0xFF) as u8, m10, v10, (r11 << 8) as u8, (r11 & 0xFF) as u8, m11, v11] -} - -const fn MODE_ENTRY_13_REG(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8, r10: u32, m10: u8, v10: u8, r11: u32, m11: u8, v11: u8, r12: u32, m12: u8, v12: u8) -> [u8; 55] { - [(mode << 8) as u8, (mode & 0xFF) as u8, 13, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9, (r10 << 8) as u8, (r10 & 0xFF) as u8, m10, v10, (r11 << 8) as u8, (r11 & 0xFF) as u8, m11, v11, (r12 << 8) as u8, (r12 & 0xFF) as u8, m12, v12] -} - -const AM_MOD_DRIVER_LEVEL_DEFAULT: u8 = 0xb9; - -const ANALOG_CONFIG_LUT_SIZE: u32 = 87; /*!< Maximum number of Configuration IDs in the Loop Up Table */ -const ANALOG_CONFIG_LUT_NOT_FOUND: u32 = 0xFF; /*!< Index value indicating no Configuration IDs found */ - -const ANALOG_CONFIG_TBL_SIZE: u32 = 1024; /*!< Maximum number of Register-Mask-Value in the Setting List */ - - -const ANALOG_CONFIG_POLL_LISTEN_MODE_MASK: u32 = 0x8000; /*!< Mask bit of Poll Mode in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_MASK: u32 = 0x7F00; /*!< Mask bits for Technology in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_MASK: u32 = 0x00F0; /*!< Mask bits for Bit rate in Analog Configuration ID */ -const ANALOG_CONFIG_DIRECTION_MASK: u32 = 0x0003; /*!< Mask bits for Direction in Analog Configuration ID */ -const ANALOG_CONFIG_CHIP_SPECIFIC_MASK: u32 = 0x00FF; /*!< Mask bits for Chip Specific Technology */ - -const ANALOG_CONFIG_POLL_LISTEN_MODE_SHIFT: u32 = 15; /*!< Shift value of Poll Mode in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_SHIFT: u32 = 8; /*!< Shift value for Technology in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_SHIFT: u32 = 4; /*!< Shift value for Technology in Analog Configuration ID */ -const ANALOG_CONFIG_DIRECTION_SHIFT: u32 = 0; /*!< Shift value for Direction in Analog Configuration ID */ - -const ANALOG_CONFIG_POLL: u32 = 0x0000; /*!< Poll Mode bit setting in Analog Configuration ID */ -const ANALOG_CONFIG_LISTEN: u32 = 0x8000; /*!< Listen Mode bit setting in Analog Configuration ID */ - -const ANALOG_CONFIG_TECH_CHIP: u32 = 0x0000; /*!< Chip-Specific bit setting in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_NFCA: u32 = 0x0100; /*!< NFC-A Technology bits setting in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_NFCB: u32 = 0x0200; /*!< NFC-B Technology bits setting in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_NFCF: u32 = 0x0400; /*!< NFC-F Technology bits setting in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_AP2P: u32 = 0x0800; /*!< AP2P Technology bits setting in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_NFCV: u32 = 0x1000; /*!< NFC-V Technology bits setting in Analog Configuration ID */ -const ANALOG_CONFIG_TECH_RFU: u32 = 0x2000; /*!< RFU for Technology bits */ - -const ANALOG_CONFIG_BITRATE_COMMON: u32 = 0x0000; /*!< Common settings for all bit rates in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_106: u32 = 0x0010; /*!< 106kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_212: u32 = 0x0020; /*!< 212kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_424: u32 = 0x0030; /*!< 424kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_848: u32 = 0x0040; /*!< 848kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_1695: u32 = 0x0050; /*!< 1695kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_3390: u32 = 0x0060; /*!< 3390kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_6780: u32 = 0x0070; /*!< 6780kbits/s settings in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_1OF4: u32 = 0x00C0; /*!< 1 out of 4 for NFC-V setting in Analog Configuration ID */ -const ANALOG_CONFIG_BITRATE_1OF256: u32 = 0x00D0; /*!< 1 out of 256 for NFC-V setting in Analog Configuration ID */ - -const ANALOG_CONFIG_NO_DIRECTION: u32 = 0x0000; /*!< No direction setting in Analog Conf ID (Chip Specific only) */ -const ANALOG_CONFIG_TX: u32 = 0x0001; /*!< Transmission bit setting in Analog Configuration ID */ -const ANALOG_CONFIG_RX: u32 = 0x0002; /*!< Reception bit setting in Analog Configuration ID */ -const ANALOG_CONFIG_ANTICOL: u32 = 0x0003; /*!< Anticollision setting in Analog Configuration ID */ - -const ANALOG_CONFIG_CHIP_INIT: u32 = 0x0000; /*!< Chip-Specific event: Startup;Reset;Initialize */ -const ANALOG_CONFIG_CHIP_DEINIT: u32 = 0x0001; /*!< Chip-Specific event: Deinitialize */ -const ANALOG_CONFIG_CHIP_FIELD_ON: u32 = 0x0002; /*!< Chip-Specific event: Field On */ -const ANALOG_CONFIG_CHIP_FIELD_OFF: u32 = 0x0003; /*!< Chip-Specific event: Field Off */ -const ANALOG_CONFIG_CHIP_WAKEUP_ON: u32 = 0x0004; /*!< Chip-Specific event: Wake-up On */ -const ANALOG_CONFIG_CHIP_WAKEUP_OFF: u32 = 0x0005; /*!< Chip-Specific event: Wake-up Off */ -const ANALOG_CONFIG_CHIP_LISTEN_ON: u32 = 0x0006; /*!< Chip-Specific event: Listen On */ -const ANALOG_CONFIG_CHIP_LISTEN_OFF: u32 = 0x0007; /*!< Chip-Specific event: Listen Off */ -const ANALOG_CONFIG_CHIP_POLL_COMMON: u32 = 0x0008; /*!< Chip-Specific event: Poll common */ -const ANALOG_CONFIG_CHIP_LISTEN_COMMON: u32 = 0x0009; /*!< Chip-Specific event: Listen common */ - -const ANALOG_CONFIG_UPDATE_LAST: u32 = 0x00; /*!< Value indicating Last configuration set during update */ -const ANALOG_CONFIG_UPDATE_MORE: u32 = 0x01; /*!< Value indicating More configuration set coming during update */ - -const DEFAULT_ANALOG_CONFIG: Vec = MODE_ENTRY_10_REG(ANALOG_CONFIG_TECH_CHIP | ANALOG_CONFIG_CHIP_INIT, - Register::OperationControl as u32, 0x30, 0x10, //Default to AM - Register::IOConfiguration1 as u32, 0x06, 0x06, //MCUCLK: HF clk off - Register::IOConfiguration1 as u32, IOConfiguration1Bits::mask_out_cl as u8 | IOConfiguration1Bits::lf_clk_off as u8, 0x07, // MCUCLK: LF clk off - Register::IOConfiguration2 as u32, 0x18, 0x18, // pull downs - Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::mask_rg2_pm as u8, 0x1 << ReceiverConfiguration4Mask::shift_rg2_pm as u8, //increase digitizer windows for PM - Register::AnntenaCalibrationTarget as u32, 0xFF, 0x80, // 90 deg, - Register::AnntenaCalibrationControl as u32, 0xF8, 0x00, // trim value from calibrate antenna - Register::AMModulationDepthControl as u32, AMModulationDepthControlConstans::am_s as u8, AMModulationDepthControlConstans::am_s as u8, // AM modulated level is defined by RFO AM Modulated Level Def Reg, fixed setting, no automatic adjustment - Register::ExternalFieldDetectorThreshold as u32, EXT_FIELD_DET_TRG_MASK, ExternalFieldDetectorThresholdTrgVoltage::trg_75mV as u8, - Register::ExternalFieldDetectorThreshold as u32, EXT_FIELD_DET_RFE_MASK, ExternalFieldDetectorThresholdRfeVoltage::rfe_75mV as u8 -).into_iter().collect(); - -pub(crate) struct AnalogConfigMgmt { - config_tbl: Box<[u8]>, - ready: bool, -} - -impl AnalogConfigMgmt { - pub fn new_default() -> Self { - Self { - config_tbl: DEFAULT_ANALOG_CONFIG.into_boxed_slice(), - ready: true, - } - } -} \ No newline at end of file diff --git a/Software/fab-reader2/st25r3911b/src/analog_config.rs b/Software/fab-reader2/st25r3911b/src/analog_config.rs new file mode 100644 index 0000000..88f4b6b --- /dev/null +++ b/Software/fab-reader2/st25r3911b/src/analog_config.rs @@ -0,0 +1,437 @@ +use array_concat::*; + +use crate::constants::*; +use crate::Register; + +/* Helpers */ +// Register Helpers for 1 to 13 sets +const fn mode_entry_1_reg(mode: u32, r0: u32, m0: u8, v0: u8) -> [u8; 7] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 1, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0] +} + +const fn mode_entry_2_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8) -> [u8; 11] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 2, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1] +} + +const fn mode_entry_3_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8) -> [u8; 15] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 3, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2] +} + +const fn mode_entry_4_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8) -> [u8; 19] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 4, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3] +} + +const fn mode_entry_5_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8) -> [u8; 23] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 5, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4] +} + +const fn mode_entry_6_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8) -> [u8; 27] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 6, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5] +} + +const fn mode_entry_7_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8) -> [u8; 31] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 7, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6] +} + +const fn mode_entry_8_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8) -> [u8; 35] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 8, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7] +} + +const fn mode_entry_9_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8) -> [u8; 39] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 9, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8] +} + +const fn mode_entry_10_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8) -> [u8; 43] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 10, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9] +} + +const fn mode_entry_11_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8, r10: u32, m10: u8, v10: u8) -> [u8; 47] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 11, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9, (r10 << 8) as u8, (r10 & 0xFF) as u8, m10, v10] +} + +const fn mode_entry_12_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8, r10: u32, m10: u8, v10: u8, r11: u32, m11: u8, v11: u8) -> [u8; 51] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 12, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9, (r10 << 8) as u8, (r10 & 0xFF) as u8, m10, v10, (r11 << 8) as u8, (r11 & 0xFF) as u8, m11, v11] +} + +const fn mode_entry_13_reg(mode: u32, r0: u32, m0: u8, v0: u8, r1: u32, m1: u8, v1: u8, r2: u32, m2: u8, v2: u8, r3: u32, m3: u8, v3: u8, r4: u32, m4: u8, v4: u8, r5: u32, m5: u8, v5: u8, r6: u32, m6: u8, v6: u8, r7: u32, m7: u8, v7: u8, r8: u32, m8: u8, v8: u8, r9: u32, m9: u8, v9: u8, r10: u32, m10: u8, v10: u8, r11: u32, m11: u8, v11: u8, r12: u32, m12: u8, v12: u8) -> [u8; 55] { + [(mode << 8) as u8, (mode & 0xFF) as u8, 13, (r0 << 8) as u8, (r0 & 0xFF) as u8, m0, v0, (r1 << 8) as u8, (r1 & 0xFF) as u8, m1, v1, (r2 << 8) as u8, (r2 & 0xFF) as u8, m2, v2, (r3 << 8) as u8, (r3 & 0xFF) as u8, m3, v3, (r4 << 8) as u8, (r4 & 0xFF) as u8, m4, v4, (r5 << 8) as u8, (r5 & 0xFF) as u8, m5, v5, (r6 << 8) as u8, (r6 & 0xFF) as u8, m6, v6, (r7 << 8) as u8, (r7 & 0xFF) as u8, m7, v7, (r8 << 8) as u8, (r8 & 0xFF) as u8, m8, v8, (r9 << 8) as u8, (r9 & 0xFF) as u8, m9, v9, (r10 << 8) as u8, (r10 & 0xFF) as u8, m10, v10, (r11 << 8) as u8, (r11 & 0xFF) as u8, m11, v11, (r12 << 8) as u8, (r12 & 0xFF) as u8, m12, v12] +} + +const AM_MOD_DRIVER_LEVEL_DEFAULT: u8 = 0xb9; + +const ANALOG_CONFIG_LUT_SIZE: u32 = 87; /* Maximum number of Configuration IDs in the Loop Up Table */ +const ANALOG_CONFIG_LUT_NOT_FOUND: u32 = 0xFF; /* Index value indicating no Configuration IDs found */ + +const ANALOG_CONFIG_TBL_SIZE: u32 = 1024; /* Maximum number of Register-Mask-Value in the Setting List */ + + +const ANALOG_CONFIG_POLL_LISTEN_MODE_MASK: u32 = 0x8000; /* Mask bit of Poll Mode in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_MASK: u32 = 0x7F00; /* Mask bits for Technology in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_MASK: u32 = 0x00F0; /* Mask bits for Bit rate in Analog Configuration ID */ +const ANALOG_CONFIG_DIRECTION_MASK: u32 = 0x0003; /* Mask bits for Direction in Analog Configuration ID */ +const ANALOG_CONFIG_CHIP_SPECIFIC_MASK: u32 = 0x00FF; /* Mask bits for Chip Specific Technology */ + +const ANALOG_CONFIG_POLL_LISTEN_MODE_SHIFT: u32 = 15; /* Shift value of Poll Mode in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_SHIFT: u32 = 8; /* Shift value for Technology in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_SHIFT: u32 = 4; /* Shift value for Technology in Analog Configuration ID */ +const ANALOG_CONFIG_DIRECTION_SHIFT: u32 = 0; /* Shift value for Direction in Analog Configuration ID */ + +const ANALOG_CONFIG_POLL: u32 = 0x0000; /* Poll Mode bit setting in Analog Configuration ID */ +const ANALOG_CONFIG_LISTEN: u32 = 0x8000; /* Listen Mode bit setting in Analog Configuration ID */ + +const ANALOG_CONFIG_TECH_CHIP: u32 = 0x0000; /* Chip-Specific bit setting in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_NFCA: u32 = 0x0100; /* NFC-A Technology bits setting in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_NFCB: u32 = 0x0200; /* NFC-B Technology bits setting in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_NFCF: u32 = 0x0400; /* NFC-F Technology bits setting in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_AP2P: u32 = 0x0800; /* AP2P Technology bits setting in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_NFCV: u32 = 0x1000; /* NFC-V Technology bits setting in Analog Configuration ID */ +const ANALOG_CONFIG_TECH_RFU: u32 = 0x2000; /* RFU for Technology bits */ + +const ANALOG_CONFIG_BITRATE_COMMON: u32 = 0x0000; /* Common settings for all bit rates in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_106: u32 = 0x0010; /* 106kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_212: u32 = 0x0020; /* 212kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_424: u32 = 0x0030; /* 424kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_848: u32 = 0x0040; /* 848kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_1695: u32 = 0x0050; /* 1695kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_3390: u32 = 0x0060; /* 3390kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_6780: u32 = 0x0070; /* 6780kbits/s settings in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_1OF4: u32 = 0x00C0; /* 1 out of 4 for NFC-V setting in Analog Configuration ID */ +const ANALOG_CONFIG_BITRATE_1OF256: u32 = 0x00D0; /* 1 out of 256 for NFC-V setting in Analog Configuration ID */ + +const ANALOG_CONFIG_NO_DIRECTION: u32 = 0x0000; /* No direction setting in Analog Conf ID (Chip Specific only) */ +const ANALOG_CONFIG_TX: u32 = 0x0001; /* Transmission bit setting in Analog Configuration ID */ +const ANALOG_CONFIG_RX: u32 = 0x0002; /* Reception bit setting in Analog Configuration ID */ +const ANALOG_CONFIG_ANTICOL: u32 = 0x0003; /* Anticollision setting in Analog Configuration ID */ + +const ANALOG_CONFIG_CHIP_INIT: u32 = 0x0000; /* Chip-Specific event: Startup;Reset;Initialize */ +const ANALOG_CONFIG_CHIP_DEINIT: u32 = 0x0001; /* Chip-Specific event: Deinitialize */ +const ANALOG_CONFIG_CHIP_FIELD_ON: u32 = 0x0002; /* Chip-Specific event: Field On */ +const ANALOG_CONFIG_CHIP_FIELD_OFF: u32 = 0x0003; /* Chip-Specific event: Field Off */ +const ANALOG_CONFIG_CHIP_WAKEUP_ON: u32 = 0x0004; /* Chip-Specific event: Wake-up On */ +const ANALOG_CONFIG_CHIP_WAKEUP_OFF: u32 = 0x0005; /* Chip-Specific event: Wake-up Off */ +const ANALOG_CONFIG_CHIP_LISTEN_ON: u32 = 0x0006; /* Chip-Specific event: Listen On */ +const ANALOG_CONFIG_CHIP_LISTEN_OFF: u32 = 0x0007; /* Chip-Specific event: Listen Off */ +const ANALOG_CONFIG_CHIP_POLL_COMMON: u32 = 0x0008; /* Chip-Specific event: Poll common */ +const ANALOG_CONFIG_CHIP_LISTEN_COMMON: u32 = 0x0009; /* Chip-Specific event: Listen common */ + +const ANALOG_CONFIG_UPDATE_LAST: u32 = 0x00; /* Value indicating Last configuration set during update */ +const ANALOG_CONFIG_UPDATE_MORE: u32 = 0x01; /* Value indicating More configuration set coming during update */ + +//****** Default Analog Configuration for Chip-Specific Reset. ******/ +const RESET_INIT: [u8; 43] = mode_entry_10_reg( + ANALOG_CONFIG_TECH_CHIP | ANALOG_CONFIG_CHIP_INIT, + Register::OperationControl as u32, 0x30, 0x10, //Default to AM + Register::IOConfiguration1 as u32, 0x06, 0x06, //MCUCLK: HF clk off + Register::IOConfiguration1 as u32, IOConfiguration1Bits::MaskOutCl as u8 | IOConfiguration1Bits::LfClkOff as u8, 0x07, // MCUCLK: LF clk off + Register::IOConfiguration2 as u32, 0x18, 0x18, // pull downs + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Pm as u8, 0x1 << ReceiverConfiguration4Mask::ShiftRg2Pm as u8, //increase digitizer windows for PM + Register::AnntenaCalibrationTarget as u32, 0xFF, 0x80, // 90 deg, + Register::AnntenaCalibrationControl as u32, 0xF8, 0x00, // trim value from calibrate antenna + Register::AMModulationDepthControl as u32, AMModulationDepthControlConstans::AmS as u8, AMModulationDepthControlConstans::AmS as u8, // AM modulated level is defined by RFO AM Modulated Level Def Reg, fixed setting, no automatic adjustment + Register::ExternalFieldDetectorThreshold as u32, EXT_FIELD_DET_TRG_MASK, ExternalFieldDetectorThresholdTrgVoltage::Trg75mV as u8, + Register::ExternalFieldDetectorThreshold as u32, EXT_FIELD_DET_RFE_MASK, ExternalFieldDetectorThresholdRfeVoltage::Rfe75mV as u8, +); + +//****** Default Analog Configuration for Poll NFC-A Rx. ******/ +const NFCA_TX_COMMON: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_TX, + Register::RFOAMModulationLevelDefinition as u32, 0xff, 0xf0, // Used for 848 TX: very high AM to keep wave shapes +); +const NFCA_TX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // OOK +); +const NFCA_TX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // OOK +); +const NFCA_TX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // OOK +); +const NFCA_TX_848: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_848 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // OOK +); +const NFCA_TX_848_AUX: [u8; 11] = mode_entry_2_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_848 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM + Register::RFOAMModulationLevelDefinition as u32, 0xff, 0x00, // Used for 848 TX: very high AM to keep wave shapes +); + +//****** Default Analog Configuration for Poll NFC-A Rx. ******/ +const NFCA_RX_COMMON: [u8; 15] = mode_entry_3_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, 0xff, 0x18, + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x2 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM + Register::AuxDefinition as u32, AuxDefinitionBits::RxTol as u8, 0x00, //rx_tol off +); +const NFCA_RX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x00, +); +const NFCA_RX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x04, +); +const NFCA_RX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x22, +); +const NFCA_RX_848: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCA | ANALOG_CONFIG_BITRATE_848 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x22, +); + +//****** Default Analog Configuration for Poll NFC-B Tx. ******/ +const NFCB_TX_COMMON: [u8; 11] = mode_entry_2_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCB | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM + Register::RFOAMModulationLevelDefinition as u32, 0xff, AM_MOD_DRIVER_LEVEL_DEFAULT, //Fixed driver for AM level: -14% +); + +//****** Default Analog Configuration for Poll NFC-B Rx. ******/ +const NFCB_RX_COMMON: [u8; 15] = mode_entry_3_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCB | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, 0xff, 0x18, + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x2 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM + Register::AuxDefinition as u32, AuxDefinitionBits::RxTol as u8, 0x00, //rx_tol off +); +const NFCB_RX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCB | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x00, +); +const NFCB_RX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCB | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x04, +); +const NFCB_RX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCB | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x22, +); +const NFCB_RX_848: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCB | ANALOG_CONFIG_BITRATE_848 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x22, +); + +//****** Default Analog Configuration for Poll NFC-F Tx. ******/ +const NFCF_TX_COMMON: [u8; 11] = mode_entry_2_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCF | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM + Register::RFOAMModulationLevelDefinition as u32, 0xff, AM_MOD_DRIVER_LEVEL_DEFAULT, //Fixed driver for AM level: -14% +); + +//****** Default Analog Configuration for Poll NFC-F Rx. ******/ +const NFCF_RX_COMMON: [u8; 15] = mode_entry_3_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCF | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, 0xff, 0x18, + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x1 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM + Register::AuxDefinition as u32, AuxDefinitionBits::RxTol as u8, AuxDefinitionBits::RxTol as u8, //rx_tol On as default +); +const NFCF_RX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCF | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x13, /* dev. from data sheet: lp 300kKz */ +); +const NFCF_RX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCF | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x0b, /* dev. from data sheet: lp 600kKz */ +); + +//****** Default Analog Configuration for Poll NFC-V Tx. ******/ +const NFCV_TX_COMMON: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCV | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // AM +); + +//****** Default Analog Configuration for Poll NFC-V Rx. ******/ +const NFCV_RX_COMMON: [u8; 19] = mode_entry_4_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_NFCV | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x0c, /* use filter settings from table 9: "Recommended for 424/484 kHz sub-carrier" */ + Register::ReceiverConfiguration3 as u32, 0xff, 0x18, + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x1 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM + Register::AuxDefinition as u32, AuxDefinitionBits::RxTol as u8, AuxDefinitionBits::RxTol as u8, //rx_tol On as default +); + +//****** Default Analog Configuration for Poll AP2P Tx. ******/ +const AP2P_TX_COMMON: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_TX, + Register::RFOAMModulationLevelDefinition as u32, 0xff, AM_MOD_DRIVER_LEVEL_DEFAULT, +); +const AP2P_TX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // OOK +); +const AP2P_TX_212: [u8; 11] = mode_entry_2_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM + Register::RFOAMModulationLevelDefinition as u32, 0xff, AM_MOD_DRIVER_LEVEL_DEFAULT, //Fixed driver for AM level: -14% +); +const AP2P_TX_424: [u8; 11] = mode_entry_2_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM + Register::RFOAMModulationLevelDefinition as u32, 0xff, AM_MOD_DRIVER_LEVEL_DEFAULT, //Fixed driver for AM level: -14% +); + +//****** Default Analog Configuration for Poll AP2P Rx. ******/ +const AP2P_RX_TECH: [u8; 19] = mode_entry_4_reg( + ANALOG_CONFIG_TECH_CHIP | ANALOG_CONFIG_CHIP_LISTEN_ON, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x45, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Bits::Lim as u8 | ReceiverConfiguration3Bits::RgNfc as u8, ReceiverConfiguration3Bits::Lim as u8 | ReceiverConfiguration3Bits::RgNfc as u8, + Register::AuxDefinition as u32, AuxDefinitionBits::RxTol as u8, AuxDefinitionBits::RxTol as u8, //rx_tol On as default + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x1 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM +); +const AP2P_RX_COMMON: [u8; 19] = mode_entry_4_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x45, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Bits::Lim as u8 | ReceiverConfiguration3Bits::RgNfc as u8, ReceiverConfiguration3Bits::Lim as u8 | ReceiverConfiguration3Bits::RgNfc as u8, + Register::AuxDefinition as u32, AuxDefinitionBits::RxTol as u8, AuxDefinitionBits::RxTol as u8, //rx_tol On as default + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x1 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM +); +const AP2P_RX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Mask::MaskRg1Am as u8, 0xc0, +); +const AP2P_RX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Mask::MaskRg1Am as u8, 0x00, +); +const AP2P_RX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_POLL | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Mask::MaskRg1Am as u8, 0x00, +); + +//****** Default Analog Configuration for Listen AP2P Tx. ******/ +const AP2P_LTX_COMMON: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_TX, + Register::RFOAMModulationLevelDefinition as u32, 0xff, AM_MOD_DRIVER_LEVEL_DEFAULT, //Fixed driver for AM level: -14% +); +const AP2P_LTX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, 0x00, // OOK +); +const AP2P_LTX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM +); +const AP2P_LTX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_TX, + Register::AuxDefinition as u32, AuxDefinitionBits::TrAm as u8, AuxDefinitionBits::TrAm as u8, // AM +); + +//****** Default Analog Configuration for Listen AP2P Rx. ******/ +const AP2P_LRX_COMMON: [u8; 15] = mode_entry_3_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_COMMON | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration1 as u32, 0x7f, 0x45, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Bits::Lim as u8 | ReceiverConfiguration3Bits::RgNfc as u8, ReceiverConfiguration3Bits::Lim as u8 | ReceiverConfiguration3Bits::RgNfc as u8, + Register::ReceiverConfiguration4 as u32, ReceiverConfiguration4Mask::MaskRg2Am as u8, 0x1 << ReceiverConfiguration4Mask::ShiftRg2Am as u8, //increase digitizer windows for AM +); +const AP2P_LRX_106: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_106 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Mask::MaskRg1Am as u8, 0xc0, +); +const AP2P_LRX_212: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_212 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Mask::MaskRg1Am as u8, 0x00, +); +const AP2P_LRX_424: [u8; 7] = mode_entry_1_reg( + ANALOG_CONFIG_LISTEN | ANALOG_CONFIG_TECH_AP2P | ANALOG_CONFIG_BITRATE_424 | ANALOG_CONFIG_RX, + Register::ReceiverConfiguration3 as u32, ReceiverConfiguration3Mask::MaskRg1Am as u8, 0x00, +); + +static DEFAULT_ANALOG_CONFIG: [u8; concat_arrays_size!( + RESET_INIT, + NFCA_TX_COMMON, + NFCA_TX_106, + NFCA_TX_212, + NFCA_TX_424, + NFCA_TX_848, + NFCA_TX_848_AUX, + NFCA_RX_COMMON, + NFCA_RX_106, + NFCA_RX_212, + NFCA_RX_424, + NFCA_RX_848, + NFCB_TX_COMMON, + NFCB_RX_COMMON, + NFCB_RX_106, + NFCB_RX_212, + NFCB_RX_424, + NFCB_RX_848, + NFCF_TX_COMMON, + NFCF_RX_COMMON, + NFCF_RX_212, + NFCF_RX_424, + NFCV_TX_COMMON, + NFCV_RX_COMMON, + AP2P_TX_COMMON, + AP2P_TX_106, + AP2P_TX_212, + AP2P_TX_424, + AP2P_RX_TECH, + AP2P_RX_COMMON, + AP2P_RX_106, + AP2P_RX_212, + AP2P_RX_424, + AP2P_LTX_COMMON, + AP2P_LTX_106, + AP2P_LTX_212, + AP2P_LTX_424, + AP2P_LRX_COMMON, + AP2P_LRX_106, + AP2P_LRX_212, + AP2P_LRX_424 +)] = concat_arrays!( + RESET_INIT, + NFCA_TX_COMMON, + NFCA_TX_106, + NFCA_TX_212, + NFCA_TX_424, + NFCA_TX_848, + NFCA_TX_848_AUX, + NFCA_RX_COMMON, + NFCA_RX_106, + NFCA_RX_212, + NFCA_RX_424, + NFCA_RX_848, + NFCB_TX_COMMON, + NFCB_RX_COMMON, + NFCB_RX_106, + NFCB_RX_212, + NFCB_RX_424, + NFCB_RX_848, + NFCF_TX_COMMON, + NFCF_RX_COMMON, + NFCF_RX_212, + NFCF_RX_424, + NFCV_TX_COMMON, + NFCV_RX_COMMON, + AP2P_TX_COMMON, + AP2P_TX_106, + AP2P_TX_212, + AP2P_TX_424, + AP2P_RX_TECH, + AP2P_RX_COMMON, + AP2P_RX_106, + AP2P_RX_212, + AP2P_RX_424, + AP2P_LTX_COMMON, + AP2P_LTX_106, + AP2P_LTX_212, + AP2P_LTX_424, + AP2P_LRX_COMMON, + AP2P_LRX_106, + AP2P_LRX_212, + AP2P_LRX_424 +); + +pub(crate) struct AnalogConfigMgmt { + config_tbl: Box<[u8]>, +} + +impl AnalogConfigMgmt { + pub fn new_default() -> Self { + Self { + config_tbl: Box::new(DEFAULT_ANALOG_CONFIG), + } + } +} \ No newline at end of file diff --git a/Software/fab-reader2/st25r3911b/src/constants.rs b/Software/fab-reader2/st25r3911b/src/constants.rs index 1f4d670..4acb68a 100644 --- a/Software/fab-reader2/st25r3911b/src/constants.rs +++ b/Software/fab-reader2/st25r3911b/src/constants.rs @@ -175,6 +175,20 @@ pub enum RegulatorControlMask { Rege = 0xf << 3, } +#[repr(u8)] +#[derive(PartialEq, Clone, Copy, Debug)] +pub enum AuxDefinitionBits { + MaskNfcN = 3 << 0, + NfcN0 = 1 << 0, + NfcN1 = 1 << 1, + RxTol = 1 << 2, + OokHr = 1 << 3, + EnFd = 1 << 4, + TrAm = 1 << 5, + Crc2Fifo = 1 << 6, + NoCrcRx = 1 << 7, +} + #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum IOConfiguration2Bits { @@ -189,13 +203,13 @@ pub enum IOConfiguration2Bits { #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum IOConfiguration1Bits { - lf_clk_off = 1 << 0, - out_cl0 = 1 << 1, - out_cl1 = 1 << 2, - mask_out_cl = 3 << 1, - osc = 1 << 3, - rfo2 = 1 << 6, - single = 1 << 7, + LfClkOff = 1 << 0, + OutCl0 = 1 << 1, + OutCl1 = 1 << 2, + MaskOutCl = 3 << 1, + Osc = 1 << 3, + Rfo2 = 1 << 6, + Single = 1 << 7, } const FIFO_LT: u8 = 1 << 4; @@ -203,8 +217,8 @@ const FIFO_LT: u8 = 1 << 4; #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum IOConfiguration1FIFOLt { - fifo_lt_32bytes = 0 << 4, - fifo_lt_16bytes = 1 << 4, + FifoLt32bytes = 0 << 4, + FifoLt16bytes = 1 << 4, } const FIFO_LR: u8 = 1 << 5; @@ -212,30 +226,52 @@ const FIFO_LR: u8 = 1 << 5; #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum IOConfiguration1FIFOLr { - fifo_lr_64bytes = 0 << 5, - fifo_lr_80bytes = 1 << 5, + FifoLr64bytes = 0 << 5, + FifoLr80bytes = 1 << 5, +} + +#[repr(u8)] +#[derive(PartialEq, Clone, Copy, Debug)] +pub enum ReceiverConfiguration3Mask { + ShiftRg1Pm = 2, + MaskRg1Pm = 0x7 << 2, + ShiftRg1Am = 5, + MaskRg1Am = 0x7 << 5, +} + +#[repr(u8)] +#[derive(PartialEq, Clone, Copy, Debug)] +pub enum ReceiverConfiguration3Bits { + RgNfc = 1 << 0, + Lim = 1 << 1, + Rg1Pm0 = 1 << 2, + Rg1Pm1 = 1 << 3, + Rg1Pm2 = 1 << 4, + Rg1Am0 = 1 << 5, + Rg1Am1 = 1 << 6, + Rg1Am2 = 1 << 7, } #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum ReceiverConfiguration4Mask { - shift_rg2_pm = 0, - mask_rg2_pm = 0xf << 0, - shift_rg2_am = 4, - mask_rg2_am = 0xf << 4, + ShiftRg2Pm = 0, + MaskRg2Pm = 0xf << 0, + ShiftRg2Am = 4, + MaskRg2Am = 0xf << 4, } #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum ReceiverConfiguration4Bits { - rg2_pm0 = 1 << 0, - rg2_pm1 = 1 << 1, - rg2_pm2 = 1 << 2, - rg2_pm3 = 1 << 3, - rg2_am0 = 1 << 4, - rg2_am1 = 1 << 5, - rg2_am2 = 1 << 6, - rg2_am3 = 1 << 7, + Rg2Pm0 = 1 << 0, + Rg2Pm1 = 1 << 1, + Rg2Pm2 = 1 << 2, + Rg2Pm3 = 1 << 3, + Rg2Am0 = 1 << 4, + Rg2Am1 = 1 << 5, + Rg2Am2 = 1 << 6, + Rg2Am3 = 1 << 7, } const AM_MOD_DEPTH_CONTROL_MASK: u8 = 0x3f << 1; @@ -244,14 +280,14 @@ const AM_MOD_DEPTH_CONTROL_SHIFT: u8 = 1; #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum AMModulationDepthControlConstans { - mod_8percent = 0xb << 1, - mod_10percent = 0xe << 1, - mod_14percent = 0x14 << 1, - mod_20percent = 0x20 << 1, - mod_25percent = 0x2a << 1, - mod_30percent = 0x37 << 1, - mod_33percent = 0x3f << 1, - am_s = 1 << 7, + Mod8percent = 0xb << 1, + Mod10percent = 0xe << 1, + Mod14percent = 0x14 << 1, + Mod20percent = 0x20 << 1, + Mod25percent = 0x2a << 1, + Mod30percent = 0x37 << 1, + Mod33percent = 0x3f << 1, + AmS = 1 << 7, } pub const EXT_FIELD_DET_RFE_MASK: u8 = 0x0f; @@ -259,54 +295,54 @@ pub const EXT_FIELD_DET_RFE_MASK: u8 = 0x0f; #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum ExternalFieldDetectorThresholdRfe { -rfe_t0 = 1<<0 , -rfe_t1 = 1<<1 , -rfe_t2 = 1<<2 , -rfe_t3 = 1<<3 , + RfeT0 = 1 << 0, + RfeT1 = 1 << 1, + RfeT2 = 1 << 2, + RfeT3 = 1 << 3, } #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum ExternalFieldDetectorThresholdRfeVoltage { - rfe_75mV = 0x00<<0 , - rfe_105mV = 0x01<<0 , - rfe_150mV = 0x02<<0 , - rfe_205mV = 0x03<<0 , - rfe_290mV = 0x04<<0 , - rfe_400mV = 0x05<<0 , - rfe_560mV = 0x06<<0 , - rfe_800mV = 0x07<<0 , - rfe_25mV = 0x08<<0 , - rfe_33mV = 0x09<<0 , - rfe_47mV = 0x0A<<0 , - rfe_64mV = 0x0B<<0 , - rfe_90mV = 0x0C<<0 , - rfe_125mV = 0x0D<<0 , - rfe_175mV = 0x0E<<0 , - rfe_250mV = 0x0F<<0 , + Rfe75mV = 0x00 << 0, + Rfe105mV = 0x01 << 0, + Rfe150mV = 0x02 << 0, + Rfe205mV = 0x03 << 0, + Rfe290mV = 0x04 << 0, + Rfe400mV = 0x05 << 0, + Rfe560mV = 0x06 << 0, + Rfe800mV = 0x07 << 0, + Rfe25mV = 0x08 << 0, + Rfe33mV = 0x09 << 0, + Rfe47mV = 0x0A << 0, + Rfe64mV = 0x0B << 0, + Rfe90mV = 0x0C << 0, + Rfe125mV = 0x0D << 0, + Rfe175mV = 0x0E << 0, + Rfe250mV = 0x0F << 0, } -pub const EXT_FIELD_DET_TRG_MASK: u8 = 0x07<<4; +pub const EXT_FIELD_DET_TRG_MASK: u8 = 0x07 << 4; #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum ExternalFieldDetectorThresholdTrg { - trg_l0 = 1<<4 , - trg_l1 = 1<<5 , - trg_l2 = 1<<6 , + TrgL0 = 1 << 4, + TrgL1 = 1 << 5, + TrgL2 = 1 << 6, } #[repr(u8)] #[derive(PartialEq, Clone, Copy, Debug)] pub enum ExternalFieldDetectorThresholdTrgVoltage { - trg_75mV = 0x00<<4 , - trg_105mV = 0x01<<4 , - trg_150mV = 0x02<<4 , - trg_205mV = 0x03<<4 , - trg_290mV = 0x04<<4 , - trg_400mV = 0x05<<4 , - trg_560mV = 0x06<<4 , - trg_800mV = 0x07<<4 , + Trg75mV = 0x00 << 4, + Trg105mV = 0x01 << 4, + Trg150mV = 0x02 << 4, + Trg205mV = 0x03 << 4, + Trg290mV = 0x04 << 4, + Trg400mV = 0x05 << 4, + Trg560mV = 0x06 << 4, + Trg800mV = 0x07 << 4, } #[repr(u8)] @@ -410,6 +446,89 @@ pub(crate) enum OperationMode { CmdMode = 3u32 << 6, } +#[repr(u8)] +#[derive(PartialEq, Clone, Copy, Debug)] +pub(crate) enum NfcState { + NotInit = 0, + Idle = 1, + StartDiscovery = 2, + WakeUpMode = 3, + PollTechDetect = 10, + PollColAvoidance = 11, + PollSelect = 12, + PollActivation = 13, + ListenTechDetect = 20, + ListenColAvoidance = 21, + ListenActivation = 22, + ListenSleep = 23, + Activated = 30, + DataExchange = 31, + DataExchangeDone = 33, + Deactivation = 34, +} + +/* RFAL Bit rates */ +#[derive(PartialEq, Clone, Copy, Debug)] +pub(crate) enum BitRate { + Br106 = 0, + /* Bit Rate 106 kbit/s (fc/128) */ + Br212 = 1, + /* Bit Rate 212 kbit/s (fc/64) */ + Br424 = 2, + /* Bit Rate 424 kbit/s (fc/32) */ + Br848 = 3, + /* Bit Rate 848 kbit/s (fc/16) */ + Br1695 = 4, + /* Bit Rate 1695 kbit/s (fc/8) */ + Br3390 = 5, + /* Bit Rate 3390 kbit/s (fc/4) */ + Br6780 = 6, + /* Bit Rate 6780 kbit/s (fc/2) */ + Br13560 = 7, + /* Bit Rate 13560 kbit/s (fc) */ + Br52p97 = 0xEB, + /* Bit Rate 52.97 kbit/s (fc/256) Fast Mode VICC->VCD */ + Br26p48 = 0xEC, + /* Bit Rate 26,48 kbit/s (fc/512) NFCV VICC->VCD & VCD->VICC 1of4 */ + Br1p66 = 0xED, + /* Bit Rate 1,66 kbit/s (fc/8192) NFCV VCD->VICC 1of256 */ + BrKeep = 0xFF, + /* Value indicating to keep the same previous bit rate */ +} + +/// Compliance modes for upper modules +#[repr(u8)] +#[derive(PartialEq, Clone, Copy, Debug)] +pub(crate) enum ComplianceMode { + /// Perform with NFC Forum 1.1 compliance + Nfc, + /// Perform with EMVCo compliance + EmvCo, + /// Perform with ISO10373 compliance + Iso, +} + +#[repr(u8)] +#[derive(Debug, Copy, Clone)] +pub(crate) enum WakeUpPeriod { + Period10ms = 0x00, + Period20ms = 0x01, + Period30ms = 0x02, + Period40ms = 0x03, + Period50ms = 0x04, + Period60ms = 0x05, + Period70ms = 0x06, + Period80ms = 0x07, + Period100ms = 0x10, + Period200ms = 0x11, + Period300ms = 0x12, + Period400ms = 0x13, + Period500ms = 0x14, + Period600ms = 0x15, + Period700ms = 0x16, + Period800ms = 0x17, +} + pub(crate) const FifoDepth: u32 = 96; pub(crate) const CmdLen: u32 = 1; pub(crate) const BufLen: u32 = CmdLen + FifoDepth; diff --git a/Software/fab-reader2/st25r3911b/src/device/iso_dep.rs b/Software/fab-reader2/st25r3911b/src/device/iso_dep.rs new file mode 100644 index 0000000..cf79603 --- /dev/null +++ b/Software/fab-reader2/st25r3911b/src/device/iso_dep.rs @@ -0,0 +1,3 @@ +struct IsoDep { + +} \ No newline at end of file diff --git a/Software/fab-reader2/st25r3911b/src/device/mod.rs b/Software/fab-reader2/st25r3911b/src/device/mod.rs new file mode 100644 index 0000000..2c8fa14 --- /dev/null +++ b/Software/fab-reader2/st25r3911b/src/device/mod.rs @@ -0,0 +1,94 @@ +use std::time::Duration; +use crate::{BitRate, NfcState}; +use crate::constants::ComplianceMode; +use crate::rf::{LmConfPA, LmConfPF}; + +// TODO: Implement NFC-B, NFC-F, NFC-V, ST25TB, AP2P +mod nfca; +mod iso_dep; + +/// NFCID1 +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct NfcId1 { + /// NFCID1 + pub nfcid1: [u8; 10], + /// Length of NFCID1 + pub len: u8, +} + + + +// TODO: Have th enum contain the device +#[derive(Debug, Copy, Clone, PartialEq)] +pub(crate) enum DeviceType { + ListenTypeNfcA = 0, /* NFC-A Listener device type */ + ListenTypeNfcB = 1, /* NFC-B Listener device type */ + ListenTypeNfcF = 2, /* NFC-F Listener device type */ + ListenTypeNfcV = 3, /* NFC-V Listener device type */ + ListenTypeST25TB = 4, /* ST25TB Listener device type */ + ListenTypeAp2p = 5, /* AP2P Listener device type */ + PollTypeNfcA = 10, /* NFC-A Poller device type */ + PollTypeNfcB = 11, /* NFC-B Poller device type */ + PollTypeNfcF = 12, /* NFC-F Poller device type */ + PollTypeNfcV = 13, /* NFC-V Poller device type */ + PollTypeAp2p = 15 /* AP2P Poller device type */ +} + +#[derive(Debug, Copy, Clone)] +pub(crate) enum RfInterface { + Rf = 0, /* RF Frame interface */ + IsoDep = 1, /* ISO-DEP interface */ + NfcDep = 2, /* NFC-DEP interface */ +} + +/// Device struct containing all its details +#[derive(Debug, Clone)] +pub(crate) struct Device { + /// Device type + pub device_type: DeviceType, // TODO: enum should wrap the device + /// NFCID1 + pub nfcid1: NfcId1, + /// RF interface + pub rf_interface: RfInterface, + // Protocol + // TODO: add enum for proto and implement isodep and nfcdep +} + +// TODO: Implement Wakeup Config + +/// Discovery Parameters + +#[derive(Debug, Copy, Clone)] +pub(crate) struct DiscoveryParams { + /// Compliance mode to be used + compliance_mode: ComplianceMode, + /// Number of Technologies to search for + techs_2_find: u16, + /// Duration of whole Poll + Listen Cycle + total_duration: Duration, + /// Max Number of devices + dev_limit: u8, + /// Bit rate to poll for NFC-F + poll_br: BitRate, + /// NFCID3 to be used on the ATR_REQ/ATR_RES + nfcid3: NfcId1, + /// General bytes to be used on the ATR-REQ + gb: [u8; 48], + /// Bit rate to poll for AP2P + ap2p_br: BitRate, + + /// Configuration for Passive Listen mode NFC-A + lm_conf_pa: LmConfPA, + /// Configuration for Passive Listen mode NFC-F + lm_conf_pf: LmConfPF, + + /// Callback to notify upper layer + notify_cb: fn(NfcState), + + /// Eanble Wake-Up mode before polling + wakeup_enable: bool, + /// Wake-Up mode default configuration + wakeup_cfg_default: bool, + /// Wake-Up mode configuration + wakeup_cfg: Wake +} diff --git a/Software/fab-reader2/st25r3911b/src/device/nfca.rs b/Software/fab-reader2/st25r3911b/src/device/nfca.rs new file mode 100644 index 0000000..1f5ca15 --- /dev/null +++ b/Software/fab-reader2/st25r3911b/src/device/nfca.rs @@ -0,0 +1,58 @@ +use super::NfcId1; + +/// NFC-A Listen device types +#[repr(u8)] +#[derive(Copy, Clone, Debug, PartialEq)] +enum ListenDeviceType { + T1T = 0x01, + T2T = 0x00, + T4T = 0x20, + NfcDep = 0x40, + T4tNfcDep = 0x60, +} + +/// SENS_RES (ATQA) format Digital 1.1 6.6.3 & Table 7 +#[derive(Copy, Clone, Debug, PartialEq)] +struct SensRes { + anti_collision_info: u8, + platform_info: u8, +} + +/// SDD_REQ (Anticollision) format Digital 1.1 6.7.1 & Table 11 +#[derive(Copy, Clone, Debug, PartialEq)] +struct SddReq { + sel_cmd: u8, + sel_par: u8, +} + +/// SDD_RES (UID CLn) format Digital 1.1 6.7.2 & Table 15 +#[derive(Copy, Clone, Debug, PartialEq)] +struct SddRes { + uid: NfcId1, + bcc: u8, +} + +/// SEL_REQ (Select) format Digital 1.1 6.8.1 & Table 17 +#[derive(Copy, Clone, Debug, PartialEq)] +struct SelReq { + sel_cmd: u8, + sel_par: u8, + uid: NfcId1, + bcc: u8, +} + +/// SEL_RES (SAK) format Digital 1.1 6.8.2 & Table 19 +#[derive(Copy, Clone, Debug, PartialEq)] +struct SelRes { + sak: u8, +} + +/// NFC-A listener device (PICC) struct +pub(crate) struct NFCAListenDevice { + device_type: ListenDeviceType, + sens_res: SensRes, + sel_res: SelRes, + nfcid1: NfcId1, + // FIXME: T1T not implemented + is_sleeping: bool, +} \ No newline at end of file diff --git a/Software/fab-reader2/st25r3911b/src/interrupts.rs b/Software/fab-reader2/st25r3911b/src/interrupts.rs index a58bc1d..616b41c 100644 --- a/Software/fab-reader2/st25r3911b/src/interrupts.rs +++ b/Software/fab-reader2/st25r3911b/src/interrupts.rs @@ -1,3 +1,6 @@ +use embedded_hal::digital::v2::InputPin; +use crate::{Interface, Register}; + #[repr(u32)] pub enum IRQMask { /* Main interrupt register. */ @@ -64,7 +67,19 @@ pub enum IRQMask { Err = 0x01, } -type InterruptCallback = fn(); +type InterruptCallback = fn(&mut Interrupt); + +const INT_REGS_LEN: u8 = Register::ErrorWakeUpInterruptStatus as u8 - Register::MainInterruptStatus as u8 + 1; +//FIXME: Finish this +pub(crate) fn default_callback(interrupt: &mut Interrupt, interface: &mut Interface, irq_pin: IRQ) { + let mut iregs: [u8; INT_REGS_LEN as usize] = interface.read_register_range(Register::MainInterruptStatus, INT_REGS_LEN).unwrap(); + while irq_pin.is_high() { + iregs = interface.read_multiple_registers(Register::MainInterruptStatus, INT_REGS_LEN).unwrap().into(); + } + + // FIXME: Protect IRQ status + interrupt.status = (iregs[0] as u32) | (iregs[1] as u32) << 8 | iregs[2] << 16 as u32; +} pub struct Interrupt { prevCallback: Option, diff --git a/Software/fab-reader2/st25r3911b/src/lib.rs b/Software/fab-reader2/st25r3911b/src/lib.rs index f6ade36..b137a40 100644 --- a/Software/fab-reader2/st25r3911b/src/lib.rs +++ b/Software/fab-reader2/st25r3911b/src/lib.rs @@ -8,11 +8,13 @@ use embedded_svc::timer::*; mod interface; mod interrupts; mod constants; -mod analogConfig; +mod analog_config; +mod device; +mod rf; use crate::interface::Interface; use crate::interrupts::{Interrupt, IRQMask}; -use crate::constants::{DirectCmd, ICIdentityBits, IOConfiguration2Bits, OperationControlBits, OscStableTimeout, Register, RegulatorControlBits, RegulatorControlMask}; +use crate::constants::{BitRate, DirectCmd, ICIdentityBits, IOConfiguration2Bits, NfcState, OperationControlBits, OscStableTimeout, Register, RegulatorControlBits, RegulatorControlMask}; /// Error #[derive(Debug)] @@ -29,10 +31,20 @@ impl From for Error { } } + +/// ST25R3911B driver struct ST25R3911B { + // Low level interface interface: Interface, interrupt: Interrupt, timer: TIMER, + // internal state + state: NfcState, + techs_found: u16, + techs_2_do: u16, + ap2p_bitrate: BitRate, + discovery_params: + } impl ST25R3911B @@ -47,6 +59,10 @@ impl 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 + + + + + + + + + + + + \ No newline at end of file diff --git a/Waveforms/st25r3911b_commandparser/README.md b/Waveforms/st25r3911b_commandparser/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Waveforms/st25r3911b_commandparser/main.py b/Waveforms/st25r3911b_commandparser/main.py new file mode 100644 index 0000000..e69de29 diff --git a/Waveforms/st25r3911b_commandparser/requirements.txt b/Waveforms/st25r3911b_commandparser/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/Waveforms/stm32.dwf3logicacq b/Waveforms/stm32.dwf3logicacq new file mode 100644 index 0000000000000000000000000000000000000000..bc299c251bf12c197facc50fbe1153d3c231d27b GIT binary patch literal 423480 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 literal 0 HcmV?d00001 diff --git a/Waveforms/stm32.dwf3work b/Waveforms/stm32.dwf3work new file mode 100644 index 0000000000000000000000000000000000000000..2ef044a57ca8af29a207d8f9a98a1cc1b773f771 GIT binary patch literal 4973 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

UFdTK)BasN zY-pS@BoCkx9j?2swm~V;;iBPezkh%G1{C_gx4&hC7zjta>BJ$<82vLmV+u`1{AnB6 z0VGtI42aRGR=XIv_h2~4(!+;qybryOiN&}9y`%bU@A3YOp~m}=9Xo>0X2<)Ftzx?$ zik%<~KHSgdM#zg`(;`x4sP~D*@=4K-if^z5JvBZG7&%6m8Xs-ObbmaJVFMYJk{*HO zjcrf|;jIcb+G0bFQRb{n0_sJgGYuZSU}&a0mc`T z_sSCYjq%8V%s2#?^b8^jA_xo*pL4grjc*LQ{hi4UMA)X(Ba>mwd5i_F*0+1CILMsG zXmGU~1KM9b{87Mt+TY>Ld5quZoChu25Obc)6>R%E(m4;A!8BrM8N^SuP8u*5>z?zV z{nbPd*>;VkFi`4le_S@u&WY{nAz;g-ACpp z&|}xCL?hb_XV}A5|J+p$t2phRRS7b;DUEa2Pa_#0<@R5bNIgqO1d%m~NF3lEcn61> z7;{5sN-burNo2BX60WtunOI-g5|QaylQ8vJlgNL0mFT$u%@K-?B8&)f%`N)I>0ZRp zkns_CN?e6CiQJxMmmMFWtzmg_a{)g>G-;X}NbjMsBJL@6DTTDLcgUJVE_Nzod_+iQ zrP|#-^qc#;Xm+%ba>#!fvnJ56@+;SxL@v7~!3s5FETvgV+PuMK3KOCjA2lxPM;nV0;pOs_LS2R05>dga}(mZ;99)cbs z^%DyMedRk851#h=-m>k*!v?{l1C+c!4_uP}ds!|WXh-?RvBL_3OZM5&fzzC8B9~fs zFGu*fs^&wOtGm_NjF{0_OF{8Pz}9oOUWCr*k^TMYMrlJQwyhGOHo5EOy(6%)&*s9a z$fL47f5!MixI6&lVpIWTisfTyp^lGcCWf)grfSz93MaT~i_}&c;Zm&>8?-nzJ_aV+ zQc1-wig@cq;GVFsiZp@i_X@M@EDYOl@>#RIxG-v`WPyLM{}ZY5H?k%P1o5B_`;2or z>B>pz%T?Yp)W>j=w`}dRD(vf8Ym}vlV7tEs=M)%;)i()mEJzSuB<6e~KIn?&ArO!j z)R|mn=gLU`REW7TEaESmjQ9)qBs3vQ6UXWkzGg6@2>BbzWFLGjStEYIyMEcN)}P+0 z64VM|gH4})3*!iHfY!q7@fe@)mzpFzJ`5c(Qaj)ai7}w&8&S!N2p__!FD?*l}%1X!b80E_l#1sgm3!x6o zZS zS{hkvP;K3bev~<>EA8$hu0(a@j0KA%mn7C;Pg+kt5x#svpErsLkrwA~%zF^Feax^4 zk~c_Nr4M(d#Y|q$T67nXPN$>-N15%DKC_jS5c3+?Vrzj- zy5plieW*IydwsUJELZO0wi)}Z%T8%aGbeOG=T1R}m2$i7BBW9IRz@R?(pl_oqjZ*T zqjdJ0E2qKMk%d_KIRYy`8QIfCAR#0mOcoA&^N01!RnRX87swQMh|`Xin$*oX8Mpa28n5v4}d-hw$f!Z z&jM1{e@-{ZEimwOpypj^R{iFiiJ?^nxrG>bg3&yYdL>Jr+rpEpj5EEv(!^uc-B#5s zYPkhE8_k1lmR0_%-4=xm#G()}V{@9=69UWIqVcuS#U`;fL(;k==t^5X8lR4#Y+ zXkI2?d>})<7hh{r(iSW=AwhhzmE06+CXu#eZ%T4qng8DcMeFU8@@<|iY?+=glRl8xpna-Emd+=BnJomlvShw5%+wfSQ zwEy#XtmD1n{(n4HuQRLvN1o|CryZU8ka#SmC)EE^JXTQq|3y3&_VP?3M+==?oabL9 z0!E;jr@wdu@)+VE0^idkr?t%Z=i#m zTr5<`_k{RiE-(Mf4YZr=0ndBL0nf$Q&?|546(~ZXEv~kQMc~B5-;(2<7jO;o;{L}w zpCD-?VfJ`uUPy9U8@F0sjE+nH0eN%aF7oJqxbq*#8>Eb`!7eX6@^;Sc(s|re?Q6!{ zLUbe~6YGTgo$dSC)8`K#^nT@CWxuKY8<m1!-|%8U|1NG5`@Uhm$zc{X(8s&EReUI9lnr$orov14FD{`Yi|jf3>?8{>r#vMEI*E!u4|Vz42Gm?}fk8_u#K~ z4+no`X3>w=1b(%<7yPR62Y_Ggeq@f_O7%V7c`*Fdn32gT z^O+Igugol*$|Ixi6Mt1g@K?K8{8dSB{8fn?f3^Ew_^aIm@K?J@?b^-auUs+u;IEGN z;IDS~!C&p}gTKPNUihosXj|`(zcLSoznV_)S5XZE@mGsSh`%!bSKzN6Gj1J#zcLSr zznV_)S1ga7l}^{Uh)c=;B>u`g(r*#pAN~sEl}wJj8#eyR{Vl@We+9W`am|ew^PsPc zFR|U&5csQm=?(jRXZi^7S1!Wty?o}OtovKU_lv(8jEBsS5#p~##KZT4znVU$7ygRq zcK3p3;IQ#m?6-*F(2hX@aCt8L)iAzAxbat2gX6Cz6L_dvZU+3yh>sM5V1@2gJ}mxf z^gn^WGT#TEf<=K|_>__1uUPa|T?=`LP?pCo6^ zj8s3ax_BXL{=JcI;DtpG_mQ*8xF7av`kWr@6{)@+>{aQx0p)<& zH#qjnRfq4R+t9vVy6wVV4Uhg%F0fbs7=XR{7y8>%?r)1D#a@lLzx`LSSB)=1|N7Ni z&G4{SHZts0k9G}?jrpgsSC3))O%L{J{5339xUg5LF6>o_CWXab`I0wwY)j(_o*00= zA`LJZH4Tcr8Yl|)d}p(}{cYTbkKrTOZ!+Tc*SHOJZW!2CBl*OE-6qfPxtzF<)O<5~ zt7xNcK-)Va+?A^c2g7x^_Q!Z;JA>~vLEG!bT@BW5UCJCG?rNlM@Arti8jOe1B_qUL zjgW`o?KNR>SF*uySA(~|^VoK4*to0V(2miTYpydA+|>`SdT>|l=;%JUtLX%HMFxCs z#1c8Zo89lGa@S2`Yd27(0hPgxOTQ=XDw^O`%q)mX01y@0E2=Mss^y-ztHY#j60jB@ zk+8RNDNxw@}z z{ChE1gYj_b;Spl4M##gzin*G;x(9RBdkG@b-&HM#jky{Q-I$GjPnfG%b^Pq1F;^w2 z@sAAyb5%kxSKP7Pn5)Lws9ht#TpjaOyD(P?J(w%?eK1!s>|B9huJ{CVmE3M(0=)r@yk}i}yiLJRdCcy4Rncw1+lrY|fH9Plu1A4W4tI_pK{Pg2duuoqtgPkL>cb)qioN^~)=47T3u8v_&0E(Ms%6|J*4U zhxyX5;Z;UAysE?nuiDDOt4j9p(e|cV!#wz^5)ZzrgvD2t41%wEtOs9(UCAzdRS8n^ z;Hw@R9AEV@4yg3ttAGmXg|7ne2C$nOf4IWJtG;^h_>mrP75M<>0#{uM_kgQDd$f8e zaMf?lAGqQHR~1)Q_rX??Bv1V5(o|rpA`AnuRgZbFRga-d7&f+wP4uJE$-q`kbtT#t zTlK^UuvM5V<-9I}ZuUh+bDjKQa0gpP?qZ$0@dNrW8s6kbbNuwZEd z&{b-ntNu*TRRCS3XaKJI+y$=MvH3ZpH(IJb@G7b6<8Ctxui~-rs-<2?-A+1woEV5E z*!)-e(A}?k&{e;`2fB)-tvQJ5l1%uPveM{VuPjXV-CgCMP3JeLB7B?fH+zU6=V6`G`KyOMlVKa}|-$1E>~An;}1b&gg1 zPRIi0wD5;XBn!wA?CTJecCe2u9_z~v%@q&^%LgtzmWbBqx{Q0e@mM|QSG_{=>N&rv z^yc?{e${@G!NBvYg06M;Ilt;P66}8GR~3-}F57tw%$*XOcAj4XF(c0-{q@A}|7)Nr zdsCO$>MT6s!zd=t;#ARvB{&d)n#Ro<&w21VGrlmyhh&C4qiB;~?mnS(3(k~*Wjr>i z-n8{k`y34;fbO^^MN|Yab4kMYzE{vly%#^;#DF=T4f`lVD$ihDk>|$*OkCpOl7qqO)ERtWbT)uPXzC*yhMwIW&J&(t?TM&k@cZ1nQMy7i||m9+#T1G_F%u>1}3@))*9Ie;Ejn#$X+~q;+beu zKozkk?=gaiFtEHRl!!Q{nU=(&fCsl(if2Xzgg}lV4@lamsL7_~Y=py;D;{tc2;!8} zCb5YebW0L;J^PuGYRRDo-R0rQ)AMVJ2vJOq63R?6RpGgto zC+VQPqhicvFNzWGAJ3T$(XlE(cw-fY{PxP<<2P9Tc3K3KO8_&gS@doU?ENy+m|xV6 z`eFj7mic5iXS>%yQd{oB>u}?nxRNA_2@!~>@^~gBcY<)+&a5dyn9O9nf~PR$UXsm} zX?&id!Vjn{k6sa3NTS)M!ji<$%p+CwyW=_A%CkaIk)vWlrVyq;+x^2W4VmK(2R#~6 zZw8Z-iI&uGnCEaJU|JN%#0|_VEVrkXP=zK#&Yj!}(BslDmLB9Hvd|WcgXjB^NRhK^6Hz`zeYDLX>!XT2{JHSt%C@G@c8}a3)x3|WX~KQBwJRtBguCp zVTUTyk;rCUj6fo-u-hg|A^lH zgXKF9{q}5nS@+mwyQd!~JtK5Nl1jlCAFNn2qFg@?6W|%M^-s?<)Tl|UwMoG&n=m-&2WD$^&Zc#voXDn5NaYW9YD(~D0jP%H1x&cStoSgV! z=(XGuE(zH^ZXa&A0s5nkO6{+w5e+Th?BtT9r;2n2nZ4=th^7ig#Q5!{_eXN}igL$u za&88C6-9E`nCv)2w}qoKg_H4#7;_Gctk_{GnPF`4FG;ld)E@kI(tGRTwnrm0{%xaE7O*0}5An71!sBt#hZWCqV_8p|%g9i_d zCdJGsPPF2_W8OL$hBpEny>pLrvNvp6!HAZLW{&eWX{v;^Wcnk0NphlV<_r;GeHnM= z@4g|$h`8k$ruAe-(M--mWcMMEaTAk_fsRgr#?LjL3G^b*le(X$vd=;8=X<5W`t_S1 zZO5^Ok}aIX-}=N@FnOSgC)(et+aJou!tG3d4kPmD8#_ksndPv0tMAHJ8{;9vP%XeKHIEQ;J1zAnEG8!xP;Ix-vS77zG9z33TGlIMSw z&VK2kuTy*0B*M1VkrQ(=Qg+o9npKz%?G+WL5`iP%!TM(t*FqOXi7kGZU}jAa7DWl! zqib@bzeNf4TEp>_+hD&jW=0(Q9TPZp)OH*OSmZaQjiwHE`A`ol>sISq{=Czo7wS_b#d3`$r&)<&2K{L8GjEDoKEiDlXDINkV)Z5CT^{9L~Zg+E)5qutLY#h%k>4=qjhDyOyB2e-vd z?DNxiJ&%3b(h%Cj)hX&&zrEP&$_))RL`s(YoWF4lM&<)8F^v#Z^9Zc-Rdp1UMWYmr0X^uJh-7K zfR7Vligr)-UYJs{rLb^AK~#g)>&$b8hAw6tL+gUJ$aEVD9tjLQnN;v;K~3Nu?}<2B z?1W+tTIHN}K^LsXAZ=YR;IDK5@eTm%(SJels7I9&#}(Y)}7E~*|Tz80>| z#8DRefH*wmaak|b_>0I2zE%^slkJd@knB5?SGfPhL;e@TOg<5I$}My+yft~-d@i2) z4O&T0QFybyOkj)2r_PnQw_bEnD{`kw<)^cqx%=0rA4WzM%RC z@i%ejx08UXtGITvZsMxGVtvWgxZm@i`#rai=ZHxZ#+$e?te}e8Y0Y{{^~VeI54eKL zw(&g~%3}E_l<*HO2(#(NA_@_}QUhTLw|U&~*Dt8*NhA~3a7d5EivdY)aWsLK01d#Or2 z&un$M30)SED(`~lS)Y4B^}@Y^Jl7qBMB%F6`rI9b8~!{S zp8H8VZA_+eNc|y6b8(3hseb8U(Jg}Y-OsA0FU}=Xf8N*Y3#5uOXtFLa z^i-z0-amAH>A@RO^MfbSjbRisufeLrH@zxus4A2b^!AM^E;GBqT3E};{OyepPKT;a z;d@shdsNllu&iL`6JxF`!rHCNWX`(l*EcYunHQL+VZz0#)h{B_VIF3FadtHGRP7kz zl}fziKf1sWKB8&)6BlxBvUjAd!wvN75u!YTm1uudKOkj9Uc0!&Mz_AtRvn%-&pK71 zg#E^CPG&0%jca~~xcX?4(`+#_C3vhb;{7gWLYRGLwRMGlI`MB7A9}CN7IJ~{(}$Di zW#WUgWcnYHTkGSxMbl}86(?OCiPS$ryj)ji%(XFR$25;|@g^fL!0f|kM>mgVd5cl# zrK~5PiOjHa)?2mL_-Fae+*(1E(Di1!_!{>t*X5J9LoXqrEA)C_@@v{*(HDrWCQqK# z^sbpsjA@W_E+`b#JBqRTQRIECxW22+*43u>CQnryy_ozO4}ewDPTPbR7_VBfNjy1V z{7DNAg)7+|>P7lUY4P03tR8@`IY&_lVE8x3%7EYp_0lsJ%^plMT&Y3+`U}YkNWE`LEkr z|BlxN&9}~=v+prt{nehdwA79(ZOpaFRb<#}@RgRg9KjKYkC>XIEj75Qk=DJhI`~`F zyRn=qQA<7!%pwPQg?5O(3~0h(UU%rP{El-D`yLk^4wxoxyhi$N)hBIhX!&2-qIis0 zmMWWBGDiM!TL_)jAe0}%uRu;6IN_bI)2o1Z%YVrdKvI3l6i~QRrQ3pGuWxHpTYXcT zt*NcrdPbi{DBY$oG<29mxe~s#QuB8w)iT9bwos=C;;5|;%Vd)hcLu2bfb68pSMgx- zKWbc97_kf)Juax-sXyvr^(WO;0(}j6N)vyppn3Z0Hj7AFQ6UPvE7MJCDfZnz_Mw)2 zzLg8nA4(%v@$<$-^Hh~2*~n;~<{BwfyvfMKDG40AmCC&8G=A$Uw=$CGA$uFn3$c>h z`McY$ekT7_TQptHKeJlCv#o-b7kMuFU2cMKJ}O^tArHpePAZ!}PjK~Zq|kL9KGMxU zuhdJ(yLn>C5l2J}J9)c`m&|YEQnj@G7+=4YgmPR#5Y=;S+Kp|ScmOFs zU}<^M_rOK(t!^nBEdfi7JtCI0KGRmevCXy?A~xzfNt#JK%j%Tqdv5*z9Ev(+b{`@#mYRhBq HMjZKn1jkWY literal 0 HcmV?d00001 diff --git a/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/command.rs b/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/command.rs index 552ed43..d67edb8 100644 --- a/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/command.rs +++ b/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/command.rs @@ -36,4 +36,4 @@ impl traits::Command for Command { fn address(self) -> u8 { self as u8 } -} \ No newline at end of file +} diff --git a/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/graphics.rs b/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/graphics.rs index 7c03e5b..f9d723e 100644 --- a/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/graphics.rs +++ b/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/graphics.rs @@ -1,5 +1,5 @@ -use crate::E2266CS0Cx::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; +use crate::E2266CS0Cx::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; @@ -27,8 +27,8 @@ impl DrawTarget for DisplayE2266CS0Cx { type Error = core::convert::Infallible; fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, + where + I: IntoIterator>, { for pixel in pixels { self.draw_helper(WIDTH, HEIGHT, pixel)?; @@ -59,4 +59,4 @@ impl Display for DisplayE2266CS0Cx { fn rotation(&self) -> DisplayRotation { self.rotation } -} \ No newline at end of file +} diff --git a/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/mod.rs b/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/mod.rs index 2fb3573..99f5096 100644 --- a/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/mod.rs +++ b/Software/fab-reader2/pervasive_epd/src/E2266CS0Cx/mod.rs @@ -8,12 +8,12 @@ pub const HEIGHT: u32 = 296; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; -use std::io::repeat; +use crate::buffer_len; use embedded_hal::{ blocking::{delay::*, spi::Write}, digital::v2::*, }; -use crate::buffer_len; +use std::io::repeat; use command::Command; @@ -35,13 +35,13 @@ pub struct E2266CS0Cx { } impl E2266CS0Cx - where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayMs, +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10); @@ -70,14 +70,14 @@ impl E2266CS0Cx } impl PervasiveDisplay -for E2266CS0Cx - where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayMs, + for E2266CS0Cx +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -110,8 +110,7 @@ for E2266CS0Cx fn power_off(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.interface - .cmd(spi, Command::PowerOff)?; + self.interface.cmd(spi, Command::PowerOff)?; Ok(()) } @@ -134,10 +133,12 @@ for E2266CS0Cx .cmd_with_data(spi, Command::DataTransmission1, buffer)?; // Transmit WIDTH * HEIGHT bytes of 0x00 - self.interface - .cmd(spi, Command::DataTransmission2)?; - self.interface - .data_x_times(spi, 0x00, buffer_len(WIDTH as usize, HEIGHT as usize) as u32)?; + self.interface.cmd(spi, Command::DataTransmission2)?; + self.interface.data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; Ok(()) } @@ -172,7 +173,11 @@ for E2266CS0Cx // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.update_frame(spi, &[0x00; buffer_len(WIDTH as usize, HEIGHT as usize)], _delay)?; + self.update_frame( + spi, + &[0x00; buffer_len(WIDTH as usize, HEIGHT as usize)], + _delay, + )?; Ok(()) } @@ -190,15 +195,15 @@ for E2266CS0Cx } impl E2266CS0Cx - where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayMs, +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, { fn wait_until_idle(&mut self) { let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } -} \ No newline at end of file +} diff --git a/Software/fab-reader2/pervasive_epd/src/color.rs b/Software/fab-reader2/pervasive_epd/src/color.rs index cf6cb26..34f0526 100644 --- a/Software/fab-reader2/pervasive_epd/src/color.rs +++ b/Software/fab-reader2/pervasive_epd/src/color.rs @@ -76,4 +76,4 @@ impl From for Color { fn from(value: u8) -> Self { Color::from_u8(value) } -} \ No newline at end of file +} diff --git a/Software/fab-reader2/pervasive_epd/src/graphics.rs b/Software/fab-reader2/pervasive_epd/src/graphics.rs index 269bad7..9eaabc3 100644 --- a/Software/fab-reader2/pervasive_epd/src/graphics.rs +++ b/Software/fab-reader2/pervasive_epd/src/graphics.rs @@ -24,7 +24,6 @@ impl Default for DisplayRotation { } } - /// Necessary traits for all displays to implement for drawing /// /// Adds support for: @@ -87,7 +86,6 @@ pub trait Display: DrawTarget { } } - /// A variable Display without a predefined buffer /// /// The buffer can be created as following: @@ -142,8 +140,8 @@ impl<'a> DrawTarget for VarDisplay<'a> { type Error = core::convert::Infallible; fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, + where + I: IntoIterator>, { for pixel in pixels { self.draw_helper(self.width, self.height, pixel)?; @@ -241,4 +239,4 @@ fn find_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotat nx / 8 + ((width + 7) / 8) * ny, 0x80 >> (nx % 8), ) -} \ No newline at end of file +} diff --git a/Software/fab-reader2/pervasive_epd/src/interface.rs b/Software/fab-reader2/pervasive_epd/src/interface.rs index 55e5351..6a15f9d 100644 --- a/Software/fab-reader2/pervasive_epd/src/interface.rs +++ b/Software/fab-reader2/pervasive_epd/src/interface.rs @@ -23,13 +23,13 @@ pub(crate) struct DisplayInterface { } impl DisplayInterface - where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayMs, +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, { pub fn new(cs: CS, busy: BUSY, dc: DC, rst: RST) -> Self { DisplayInterface { diff --git a/Software/fab-reader2/pervasive_epd/src/lib.rs b/Software/fab-reader2/pervasive_epd/src/lib.rs index a7f7879..1e4862c 100644 --- a/Software/fab-reader2/pervasive_epd/src/lib.rs +++ b/Software/fab-reader2/pervasive_epd/src/lib.rs @@ -1,7 +1,7 @@ -mod interface; -mod traits; pub mod color; pub mod graphics; +mod interface; +mod traits; pub mod E2266CS0Cx; @@ -14,7 +14,6 @@ pub mod prelude { pub use crate::graphics::{Display, DisplayRotation}; } - /// Computes the needed buffer length. Takes care of rounding up in case width /// is not divisible by 8. /// @@ -35,4 +34,4 @@ use embedded_hal::spi::{Mode, Phase, Polarity}; pub const SPI_MODE: Mode = Mode { phase: Phase::CaptureOnFirstTransition, polarity: Polarity::IdleLow, -}; \ No newline at end of file +}; diff --git a/Software/fab-reader2/pervasive_epd/src/traits.rs b/Software/fab-reader2/pervasive_epd/src/traits.rs index b509681..0799fc5 100644 --- a/Software/fab-reader2/pervasive_epd/src/traits.rs +++ b/Software/fab-reader2/pervasive_epd/src/traits.rs @@ -10,13 +10,13 @@ pub(crate) trait Command { } pub trait PervasiveDisplay - where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayMs, +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, { /// The Color Type used by the Display type DisplayColor; @@ -31,8 +31,8 @@ pub trait PervasiveDisplay rst: RST, delay: &mut DELAY, ) -> Result - where - Self: Sized; + where + Self: Sized; /// Let the device enter deep-sleep mode to save power. /// @@ -64,7 +64,6 @@ pub trait PervasiveDisplay delay: &mut DELAY, ) -> Result<(), SPI::Error>; - /// Displays the frame data from SRAM /// /// This function waits until the device isn`t busy anymore @@ -89,4 +88,4 @@ pub trait PervasiveDisplay /// but in the case you send data and commands directly you might need to check /// if the device is still busy fn is_busy(&self) -> bool; -} \ No newline at end of file +} diff --git a/Software/fab-reader2/rout.bin b/Software/fab-reader2/rout.bin new file mode 100644 index 0000000000000000000000000000000000000000..c33d30be3a36903cafe20be711f94a0863f24ae2 GIT binary patch literal 395712 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