From 4c6f0969c11152825906d62c843d55aa469b394d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 5 Jan 2019 20:58:39 -0500 Subject: [PATCH 01/96] add spi --- targets/stm32l432/lib/stm32l4xx_ll_spi.c | 307 +++++ targets/stm32l432/lib/stm32l4xx_ll_spi.h | 1436 ++++++++++++++++++++++ targets/stm32l432/src/init.c | 46 + 3 files changed, 1789 insertions(+) create mode 100644 targets/stm32l432/lib/stm32l4xx_ll_spi.c create mode 100644 targets/stm32l432/lib/stm32l4xx_ll_spi.h diff --git a/targets/stm32l432/lib/stm32l4xx_ll_spi.c b/targets/stm32l432/lib/stm32l4xx_ll_spi.c new file mode 100644 index 0000000..99e28de --- /dev/null +++ b/targets/stm32l432/lib/stm32l4xx_ll_spi.c @@ -0,0 +1,307 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_spi.c + * @author MCD Application Team + * @brief SPI LL module driver. + ****************************************************************************** + * @attention + * + *

© 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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_ll_spi.h" +#include "stm32l4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @addtogroup SPI_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SPI_LL_Private_Constants SPI Private Constants + * @{ + */ +/* SPI registers Masks */ +#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \ + SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \ + SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_CRCL | \ + SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \ + SPI_CR1_BIDIMODE) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Private_Macros SPI Private Macros + * @{ + */ +#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \ + || ((__VALUE__) == LL_SPI_SIMPLEX_RX) \ + || ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \ + || ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX)) + +#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \ + || ((__VALUE__) == LL_SPI_MODE_SLAVE)) + +#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT)) + +#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \ + || ((__VALUE__) == LL_SPI_POLARITY_HIGH)) + +#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \ + || ((__VALUE__) == LL_SPI_PHASE_2EDGE)) + +#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \ + || ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \ + || ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT)) + +#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256)) + +#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \ + || ((__VALUE__) == LL_SPI_MSB_FIRST)) + +#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \ + || ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE)) + +#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SPI_LL_Exported_Functions + * @{ + */ + +/** @addtogroup SPI_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the SPI registers to their default reset values. + * @param SPIx SPI Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: SPI registers are de-initialized + * - ERROR: SPI registers are not de-initialized + */ +ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx) +{ + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_SPI_ALL_INSTANCE(SPIx)); + +#if defined(SPI1) + if (SPIx == SPI1) + { + /* Force reset of SPI clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); + + /* Release reset of SPI clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); + + status = SUCCESS; + } +#endif /* SPI1 */ +#if defined(SPI2) + if (SPIx == SPI2) + { + /* Force reset of SPI clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); + + /* Release reset of SPI clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); + + status = SUCCESS; + } +#endif /* SPI2 */ +#if defined(SPI3) + if (SPIx == SPI3) + { + /* Force reset of SPI clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3); + + /* Release reset of SPI clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3); + + status = SUCCESS; + } +#endif /* SPI3 */ + + return status; +} + +/** + * @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct. + * @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0), + * SPI IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. + * @param SPIx SPI Instance + * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure + * @retval An ErrorStatus enumeration value. (Return always SUCCESS) + */ +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct) +{ + ErrorStatus status = ERROR; + + /* Check the SPI Instance SPIx*/ + assert_param(IS_SPI_ALL_INSTANCE(SPIx)); + + /* Check the SPI parameters from SPI_InitStruct*/ + assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection)); + assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode)); + assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth)); + assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity)); + assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase)); + assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS)); + assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate)); + assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder)); + assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation)); + + if (LL_SPI_IsEnabled(SPIx) == 0x00000000U) + { + /*---------------------------- SPIx CR1 Configuration ------------------------ + * Configure SPIx CR1 with parameters: + * - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits + * - Master/Slave Mode: SPI_CR1_MSTR bit + * - ClockPolarity: SPI_CR1_CPOL bit + * - ClockPhase: SPI_CR1_CPHA bit + * - NSS management: SPI_CR1_SSM bit + * - BaudRate prescaler: SPI_CR1_BR[2:0] bits + * - BitOrder: SPI_CR1_LSBFIRST bit + * - CRCCalculation: SPI_CR1_CRCEN bit + */ + MODIFY_REG(SPIx->CR1, + SPI_CR1_CLEAR_MASK, + SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode | + SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase | + SPI_InitStruct->NSS | SPI_InitStruct->BaudRate | + SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation); + + /*---------------------------- SPIx CR2 Configuration ------------------------ + * Configure SPIx CR2 with parameters: + * - DataWidth: DS[3:0] bits + * - NSS management: SSOE bit + */ + MODIFY_REG(SPIx->CR2, + SPI_CR2_DS | SPI_CR2_SSOE, + SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U)); + + /*---------------------------- SPIx CRCPR Configuration ---------------------- + * Configure SPIx CRCPR with parameters: + * - CRCPoly: CRCPOLY[15:0] bits + */ + if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE) + { + assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly)); + LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly); + } + status = SUCCESS; + } + + return status; +} + +/** + * @brief Set each @ref LL_SPI_InitTypeDef field to default value. + * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct) +{ + /* Set SPI_InitStruct fields to default values */ + SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE; + SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT; + SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW; + SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE; + SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT; + SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST; + SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct->CRCPoly = 7U; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l432/lib/stm32l4xx_ll_spi.h b/targets/stm32l432/lib/stm32l4xx_ll_spi.h new file mode 100644 index 0000000..b5bc17a --- /dev/null +++ b/targets/stm32l432/lib/stm32l4xx_ll_spi.h @@ -0,0 +1,1436 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_spi.h + * @author MCD Application Team + * @brief Header file of SPI LL module. + ****************************************************************************** + * @attention + * + *

© 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32L4xx_LL_SPI_H +#define STM32L4xx_LL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @defgroup SPI_LL SPI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_ES_INIT SPI Exported Init structure + * @{ + */ + +/** + * @brief SPI Init structures definition + */ +typedef struct +{ + uint32_t TransferDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferDirection().*/ + + uint32_t Mode; /*!< Specifies the SPI mode (Master/Slave). + This parameter can be a value of @ref SPI_LL_EC_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetMode().*/ + + uint32_t DataWidth; /*!< Specifies the SPI data width. + This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetDataWidth().*/ + + uint32_t ClockPolarity; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_LL_EC_POLARITY. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPolarity().*/ + + uint32_t ClockPhase; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_LL_EC_PHASE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPhase().*/ + + uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_LL_EC_NSS_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetNSSMode().*/ + + uint32_t BaudRate; /*!< Specifies the BaudRate prescaler value which will be used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER. + @note The communication clock is derived from the master clock. The slave clock does not need to be set. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetBaudRatePrescaler().*/ + + uint32_t BitOrder; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferBitOrder().*/ + + uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. + This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION. + + This feature can be modified afterwards using unitary functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/ + + uint32_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetCRCPolynomial().*/ + +} LL_SPI_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Constants SPI Exported Constants + * @{ + */ + +/** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_SPI_ReadReg function + * @{ + */ +#define LL_SPI_SR_RXNE SPI_SR_RXNE /*!< Rx buffer not empty flag */ +#define LL_SPI_SR_TXE SPI_SR_TXE /*!< Tx buffer empty flag */ +#define LL_SPI_SR_BSY SPI_SR_BSY /*!< Busy flag */ +#define LL_SPI_SR_CRCERR SPI_SR_CRCERR /*!< CRC error flag */ +#define LL_SPI_SR_MODF SPI_SR_MODF /*!< Mode fault flag */ +#define LL_SPI_SR_OVR SPI_SR_OVR /*!< Overrun flag */ +#define LL_SPI_SR_FRE SPI_SR_FRE /*!< TI mode frame format error flag */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions + * @{ + */ +#define LL_SPI_CR2_RXNEIE SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ +#define LL_SPI_CR2_TXEIE SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ +#define LL_SPI_CR2_ERRIE SPI_CR2_ERRIE /*!< Error interrupt enable */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_MODE Operation Mode + * @{ + */ +#define LL_SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /*!< Master configuration */ +#define LL_SPI_MODE_SLAVE 0x00000000U /*!< Slave configuration */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_PROTOCOL Serial Protocol + * @{ + */ +#define LL_SPI_PROTOCOL_MOTOROLA 0x00000000U /*!< Motorola mode. Used as default value */ +#define LL_SPI_PROTOCOL_TI (SPI_CR2_FRF) /*!< TI mode */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_SPI_PHASE_1EDGE 0x00000000U /*!< First clock transition is the first data capture edge */ +#define LL_SPI_PHASE_2EDGE (SPI_CR1_CPHA) /*!< Second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_SPI_POLARITY_LOW 0x00000000U /*!< Clock to 0 when idle */ +#define LL_SPI_POLARITY_HIGH (SPI_CR1_CPOL) /*!< Clock to 1 when idle */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler + * @{ + */ +#define LL_SPI_BAUDRATEPRESCALER_DIV2 0x00000000U /*!< BaudRate control equal to fPCLK/2 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV4 (SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/4 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV8 (SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/8 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/16 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV32 (SPI_CR1_BR_2) /*!< BaudRate control equal to fPCLK/32 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/64 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/128 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/256 */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order + * @{ + */ +#define LL_SPI_LSB_FIRST (SPI_CR1_LSBFIRST) /*!< Data is transmitted/received with the LSB first */ +#define LL_SPI_MSB_FIRST 0x00000000U /*!< Data is transmitted/received with the MSB first */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode + * @{ + */ +#define LL_SPI_FULL_DUPLEX 0x00000000U /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */ +#define LL_SPI_SIMPLEX_RX (SPI_CR1_RXONLY) /*!< Simplex Rx mode. Rx transfer only on 1 line */ +#define LL_SPI_HALF_DUPLEX_RX (SPI_CR1_BIDIMODE) /*!< Half-Duplex Rx mode. Rx transfer on 1 line */ +#define LL_SPI_HALF_DUPLEX_TX (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE) /*!< Half-Duplex Tx mode. Tx transfer on 1 line */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode + * @{ + */ +#define LL_SPI_NSS_SOFT (SPI_CR1_SSM) /*!< NSS managed internally. NSS pin not used and free */ +#define LL_SPI_NSS_HARD_INPUT 0x00000000U /*!< NSS pin used in Input. Only used in Master mode */ +#define LL_SPI_NSS_HARD_OUTPUT (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DATAWIDTH Datawidth + * @{ + */ +#define LL_SPI_DATAWIDTH_4BIT (SPI_CR2_DS_0 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 4 bits */ +#define LL_SPI_DATAWIDTH_5BIT (SPI_CR2_DS_2) /*!< Data length for SPI transfer: 5 bits */ +#define LL_SPI_DATAWIDTH_6BIT (SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 6 bits */ +#define LL_SPI_DATAWIDTH_7BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 7 bits */ +#define LL_SPI_DATAWIDTH_8BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 8 bits */ +#define LL_SPI_DATAWIDTH_9BIT (SPI_CR2_DS_3) /*!< Data length for SPI transfer: 9 bits */ +#define LL_SPI_DATAWIDTH_10BIT (SPI_CR2_DS_3 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 10 bits */ +#define LL_SPI_DATAWIDTH_11BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 11 bits */ +#define LL_SPI_DATAWIDTH_12BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 12 bits */ +#define LL_SPI_DATAWIDTH_13BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2) /*!< Data length for SPI transfer: 13 bits */ +#define LL_SPI_DATAWIDTH_14BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 14 bits */ +#define LL_SPI_DATAWIDTH_15BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 15 bits */ +#define LL_SPI_DATAWIDTH_16BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 16 bits */ +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation + * @{ + */ +#define LL_SPI_CRCCALCULATION_DISABLE 0x00000000U /*!< CRC calculation disabled */ +#define LL_SPI_CRCCALCULATION_ENABLE (SPI_CR1_CRCEN) /*!< CRC calculation enabled */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup SPI_LL_EC_CRC_LENGTH CRC Length + * @{ + */ +#define LL_SPI_CRC_8BIT 0x00000000U /*!< 8-bit CRC length */ +#define LL_SPI_CRC_16BIT (SPI_CR1_CRCL) /*!< 16-bit CRC length */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_RX_FIFO_TH RX FIFO Threshold + * @{ + */ +#define LL_SPI_RX_FIFO_TH_HALF 0x00000000U /*!< RXNE event is generated if FIFO level is greater than or equel to 1/2 (16-bit) */ +#define LL_SPI_RX_FIFO_TH_QUARTER (SPI_CR2_FRXTH) /*!< RXNE event is generated if FIFO level is greater than or equel to 1/4 (8-bit) */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_RX_FIFO RX FIFO Level + * @{ + */ +#define LL_SPI_RX_FIFO_EMPTY 0x00000000U /*!< FIFO reception empty */ +#define LL_SPI_RX_FIFO_QUARTER_FULL (SPI_SR_FRLVL_0) /*!< FIFO reception 1/4 */ +#define LL_SPI_RX_FIFO_HALF_FULL (SPI_SR_FRLVL_1) /*!< FIFO reception 1/2 */ +#define LL_SPI_RX_FIFO_FULL (SPI_SR_FRLVL_1 | SPI_SR_FRLVL_0) /*!< FIFO reception full */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TX_FIFO TX FIFO Level + * @{ + */ +#define LL_SPI_TX_FIFO_EMPTY 0x00000000U /*!< FIFO transmission empty */ +#define LL_SPI_TX_FIFO_QUARTER_FULL (SPI_SR_FTLVL_0) /*!< FIFO transmission 1/4 */ +#define LL_SPI_TX_FIFO_HALF_FULL (SPI_SR_FTLVL_1) /*!< FIFO transmission 1/2 */ +#define LL_SPI_TX_FIFO_FULL (SPI_SR_FTLVL_1 | SPI_SR_FTLVL_0) /*!< FIFO transmission full */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DMA_PARITY DMA Parity + * @{ + */ +#define LL_SPI_DMA_PARITY_EVEN 0x00000000U /*!< Select DMA parity Even */ +#define LL_SPI_DMA_PARITY_ODD 0x00000001U /*!< Select DMA parity Odd */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Macros SPI Exported Macros + * @{ + */ + +/** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Functions SPI Exported Functions + * @{ + */ + +/** @defgroup SPI_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable SPI peripheral + * @rmtoll CR1 SPE LL_SPI_Enable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Disable SPI peripheral + * @note When disabling the SPI, follow the procedure described in the Reference Manual. + * @rmtoll CR1 SPE LL_SPI_Disable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Check if SPI peripheral is enabled + * @rmtoll CR1 SPE LL_SPI_IsEnabled + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabled(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL); +} + +/** + * @brief Set SPI operation mode to Master or Slave + * @note This bit should not be changed when communication is ongoing. + * @rmtoll CR1 MSTR LL_SPI_SetMode\n + * CR1 SSI LL_SPI_SetMode + * @param SPIx SPI Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode); +} + +/** + * @brief Get SPI operation mode (Master or Slave) + * @rmtoll CR1 MSTR LL_SPI_GetMode\n + * CR1 SSI LL_SPI_GetMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + */ +__STATIC_INLINE uint32_t LL_SPI_GetMode(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI)); +} + +/** + * @brief Set serial protocol used + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR2 FRF LL_SPI_SetStandard + * @param SPIx SPI Instance + * @param Standard This parameter can be one of the following values: + * @arg @ref LL_SPI_PROTOCOL_MOTOROLA + * @arg @ref LL_SPI_PROTOCOL_TI + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_FRF, Standard); +} + +/** + * @brief Get serial protocol used + * @rmtoll CR2 FRF LL_SPI_GetStandard + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PROTOCOL_MOTOROLA + * @arg @ref LL_SPI_PROTOCOL_TI + */ +__STATIC_INLINE uint32_t LL_SPI_GetStandard(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRF)); +} + +/** + * @brief Set clock phase + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPHA LL_SPI_SetClockPhase + * @param SPIx SPI Instance + * @param ClockPhase This parameter can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase); +} + +/** + * @brief Get clock phase + * @rmtoll CR1 CPHA LL_SPI_GetClockPhase + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPhase(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA)); +} + +/** + * @brief Set clock polarity + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPOL LL_SPI_SetClockPolarity + * @param SPIx SPI Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity); +} + +/** + * @brief Get clock polarity + * @rmtoll CR1 CPOL LL_SPI_GetClockPolarity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL)); +} + +/** + * @brief Set baud rate prescaler + * @note These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler. + * @rmtoll CR1 BR LL_SPI_SetBaudRatePrescaler + * @param SPIx SPI Instance + * @param BaudRate This parameter can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate); +} + +/** + * @brief Get baud rate prescaler + * @rmtoll CR1 BR LL_SPI_GetBaudRatePrescaler + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + */ +__STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR)); +} + +/** + * @brief Set transfer bit order + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR1 LSBFIRST LL_SPI_SetTransferBitOrder + * @param SPIx SPI Instance + * @param BitOrder This parameter can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder); +} + +/** + * @brief Get transfer bit order + * @rmtoll CR1 LSBFIRST LL_SPI_GetTransferBitOrder + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST)); +} + +/** + * @brief Set transfer direction mode + * @note For Half-Duplex mode, Rx Direction is set by default. + * In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex. + * @rmtoll CR1 RXONLY LL_SPI_SetTransferDirection\n + * CR1 BIDIMODE LL_SPI_SetTransferDirection\n + * CR1 BIDIOE LL_SPI_SetTransferDirection + * @param SPIx SPI Instance + * @param TransferDirection This parameter can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection); +} + +/** + * @brief Get transfer direction mode + * @rmtoll CR1 RXONLY LL_SPI_GetTransferDirection\n + * CR1 BIDIMODE LL_SPI_GetTransferDirection\n + * CR1 BIDIOE LL_SPI_GetTransferDirection + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)); +} + +/** + * @brief Set frame data width + * @rmtoll CR2 DS LL_SPI_SetDataWidth + * @param SPIx SPI Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_4BIT + * @arg @ref LL_SPI_DATAWIDTH_5BIT + * @arg @ref LL_SPI_DATAWIDTH_6BIT + * @arg @ref LL_SPI_DATAWIDTH_7BIT + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_9BIT + * @arg @ref LL_SPI_DATAWIDTH_10BIT + * @arg @ref LL_SPI_DATAWIDTH_11BIT + * @arg @ref LL_SPI_DATAWIDTH_12BIT + * @arg @ref LL_SPI_DATAWIDTH_13BIT + * @arg @ref LL_SPI_DATAWIDTH_14BIT + * @arg @ref LL_SPI_DATAWIDTH_15BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_DS, DataWidth); +} + +/** + * @brief Get frame data width + * @rmtoll CR2 DS LL_SPI_GetDataWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_4BIT + * @arg @ref LL_SPI_DATAWIDTH_5BIT + * @arg @ref LL_SPI_DATAWIDTH_6BIT + * @arg @ref LL_SPI_DATAWIDTH_7BIT + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_9BIT + * @arg @ref LL_SPI_DATAWIDTH_10BIT + * @arg @ref LL_SPI_DATAWIDTH_11BIT + * @arg @ref LL_SPI_DATAWIDTH_12BIT + * @arg @ref LL_SPI_DATAWIDTH_13BIT + * @arg @ref LL_SPI_DATAWIDTH_14BIT + * @arg @ref LL_SPI_DATAWIDTH_15BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_DS)); +} + +/** + * @brief Set threshold of RXFIFO that triggers an RXNE event + * @rmtoll CR2 FRXTH LL_SPI_SetRxFIFOThreshold + * @param SPIx SPI Instance + * @param Threshold This parameter can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_TH_HALF + * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetRxFIFOThreshold(SPI_TypeDef *SPIx, uint32_t Threshold) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_FRXTH, Threshold); +} + +/** + * @brief Get threshold of RXFIFO that triggers an RXNE event + * @rmtoll CR2 FRXTH LL_SPI_GetRxFIFOThreshold + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_TH_HALF + * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOThreshold(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRXTH)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_CRC_Management CRC Management + * @{ + */ + +/** + * @brief Enable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_EnableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Disable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_DisableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Check if CRC is enabled + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_IsEnabledCRC + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL); +} + +/** + * @brief Set CRC Length + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCL LL_SPI_SetCRCWidth + * @param SPIx SPI Instance + * @param CRCLength This parameter can be one of the following values: + * @arg @ref LL_SPI_CRC_8BIT + * @arg @ref LL_SPI_CRC_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCWidth(SPI_TypeDef *SPIx, uint32_t CRCLength) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CRCL, CRCLength); +} + +/** + * @brief Get CRC Length + * @rmtoll CR1 CRCL LL_SPI_GetCRCWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_CRC_8BIT + * @arg @ref LL_SPI_CRC_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CRCL)); +} + +/** + * @brief Set CRCNext to transfer CRC on the line + * @note This bit has to be written as soon as the last data is written in the SPIx_DR register. + * @rmtoll CR1 CRCNEXT LL_SPI_SetCRCNext + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT); +} + +/** + * @brief Set polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_SetCRCPolynomial + * @param SPIx SPI Instance + * @param CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly) +{ + WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly); +} + +/** + * @brief Get polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_GetCRCPolynomial + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->CRCPR)); +} + +/** + * @brief Get Rx CRC + * @rmtoll RXCRCR RXCRC LL_SPI_GetRxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxCRC(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->RXCRCR)); +} + +/** + * @brief Get Tx CRC + * @rmtoll TXCRCR TXCRC LL_SPI_GetTxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxCRC(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->TXCRCR)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management + * @{ + */ + +/** + * @brief Set NSS mode + * @note LL_SPI_NSS_SOFT Mode is not used in SPI TI mode. + * @rmtoll CR1 SSM LL_SPI_SetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_SetNSSMode + * @param SPIx SPI Instance + * @param NSS This parameter can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_SSM, NSS); + MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U))); +} + +/** + * @brief Get NSS mode + * @rmtoll CR1 SSM LL_SPI_GetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_GetNSSMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + */ +__STATIC_INLINE uint32_t LL_SPI_GetNSSMode(SPI_TypeDef *SPIx) +{ + register uint32_t Ssm = (READ_BIT(SPIx->CR1, SPI_CR1_SSM)); + register uint32_t Ssoe = (READ_BIT(SPIx->CR2, SPI_CR2_SSOE) << 16U); + return (Ssm | Ssoe); +} + +/** + * @brief Enable NSS pulse management + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_EnableNSSPulseMgt + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableNSSPulseMgt(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_NSSP); +} + +/** + * @brief Disable NSS pulse management + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_DisableNSSPulseMgt + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableNSSPulseMgt(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_NSSP); +} + +/** + * @brief Check if NSS pulse is enabled + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_IsEnabledNSSPulse + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledNSSPulse(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_NSSP) == (SPI_CR2_NSSP)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_FLAG_Management FLAG Management + * @{ + */ + +/** + * @brief Check if Rx buffer is not empty + * @rmtoll SR RXNE LL_SPI_IsActiveFlag_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer is empty + * @rmtoll SR TXE LL_SPI_IsActiveFlag_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL); +} + +/** + * @brief Get CRC error flag + * @rmtoll SR CRCERR LL_SPI_IsActiveFlag_CRCERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL); +} + +/** + * @brief Get mode fault error flag + * @rmtoll SR MODF LL_SPI_IsActiveFlag_MODF + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL); +} + +/** + * @brief Get overrun error flag + * @rmtoll SR OVR LL_SPI_IsActiveFlag_OVR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Get busy flag + * @note The BSY flag is cleared under any one of the following conditions: + * -When the SPI is correctly disabled + * -When a fault is detected in Master mode (MODF bit set to 1) + * -In Master mode, when it finishes a data transmission and no new data is ready to be + * sent + * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between + * each data transfer. + * @rmtoll SR BSY LL_SPI_IsActiveFlag_BSY + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL); +} + +/** + * @brief Get frame format error flag + * @rmtoll SR FRE LL_SPI_IsActiveFlag_FRE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_FRE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_FRE) == (SPI_SR_FRE)) ? 1UL : 0UL); +} + +/** + * @brief Get FIFO reception Level + * @rmtoll SR FRLVL LL_SPI_GetRxFIFOLevel + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_EMPTY + * @arg @ref LL_SPI_RX_FIFO_QUARTER_FULL + * @arg @ref LL_SPI_RX_FIFO_HALF_FULL + * @arg @ref LL_SPI_RX_FIFO_FULL + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOLevel(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FRLVL)); +} + +/** + * @brief Get FIFO Transmission Level + * @rmtoll SR FTLVL LL_SPI_GetTxFIFOLevel + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_TX_FIFO_EMPTY + * @arg @ref LL_SPI_TX_FIFO_QUARTER_FULL + * @arg @ref LL_SPI_TX_FIFO_HALF_FULL + * @arg @ref LL_SPI_TX_FIFO_FULL + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxFIFOLevel(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FTLVL)); +} + +/** + * @brief Clear CRC error flag + * @rmtoll SR CRCERR LL_SPI_ClearFlag_CRCERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR); +} + +/** + * @brief Clear mode fault error flag + * @note Clearing this flag is done by a read access to the SPIx_SR + * register followed by a write access to the SPIx_CR1 register + * @rmtoll SR MODF LL_SPI_ClearFlag_MODF + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg_sr; + tmpreg_sr = SPIx->SR; + (void) tmpreg_sr; + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Clear overrun error flag + * @note Clearing this flag is done by a read access to the SPIx_DR + * register followed by a read access to the SPIx_SR register + * @rmtoll SR OVR LL_SPI_ClearFlag_OVR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->DR; + (void) tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @brief Clear frame format error flag + * @note Clearing this flag is done by reading SPIx_SR register + * @rmtoll SR FRE LL_SPI_ClearFlag_FRE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_IT_Management Interrupt Management + * @{ + */ + +/** + * @brief Enable error interrupt + * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_EnableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Enable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_EnableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Enable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_EnableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Disable error interrupt + * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_DisableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Disable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_DisableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Disable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_DisableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Check if error interrupt is enabled + * @rmtoll CR2 ERRIE LL_SPI_IsEnabledIT_ERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Rx buffer not empty interrupt is enabled + * @rmtoll CR2 RXNEIE LL_SPI_IsEnabledIT_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_IsEnabledIT_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DMA_Management DMA Management + * @{ + */ + +/** + * @brief Enable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_EnableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Disable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_DisableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Check if DMA Rx is enabled + * @rmtoll CR2 RXDMAEN LL_SPI_IsEnabledDMAReq_RX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_EnableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Disable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_DisableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Check if DMA Tx is enabled + * @rmtoll CR2 TXDMAEN LL_SPI_IsEnabledDMAReq_TX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Set parity of Last DMA reception + * @rmtoll CR2 LDMARX LL_SPI_SetDMAParity_RX + * @param SPIx SPI Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDMAParity_RX(SPI_TypeDef *SPIx, uint32_t Parity) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_LDMARX, (Parity << SPI_CR2_LDMARX_Pos)); +} + +/** + * @brief Get parity configuration for Last DMA reception + * @rmtoll CR2 LDMARX LL_SPI_GetDMAParity_RX + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + */ +__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_RX(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMARX) >> SPI_CR2_LDMARX_Pos); +} + +/** + * @brief Set parity of Last DMA transmission + * @rmtoll CR2 LDMATX LL_SPI_SetDMAParity_TX + * @param SPIx SPI Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDMAParity_TX(SPI_TypeDef *SPIx, uint32_t Parity) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_LDMATX, (Parity << SPI_CR2_LDMATX_Pos)); +} + +/** + * @brief Get parity configuration for Last DMA transmission + * @rmtoll CR2 LDMATX LL_SPI_GetDMAParity_TX + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + */ +__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_TX(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMATX) >> SPI_CR2_LDMATX_Pos); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll DR DR LL_SPI_DMA_GetRegAddr + * @param SPIx SPI Instance + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(SPI_TypeDef *SPIx) +{ + return (uint32_t) & (SPIx->DR); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DATA_Management DATA Management + * @{ + */ + +/** + * @brief Read 8-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData8 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx) +{ + return (uint8_t)(READ_REG(SPIx->DR)); +} + +/** + * @brief Read 16-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData16 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx) +{ + return (uint16_t)(READ_REG(SPIx->DR)); +} + +/** + * @brief Write 8-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData8 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData) +{ +#if defined (__GNUC__) + __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR); + *spidr = TxData; +#else + *((__IO uint8_t *)&SPIx->DR) = TxData; +#endif +} + +/** + * @brief Write 16-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData16 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) +{ +#if defined (__GNUC__) + __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR); + *spidr = TxData; +#else + SPIx->DR = TxData; +#endif +} + +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx); +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct); +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_SPI_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index daa81d0..aa66189 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -33,6 +33,7 @@ #include "stm32l4xx_ll_bus.h" #include "stm32l4xx_ll_tim.h" #include "stm32l4xx_ll_rng.h" +#include "stm32l4xx_ll_spi.h" #include "stm32l4xx_ll_usb.h" #include "stm32l4xx_hal_pcd.h" #include "stm32l4xx_hal.h" @@ -62,6 +63,7 @@ static void MX_USART1_UART_Init(void); static void MX_TIM2_Init(void); static void MX_TIM6_Init(void); static void MX_RNG_Init(void); +static void MX_SPI1_Init(void); #define Error_Handler() _Error_Handler(__FILE__,__LINE__) void _Error_Handler(char *file, int line); @@ -83,6 +85,7 @@ void hw_init(void) MX_TIM2_Init(); // PWM for LEDs MX_TIM6_Init(); // ~1 ms timer + MX_SPI1_Init(); #if DEBUG_LEVEL > 0 MX_USART1_UART_Init();// debug uart @@ -416,3 +419,46 @@ static void MX_RNG_Init(void) LL_RNG_Enable(RNG); } + +/* SPI1 init function */ +static void MX_SPI1_Init(void) +{ + + LL_SPI_InitTypeDef SPI_InitStruct; + + LL_GPIO_InitTypeDef GPIO_InitStruct; + + /* Peripheral clock enable */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); + + /**SPI1 GPIO Configuration + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_5|LL_GPIO_PIN_6|LL_GPIO_PIN_7; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_5; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* SPI1 parameter configuration*/ + SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; + SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; + SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; + SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE; + SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; + SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; + SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct.CRCPoly = 7; + LL_SPI_Init(SPI1, &SPI_InitStruct); + + LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA); + + LL_SPI_EnableNSSPulseMgt(SPI1); + +} From 44077a4f2f7c2b3857507853f51a616fdae9dcce Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 6 Jan 2019 17:12:26 -0500 Subject: [PATCH 02/96] spi interface WORKS --- targets/stm32l432/src/device.c | 182 +++++++++++++++++++++++++++++++++ targets/stm32l432/src/init.c | 74 ++++++++------ 2 files changed, 223 insertions(+), 33 deletions(-) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 7bc5f48..60e0b76 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -25,6 +25,7 @@ #include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_tim.h" #include "stm32l4xx_ll_usart.h" +#include "stm32l4xx_ll_spi.h" #include "usbd_hid.h" #include APP_CONFIG @@ -369,6 +370,141 @@ uint32_t ctap_atomic_count(int sel) return lastc; } +static void flush_rx() +{ + while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0) + { + LL_SPI_ReceiveData8(SPI1); + } +} +static void wait_for_tx() +{ + // while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) + // ; + while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY) + ; +} +static void wait_for_rx() +{ + while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0) + ; +} + +void ams_write_reg(uint8_t addr, uint8_t tx) +{ + LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(1); + LL_SPI_TransmitData8(SPI1,0x00| addr); + LL_SPI_ReceiveData8(SPI1); + while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) + ; + LL_SPI_TransmitData8(SPI1,tx); + while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) + ; + LL_SPI_ReceiveData8(SPI1); + + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + // delay(1); + LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + +} + +uint8_t send_recv(uint8_t b) +{ + wait_for_tx(); + LL_SPI_TransmitData8(SPI1, b); + wait_for_rx(); + b = LL_SPI_ReceiveData8(SPI1); + return b; +} + +uint8_t send_recv2(uint8_t b1,uint8_t b2) +{ + wait_for_tx(); + LL_SPI_TransmitData8(SPI1, b1); + LL_SPI_TransmitData8(SPI1, b2); + wait_for_tx(); + LL_SPI_ReceiveData8(SPI1); + uint8_t b = LL_SPI_ReceiveData8(SPI1); + return b; +} +#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +uint8_t ams_read_reg(uint8_t addr) +{ + delay(2); + flush_rx(); + LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(2); + + uint8_t data = send_recv2(0x20| (addr & 0x1f), 0); + // send_recv(0x20| addr); + // + // uint8_t data = send_recv(0); + + delay(2); + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(2); + return data; +} + +// data must be 14 bytes long +void read_reg_block2(uint8_t * data) +{ + int i; + + for (i = 0; i < 0x20; i++) + { + if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) + { + *data = ams_read_reg(i); + data++; + } + } + +} + + +// data must be 14 bytes long +void read_reg_block(uint8_t * data, int count) +{ + int i; + uint8_t mode = 0x20 | (0 ); + flush_rx(); + SELECT(); + delay(2); + send_recv(mode); + for (i = 0; i < count; i++) + { + mode = send_recv(0); + // if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) + // { + *data = mode; + data++; + // } + } + + delay(2); + UNSELECT(); + // delay(2); + // SELECT(); +} + +void ams_write_command(uint8_t cmd) +{ + + uint8_t mode = cmd; + // delay(10); + + // delay(10); + SELECT(); + delay(1); + send_recv(mode); + UNSELECT(); + SELECT(); + +} + void device_manage() @@ -391,6 +527,52 @@ void device_manage() } } #endif + + static int run = 0; + + if (!run) + { + uint8_t regs[0x20]; + run = 1; + + LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + + LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW); + LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); + LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); + LL_SPI_Enable(SPI1); + + delay(10); + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(10); + // LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(10); + // ams_write_command(0xC2); // Set to default state + // ams_write_command(0xC4); // Clear buffer + + int x; + for (x = 0 ; x < 10; x++) + { + flush_rx(); + + + memset(regs,0,sizeof(regs)); + read_reg_block(regs,sizeof(regs)); + printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); + + } + + // + // LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + // + // memset(regs,0,sizeof(regs)); + // for (x = 0 ; x < sizeof(regs); x++) + // { + // regs[x] = ams_read_reg(x); + // } + // printf1(TAG_NFC,"regs2: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); + } } static int handle_packets() diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index aa66189..bb65b32 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -85,14 +85,14 @@ void hw_init(void) MX_TIM2_Init(); // PWM for LEDs MX_TIM6_Init(); // ~1 ms timer - MX_SPI1_Init(); + #if DEBUG_LEVEL > 0 MX_USART1_UART_Init();// debug uart #endif MX_RNG_Init(); - + MX_SPI1_Init(); TIM6->SR = 0; __enable_irq(); NVIC_EnableIRQ(TIM6_IRQn); @@ -145,8 +145,15 @@ void SystemClock_Config(void) { } - LL_RCC_MSI_Enable(); + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); /* Wait till MSI is ready */ while(LL_RCC_MSI_IsReady() != 1) { @@ -424,41 +431,42 @@ static void MX_RNG_Init(void) static void MX_SPI1_Init(void) { - LL_SPI_InitTypeDef SPI_InitStruct; + LL_SPI_InitTypeDef SPI_InitStruct; - LL_GPIO_InitTypeDef GPIO_InitStruct; + LL_GPIO_InitTypeDef GPIO_InitStruct; - /* Peripheral clock enable */ - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); + /* Peripheral clock enable */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); - /**SPI1 GPIO Configuration - PA5 ------> SPI1_SCK - PA6 ------> SPI1_MISO - PA7 ------> SPI1_MOSI - */ - GPIO_InitStruct.Pin = LL_GPIO_PIN_5|LL_GPIO_PIN_6|LL_GPIO_PIN_7; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_5; - LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + /**SPI1 GPIO Configuration + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_5|LL_GPIO_PIN_6|LL_GPIO_PIN_7; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_5; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /* SPI1 parameter configuration*/ - SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; - SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; - SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; - SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; - SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE; - SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; - SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; - SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; - SPI_InitStruct.CRCPoly = 7; - LL_SPI_Init(SPI1, &SPI_InitStruct); + /* SPI1 parameter configuration*/ + SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; + SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; + SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; + SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; + SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; + SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; + SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct.CRCPoly = 7; + LL_SPI_Init(SPI1, &SPI_InitStruct); - LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA); + LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA); + + // LL_SPI_EnableNSSPulseMgt(SPI1); - LL_SPI_EnableNSSPulseMgt(SPI1); } From eda26e3c935a3bb12943b42991b36dc4369e4b44 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 18:17:33 -0500 Subject: [PATCH 03/96] add ST spi LL driver --- targets/stm32l442/lib/stm32l4xx_ll_spi.c | 307 +++++ targets/stm32l442/lib/stm32l4xx_ll_spi.h | 1436 ++++++++++++++++++++++ 2 files changed, 1743 insertions(+) create mode 100644 targets/stm32l442/lib/stm32l4xx_ll_spi.c create mode 100644 targets/stm32l442/lib/stm32l4xx_ll_spi.h diff --git a/targets/stm32l442/lib/stm32l4xx_ll_spi.c b/targets/stm32l442/lib/stm32l4xx_ll_spi.c new file mode 100644 index 0000000..99e28de --- /dev/null +++ b/targets/stm32l442/lib/stm32l4xx_ll_spi.c @@ -0,0 +1,307 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_spi.c + * @author MCD Application Team + * @brief SPI LL module driver. + ****************************************************************************** + * @attention + * + *

© 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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_ll_spi.h" +#include "stm32l4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @addtogroup SPI_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SPI_LL_Private_Constants SPI Private Constants + * @{ + */ +/* SPI registers Masks */ +#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \ + SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \ + SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_CRCL | \ + SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \ + SPI_CR1_BIDIMODE) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Private_Macros SPI Private Macros + * @{ + */ +#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \ + || ((__VALUE__) == LL_SPI_SIMPLEX_RX) \ + || ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \ + || ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX)) + +#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \ + || ((__VALUE__) == LL_SPI_MODE_SLAVE)) + +#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT)) + +#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \ + || ((__VALUE__) == LL_SPI_POLARITY_HIGH)) + +#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \ + || ((__VALUE__) == LL_SPI_PHASE_2EDGE)) + +#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \ + || ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \ + || ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT)) + +#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256)) + +#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \ + || ((__VALUE__) == LL_SPI_MSB_FIRST)) + +#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \ + || ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE)) + +#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SPI_LL_Exported_Functions + * @{ + */ + +/** @addtogroup SPI_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the SPI registers to their default reset values. + * @param SPIx SPI Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: SPI registers are de-initialized + * - ERROR: SPI registers are not de-initialized + */ +ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx) +{ + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_SPI_ALL_INSTANCE(SPIx)); + +#if defined(SPI1) + if (SPIx == SPI1) + { + /* Force reset of SPI clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); + + /* Release reset of SPI clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); + + status = SUCCESS; + } +#endif /* SPI1 */ +#if defined(SPI2) + if (SPIx == SPI2) + { + /* Force reset of SPI clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); + + /* Release reset of SPI clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); + + status = SUCCESS; + } +#endif /* SPI2 */ +#if defined(SPI3) + if (SPIx == SPI3) + { + /* Force reset of SPI clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3); + + /* Release reset of SPI clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3); + + status = SUCCESS; + } +#endif /* SPI3 */ + + return status; +} + +/** + * @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct. + * @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0), + * SPI IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. + * @param SPIx SPI Instance + * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure + * @retval An ErrorStatus enumeration value. (Return always SUCCESS) + */ +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct) +{ + ErrorStatus status = ERROR; + + /* Check the SPI Instance SPIx*/ + assert_param(IS_SPI_ALL_INSTANCE(SPIx)); + + /* Check the SPI parameters from SPI_InitStruct*/ + assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection)); + assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode)); + assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth)); + assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity)); + assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase)); + assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS)); + assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate)); + assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder)); + assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation)); + + if (LL_SPI_IsEnabled(SPIx) == 0x00000000U) + { + /*---------------------------- SPIx CR1 Configuration ------------------------ + * Configure SPIx CR1 with parameters: + * - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits + * - Master/Slave Mode: SPI_CR1_MSTR bit + * - ClockPolarity: SPI_CR1_CPOL bit + * - ClockPhase: SPI_CR1_CPHA bit + * - NSS management: SPI_CR1_SSM bit + * - BaudRate prescaler: SPI_CR1_BR[2:0] bits + * - BitOrder: SPI_CR1_LSBFIRST bit + * - CRCCalculation: SPI_CR1_CRCEN bit + */ + MODIFY_REG(SPIx->CR1, + SPI_CR1_CLEAR_MASK, + SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode | + SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase | + SPI_InitStruct->NSS | SPI_InitStruct->BaudRate | + SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation); + + /*---------------------------- SPIx CR2 Configuration ------------------------ + * Configure SPIx CR2 with parameters: + * - DataWidth: DS[3:0] bits + * - NSS management: SSOE bit + */ + MODIFY_REG(SPIx->CR2, + SPI_CR2_DS | SPI_CR2_SSOE, + SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U)); + + /*---------------------------- SPIx CRCPR Configuration ---------------------- + * Configure SPIx CRCPR with parameters: + * - CRCPoly: CRCPOLY[15:0] bits + */ + if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE) + { + assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly)); + LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly); + } + status = SUCCESS; + } + + return status; +} + +/** + * @brief Set each @ref LL_SPI_InitTypeDef field to default value. + * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct) +{ + /* Set SPI_InitStruct fields to default values */ + SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE; + SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT; + SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW; + SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE; + SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT; + SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST; + SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct->CRCPoly = 7U; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l442/lib/stm32l4xx_ll_spi.h b/targets/stm32l442/lib/stm32l4xx_ll_spi.h new file mode 100644 index 0000000..b5bc17a --- /dev/null +++ b/targets/stm32l442/lib/stm32l4xx_ll_spi.h @@ -0,0 +1,1436 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_spi.h + * @author MCD Application Team + * @brief Header file of SPI LL module. + ****************************************************************************** + * @attention + * + *

© 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32L4xx_LL_SPI_H +#define STM32L4xx_LL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @defgroup SPI_LL SPI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_ES_INIT SPI Exported Init structure + * @{ + */ + +/** + * @brief SPI Init structures definition + */ +typedef struct +{ + uint32_t TransferDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferDirection().*/ + + uint32_t Mode; /*!< Specifies the SPI mode (Master/Slave). + This parameter can be a value of @ref SPI_LL_EC_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetMode().*/ + + uint32_t DataWidth; /*!< Specifies the SPI data width. + This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetDataWidth().*/ + + uint32_t ClockPolarity; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_LL_EC_POLARITY. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPolarity().*/ + + uint32_t ClockPhase; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_LL_EC_PHASE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPhase().*/ + + uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_LL_EC_NSS_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetNSSMode().*/ + + uint32_t BaudRate; /*!< Specifies the BaudRate prescaler value which will be used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER. + @note The communication clock is derived from the master clock. The slave clock does not need to be set. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetBaudRatePrescaler().*/ + + uint32_t BitOrder; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferBitOrder().*/ + + uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. + This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION. + + This feature can be modified afterwards using unitary functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/ + + uint32_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetCRCPolynomial().*/ + +} LL_SPI_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Constants SPI Exported Constants + * @{ + */ + +/** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_SPI_ReadReg function + * @{ + */ +#define LL_SPI_SR_RXNE SPI_SR_RXNE /*!< Rx buffer not empty flag */ +#define LL_SPI_SR_TXE SPI_SR_TXE /*!< Tx buffer empty flag */ +#define LL_SPI_SR_BSY SPI_SR_BSY /*!< Busy flag */ +#define LL_SPI_SR_CRCERR SPI_SR_CRCERR /*!< CRC error flag */ +#define LL_SPI_SR_MODF SPI_SR_MODF /*!< Mode fault flag */ +#define LL_SPI_SR_OVR SPI_SR_OVR /*!< Overrun flag */ +#define LL_SPI_SR_FRE SPI_SR_FRE /*!< TI mode frame format error flag */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions + * @{ + */ +#define LL_SPI_CR2_RXNEIE SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ +#define LL_SPI_CR2_TXEIE SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ +#define LL_SPI_CR2_ERRIE SPI_CR2_ERRIE /*!< Error interrupt enable */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_MODE Operation Mode + * @{ + */ +#define LL_SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /*!< Master configuration */ +#define LL_SPI_MODE_SLAVE 0x00000000U /*!< Slave configuration */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_PROTOCOL Serial Protocol + * @{ + */ +#define LL_SPI_PROTOCOL_MOTOROLA 0x00000000U /*!< Motorola mode. Used as default value */ +#define LL_SPI_PROTOCOL_TI (SPI_CR2_FRF) /*!< TI mode */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_SPI_PHASE_1EDGE 0x00000000U /*!< First clock transition is the first data capture edge */ +#define LL_SPI_PHASE_2EDGE (SPI_CR1_CPHA) /*!< Second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_SPI_POLARITY_LOW 0x00000000U /*!< Clock to 0 when idle */ +#define LL_SPI_POLARITY_HIGH (SPI_CR1_CPOL) /*!< Clock to 1 when idle */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler + * @{ + */ +#define LL_SPI_BAUDRATEPRESCALER_DIV2 0x00000000U /*!< BaudRate control equal to fPCLK/2 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV4 (SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/4 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV8 (SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/8 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/16 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV32 (SPI_CR1_BR_2) /*!< BaudRate control equal to fPCLK/32 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/64 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/128 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/256 */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order + * @{ + */ +#define LL_SPI_LSB_FIRST (SPI_CR1_LSBFIRST) /*!< Data is transmitted/received with the LSB first */ +#define LL_SPI_MSB_FIRST 0x00000000U /*!< Data is transmitted/received with the MSB first */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode + * @{ + */ +#define LL_SPI_FULL_DUPLEX 0x00000000U /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */ +#define LL_SPI_SIMPLEX_RX (SPI_CR1_RXONLY) /*!< Simplex Rx mode. Rx transfer only on 1 line */ +#define LL_SPI_HALF_DUPLEX_RX (SPI_CR1_BIDIMODE) /*!< Half-Duplex Rx mode. Rx transfer on 1 line */ +#define LL_SPI_HALF_DUPLEX_TX (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE) /*!< Half-Duplex Tx mode. Tx transfer on 1 line */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode + * @{ + */ +#define LL_SPI_NSS_SOFT (SPI_CR1_SSM) /*!< NSS managed internally. NSS pin not used and free */ +#define LL_SPI_NSS_HARD_INPUT 0x00000000U /*!< NSS pin used in Input. Only used in Master mode */ +#define LL_SPI_NSS_HARD_OUTPUT (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DATAWIDTH Datawidth + * @{ + */ +#define LL_SPI_DATAWIDTH_4BIT (SPI_CR2_DS_0 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 4 bits */ +#define LL_SPI_DATAWIDTH_5BIT (SPI_CR2_DS_2) /*!< Data length for SPI transfer: 5 bits */ +#define LL_SPI_DATAWIDTH_6BIT (SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 6 bits */ +#define LL_SPI_DATAWIDTH_7BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 7 bits */ +#define LL_SPI_DATAWIDTH_8BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 8 bits */ +#define LL_SPI_DATAWIDTH_9BIT (SPI_CR2_DS_3) /*!< Data length for SPI transfer: 9 bits */ +#define LL_SPI_DATAWIDTH_10BIT (SPI_CR2_DS_3 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 10 bits */ +#define LL_SPI_DATAWIDTH_11BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 11 bits */ +#define LL_SPI_DATAWIDTH_12BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 12 bits */ +#define LL_SPI_DATAWIDTH_13BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2) /*!< Data length for SPI transfer: 13 bits */ +#define LL_SPI_DATAWIDTH_14BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 14 bits */ +#define LL_SPI_DATAWIDTH_15BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 15 bits */ +#define LL_SPI_DATAWIDTH_16BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 16 bits */ +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation + * @{ + */ +#define LL_SPI_CRCCALCULATION_DISABLE 0x00000000U /*!< CRC calculation disabled */ +#define LL_SPI_CRCCALCULATION_ENABLE (SPI_CR1_CRCEN) /*!< CRC calculation enabled */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup SPI_LL_EC_CRC_LENGTH CRC Length + * @{ + */ +#define LL_SPI_CRC_8BIT 0x00000000U /*!< 8-bit CRC length */ +#define LL_SPI_CRC_16BIT (SPI_CR1_CRCL) /*!< 16-bit CRC length */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_RX_FIFO_TH RX FIFO Threshold + * @{ + */ +#define LL_SPI_RX_FIFO_TH_HALF 0x00000000U /*!< RXNE event is generated if FIFO level is greater than or equel to 1/2 (16-bit) */ +#define LL_SPI_RX_FIFO_TH_QUARTER (SPI_CR2_FRXTH) /*!< RXNE event is generated if FIFO level is greater than or equel to 1/4 (8-bit) */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_RX_FIFO RX FIFO Level + * @{ + */ +#define LL_SPI_RX_FIFO_EMPTY 0x00000000U /*!< FIFO reception empty */ +#define LL_SPI_RX_FIFO_QUARTER_FULL (SPI_SR_FRLVL_0) /*!< FIFO reception 1/4 */ +#define LL_SPI_RX_FIFO_HALF_FULL (SPI_SR_FRLVL_1) /*!< FIFO reception 1/2 */ +#define LL_SPI_RX_FIFO_FULL (SPI_SR_FRLVL_1 | SPI_SR_FRLVL_0) /*!< FIFO reception full */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TX_FIFO TX FIFO Level + * @{ + */ +#define LL_SPI_TX_FIFO_EMPTY 0x00000000U /*!< FIFO transmission empty */ +#define LL_SPI_TX_FIFO_QUARTER_FULL (SPI_SR_FTLVL_0) /*!< FIFO transmission 1/4 */ +#define LL_SPI_TX_FIFO_HALF_FULL (SPI_SR_FTLVL_1) /*!< FIFO transmission 1/2 */ +#define LL_SPI_TX_FIFO_FULL (SPI_SR_FTLVL_1 | SPI_SR_FTLVL_0) /*!< FIFO transmission full */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DMA_PARITY DMA Parity + * @{ + */ +#define LL_SPI_DMA_PARITY_EVEN 0x00000000U /*!< Select DMA parity Even */ +#define LL_SPI_DMA_PARITY_ODD 0x00000001U /*!< Select DMA parity Odd */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Macros SPI Exported Macros + * @{ + */ + +/** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Functions SPI Exported Functions + * @{ + */ + +/** @defgroup SPI_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable SPI peripheral + * @rmtoll CR1 SPE LL_SPI_Enable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Disable SPI peripheral + * @note When disabling the SPI, follow the procedure described in the Reference Manual. + * @rmtoll CR1 SPE LL_SPI_Disable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Check if SPI peripheral is enabled + * @rmtoll CR1 SPE LL_SPI_IsEnabled + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabled(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL); +} + +/** + * @brief Set SPI operation mode to Master or Slave + * @note This bit should not be changed when communication is ongoing. + * @rmtoll CR1 MSTR LL_SPI_SetMode\n + * CR1 SSI LL_SPI_SetMode + * @param SPIx SPI Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode); +} + +/** + * @brief Get SPI operation mode (Master or Slave) + * @rmtoll CR1 MSTR LL_SPI_GetMode\n + * CR1 SSI LL_SPI_GetMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + */ +__STATIC_INLINE uint32_t LL_SPI_GetMode(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI)); +} + +/** + * @brief Set serial protocol used + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR2 FRF LL_SPI_SetStandard + * @param SPIx SPI Instance + * @param Standard This parameter can be one of the following values: + * @arg @ref LL_SPI_PROTOCOL_MOTOROLA + * @arg @ref LL_SPI_PROTOCOL_TI + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_FRF, Standard); +} + +/** + * @brief Get serial protocol used + * @rmtoll CR2 FRF LL_SPI_GetStandard + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PROTOCOL_MOTOROLA + * @arg @ref LL_SPI_PROTOCOL_TI + */ +__STATIC_INLINE uint32_t LL_SPI_GetStandard(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRF)); +} + +/** + * @brief Set clock phase + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPHA LL_SPI_SetClockPhase + * @param SPIx SPI Instance + * @param ClockPhase This parameter can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase); +} + +/** + * @brief Get clock phase + * @rmtoll CR1 CPHA LL_SPI_GetClockPhase + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPhase(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA)); +} + +/** + * @brief Set clock polarity + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPOL LL_SPI_SetClockPolarity + * @param SPIx SPI Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity); +} + +/** + * @brief Get clock polarity + * @rmtoll CR1 CPOL LL_SPI_GetClockPolarity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL)); +} + +/** + * @brief Set baud rate prescaler + * @note These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler. + * @rmtoll CR1 BR LL_SPI_SetBaudRatePrescaler + * @param SPIx SPI Instance + * @param BaudRate This parameter can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate); +} + +/** + * @brief Get baud rate prescaler + * @rmtoll CR1 BR LL_SPI_GetBaudRatePrescaler + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + */ +__STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR)); +} + +/** + * @brief Set transfer bit order + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR1 LSBFIRST LL_SPI_SetTransferBitOrder + * @param SPIx SPI Instance + * @param BitOrder This parameter can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder); +} + +/** + * @brief Get transfer bit order + * @rmtoll CR1 LSBFIRST LL_SPI_GetTransferBitOrder + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST)); +} + +/** + * @brief Set transfer direction mode + * @note For Half-Duplex mode, Rx Direction is set by default. + * In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex. + * @rmtoll CR1 RXONLY LL_SPI_SetTransferDirection\n + * CR1 BIDIMODE LL_SPI_SetTransferDirection\n + * CR1 BIDIOE LL_SPI_SetTransferDirection + * @param SPIx SPI Instance + * @param TransferDirection This parameter can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection); +} + +/** + * @brief Get transfer direction mode + * @rmtoll CR1 RXONLY LL_SPI_GetTransferDirection\n + * CR1 BIDIMODE LL_SPI_GetTransferDirection\n + * CR1 BIDIOE LL_SPI_GetTransferDirection + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)); +} + +/** + * @brief Set frame data width + * @rmtoll CR2 DS LL_SPI_SetDataWidth + * @param SPIx SPI Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_4BIT + * @arg @ref LL_SPI_DATAWIDTH_5BIT + * @arg @ref LL_SPI_DATAWIDTH_6BIT + * @arg @ref LL_SPI_DATAWIDTH_7BIT + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_9BIT + * @arg @ref LL_SPI_DATAWIDTH_10BIT + * @arg @ref LL_SPI_DATAWIDTH_11BIT + * @arg @ref LL_SPI_DATAWIDTH_12BIT + * @arg @ref LL_SPI_DATAWIDTH_13BIT + * @arg @ref LL_SPI_DATAWIDTH_14BIT + * @arg @ref LL_SPI_DATAWIDTH_15BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_DS, DataWidth); +} + +/** + * @brief Get frame data width + * @rmtoll CR2 DS LL_SPI_GetDataWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_4BIT + * @arg @ref LL_SPI_DATAWIDTH_5BIT + * @arg @ref LL_SPI_DATAWIDTH_6BIT + * @arg @ref LL_SPI_DATAWIDTH_7BIT + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_9BIT + * @arg @ref LL_SPI_DATAWIDTH_10BIT + * @arg @ref LL_SPI_DATAWIDTH_11BIT + * @arg @ref LL_SPI_DATAWIDTH_12BIT + * @arg @ref LL_SPI_DATAWIDTH_13BIT + * @arg @ref LL_SPI_DATAWIDTH_14BIT + * @arg @ref LL_SPI_DATAWIDTH_15BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_DS)); +} + +/** + * @brief Set threshold of RXFIFO that triggers an RXNE event + * @rmtoll CR2 FRXTH LL_SPI_SetRxFIFOThreshold + * @param SPIx SPI Instance + * @param Threshold This parameter can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_TH_HALF + * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetRxFIFOThreshold(SPI_TypeDef *SPIx, uint32_t Threshold) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_FRXTH, Threshold); +} + +/** + * @brief Get threshold of RXFIFO that triggers an RXNE event + * @rmtoll CR2 FRXTH LL_SPI_GetRxFIFOThreshold + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_TH_HALF + * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOThreshold(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRXTH)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_CRC_Management CRC Management + * @{ + */ + +/** + * @brief Enable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_EnableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Disable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_DisableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Check if CRC is enabled + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_IsEnabledCRC + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL); +} + +/** + * @brief Set CRC Length + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCL LL_SPI_SetCRCWidth + * @param SPIx SPI Instance + * @param CRCLength This parameter can be one of the following values: + * @arg @ref LL_SPI_CRC_8BIT + * @arg @ref LL_SPI_CRC_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCWidth(SPI_TypeDef *SPIx, uint32_t CRCLength) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CRCL, CRCLength); +} + +/** + * @brief Get CRC Length + * @rmtoll CR1 CRCL LL_SPI_GetCRCWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_CRC_8BIT + * @arg @ref LL_SPI_CRC_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CRCL)); +} + +/** + * @brief Set CRCNext to transfer CRC on the line + * @note This bit has to be written as soon as the last data is written in the SPIx_DR register. + * @rmtoll CR1 CRCNEXT LL_SPI_SetCRCNext + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT); +} + +/** + * @brief Set polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_SetCRCPolynomial + * @param SPIx SPI Instance + * @param CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly) +{ + WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly); +} + +/** + * @brief Get polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_GetCRCPolynomial + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->CRCPR)); +} + +/** + * @brief Get Rx CRC + * @rmtoll RXCRCR RXCRC LL_SPI_GetRxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxCRC(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->RXCRCR)); +} + +/** + * @brief Get Tx CRC + * @rmtoll TXCRCR TXCRC LL_SPI_GetTxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxCRC(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->TXCRCR)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management + * @{ + */ + +/** + * @brief Set NSS mode + * @note LL_SPI_NSS_SOFT Mode is not used in SPI TI mode. + * @rmtoll CR1 SSM LL_SPI_SetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_SetNSSMode + * @param SPIx SPI Instance + * @param NSS This parameter can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_SSM, NSS); + MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U))); +} + +/** + * @brief Get NSS mode + * @rmtoll CR1 SSM LL_SPI_GetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_GetNSSMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + */ +__STATIC_INLINE uint32_t LL_SPI_GetNSSMode(SPI_TypeDef *SPIx) +{ + register uint32_t Ssm = (READ_BIT(SPIx->CR1, SPI_CR1_SSM)); + register uint32_t Ssoe = (READ_BIT(SPIx->CR2, SPI_CR2_SSOE) << 16U); + return (Ssm | Ssoe); +} + +/** + * @brief Enable NSS pulse management + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_EnableNSSPulseMgt + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableNSSPulseMgt(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_NSSP); +} + +/** + * @brief Disable NSS pulse management + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_DisableNSSPulseMgt + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableNSSPulseMgt(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_NSSP); +} + +/** + * @brief Check if NSS pulse is enabled + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_IsEnabledNSSPulse + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledNSSPulse(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_NSSP) == (SPI_CR2_NSSP)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_FLAG_Management FLAG Management + * @{ + */ + +/** + * @brief Check if Rx buffer is not empty + * @rmtoll SR RXNE LL_SPI_IsActiveFlag_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer is empty + * @rmtoll SR TXE LL_SPI_IsActiveFlag_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL); +} + +/** + * @brief Get CRC error flag + * @rmtoll SR CRCERR LL_SPI_IsActiveFlag_CRCERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL); +} + +/** + * @brief Get mode fault error flag + * @rmtoll SR MODF LL_SPI_IsActiveFlag_MODF + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL); +} + +/** + * @brief Get overrun error flag + * @rmtoll SR OVR LL_SPI_IsActiveFlag_OVR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Get busy flag + * @note The BSY flag is cleared under any one of the following conditions: + * -When the SPI is correctly disabled + * -When a fault is detected in Master mode (MODF bit set to 1) + * -In Master mode, when it finishes a data transmission and no new data is ready to be + * sent + * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between + * each data transfer. + * @rmtoll SR BSY LL_SPI_IsActiveFlag_BSY + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL); +} + +/** + * @brief Get frame format error flag + * @rmtoll SR FRE LL_SPI_IsActiveFlag_FRE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_FRE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_FRE) == (SPI_SR_FRE)) ? 1UL : 0UL); +} + +/** + * @brief Get FIFO reception Level + * @rmtoll SR FRLVL LL_SPI_GetRxFIFOLevel + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_EMPTY + * @arg @ref LL_SPI_RX_FIFO_QUARTER_FULL + * @arg @ref LL_SPI_RX_FIFO_HALF_FULL + * @arg @ref LL_SPI_RX_FIFO_FULL + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOLevel(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FRLVL)); +} + +/** + * @brief Get FIFO Transmission Level + * @rmtoll SR FTLVL LL_SPI_GetTxFIFOLevel + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_TX_FIFO_EMPTY + * @arg @ref LL_SPI_TX_FIFO_QUARTER_FULL + * @arg @ref LL_SPI_TX_FIFO_HALF_FULL + * @arg @ref LL_SPI_TX_FIFO_FULL + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxFIFOLevel(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FTLVL)); +} + +/** + * @brief Clear CRC error flag + * @rmtoll SR CRCERR LL_SPI_ClearFlag_CRCERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR); +} + +/** + * @brief Clear mode fault error flag + * @note Clearing this flag is done by a read access to the SPIx_SR + * register followed by a write access to the SPIx_CR1 register + * @rmtoll SR MODF LL_SPI_ClearFlag_MODF + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg_sr; + tmpreg_sr = SPIx->SR; + (void) tmpreg_sr; + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Clear overrun error flag + * @note Clearing this flag is done by a read access to the SPIx_DR + * register followed by a read access to the SPIx_SR register + * @rmtoll SR OVR LL_SPI_ClearFlag_OVR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->DR; + (void) tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @brief Clear frame format error flag + * @note Clearing this flag is done by reading SPIx_SR register + * @rmtoll SR FRE LL_SPI_ClearFlag_FRE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_IT_Management Interrupt Management + * @{ + */ + +/** + * @brief Enable error interrupt + * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_EnableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Enable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_EnableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Enable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_EnableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Disable error interrupt + * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_DisableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Disable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_DisableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Disable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_DisableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Check if error interrupt is enabled + * @rmtoll CR2 ERRIE LL_SPI_IsEnabledIT_ERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Rx buffer not empty interrupt is enabled + * @rmtoll CR2 RXNEIE LL_SPI_IsEnabledIT_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_IsEnabledIT_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DMA_Management DMA Management + * @{ + */ + +/** + * @brief Enable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_EnableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Disable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_DisableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Check if DMA Rx is enabled + * @rmtoll CR2 RXDMAEN LL_SPI_IsEnabledDMAReq_RX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_EnableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Disable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_DisableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Check if DMA Tx is enabled + * @rmtoll CR2 TXDMAEN LL_SPI_IsEnabledDMAReq_TX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Set parity of Last DMA reception + * @rmtoll CR2 LDMARX LL_SPI_SetDMAParity_RX + * @param SPIx SPI Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDMAParity_RX(SPI_TypeDef *SPIx, uint32_t Parity) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_LDMARX, (Parity << SPI_CR2_LDMARX_Pos)); +} + +/** + * @brief Get parity configuration for Last DMA reception + * @rmtoll CR2 LDMARX LL_SPI_GetDMAParity_RX + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + */ +__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_RX(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMARX) >> SPI_CR2_LDMARX_Pos); +} + +/** + * @brief Set parity of Last DMA transmission + * @rmtoll CR2 LDMATX LL_SPI_SetDMAParity_TX + * @param SPIx SPI Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDMAParity_TX(SPI_TypeDef *SPIx, uint32_t Parity) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_LDMATX, (Parity << SPI_CR2_LDMATX_Pos)); +} + +/** + * @brief Get parity configuration for Last DMA transmission + * @rmtoll CR2 LDMATX LL_SPI_GetDMAParity_TX + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + */ +__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_TX(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMATX) >> SPI_CR2_LDMATX_Pos); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll DR DR LL_SPI_DMA_GetRegAddr + * @param SPIx SPI Instance + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(SPI_TypeDef *SPIx) +{ + return (uint32_t) & (SPIx->DR); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DATA_Management DATA Management + * @{ + */ + +/** + * @brief Read 8-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData8 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx) +{ + return (uint8_t)(READ_REG(SPIx->DR)); +} + +/** + * @brief Read 16-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData16 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx) +{ + return (uint16_t)(READ_REG(SPIx->DR)); +} + +/** + * @brief Write 8-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData8 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData) +{ +#if defined (__GNUC__) + __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR); + *spidr = TxData; +#else + *((__IO uint8_t *)&SPIx->DR) = TxData; +#endif +} + +/** + * @brief Write 16-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData16 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) +{ +#if defined (__GNUC__) + __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR); + *spidr = TxData; +#else + SPIx->DR = TxData; +#endif +} + +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx); +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct); +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_SPI_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From c330346c314e21ab2d7bc4b279fd13b5091f15d4 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 18:29:38 -0500 Subject: [PATCH 04/96] add nfc log tag --- fido2/log.c | 13 +++++++------ fido2/log.h | 11 ++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/fido2/log.c b/fido2/log.c index be7a7af..6161191 100644 --- a/fido2/log.c +++ b/fido2/log.c @@ -1,21 +1,21 @@ /* * Copyright (C) 2018 SoloKeys, Inc. - * + * * This file is part of Solo. - * + * * Solo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * Solo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Solo. If not, see - * + * * This code is available under licenses for commercial use. * Please contact SoloKeys for more information. */ @@ -61,7 +61,8 @@ struct logtag tagtable[] = { {TAG_WALLET,"WALLET"}, {TAG_STOR,"STOR"}, {TAG_BOOT,"BOOT"}, - {TAG_BOOT,"EXT"}, + {TAG_EXT,"EXT"}, + {TAG_NFC,"NFC"}, }; diff --git a/fido2/log.h b/fido2/log.h index 8eba24d..1ef8850 100644 --- a/fido2/log.h +++ b/fido2/log.h @@ -1,21 +1,21 @@ /* * Copyright (C) 2018 SoloKeys, Inc. - * + * * This file is part of Solo. - * + * * Solo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * Solo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Solo. If not, see - * + * * This code is available under licenses for commercial use. * Please contact SoloKeys for more information. */ @@ -57,6 +57,7 @@ typedef enum TAG_DUMP2 = (1 << 16), TAG_BOOT = (1 << 17), TAG_EXT = (1 << 17), + TAG_NFC = (1 << 18), TAG_FILENO = (1<<31) } LOG_TAG; From 6ffba7d472e96351c13cd83db79f7b03a4e3be9c Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 18:50:01 -0500 Subject: [PATCH 05/96] move to new file --- targets/stm32l432/application.mk | 2 +- targets/stm32l432/src/device.c | 185 +----------------------------- targets/stm32l432/src/nfc.c | 188 +++++++++++++++++++++++++++++++ targets/stm32l432/src/nfc.h | 7 ++ 4 files changed, 200 insertions(+), 182 deletions(-) create mode 100644 targets/stm32l432/src/nfc.c create mode 100644 targets/stm32l432/src/nfc.h diff --git a/targets/stm32l432/application.mk b/targets/stm32l432/application.mk index 89ece0d..70bbc3f 100644 --- a/targets/stm32l432/application.mk +++ b/targets/stm32l432/application.mk @@ -5,7 +5,7 @@ AR=$(PREFIX)arm-none-eabi-ar # ST related SRC = src/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c -SRC += src/fifo.c src/crypto.c src/attestation.c +SRC += src/fifo.c src/crypto.c src/attestation.c src/nfc.c SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 60e0b76..bff18b7 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -25,7 +25,7 @@ #include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_tim.h" #include "stm32l4xx_ll_usart.h" -#include "stm32l4xx_ll_spi.h" + #include "usbd_hid.h" #include APP_CONFIG @@ -42,6 +42,7 @@ #include "memory_layout.h" #include "stm32l4xx_ll_iwdg.h" #include "usbd_cdc_if.h" +#include "nfc.h" uint32_t __90_ms = 0; uint32_t __device_status = 0; @@ -107,6 +108,7 @@ void device_reboot() void device_init() { hw_init(); + nfc_init(); LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); @@ -370,140 +372,6 @@ uint32_t ctap_atomic_count(int sel) return lastc; } -static void flush_rx() -{ - while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0) - { - LL_SPI_ReceiveData8(SPI1); - } -} -static void wait_for_tx() -{ - // while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) - // ; - while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY) - ; -} -static void wait_for_rx() -{ - while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0) - ; -} - -void ams_write_reg(uint8_t addr, uint8_t tx) -{ - LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - delay(1); - LL_SPI_TransmitData8(SPI1,0x00| addr); - LL_SPI_ReceiveData8(SPI1); - while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) - ; - LL_SPI_TransmitData8(SPI1,tx); - while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) - ; - LL_SPI_ReceiveData8(SPI1); - - LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - // delay(1); - LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - -} - -uint8_t send_recv(uint8_t b) -{ - wait_for_tx(); - LL_SPI_TransmitData8(SPI1, b); - wait_for_rx(); - b = LL_SPI_ReceiveData8(SPI1); - return b; -} - -uint8_t send_recv2(uint8_t b1,uint8_t b2) -{ - wait_for_tx(); - LL_SPI_TransmitData8(SPI1, b1); - LL_SPI_TransmitData8(SPI1, b2); - wait_for_tx(); - LL_SPI_ReceiveData8(SPI1); - uint8_t b = LL_SPI_ReceiveData8(SPI1); - return b; -} -#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) -#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) -uint8_t ams_read_reg(uint8_t addr) -{ - delay(2); - flush_rx(); - LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - delay(2); - - uint8_t data = send_recv2(0x20| (addr & 0x1f), 0); - // send_recv(0x20| addr); - // - // uint8_t data = send_recv(0); - - delay(2); - LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - delay(2); - return data; -} - -// data must be 14 bytes long -void read_reg_block2(uint8_t * data) -{ - int i; - - for (i = 0; i < 0x20; i++) - { - if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) - { - *data = ams_read_reg(i); - data++; - } - } - -} - - -// data must be 14 bytes long -void read_reg_block(uint8_t * data, int count) -{ - int i; - uint8_t mode = 0x20 | (0 ); - flush_rx(); - SELECT(); - delay(2); - send_recv(mode); - for (i = 0; i < count; i++) - { - mode = send_recv(0); - // if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) - // { - *data = mode; - data++; - // } - } - - delay(2); - UNSELECT(); - // delay(2); - // SELECT(); -} - -void ams_write_command(uint8_t cmd) -{ - - uint8_t mode = cmd; - // delay(10); - - // delay(10); - SELECT(); - delay(1); - send_recv(mode); - UNSELECT(); - SELECT(); - -} @@ -527,52 +395,7 @@ void device_manage() } } #endif - - static int run = 0; - - if (!run) - { - uint8_t regs[0x20]; - run = 1; - - LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); - LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - - LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW); - LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); - LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); - LL_SPI_Enable(SPI1); - - delay(10); - LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - delay(10); - // LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - delay(10); - // ams_write_command(0xC2); // Set to default state - // ams_write_command(0xC4); // Clear buffer - - int x; - for (x = 0 ; x < 10; x++) - { - flush_rx(); - - - memset(regs,0,sizeof(regs)); - read_reg_block(regs,sizeof(regs)); - printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); - - } - - // - // LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - // - // memset(regs,0,sizeof(regs)); - // for (x = 0 ; x < sizeof(regs); x++) - // { - // regs[x] = ams_read_reg(x); - // } - // printf1(TAG_NFC,"regs2: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); - } + nfc_loop(); } static int handle_packets() diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c new file mode 100644 index 0000000..da3fe87 --- /dev/null +++ b/targets/stm32l432/src/nfc.c @@ -0,0 +1,188 @@ +#include + +#include "stm32l4xx.h" +#include "stm32l4xx_ll_gpio.h" +#include "stm32l4xx_ll_spi.h" +#include "nfc.h" +#include "log.h" +#include "util.h" + + +static void flush_rx() +{ + while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0) + { + LL_SPI_ReceiveData8(SPI1); + } +} +static void wait_for_tx() +{ + // while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) + // ; + while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY) + ; +} +static void wait_for_rx() +{ + while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0) + ; +} + + +#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) + +uint8_t send_recv(uint8_t b) +{ + wait_for_tx(); + LL_SPI_TransmitData8(SPI1, b); + wait_for_rx(); + b = LL_SPI_ReceiveData8(SPI1); + return b; +} + +uint8_t send_recv2(uint8_t b1,uint8_t b2) +{ + send_recv(b1); + return send_recv(b2); +} + +void ams_write_reg(uint8_t addr, uint8_t tx) +{ + SELECT(); + delay(2); + send_recv(0x00| addr); + send_recv(tx); + UNSELECT(); +} + + +uint8_t ams_read_reg(uint8_t addr) +{ + SELECT(); + delay(2); + + uint8_t data = send_recv2(0x20| (addr & 0x1f), 0); + // send_recv(0x20| addr); + // + // uint8_t data = send_recv(0); + + // delay(2); + UNSELECT(); + return data; +} + +// data must be 14 bytes long +void read_reg_block2(uint8_t * data) +{ + int i; + + for (i = 0; i < 0x20; i++) + { + if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) + { + *data = ams_read_reg(i); + data++; + } + } + +} + + +// data must be 14 bytes long +void read_reg_block(uint8_t * data) +{ + int i; + uint8_t mode = 0x20 | (0 ); + flush_rx(); + SELECT(); + + send_recv(mode); + for (i = 0; i < 0x20; i++) + { + mode = send_recv(0); + // if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) + // { + *data = mode; + data++; + // } + } + + + UNSELECT(); + // delay(2); + // SELECT(); +} + +void ams_write_command(uint8_t cmd) +{ + + uint8_t mode = cmd; + // delay(10); + + // delay(10); + SELECT(); + delay(1); + send_recv(mode); + UNSELECT(); + SELECT(); + +} + +void nfc_init() +{ + LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + + LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW); + LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); + LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); + LL_SPI_Enable(SPI1); +} + +void nfc_loop() +{ + + static int run = 0; + + if (!run) + { + uint8_t regs[0x20]; + run = 1; + + delay(10); + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(10); + // LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + delay(10); + // ams_write_command(0xC2); // Set to default state + // ams_write_command(0xC4); // Clear buffer + ams_write_reg(1,7); + int x; + for (x = 0 ; x < 10; x++) + { + memset(regs,0,sizeof(regs)); + ams_write_reg(1,7); + read_reg_block(regs); + printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); + + + } + printf1(TAG_NFC,"---\r\n"); + for (x = 0 ; x < 10; x++) + { + memset(regs,0,sizeof(regs)); + read_reg_block2(regs); + printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); + } + // + // LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + // + // memset(regs,0,sizeof(regs)); + // for (x = 0 ; x < sizeof(regs); x++) + // { + // regs[x] = ams_read_reg(x); + // } + // printf1(TAG_NFC,"regs2: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); + } +} diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h new file mode 100644 index 0000000..b686f81 --- /dev/null +++ b/targets/stm32l432/src/nfc.h @@ -0,0 +1,7 @@ +#ifndef _NFC_H_ +#define _NFC_H_ + +void nfc_loop(); +void nfc_init(); + +#endif From b7c0e4ea92cb37375e6eb6b7a5825f875bab0903 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 19:05:39 -0500 Subject: [PATCH 06/96] no delays --- targets/stm32l432/src/nfc.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index da3fe87..8d73a30 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -49,18 +49,20 @@ uint8_t send_recv2(uint8_t b1,uint8_t b2) void ams_write_reg(uint8_t addr, uint8_t tx) { - SELECT(); - delay(2); + // SELECT(); + // delay(2); send_recv(0x00| addr); send_recv(tx); + UNSELECT(); + SELECT(); } uint8_t ams_read_reg(uint8_t addr) { - SELECT(); - delay(2); + // SELECT(); + // delay(2); uint8_t data = send_recv2(0x20| (addr & 0x1f), 0); // send_recv(0x20| addr); @@ -68,7 +70,8 @@ uint8_t ams_read_reg(uint8_t addr) // uint8_t data = send_recv(0); // delay(2); - UNSELECT(); + UNSELECT(); + SELECT(); return data; } @@ -79,7 +82,7 @@ void read_reg_block2(uint8_t * data) for (i = 0; i < 0x20; i++) { - if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) + // if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) { *data = ams_read_reg(i); data++; @@ -95,7 +98,8 @@ void read_reg_block(uint8_t * data) int i; uint8_t mode = 0x20 | (0 ); flush_rx(); - SELECT(); + // SELECT(); + // delay(2); send_recv(mode); for (i = 0; i < 0x20; i++) @@ -108,8 +112,9 @@ void read_reg_block(uint8_t * data) // } } - - UNSELECT(); + UNSELECT(); + SELECT(); + // UNSELECT(); // delay(2); // SELECT(); } @@ -155,14 +160,16 @@ void nfc_loop() delay(10); // LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); delay(10); + SELECT(); + delay(10); // ams_write_command(0xC2); // Set to default state // ams_write_command(0xC4); // Clear buffer - ams_write_reg(1,7); + ams_write_reg(2,7); int x; for (x = 0 ; x < 10; x++) { memset(regs,0,sizeof(regs)); - ams_write_reg(1,7); + // ams_write_reg(1,7); read_reg_block(regs); printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); @@ -175,6 +182,10 @@ void nfc_loop() read_reg_block2(regs); printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); } + + printf1(TAG_NFC,"Version: %02x\r\n",ams_read_reg(0x1e)); + printf1(TAG_NFC,"Product Type: %02x\r\n",ams_read_reg(0x1c)); + // // LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); // From aa978abfc7bf44074c9605f09ab6cc2d86aac66d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 19:40:20 -0500 Subject: [PATCH 07/96] cleanup --- targets/stm32l432/src/nfc.c | 132 +++++++++++++++--------------------- targets/stm32l432/src/nfc.h | 47 +++++++++++++ 2 files changed, 100 insertions(+), 79 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 8d73a30..980367f 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -7,6 +7,9 @@ #include "log.h" #include "util.h" +#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) + static void flush_rx() { @@ -29,10 +32,29 @@ static void wait_for_rx() } -#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) -#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +static void ams_print_device(AMS_DEVICE * dev) +{ + printf1(TAG_NFC, "AMS_DEVICE:\r\n"); + printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); + printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0); + printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1); + printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2); + printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status); + printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status); + printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0); + printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1); + printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0); + printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1); + printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2); + printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1); + printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr); + printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type); + printf1(TAG_NFC, " product_subtype: %02x\r\n",dev->regs.product_subtype); + printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj); + printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min); +} -uint8_t send_recv(uint8_t b) +static uint8_t send_recv(uint8_t b) { wait_for_tx(); LL_SPI_TransmitData8(SPI1, b); @@ -41,16 +63,9 @@ uint8_t send_recv(uint8_t b) return b; } -uint8_t send_recv2(uint8_t b1,uint8_t b2) -{ - send_recv(b1); - return send_recv(b2); -} -void ams_write_reg(uint8_t addr, uint8_t tx) +static void ams_write_reg(uint8_t addr, uint8_t tx) { - // SELECT(); - // delay(2); send_recv(0x00| addr); send_recv(tx); @@ -61,77 +76,48 @@ void ams_write_reg(uint8_t addr, uint8_t tx) uint8_t ams_read_reg(uint8_t addr) { - // SELECT(); - // delay(2); - - uint8_t data = send_recv2(0x20| (addr & 0x1f), 0); - // send_recv(0x20| addr); - // - // uint8_t data = send_recv(0); - - // delay(2); + send_recv(0x20| (addr & 0x1f)); + uint8_t data = send_recv(0); UNSELECT(); SELECT(); return data; } // data must be 14 bytes long -void read_reg_block2(uint8_t * data) +void read_reg_block2(AMS_DEVICE * dev) { int i; - for (i = 0; i < 0x20; i++) + for (i = 0; i < 0x20; i++) { - // if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) - { - *data = ams_read_reg(i); - data++; - } + dev->buf[i] = ams_read_reg(i); } - } // data must be 14 bytes long -void read_reg_block(uint8_t * data) +void read_reg_block(AMS_DEVICE * dev) { int i; uint8_t mode = 0x20 | (0 ); flush_rx(); - // SELECT(); - // delay(2); send_recv(mode); for (i = 0; i < 0x20; i++) { - mode = send_recv(0); - // if (i < 6 || (i >=8 && i < 0x0f) || (i >= 0x1e)) - // { - *data = mode; - data++; - // } + dev->buf[i] = send_recv(0); } UNSELECT(); SELECT(); - // UNSELECT(); - // delay(2); - // SELECT(); + } void ams_write_command(uint8_t cmd) { - - uint8_t mode = cmd; - // delay(10); - - // delay(10); - SELECT(); - delay(1); - send_recv(mode); + send_recv(0xc0 | cmd); UNSELECT(); SELECT(); - } void nfc_init() @@ -149,51 +135,39 @@ void nfc_loop() { static int run = 0; + AMS_DEVICE ams,ams2; if (!run) { - uint8_t regs[0x20]; run = 1; - delay(10); - LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - delay(10); - // LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); delay(10); SELECT(); delay(10); - // ams_write_command(0xC2); // Set to default state - // ams_write_command(0xC4); // Clear buffer - ams_write_reg(2,7); + + ams_write_command(AMS_CMD_DEFAULT); + ams_write_command(AMS_CMD_CLEAR_BUFFER); + + ams_write_reg(AMS_REG_IC_CONF1,7); + int x; - for (x = 0 ; x < 10; x++) + for (x = 0 ; x < 2; x++) { - memset(regs,0,sizeof(regs)); - // ams_write_reg(1,7); - read_reg_block(regs); - printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); - - + read_reg_block(&ams); + printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); + ams_print_device(&ams); } + printf1(TAG_NFC,"---\r\n"); - for (x = 0 ; x < 10; x++) + for (x = 0 ; x < 2; x++) { - memset(regs,0,sizeof(regs)); - read_reg_block2(regs); - printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); + read_reg_block2(&ams2); + printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); } - printf1(TAG_NFC,"Version: %02x\r\n",ams_read_reg(0x1e)); - printf1(TAG_NFC,"Product Type: %02x\r\n",ams_read_reg(0x1c)); + printf1(TAG_NFC,"Version: %02x vs %02x\r\n",ams_read_reg(0x1e), ams.regs.version_maj); + printf1(TAG_NFC,"Product Type: %02x vs %02x\r\n",ams_read_reg(0x1c), ams.regs.product_type); + printf1(TAG_NFC,"Electrical: %02x vs %02x\r\n",ams_read_reg(2), ams.regs.ic_conf1); - // - // LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - // - // memset(regs,0,sizeof(regs)); - // for (x = 0 ; x < sizeof(regs); x++) - // { - // regs[x] = ams_read_reg(x); - // } - // printf1(TAG_NFC,"regs2: "); dump_hex1(TAG_NFC,regs,sizeof(regs)); } } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index b686f81..1d2fdbd 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -1,7 +1,54 @@ #ifndef _NFC_H_ #define _NFC_H_ +#include + void nfc_loop(); void nfc_init(); +typedef union +{ + uint8_t buf[0x20]; + struct { + uint8_t io_conf; // 0x00 + uint8_t ic_conf0; // 0x01 + uint8_t ic_conf1; // 0x02 + uint8_t ic_conf2; // 0x03 + uint8_t rfid_status; // 0x04 + uint8_t ic_status; // 0x05 + uint8_t _nc0[2]; // 0x06 - 0x07 + uint8_t mask_int0; // 0x08 + uint8_t mask_int1; // 0x09 + uint8_t int0; // 0x0a + uint8_t int1; // 0x0b + uint8_t buffer_status2; // 0x0c + uint8_t buffer_status1; // 0x0d + uint8_t last_nfc_addr; // 0x0e + uint8_t _nc1[0x1b - 0x0f + 1]; // 0x0f - 0x1b + uint8_t product_type; // 0x1c + uint8_t product_subtype; // 0x1d + uint8_t version_maj; // 0x1e + uint8_t version_min; // 0x1f + } regs; +} AMS_DEVICE; + +#define AMS_REG_IO_CONF 0x00 +#define AMS_REG_IC_CONF0 0x01 +#define AMS_REG_IC_CONF1 0x02 +#define AMS_REG_IC_CONF2 0x03 + +#define AMS_CMD_DEFAULT 0x02 +#define AMS_CMD_CLEAR_BUFFER 0x04 +#define AMS_CMD_RESTART_TRANSCEIVER 0x06 +#define AMS_CMD_DIS_EN_TRANSCEIVER 0x07 +#define AMS_CMD_TRANSMIT_BUFFER 0x08 +#define AMS_CMD_TRANSMIT_ACK 0x09 +#define AMS_CMD_TRANSMIT_NACK0 0x0A +#define AMS_CMD_TRANSMIT_NACK1 0x0B +#define AMS_CMD_TRANSMIT_NACK4 0x0D +#define AMS_CMD_TRANSMIT_NACK5 0x0C +#define AMS_CMD_SLEEP 0x10 +#define AMS_CMD_SENSE 0x11 +#define AMS_CMD_SENSE_SLEEP 0x12 + #endif From 78c40976c3921ea857a3b99478692bb9f76aaa2a Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 21:19:45 -0500 Subject: [PATCH 08/96] log interrupts and recv'd data --- fido2/log.c | 2 +- fido2/log.h | 1 + targets/stm32l432/src/nfc.c | 207 +++++++++++++++++++++++++++--------- targets/stm32l432/src/nfc.h | 40 +++++++ 4 files changed, 201 insertions(+), 49 deletions(-) diff --git a/fido2/log.c b/fido2/log.c index 6161191..01514db 100644 --- a/fido2/log.c +++ b/fido2/log.c @@ -83,7 +83,7 @@ void LOG(uint32_t tag, const char * filename, int num, const char * fmt, ...) { if (tag & tagtable[i].tagn) { - if (tagtable[i].tag[0]) printf("[%s] ", tagtable[i].tag); + if (tagtable[i].tag[0] && !(tag & TAG_NO_TAG)) printf("[%s] ", tagtable[i].tag); i = 0; break; } diff --git a/fido2/log.h b/fido2/log.h index 1ef8850..9ba145a 100644 --- a/fido2/log.h +++ b/fido2/log.h @@ -59,6 +59,7 @@ typedef enum TAG_EXT = (1 << 17), TAG_NFC = (1 << 18), + TAG_NO_TAG = (1<<30), TAG_FILENO = (1<<31) } LOG_TAG; diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 980367f..986810a 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -35,23 +35,23 @@ static void wait_for_rx() static void ams_print_device(AMS_DEVICE * dev) { printf1(TAG_NFC, "AMS_DEVICE:\r\n"); - printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); - printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0); - printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1); - printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2); - printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status); - printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status); - printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0); - printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1); - printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0); - printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1); + printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); + printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0); + printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1); + printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2); + printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status); + printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status); + printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0); + printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1); + printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0); + printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1); printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2); printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1); - printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr); - printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type); - printf1(TAG_NFC, " product_subtype: %02x\r\n",dev->regs.product_subtype); - printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj); - printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min); + printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr); + printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type); + printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype); + printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj); + printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min); } static uint8_t send_recv(uint8_t b) @@ -110,7 +110,19 @@ void read_reg_block(AMS_DEVICE * dev) UNSELECT(); SELECT(); +} +void ams_read_buffer(uint8_t * data, int len) +{ + int i; + send_recv(0xa0); + while(len--) + { + *data++ = send_recv(0x00); + } + + UNSELECT(); + SELECT(); } void ams_write_command(uint8_t cmd) @@ -120,6 +132,87 @@ void ams_write_command(uint8_t cmd) SELECT(); } +const char * ams_get_state_string(uint8_t regval) +{ + if (regval & AMS_STATE_INVALID) + { + return "STATE_INVALID"; + } + switch (regval & AMS_STATE_MASK) + { + case AMS_STATE_OFF: + return "STATE_OFF"; + case AMS_STATE_SENSE: + return "STATE_SENSE"; + case AMS_STATE_RESOLUTION: + return "STATE_RESOLUTION"; + case AMS_STATE_RESOLUTION_L2: + return "STATE_RESOLUTION_L2"; + case AMS_STATE_SELECTED: + return "STATE_SELECTED"; + case AMS_STATE_SECTOR2: + return "STATE_SECTOR2"; + case AMS_STATE_SECTORX_2: + return "STATE_SECTORX_2"; + case AMS_STATE_SELECTEDX: + return "STATE_SELECTEDX"; + case AMS_STATE_SENSEX_L2: + return "STATE_SENSEX_L2"; + case AMS_STATE_SENSEX: + return "STATE_SENSEX"; + case AMS_STATE_SLEEP: + return "STATE_SLEEP"; + } + return "STATE_WRONG"; +} + +void ams_print_int0(uint8_t int0) +{ + printf1(TAG_NFC," "); + if (int0 & AMS_INT_XRF) + printf1(TAG_NFC|TAG_NO_TAG," XRF"); + if (int0 & AMS_INT_TXE) + printf1(TAG_NFC|TAG_NO_TAG," TXE"); + if (int0 & AMS_INT_RXE) + printf1(TAG_NFC|TAG_NO_TAG," RXE"); + if (int0 & AMS_INT_EER_RF) + printf1(TAG_NFC|TAG_NO_TAG," EER_RF"); + if (int0 & AMS_INT_EEW_RF) + printf1(TAG_NFC|TAG_NO_TAG," EEW_RF"); + if (int0 & AMS_INT_SLP) + printf1(TAG_NFC|TAG_NO_TAG," SLP"); + if (int0 & AMS_INT_WU_A) + printf1(TAG_NFC|TAG_NO_TAG," WU_A"); + if (int0 & AMS_INT_INIT) + printf1(TAG_NFC|TAG_NO_TAG," INIT"); + + printf1(TAG_NFC|TAG_NO_TAG,"\r\n"); +} + +void ams_print_int1(uint8_t int0) +{ + printf1(TAG_NFC," "); + if (int0 & AMS_INT_ACC_ERR) + printf1(TAG_NFC|TAG_NO_TAG," ACC_ERR"); + if (int0 & AMS_INT_EEAC_ERR) + printf1(TAG_NFC|TAG_NO_TAG," EEAC_ERR"); + if (int0 & AMS_INT_IO_EEWR) + printf1(TAG_NFC|TAG_NO_TAG," IO_EEWR"); + if (int0 & AMS_INT_BF_ERR) + printf1(TAG_NFC|TAG_NO_TAG," BF_ERR"); + if (int0 & AMS_INT_CRC_ERR) + printf1(TAG_NFC|TAG_NO_TAG," CRC_ERR"); + if (int0 & AMS_INT_PAR_ERR) + printf1(TAG_NFC|TAG_NO_TAG," PAR_ERR"); + if (int0 & AMS_INT_FRM_ERR) + printf1(TAG_NFC|TAG_NO_TAG," FRM_ERR"); + if (int0 & AMS_INT_RXS) + printf1(TAG_NFC|TAG_NO_TAG," RXS"); + + printf1(TAG_NFC|TAG_NO_TAG,"\r\n"); +} + + void nfc_init() { LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); @@ -129,45 +222,63 @@ void nfc_init() LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); LL_SPI_Enable(SPI1); + + delay(10); + SELECT(); + delay(10); + + + ams_write_command(AMS_CMD_DEFAULT); + ams_write_command(AMS_CMD_CLEAR_BUFFER); + + // enable tunneling mode and RF configuration + ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); } void nfc_loop() { - static int run = 0; - AMS_DEVICE ams,ams2; + const uint32_t interval = 200; + static uint32_t t1 = 0; + uint8_t buf[32]; + AMS_DEVICE ams,ams2; + int len = 0; - if (!run) + if (millis() - t1 > interval) + { + t1 = millis(); + read_reg_block(&ams); + printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); + + if (ams.regs.rfid_status) { - run = 1; - - delay(10); - SELECT(); - delay(10); - - ams_write_command(AMS_CMD_DEFAULT); - ams_write_command(AMS_CMD_CLEAR_BUFFER); - - ams_write_reg(AMS_REG_IC_CONF1,7); - - int x; - for (x = 0 ; x < 2; x++) - { - read_reg_block(&ams); - printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); - ams_print_device(&ams); - } - - printf1(TAG_NFC,"---\r\n"); - for (x = 0 ; x < 2; x++) - { - read_reg_block2(&ams2); - printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); - } - - printf1(TAG_NFC,"Version: %02x vs %02x\r\n",ams_read_reg(0x1e), ams.regs.version_maj); - printf1(TAG_NFC,"Product Type: %02x vs %02x\r\n",ams_read_reg(0x1c), ams.regs.product_type); - printf1(TAG_NFC,"Electrical: %02x vs %02x\r\n",ams_read_reg(2), ams.regs.ic_conf1); - + printf1(TAG_NFC," %s\r\n", ams_get_state_string(ams.regs.rfid_status)); } + if (ams.regs.int0) + { + ams_print_int0(ams.regs.int0); + } + if (ams.regs.int1) + { + ams_print_int1(ams.regs.int1); + } + if (ams.regs.buffer_status2) + { + if (ams.regs.buffer_status2 & AMS_BUF_INVALID) + { + printf1(TAG_NFC,"Buffer being updated!\r\n"); + } + else + { + len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; + printf1(TAG_NFC,"%d bytes in buffer\r\n", len); + ams_read_buffer(buf, len); + dump_hex1(TAG_NFC, buf, len); + } + } + // ams_print_device( &ams); + } + + + } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 1d2fdbd..07c87cc 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -36,6 +36,46 @@ typedef union #define AMS_REG_IC_CONF0 0x01 #define AMS_REG_IC_CONF1 0x02 #define AMS_REG_IC_CONF2 0x03 + #define AMS_RFCFG_EN 0x80 + #define AMS_TUN_MOD 0x40 +#define AMS_REG_RFID_STATUS 0x04 + #define AMS_HF_PON 0x80 + #define AMS_STATE_MASK 0x78 + #define AMS_STATE_INVALID 0x04 + #define AMS_STATE_OFF (0 << 3) + #define AMS_STATE_SENSE (1 << 3) + #define AMS_STATE_RESOLUTION (3 << 3) + #define AMS_STATE_RESOLUTION_L2 (2 << 3) + #define AMS_STATE_SELECTED (6 << 3) + #define AMS_STATE_SECTOR2 (7 << 3) + #define AMS_STATE_SECTORX_2 (0xf << 3) + #define AMS_STATE_SELECTEDX (0xd << 3) + #define AMS_STATE_SENSEX_L2 (0xa << 3) + #define AMS_STATE_SENSEX (0xb << 3) + #define AMS_STATE_SLEEP (0x9 << 3) +// ... // +#define AMS_REG_INT0 0x0a + #define AMS_INT_XRF (1<<0) + #define AMS_INT_TXE (1<<1) + #define AMS_INT_RXE (1<<2) + #define AMS_INT_EER_RF (1<<3) + #define AMS_INT_EEW_RF (1<<4) + #define AMS_INT_SLP (1<<5) + #define AMS_INT_WU_A (1<<6) + #define AMS_INT_INIT (1<<7) +#define AMS_REG_INT0 0x0b + #define AMS_INT_ACC_ERR (1<<0) + #define AMS_INT_EEAC_ERR (1<<1) + #define AMS_INT_IO_EEWR (1<<2) + #define AMS_INT_BF_ERR (1<<3) + #define AMS_INT_CRC_ERR (1<<4) + #define AMS_INT_PAR_ERR (1<<5) + #define AMS_INT_FRM_ERR (1<<6) + #define AMS_INT_RXS (1<<7) +#define AMS_REG_BUF2 0x0c + #define AMS_BUF_LEN_MASK 0x1f + #define AMS_BUF_INVALID 0x80 + #define AMS_CMD_DEFAULT 0x02 #define AMS_CMD_CLEAR_BUFFER 0x04 From 96f65be9c271ac8ccb8a9cecae6b6088c4b5f090 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 21:19:56 -0500 Subject: [PATCH 09/96] disable main app for now --- targets/stm32l432/src/app.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index c14a7ed..dadafc1 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -38,11 +38,11 @@ //#define ENABLE_U2F_EXTENSIONS -#define ENABLE_U2F +// #define ENABLE_U2F -// #define DISABLE_CTAPHID_PING -// #define DISABLE_CTAPHID_WINK -// #define DISABLE_CTAPHID_CBOR +#define DISABLE_CTAPHID_PING +#define DISABLE_CTAPHID_WINK +#define DISABLE_CTAPHID_CBOR void printing_init(); void hw_init(void); @@ -70,6 +70,9 @@ void hw_init(void); #define SOLO_BUTTON_PORT GPIOA #define SOLO_BUTTON_PIN LL_GPIO_PIN_0 +#define SOLO_AMS_CS_PORT GPIOB +#define SOLO_AMS_CS_PIN LL_GPIO_PIN_0 + #define SKIP_BUTTON_CHECK_WITH_DELAY 0 #define SKIP_BUTTON_CHECK_FAST 0 From 121070822f0bda76f4364d79da9e35d626e3131e Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 7 Jan 2019 21:20:07 -0500 Subject: [PATCH 10/96] Update main.c --- fido2/main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fido2/main.c b/fido2/main.c index 3f90009..875c69a 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -1,21 +1,21 @@ /* * Copyright (C) 2018 SoloKeys, Inc. - * + * * This file is part of Solo. - * + * * Solo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * Solo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Solo. If not, see - * + * * This code is available under licenses for commercial use. * Please contact SoloKeys for more information. */ @@ -46,6 +46,7 @@ int main(int argc, char * argv[]) // TAG_GA | // TAG_WALLET | TAG_STOR | + TAG_NFC | // TAG_CP | // TAG_CTAP| // TAG_HID| @@ -95,6 +96,7 @@ int main(int argc, char * argv[]) { } ctaphid_check_timeouts(); + } // Should never get here From 20f8aac768441367d295366c326fe2502cd3fa04 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 12 Jan 2019 16:19:44 -0500 Subject: [PATCH 11/96] option to boot at 4MHz with no USB --- targets/stm32l432/src/device.c | 6 +- targets/stm32l432/src/init.c | 330 +++++++++++++++++++------------ targets/stm32l432/src/redirect.c | 9 +- 3 files changed, 212 insertions(+), 133 deletions(-) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index bff18b7..ce9a20d 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -108,7 +108,9 @@ void device_reboot() void device_init() { hw_init(); - nfc_init(); + #ifndef IS_BOOTLOADER + nfc_init(); + #endif LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); @@ -395,7 +397,9 @@ void device_manage() } } #endif +#ifndef IS_BOOTLOADER nfc_loop(); +#endif } static int handle_packets() diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index bb65b32..1d39634 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -122,189 +122,254 @@ static void LL_Init(void) NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); } - +static int NFC = 0; /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { + if (!NFC) + { - LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); - if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) - { - Error_Handler(); - } - LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); - LL_RCC_HSI48_Enable(); + LL_RCC_HSI48_Enable(); - /* Wait till HSI48 is ready */ - while(LL_RCC_HSI48_IsReady() != 1) - { + /* Wait till HSI48 is ready */ + while(LL_RCC_HSI48_IsReady() != 1) + { - } + } - LL_RCC_LSI_Enable(); + LL_RCC_LSI_Enable(); - /* Wait till LSI is ready */ - while(LL_RCC_LSI_IsReady() != 1) - { + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { - } - LL_RCC_MSI_Enable(); - /* Wait till MSI is ready */ - while(LL_RCC_MSI_IsReady() != 1) - { + } + LL_RCC_MSI_Enable(); + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { - } - LL_RCC_MSI_EnableRangeSelection(); + } + LL_RCC_MSI_EnableRangeSelection(); - LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11); + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11); - LL_RCC_MSI_SetCalibTrimming(0); + LL_RCC_MSI_SetCalibTrimming(0); - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); - /* Wait till System clock is ready */ - while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) - { + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { - } - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16); - LL_Init1msTick(48000000); + LL_Init1msTick(48000000); - LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); - LL_SetSystemCoreClock(48000000); + LL_SetSystemCoreClock(48000000); - LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); - LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_HSI48); + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_HSI48); - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS); + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS); - LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_CRS); + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_CRS); - LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_CRS); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_CRS); - LL_CRS_SetSyncDivider(LL_CRS_SYNC_DIV_1); + LL_CRS_SetSyncDivider(LL_CRS_SYNC_DIV_1); - LL_CRS_SetSyncPolarity(LL_CRS_SYNC_POLARITY_RISING); + LL_CRS_SetSyncPolarity(LL_CRS_SYNC_POLARITY_RISING); - LL_CRS_SetSyncSignalSource(LL_CRS_SYNC_SOURCE_USB); + LL_CRS_SetSyncSignalSource(LL_CRS_SYNC_SOURCE_USB); - LL_CRS_SetReloadCounter(__LL_CRS_CALC_CALCULATE_RELOADVALUE(48000000,1000)); + LL_CRS_SetReloadCounter(__LL_CRS_CALC_CALCULATE_RELOADVALUE(48000000,1000)); - LL_CRS_SetFreqErrorLimit(34); + LL_CRS_SetFreqErrorLimit(34); - LL_CRS_SetHSI48SmoothTrimming(32); + LL_CRS_SetHSI48SmoothTrimming(32); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + } + else + { + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(4000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(4000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + } - /* SysTick_IRQn interrupt configuration */ - NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); } void usb_init() { - // enable USB power - SET_BIT(PWR->CR2, PWR_CR2_USV); + if (!NFC) + { + // enable USB power + SET_BIT(PWR->CR2, PWR_CR2_USV); - // Enable USB Clock - SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); + // Enable USB Clock + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); - USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC); - in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0; - out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0; + USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC); + in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0; + out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0; - in_endpoint_to_class[CDC_IN_EP & 0x7F] = 1; - out_endpoint_to_class[CDC_OUT_EP & 0x7F] = 1; + in_endpoint_to_class[CDC_IN_EP & 0x7F] = 1; + out_endpoint_to_class[CDC_OUT_EP & 0x7F] = 1; - USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0); - USBD_RegisterClass(&Solo_USBD_Device, &USBD_Composite); - // USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID); - // - // USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC); - USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS); + USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0); + USBD_RegisterClass(&Solo_USBD_Device, &USBD_Composite); + // USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID); + // + // USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC); + USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS); - USBD_Start(&Solo_USBD_Device); + USBD_Start(&Solo_USBD_Device); + } } /* TIM2 init function */ static void MX_TIM2_Init(void) { + // if(!NFC) + { + LL_TIM_InitTypeDef TIM_InitStruct; + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; - LL_TIM_InitTypeDef TIM_InitStruct; - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; + LL_GPIO_InitTypeDef GPIO_InitStruct; - LL_GPIO_InitTypeDef GPIO_InitStruct; + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); - /* Peripheral clock enable */ - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); + TIM2->SR = 0 ; - TIM2->SR = 0 ; + TIM_InitStruct.Prescaler = 0; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 1000; + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; + LL_TIM_Init(TIM2, &TIM_InitStruct); - TIM_InitStruct.Prescaler = 0; - TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; - TIM_InitStruct.Autoreload = 1000; - TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; - LL_TIM_Init(TIM2, &TIM_InitStruct); + LL_TIM_EnableARRPreload(TIM2); - LL_TIM_EnableARRPreload(TIM2); + LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); - LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.CompareValue = 1000; + TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct); - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 1000; - TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; - LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct); + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2); - LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2); + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct); - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; - LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct); + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3); - LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3); + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct); - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; - LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct); + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH4); - LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH4); + LL_TIM_SetOCRefClearInputSource(TIM2, LL_TIM_OCREF_CLR_INT_NC); - LL_TIM_SetOCRefClearInputSource(TIM2, LL_TIM_OCREF_CLR_INT_NC); + LL_TIM_DisableExternalClock(TIM2); - LL_TIM_DisableExternalClock(TIM2); + LL_TIM_ConfigETR(TIM2, LL_TIM_ETR_POLARITY_NONINVERTED, LL_TIM_ETR_PRESCALER_DIV1, LL_TIM_ETR_FILTER_FDIV1); - LL_TIM_ConfigETR(TIM2, LL_TIM_ETR_POLARITY_NONINVERTED, LL_TIM_ETR_PRESCALER_DIV1, LL_TIM_ETR_FILTER_FDIV1); + LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); - LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(TIM2); - LL_TIM_DisableMasterSlaveMode(TIM2); + /**TIM2 GPIO Configuration + PA1 ------> TIM2_CH2 + PA2 ------> TIM2_CH3 + PA3 ------> TIM2_CH4 + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_1; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /**TIM2 GPIO Configuration - PA1 ------> TIM2_CH2 - PA2 ------> TIM2_CH3 - PA3 ------> TIM2_CH4 - */ - GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_1; - LL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - LL_TIM_EnableCounter(TIM2); + LL_TIM_EnableCounter(TIM2); + } } @@ -362,29 +427,33 @@ static void MX_GPIO_Init(void) static void MX_TIM6_Init(void) { - LL_TIM_InitTypeDef TIM_InitStruct; + LL_TIM_InitTypeDef TIM_InitStruct; - /* Peripheral clock enable */ - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6); + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6); - // 48 MHz sys clock --> 6 MHz timer clock - // 48 MHz / 48000 == 1000 Hz - TIM_InitStruct.Prescaler = 48000; - TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; - TIM_InitStruct.Autoreload = 90; - LL_TIM_Init(TIM6, &TIM_InitStruct); + // 48 MHz sys clock --> 6 MHz timer clock + // 48 MHz / 48000 == 1000 Hz + if (!NFC) + TIM_InitStruct.Prescaler = 48000; + else + TIM_InitStruct.Prescaler = 4000; - LL_TIM_DisableARRPreload(TIM6); + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 90; + LL_TIM_Init(TIM6, &TIM_InitStruct); - LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET); + LL_TIM_DisableARRPreload(TIM6); - LL_TIM_DisableMasterSlaveMode(TIM6); + LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET); - // enable interrupt - TIM6->DIER |= 1; + LL_TIM_DisableMasterSlaveMode(TIM6); - // Start immediately - LL_TIM_EnableCounter(TIM6); + // enable interrupt + TIM6->DIER |= 1; + + // Start immediately + LL_TIM_EnableCounter(TIM6); } /* TIM7 init function */ @@ -458,7 +527,10 @@ static void MX_SPI1_Init(void) SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; + if (!NFC) + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; + else + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct.CRCPoly = 7; diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index 8021d5e..431bc18 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -37,15 +37,18 @@ void _putchar(char c) LL_USART_TransmitData8(DEBUG_UART,c); #endif } - +static int NFC = 0; int _write (int fd, const void *buf, long int len) { uint8_t * data = (uint8_t *) buf; - // Send out USB serial - CDC_Transmit_FS(data, len); + if (!NFC) + { + // Send out USB serial + CDC_Transmit_FS(data, len); + } // Send out UART serial while(len--) From 62cd7cc728a412e4312f55bb158edf231a79a9ac Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 12 Jan 2019 16:20:11 -0500 Subject: [PATCH 12/96] enable energy harvesting and tunneling in eeprom --- fido2/log.h | 4 +- targets/stm32l432/src/nfc.c | 109 +++++++++++++++++++++++++++++------- targets/stm32l432/src/nfc.h | 15 ++++- 3 files changed, 106 insertions(+), 22 deletions(-) diff --git a/fido2/log.h b/fido2/log.h index 9ba145a..a6f5097 100644 --- a/fido2/log.h +++ b/fido2/log.h @@ -59,8 +59,8 @@ typedef enum TAG_EXT = (1 << 17), TAG_NFC = (1 << 18), - TAG_NO_TAG = (1<<30), - TAG_FILENO = (1<<31) + TAG_NO_TAG = (1UL<<30), + TAG_FILENO = (1UL<<31) } LOG_TAG; #if DEBUG_LEVEL > 0 diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 986810a..5583aaf 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -125,6 +125,39 @@ void ams_read_buffer(uint8_t * data, int len) SELECT(); } +// data must be 4 bytes +void ams_read_eeprom_block(uint8_t block, uint8_t * data) +{ + int i; + send_recv(0x7f); + send_recv(block << 1); + + data[0] = send_recv(0); + data[1] = send_recv(0); + data[2] = send_recv(0); + data[3] = send_recv(0); + + UNSELECT(); + SELECT(); +} + + +// data must be 4 bytes +void ams_write_eeprom_block(uint8_t block, uint8_t * data) +{ + int i; + send_recv(0x40); + send_recv(block << 1); + + send_recv(data[0]); + send_recv(data[1]); + send_recv(data[2]); + send_recv(data[3]); + + UNSELECT(); + SELECT(); +} + void ams_write_command(uint8_t cmd) { send_recv(0xc0 | cmd); @@ -168,53 +201,56 @@ const char * ams_get_state_string(uint8_t regval) void ams_print_int0(uint8_t int0) { + uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); printf1(TAG_NFC," "); if (int0 & AMS_INT_XRF) - printf1(TAG_NFC|TAG_NO_TAG," XRF"); + printf1(tag," XRF"); if (int0 & AMS_INT_TXE) - printf1(TAG_NFC|TAG_NO_TAG," TXE"); + printf1(tag," TXE"); if (int0 & AMS_INT_RXE) - printf1(TAG_NFC|TAG_NO_TAG," RXE"); + printf1(tag," RXE"); if (int0 & AMS_INT_EER_RF) - printf1(TAG_NFC|TAG_NO_TAG," EER_RF"); + printf1(tag," EER_RF"); if (int0 & AMS_INT_EEW_RF) - printf1(TAG_NFC|TAG_NO_TAG," EEW_RF"); + printf1(tag," EEW_RF"); if (int0 & AMS_INT_SLP) - printf1(TAG_NFC|TAG_NO_TAG," SLP"); + printf1(tag," SLP"); if (int0 & AMS_INT_WU_A) - printf1(TAG_NFC|TAG_NO_TAG," WU_A"); + printf1(tag," WU_A"); if (int0 & AMS_INT_INIT) - printf1(TAG_NFC|TAG_NO_TAG," INIT"); + printf1(tag," INIT"); - printf1(TAG_NFC|TAG_NO_TAG,"\r\n"); + printf1(tag,"\r\n"); } void ams_print_int1(uint8_t int0) { + uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); printf1(TAG_NFC," "); if (int0 & AMS_INT_ACC_ERR) - printf1(TAG_NFC|TAG_NO_TAG," ACC_ERR"); + printf1(tag," ACC_ERR"); if (int0 & AMS_INT_EEAC_ERR) - printf1(TAG_NFC|TAG_NO_TAG," EEAC_ERR"); + printf1(tag," EEAC_ERR"); if (int0 & AMS_INT_IO_EEWR) - printf1(TAG_NFC|TAG_NO_TAG," IO_EEWR"); + printf1(tag," IO_EEWR"); if (int0 & AMS_INT_BF_ERR) - printf1(TAG_NFC|TAG_NO_TAG," BF_ERR"); + printf1(tag," BF_ERR"); if (int0 & AMS_INT_CRC_ERR) - printf1(TAG_NFC|TAG_NO_TAG," CRC_ERR"); + printf1(tag," CRC_ERR"); if (int0 & AMS_INT_PAR_ERR) - printf1(TAG_NFC|TAG_NO_TAG," PAR_ERR"); + printf1(tag," PAR_ERR"); if (int0 & AMS_INT_FRM_ERR) - printf1(TAG_NFC|TAG_NO_TAG," FRM_ERR"); + printf1(tag," FRM_ERR"); if (int0 & AMS_INT_RXS) - printf1(TAG_NFC|TAG_NO_TAG," RXS"); + printf1(tag," RXS"); - printf1(TAG_NFC|TAG_NO_TAG,"\r\n"); + printf1(tag,"\r\n"); } void nfc_init() { + uint8_t block[4]; LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); @@ -233,6 +269,40 @@ void nfc_init() // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); + + ams_read_eeprom_block(0, block); + printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); + + ams_read_eeprom_block(0, block); + printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); + + ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + + ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + + uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; + uint8_t ic_cfg2 = AMS_CFG2_RFCFG_EN | AMS_CFG2_TUN_MOD; + + if (block[0] != ic_cfg1 || block[1] != ic_cfg2) + { + printf1(TAG_NFC,"Writing...\r\n"); + // set IC_CFG1 + block[0] = ic_cfg1; + + // set IC_CFG2 + block[1] = ic_cfg2; + + // mask interrupt bits + block[2] = 0x80; + block[3] = 0; + + ams_write_eeprom_block(0x7F, block); + } + + ams_read_eeprom_block(0x7F, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); } void nfc_loop() @@ -244,7 +314,8 @@ void nfc_loop() AMS_DEVICE ams,ams2; int len = 0; - if (millis() - t1 > interval) + // if (millis() - t1 > interval) + if (0) { t1 = millis(); read_reg_block(&ams); diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 07c87cc..16109b1 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -63,7 +63,7 @@ typedef union #define AMS_INT_SLP (1<<5) #define AMS_INT_WU_A (1<<6) #define AMS_INT_INIT (1<<7) -#define AMS_REG_INT0 0x0b +#define AMS_REG_INT1 0x0b #define AMS_INT_ACC_ERR (1<<0) #define AMS_INT_EEAC_ERR (1<<1) #define AMS_INT_IO_EEWR (1<<2) @@ -76,6 +76,19 @@ typedef union #define AMS_BUF_LEN_MASK 0x1f #define AMS_BUF_INVALID 0x80 +#define AMS_CONFIG_BLOCK0_ADDR 0x7e +#define AMS_CONFIG_BLOCK1_ADDR 0x7f + +#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2) + +#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00 +#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01 +#define AMS_CFG1_OUTPUT_RESISTANCE_50 0x02 +#define AMS_CFG1_OUTPUT_RESISTANCE_25 0x03 + +#define AMS_CFG2_RFCFG_EN (1<<7) +#define AMS_CFG2_TUN_MOD (1<<6) #define AMS_CMD_DEFAULT 0x02 #define AMS_CMD_CLEAR_BUFFER 0x04 From 302ce75ce6695ee7b80eb2b4a6624dbb1c14f1d9 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 12 Jan 2019 20:20:47 -0500 Subject: [PATCH 13/96] responds to RATS correctly --- fido2/main.c | 1 + targets/stm32l432/src/device.c | 7 +- targets/stm32l432/src/init.c | 8 +- targets/stm32l432/src/nfc.c | 142 +++++++++++++++++++++++++++++---- targets/stm32l432/src/nfc.h | 8 +- 5 files changed, 140 insertions(+), 26 deletions(-) diff --git a/fido2/main.c b/fido2/main.c index 875c69a..51e15ec 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -65,6 +65,7 @@ int main(int argc, char * argv[]) usbhid_init(); printf1(TAG_GEN,"init usb\n"); + nfc_init(); ctaphid_init(); printf1(TAG_GEN,"init ctaphid\n"); diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index ce9a20d..33d9113 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -108,9 +108,7 @@ void device_reboot() void device_init() { hw_init(); - #ifndef IS_BOOTLOADER - nfc_init(); - #endif + LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); @@ -133,9 +131,10 @@ void usbhid_init() #if DEBUG_LEVEL>1 wait_for_usb_tether(); #endif - } + + void wait_for_usb_tether() { while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) ) diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index 1d39634..056a7ba 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -527,10 +527,10 @@ static void MX_SPI1_Init(void) SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; - if (!NFC) - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; - else - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; + // if (!NFC) + // SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; + // else + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct.CRCPoly = 7; diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 5583aaf..3901de1 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -10,6 +10,12 @@ #define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) #define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +static struct +{ + uint8_t max_frame_size; + uint8_t cid; +} NFC_STATE; + static void flush_rx() { @@ -125,6 +131,19 @@ void ams_read_buffer(uint8_t * data, int len) SELECT(); } +void ams_write_buffer(uint8_t * data, int len) +{ + int i; + send_recv(0x80); + while(len--) + { + send_recv(*data++); + } + + UNSELECT(); + SELECT(); +} + // data must be 4 bytes void ams_read_eeprom_block(uint8_t block, uint8_t * data) { @@ -251,6 +270,10 @@ void ams_print_int1(uint8_t int0) void nfc_init() { uint8_t block[4]; + + memset(&NFC_STATE,0,sizeof(NFC_STATE)); + NFC_STATE.max_frame_size = 32; + LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); @@ -279,15 +302,37 @@ void nfc_init() ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + uint8_t sense1 = 0x44; + uint8_t sense2 = 0x00; + uint8_t selr = 0x20; // SAK + + if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) + { + printf1(TAG_NFC,"Writing config block 0\r\n"); + block[0] = sense1; + block[1] = sense2; + block[2] = selr; + block[3] = 0x00; + + ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + UNSELECT(); + delay(10); + SELECT(); + delay(10); + + ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + } + ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; - uint8_t ic_cfg2 = AMS_CFG2_RFCFG_EN | AMS_CFG2_TUN_MOD; + uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; if (block[0] != ic_cfg1 || block[1] != ic_cfg2) { - printf1(TAG_NFC,"Writing...\r\n"); + printf1(TAG_NFC,"Writing config block 1\r\n"); // set IC_CFG1 block[0] = ic_cfg1; @@ -298,11 +343,58 @@ void nfc_init() block[2] = 0x80; block[3] = 0; - ams_write_eeprom_block(0x7F, block); + ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + + UNSELECT(); + delay(10); + SELECT(); + delay(10); + + ams_read_eeprom_block(0x7F, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); } - ams_read_eeprom_block(0x7F, block); - printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); +} + +void nfc_write_frame(uint8_t * data, uint8_t len) +{ + if (len > 32) + { + len = 32; + } + ams_write_command(AMS_CMD_CLEAR_BUFFER); + ams_write_buffer(data,len); + ams_write_command(AMS_CMD_TRANSMIT_BUFFER); + +} + +int answer_rats(RATS_REQUEST * rats) +{ + if (rats->start != 0xE0) + { + printf1(TAG_ERR, "Not a RATS request. Ignoring.\r\n"); + return 1; + } + + uint8_t fsdi = (rats->parameter & 0xf0) >> 4; + uint8_t cid = (rats->parameter & 0x0f); + + // printf1(TAG_NFC, "fsdi: %x\r\n",fsdi); + // printf1(TAG_NFC, "cid: %x\r\n",cid); + + if (fsdi == 0) + NFC_STATE.max_frame_size = 16; + else if (fsdi == 1) + NFC_STATE.max_frame_size = 24; + else + NFC_STATE.max_frame_size = 32; + + uint8_t res[2]; + res[0] = 2; + res[1] = 2; // 2 FSCI == 32 byte frame size + + nfc_write_frame(res,2); + return 0; } void nfc_loop() @@ -310,30 +402,39 @@ void nfc_loop() const uint32_t interval = 200; static uint32_t t1 = 0; + static uint32_t c = 0; uint8_t buf[32]; AMS_DEVICE ams,ams2; int len = 0; - + uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00"; // if (millis() - t1 > interval) - if (0) + if (1) { t1 = millis(); read_reg_block(&ams); - printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); - + // if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0) + // { + // printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); + // } if (ams.regs.rfid_status) { - printf1(TAG_NFC," %s\r\n", ams_get_state_string(ams.regs.rfid_status)); + uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; + // if (state != AMS_STATE_SENSE) + // printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis()); } if (ams.regs.int0) { - ams_print_int0(ams.regs.int0); + // ams_print_int0(ams.regs.int0); + if (ams.regs.int0 & AMS_INT_XRF) + { + printf1(TAG_NFC," %d\r\n", millis()); + } } if (ams.regs.int1) { - ams_print_int1(ams.regs.int1); + // ams_print_int1(ams.regs.int1); } - if (ams.regs.buffer_status2) + if (ams.regs.buffer_status2 && (ams.regs.int0 & AMS_INT_RXE)) { if (ams.regs.buffer_status2 & AMS_BUF_INVALID) { @@ -342,14 +443,21 @@ void nfc_loop() else { len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; - printf1(TAG_NFC,"%d bytes in buffer\r\n", len); ams_read_buffer(buf, len); - dump_hex1(TAG_NFC, buf, len); + // printf1(TAG_NFC,"%d bytes in buffer\r\n", len); + // dump_hex1(TAG_NFC, buf, len); } } - // ams_print_device( &ams); + + if (len) + { + // printf1(TAG_NFC,"RATS %d\r\n",c++); + // ams_write_command(AMS_CMD_TRANSMIT_ACK); + t1 = millis(); + answer_rats((RATS_REQUEST*)buf); + printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); + } } - } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 16109b1..2aad246 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -30,7 +30,13 @@ typedef union uint8_t version_maj; // 0x1e uint8_t version_min; // 0x1f } regs; -} AMS_DEVICE; +} __attribute__((packed)) AMS_DEVICE; + +typedef struct +{ + uint8_t start; + uint8_t parameter; +} __attribute__((packed)) RATS_REQUEST; #define AMS_REG_IO_CONF 0x00 #define AMS_REG_IC_CONF0 0x01 From 1874e11fba662360c7d11321ba08a81af93c8915 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 13 Jan 2019 00:02:37 -0500 Subject: [PATCH 14/96] organize --- targets/stm32l432/src/nfc.c | 83 +++++++++++++++++++++++++++---------- targets/stm32l432/src/nfc.h | 14 +++++++ 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 3901de1..133f4c2 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -120,7 +120,6 @@ void read_reg_block(AMS_DEVICE * dev) void ams_read_buffer(uint8_t * data, int len) { - int i; send_recv(0xa0); while(len--) { @@ -133,7 +132,6 @@ void ams_read_buffer(uint8_t * data, int len) void ams_write_buffer(uint8_t * data, int len) { - int i; send_recv(0x80); while(len--) { @@ -147,7 +145,6 @@ void ams_write_buffer(uint8_t * data, int len) // data must be 4 bytes void ams_read_eeprom_block(uint8_t block, uint8_t * data) { - int i; send_recv(0x7f); send_recv(block << 1); @@ -164,7 +161,6 @@ void ams_read_eeprom_block(uint8_t block, uint8_t * data) // data must be 4 bytes void ams_write_eeprom_block(uint8_t block, uint8_t * data) { - int i; send_recv(0x40); send_recv(block << 1); @@ -368,19 +364,13 @@ void nfc_write_frame(uint8_t * data, uint8_t len) } -int answer_rats(RATS_REQUEST * rats) +int answer_rats(uint8_t parameter) { - if (rats->start != 0xE0) - { - printf1(TAG_ERR, "Not a RATS request. Ignoring.\r\n"); - return 1; - } - uint8_t fsdi = (rats->parameter & 0xf0) >> 4; - uint8_t cid = (rats->parameter & 0x0f); + uint8_t fsdi = (parameter & 0xf0) >> 4; + uint8_t cid = (parameter & 0x0f); - // printf1(TAG_NFC, "fsdi: %x\r\n",fsdi); - // printf1(TAG_NFC, "cid: %x\r\n",cid); + NFC_STATE.cid = cid; if (fsdi == 0) NFC_STATE.max_frame_size = 16; @@ -389,11 +379,20 @@ int answer_rats(RATS_REQUEST * rats) else NFC_STATE.max_frame_size = 32; - uint8_t res[2]; - res[0] = 2; - res[1] = 2; // 2 FSCI == 32 byte frame size + uint8_t res[3]; + res[0] = 3; + res[1] = 2 | (1<<5); // 2 FSCI == 32 byte frame size, TB is enabled - nfc_write_frame(res,2); + // frame wait time = (256 * 16 / 13.56MHz) * 2^FWI + // FWI=0, FMT=0.3ms (min) + // FWI=4, FMT=4.8ms (default) + // FWI=10, FMT=309ms + // FWI=12, FMT=1237ms + // FWI=14, FMT=4949ms (max) + res[2] = (12<<4) | (0); // TB (FWI << 4) | (SGTI) + + + nfc_write_frame(res,3); return 0; } @@ -453,9 +452,51 @@ void nfc_loop() { // printf1(TAG_NFC,"RATS %d\r\n",c++); // ams_write_command(AMS_CMD_TRANSMIT_ACK); - t1 = millis(); - answer_rats((RATS_REQUEST*)buf); - printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); + switch(buf[0]) + { + case NFC_CMD_REQA: + printf1(TAG_NFC, "NFC_CMD_REQA\r\n"); + break; + case NFC_CMD_WUPA: + printf1(TAG_NFC, "NFC_CMD_WUPA\r\n"); + break; + case NFC_CMD_HLTA: + printf1(TAG_NFC, "HLTA/Halt\r\n"); + break; + case NFC_CMD_RATS: + t1 = millis(); + answer_rats(buf[1]); + printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); + break; + default: + + if (IS_PPSS_CMD(buf[0])) + { + printf1(TAG_NFC, "NFC_CMD_PPSS\r\n"); + } + else if (IS_IBLOCK(buf[0])) + { + printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + } + else if (IS_RBLOCK(buf[0])) + { + printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + } + else if (IS_SBLOCK(buf[0])) + { + printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + } + else + { + printf1(TAG_NFC, "unknown NFC request\r\n len[%d]:", len); + dump_hex1(TAG_NFC, buf, len); + } + + break; + } + + + } } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 2aad246..7cc9556 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -110,4 +110,18 @@ typedef struct #define AMS_CMD_SENSE 0x11 #define AMS_CMD_SENSE_SLEEP 0x12 +#define NFC_CMD_REQA 0x26 +#define NFC_CMD_WUPA 0x52 +#define NFC_CMD_HLTA 0x50 +#define NFC_CMD_RATS 0xe0 + +#define NFC_CMD_PPSS 0xd0 +#define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS) +#define NFC_CMD_IBLOCK 0x00 +#define IS_IBLOCK(x) (((x) & 0xe0) == NFC_CMD_IBLOCK) +#define NFC_CMD_RBLOCK 0xa0 +#define IS_RBLOCK(x) (((x) & 0xe0) == NFC_CMD_RBLOCK) +#define NFC_CMD_SBLOCK 0xc0 +#define IS_SBLOCK(x) (((x) & 0xc0) == NFC_CMD_SBLOCK) + #endif From dcf7940b3d5dd64ed2875ef840a641c3151430a5 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 13 Jan 2019 17:25:32 -0500 Subject: [PATCH 15/96] basic ndef message works --- targets/stm32l432/application.mk | 2 +- targets/stm32l432/src/ams.c | 340 ++++++++++++++++++ targets/stm32l432/src/ams.h | 127 +++++++ targets/stm32l432/src/nfc.c | 576 +++++++++++-------------------- targets/stm32l432/src/nfc.h | 147 +++----- targets/stm32l432/src/redirect.c | 2 +- 6 files changed, 719 insertions(+), 475 deletions(-) create mode 100644 targets/stm32l432/src/ams.c create mode 100644 targets/stm32l432/src/ams.h diff --git a/targets/stm32l432/application.mk b/targets/stm32l432/application.mk index 70bbc3f..110c069 100644 --- a/targets/stm32l432/application.mk +++ b/targets/stm32l432/application.mk @@ -5,7 +5,7 @@ AR=$(PREFIX)arm-none-eabi-ar # ST related SRC = src/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c -SRC += src/fifo.c src/crypto.c src/attestation.c src/nfc.c +SRC += src/fifo.c src/crypto.c src/attestation.c src/nfc.c src/ams.c SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c new file mode 100644 index 0000000..1b2c87a --- /dev/null +++ b/targets/stm32l432/src/ams.c @@ -0,0 +1,340 @@ +#include + +#include "stm32l4xx_ll_spi.h" + +#include "ams.h" +#include "log.h" +#include "util.h" +#include "device.h" + +static void flush_rx() +{ + while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0) + { + LL_SPI_ReceiveData8(SPI1); + } +} +static void wait_for_tx() +{ + // while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) + // ; + while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY) + ; +} +static void wait_for_rx() +{ + while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0) + ; +} + + +static void ams_print_device(AMS_DEVICE * dev) +{ + printf1(TAG_NFC, "AMS_DEVICE:\r\n"); + printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); + printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0); + printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1); + printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2); + printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status); + printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status); + printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0); + printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1); + printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0); + printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1); + printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2); + printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1); + printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr); + printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type); + printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype); + printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj); + printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min); +} + +static uint8_t send_recv(uint8_t b) +{ + wait_for_tx(); + LL_SPI_TransmitData8(SPI1, b); + wait_for_rx(); + b = LL_SPI_ReceiveData8(SPI1); + return b; +} + + +void ams_write_reg(uint8_t addr, uint8_t tx) +{ + send_recv(0x00| addr); + send_recv(tx); + + UNSELECT(); + SELECT(); +} + + +uint8_t ams_read_reg(uint8_t addr) +{ + send_recv(0x20| (addr & 0x1f)); + uint8_t data = send_recv(0); + UNSELECT(); + SELECT(); + return data; +} + +// data must be 14 bytes long +void read_reg_block2(AMS_DEVICE * dev) +{ + int i; + + for (i = 0; i < 0x20; i++) + { + dev->buf[i] = ams_read_reg(i); + } +} + + +// data must be 14 bytes long +void read_reg_block(AMS_DEVICE * dev) +{ + int i; + uint8_t mode = 0x20 | (0 ); + flush_rx(); + + send_recv(mode); + for (i = 0; i < 0x20; i++) + { + dev->buf[i] = send_recv(0); + } + + UNSELECT(); + SELECT(); +} + +void ams_read_buffer(uint8_t * data, int len) +{ + send_recv(0xa0); + while(len--) + { + *data++ = send_recv(0x00); + } + + UNSELECT(); + SELECT(); +} + +void ams_write_buffer(uint8_t * data, int len) +{ + send_recv(0x80); + while(len--) + { + send_recv(*data++); + } + + UNSELECT(); + SELECT(); +} + +// data must be 4 bytes +void ams_read_eeprom_block(uint8_t block, uint8_t * data) +{ + send_recv(0x7f); + send_recv(block << 1); + + data[0] = send_recv(0); + data[1] = send_recv(0); + data[2] = send_recv(0); + data[3] = send_recv(0); + + UNSELECT(); + SELECT(); +} + + +// data must be 4 bytes +void ams_write_eeprom_block(uint8_t block, uint8_t * data) +{ + send_recv(0x40); + send_recv(block << 1); + + send_recv(data[0]); + send_recv(data[1]); + send_recv(data[2]); + send_recv(data[3]); + + UNSELECT(); + SELECT(); +} + +void ams_write_command(uint8_t cmd) +{ + send_recv(0xc0 | cmd); + UNSELECT(); + SELECT(); +} + +const char * ams_get_state_string(uint8_t regval) +{ + if (regval & AMS_STATE_INVALID) + { + return "STATE_INVALID"; + } + switch (regval & AMS_STATE_MASK) + { + case AMS_STATE_OFF: + return "STATE_OFF"; + case AMS_STATE_SENSE: + return "STATE_SENSE"; + case AMS_STATE_RESOLUTION: + return "STATE_RESOLUTION"; + case AMS_STATE_RESOLUTION_L2: + return "STATE_RESOLUTION_L2"; + case AMS_STATE_SELECTED: + return "STATE_SELECTED"; + case AMS_STATE_SECTOR2: + return "STATE_SECTOR2"; + case AMS_STATE_SECTORX_2: + return "STATE_SECTORX_2"; + case AMS_STATE_SELECTEDX: + return "STATE_SELECTEDX"; + case AMS_STATE_SENSEX_L2: + return "STATE_SENSEX_L2"; + case AMS_STATE_SENSEX: + return "STATE_SENSEX"; + case AMS_STATE_SLEEP: + return "STATE_SLEEP"; + } + return "STATE_WRONG"; +} + +void ams_print_int0(uint8_t int0) +{ + uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); + printf1(TAG_NFC," "); + if (int0 & AMS_INT_XRF) + printf1(tag," XRF"); + if (int0 & AMS_INT_TXE) + printf1(tag," TXE"); + if (int0 & AMS_INT_RXE) + printf1(tag," RXE"); + if (int0 & AMS_INT_EER_RF) + printf1(tag," EER_RF"); + if (int0 & AMS_INT_EEW_RF) + printf1(tag," EEW_RF"); + if (int0 & AMS_INT_SLP) + printf1(tag," SLP"); + if (int0 & AMS_INT_WU_A) + printf1(tag," WU_A"); + if (int0 & AMS_INT_INIT) + printf1(tag," INIT"); + + printf1(tag,"\r\n"); +} + +void ams_print_int1(uint8_t int0) +{ + uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); + printf1(TAG_NFC," "); + if (int0 & AMS_INT_ACC_ERR) + printf1(tag," ACC_ERR"); + if (int0 & AMS_INT_EEAC_ERR) + printf1(tag," EEAC_ERR"); + if (int0 & AMS_INT_IO_EEWR) + printf1(tag," IO_EEWR"); + if (int0 & AMS_INT_BF_ERR) + printf1(tag," BF_ERR"); + if (int0 & AMS_INT_CRC_ERR) + printf1(tag," CRC_ERR"); + if (int0 & AMS_INT_PAR_ERR) + printf1(tag," PAR_ERR"); + if (int0 & AMS_INT_FRM_ERR) + printf1(tag," FRM_ERR"); + if (int0 & AMS_INT_RXS) + printf1(tag," RXS"); + + printf1(tag,"\r\n"); +} + +void ams_init() +{ + + uint8_t block[4]; + + LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); + + LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW); + LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); + LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); + LL_SPI_Enable(SPI1); + + delay(10); + SELECT(); + delay(10); + + + ams_write_command(AMS_CMD_DEFAULT); + ams_write_command(AMS_CMD_CLEAR_BUFFER); + + // enable tunneling mode and RF configuration + ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); + + ams_read_eeprom_block(0, block); + printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); + + ams_read_eeprom_block(0, block); + printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); + + ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + + uint8_t sense1 = 0x44; + uint8_t sense2 = 0x00; + uint8_t selr = 0x20; // SAK + + if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) + { + printf1(TAG_NFC,"Writing config block 0\r\n"); + block[0] = sense1; + block[1] = sense2; + block[2] = selr; + block[3] = 0x00; + + ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + UNSELECT(); + delay(10); + SELECT(); + delay(10); + + ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + } + + ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + + uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; + uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; + + if (block[0] != ic_cfg1 || block[1] != ic_cfg2) + { + printf1(TAG_NFC,"Writing config block 1\r\n"); + // set IC_CFG1 + block[0] = ic_cfg1; + + // set IC_CFG2 + block[1] = ic_cfg2; + + // mask interrupt bits + block[2] = 0x80; + block[3] = 0; + + ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + + UNSELECT(); + delay(10); + SELECT(); + delay(10); + + ams_read_eeprom_block(0x7F, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + } + +} diff --git a/targets/stm32l432/src/ams.h b/targets/stm32l432/src/ams.h new file mode 100644 index 0000000..361cb0d --- /dev/null +++ b/targets/stm32l432/src/ams.h @@ -0,0 +1,127 @@ +#ifndef _AMS_H_ +#define _AMS_H_ + +#include +#include +#include "stm32l4xx_ll_gpio.h" + + +typedef union +{ + uint8_t buf[0x20]; + struct { + uint8_t io_conf; // 0x00 + uint8_t ic_conf0; // 0x01 + uint8_t ic_conf1; // 0x02 + uint8_t ic_conf2; // 0x03 + uint8_t rfid_status; // 0x04 + uint8_t ic_status; // 0x05 + uint8_t _nc0[2]; // 0x06 - 0x07 + uint8_t mask_int0; // 0x08 + uint8_t mask_int1; // 0x09 + uint8_t int0; // 0x0a + uint8_t int1; // 0x0b + uint8_t buffer_status2; // 0x0c + uint8_t buffer_status1; // 0x0d + uint8_t last_nfc_addr; // 0x0e + uint8_t _nc1[0x1b - 0x0f + 1]; // 0x0f - 0x1b + uint8_t product_type; // 0x1c + uint8_t product_subtype; // 0x1d + uint8_t version_maj; // 0x1e + uint8_t version_min; // 0x1f + } regs; +} __attribute__((packed)) AMS_DEVICE; + +#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) + +void ams_init(); + +void ams_read_buffer(uint8_t * data, int len); +void ams_write_buffer(uint8_t * data, int len); + +void ams_write_command(uint8_t cmd); + +void read_reg_block(AMS_DEVICE * dev); + +uint8_t ams_read_reg(uint8_t addr); + +void ams_write_reg(uint8_t addr, uint8_t tx); + + +#define AMS_REG_IO_CONF 0x00 +#define AMS_REG_IC_CONF0 0x01 +#define AMS_REG_IC_CONF1 0x02 +#define AMS_REG_IC_CONF2 0x03 + #define AMS_RFCFG_EN 0x80 + #define AMS_TUN_MOD 0x40 +#define AMS_REG_RFID_STATUS 0x04 + #define AMS_HF_PON 0x80 + #define AMS_STATE_MASK 0x78 + #define AMS_STATE_INVALID 0x04 + #define AMS_STATE_OFF (0 << 3) + #define AMS_STATE_SENSE (1 << 3) + #define AMS_STATE_RESOLUTION (3 << 3) + #define AMS_STATE_RESOLUTION_L2 (2 << 3) + #define AMS_STATE_SELECTED (6 << 3) + #define AMS_STATE_SECTOR2 (7 << 3) + #define AMS_STATE_SECTORX_2 (0xf << 3) + #define AMS_STATE_SELECTEDX (0xd << 3) + #define AMS_STATE_SENSEX_L2 (0xa << 3) + #define AMS_STATE_SENSEX (0xb << 3) + #define AMS_STATE_SLEEP (0x9 << 3) +// ... // +#define AMS_REG_INT0 0x0a + #define AMS_INT_XRF (1<<0) + #define AMS_INT_TXE (1<<1) + #define AMS_INT_RXE (1<<2) + #define AMS_INT_EER_RF (1<<3) + #define AMS_INT_EEW_RF (1<<4) + #define AMS_INT_SLP (1<<5) + #define AMS_INT_WU_A (1<<6) + #define AMS_INT_INIT (1<<7) +#define AMS_REG_INT1 0x0b + #define AMS_INT_ACC_ERR (1<<0) + #define AMS_INT_EEAC_ERR (1<<1) + #define AMS_INT_IO_EEWR (1<<2) + #define AMS_INT_BF_ERR (1<<3) + #define AMS_INT_CRC_ERR (1<<4) + #define AMS_INT_PAR_ERR (1<<5) + #define AMS_INT_FRM_ERR (1<<6) + #define AMS_INT_RXS (1<<7) +#define AMS_REG_BUF2 0x0c + #define AMS_BUF_LEN_MASK 0x1f + #define AMS_BUF_INVALID 0x80 + +#define AMS_CONFIG_BLOCK0_ADDR 0x7e +#define AMS_CONFIG_BLOCK1_ADDR 0x7f + +#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2) + +#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00 +#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01 +#define AMS_CFG1_OUTPUT_RESISTANCE_50 0x02 +#define AMS_CFG1_OUTPUT_RESISTANCE_25 0x03 + +#define AMS_CFG2_RFCFG_EN (1<<7) +#define AMS_CFG2_TUN_MOD (1<<6) + +#define AMS_CMD_DEFAULT 0x02 +#define AMS_CMD_CLEAR_BUFFER 0x04 +#define AMS_CMD_RESTART_TRANSCEIVER 0x06 +#define AMS_CMD_DIS_EN_TRANSCEIVER 0x07 +#define AMS_CMD_TRANSMIT_BUFFER 0x08 +#define AMS_CMD_TRANSMIT_ACK 0x09 +#define AMS_CMD_TRANSMIT_NACK0 0x0A +#define AMS_CMD_TRANSMIT_NACK1 0x0B +#define AMS_CMD_TRANSMIT_NACK4 0x0D +#define AMS_CMD_TRANSMIT_NACK5 0x0C +#define AMS_CMD_SLEEP 0x10 +#define AMS_CMD_SENSE 0x11 +#define AMS_CMD_SENSE_SLEEP 0x12 + + + + +#endif diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 133f4c2..ed3e9d8 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -1,355 +1,50 @@ #include #include "stm32l4xx.h" -#include "stm32l4xx_ll_gpio.h" -#include "stm32l4xx_ll_spi.h" + #include "nfc.h" +#include "ams.h" #include "log.h" #include "util.h" +#include "device.h" -#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) -#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) +// Capability container + + +const CAPABILITY_CONTAINER NFC_CC = { + .cclen_hi = 0x00, .cclen_lo = 0x0f, + .version = 0x01, + .MLe_hi = 0x00, .MLe_lo = 0xff, + .MLc_hi = 0x00, .MLc_lo = 0xff, + .tlv = { 0x04,0x06, + 0x11,0x11, + 0x00,0xff, + 0x00,0xff } +}; + +uint8_t NDEF_SAMPLE[] = "\x00\x13\xD1\x01\x0ET\x02enHello World"; static struct { uint8_t max_frame_size; uint8_t cid; + uint8_t block_num; + uint8_t selected_applet; } NFC_STATE; - -static void flush_rx() +void nfc_state_init() { - while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0) - { - LL_SPI_ReceiveData8(SPI1); - } + memset(&NFC_STATE,0,sizeof(NFC_STATE)); + NFC_STATE.max_frame_size = 32; + NFC_STATE.block_num = 1; } -static void wait_for_tx() -{ - // while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) - // ; - while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY) - ; -} -static void wait_for_rx() -{ - while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0) - ; -} - - -static void ams_print_device(AMS_DEVICE * dev) -{ - printf1(TAG_NFC, "AMS_DEVICE:\r\n"); - printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); - printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0); - printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1); - printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2); - printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status); - printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status); - printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0); - printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1); - printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0); - printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1); - printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2); - printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1); - printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr); - printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type); - printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype); - printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj); - printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min); -} - -static uint8_t send_recv(uint8_t b) -{ - wait_for_tx(); - LL_SPI_TransmitData8(SPI1, b); - wait_for_rx(); - b = LL_SPI_ReceiveData8(SPI1); - return b; -} - - -static void ams_write_reg(uint8_t addr, uint8_t tx) -{ - send_recv(0x00| addr); - send_recv(tx); - - UNSELECT(); - SELECT(); -} - - -uint8_t ams_read_reg(uint8_t addr) -{ - send_recv(0x20| (addr & 0x1f)); - uint8_t data = send_recv(0); - UNSELECT(); - SELECT(); - return data; -} - -// data must be 14 bytes long -void read_reg_block2(AMS_DEVICE * dev) -{ - int i; - - for (i = 0; i < 0x20; i++) - { - dev->buf[i] = ams_read_reg(i); - } -} - - -// data must be 14 bytes long -void read_reg_block(AMS_DEVICE * dev) -{ - int i; - uint8_t mode = 0x20 | (0 ); - flush_rx(); - - send_recv(mode); - for (i = 0; i < 0x20; i++) - { - dev->buf[i] = send_recv(0); - } - - UNSELECT(); - SELECT(); -} - -void ams_read_buffer(uint8_t * data, int len) -{ - send_recv(0xa0); - while(len--) - { - *data++ = send_recv(0x00); - } - - UNSELECT(); - SELECT(); -} - -void ams_write_buffer(uint8_t * data, int len) -{ - send_recv(0x80); - while(len--) - { - send_recv(*data++); - } - - UNSELECT(); - SELECT(); -} - -// data must be 4 bytes -void ams_read_eeprom_block(uint8_t block, uint8_t * data) -{ - send_recv(0x7f); - send_recv(block << 1); - - data[0] = send_recv(0); - data[1] = send_recv(0); - data[2] = send_recv(0); - data[3] = send_recv(0); - - UNSELECT(); - SELECT(); -} - - -// data must be 4 bytes -void ams_write_eeprom_block(uint8_t block, uint8_t * data) -{ - send_recv(0x40); - send_recv(block << 1); - - send_recv(data[0]); - send_recv(data[1]); - send_recv(data[2]); - send_recv(data[3]); - - UNSELECT(); - SELECT(); -} - -void ams_write_command(uint8_t cmd) -{ - send_recv(0xc0 | cmd); - UNSELECT(); - SELECT(); -} - -const char * ams_get_state_string(uint8_t regval) -{ - if (regval & AMS_STATE_INVALID) - { - return "STATE_INVALID"; - } - switch (regval & AMS_STATE_MASK) - { - case AMS_STATE_OFF: - return "STATE_OFF"; - case AMS_STATE_SENSE: - return "STATE_SENSE"; - case AMS_STATE_RESOLUTION: - return "STATE_RESOLUTION"; - case AMS_STATE_RESOLUTION_L2: - return "STATE_RESOLUTION_L2"; - case AMS_STATE_SELECTED: - return "STATE_SELECTED"; - case AMS_STATE_SECTOR2: - return "STATE_SECTOR2"; - case AMS_STATE_SECTORX_2: - return "STATE_SECTORX_2"; - case AMS_STATE_SELECTEDX: - return "STATE_SELECTEDX"; - case AMS_STATE_SENSEX_L2: - return "STATE_SENSEX_L2"; - case AMS_STATE_SENSEX: - return "STATE_SENSEX"; - case AMS_STATE_SLEEP: - return "STATE_SLEEP"; - } - return "STATE_WRONG"; -} - -void ams_print_int0(uint8_t int0) -{ - uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); - printf1(TAG_NFC," "); - if (int0 & AMS_INT_XRF) - printf1(tag," XRF"); - if (int0 & AMS_INT_TXE) - printf1(tag," TXE"); - if (int0 & AMS_INT_RXE) - printf1(tag," RXE"); - if (int0 & AMS_INT_EER_RF) - printf1(tag," EER_RF"); - if (int0 & AMS_INT_EEW_RF) - printf1(tag," EEW_RF"); - if (int0 & AMS_INT_SLP) - printf1(tag," SLP"); - if (int0 & AMS_INT_WU_A) - printf1(tag," WU_A"); - if (int0 & AMS_INT_INIT) - printf1(tag," INIT"); - - printf1(tag,"\r\n"); -} - -void ams_print_int1(uint8_t int0) -{ - uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); - printf1(TAG_NFC," "); - if (int0 & AMS_INT_ACC_ERR) - printf1(tag," ACC_ERR"); - if (int0 & AMS_INT_EEAC_ERR) - printf1(tag," EEAC_ERR"); - if (int0 & AMS_INT_IO_EEWR) - printf1(tag," IO_EEWR"); - if (int0 & AMS_INT_BF_ERR) - printf1(tag," BF_ERR"); - if (int0 & AMS_INT_CRC_ERR) - printf1(tag," CRC_ERR"); - if (int0 & AMS_INT_PAR_ERR) - printf1(tag," PAR_ERR"); - if (int0 & AMS_INT_FRM_ERR) - printf1(tag," FRM_ERR"); - if (int0 & AMS_INT_RXS) - printf1(tag," RXS"); - - printf1(tag,"\r\n"); -} - void nfc_init() { - uint8_t block[4]; - - memset(&NFC_STATE,0,sizeof(NFC_STATE)); - NFC_STATE.max_frame_size = 32; - - LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); - LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); - - LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW); - LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); - LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); - LL_SPI_Enable(SPI1); - - delay(10); - SELECT(); - delay(10); - ams_write_command(AMS_CMD_DEFAULT); - ams_write_command(AMS_CMD_CLEAR_BUFFER); - - // enable tunneling mode and RF configuration - ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); - - ams_read_eeprom_block(0, block); - printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); - - ams_read_eeprom_block(0, block); - printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); - - ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); - - uint8_t sense1 = 0x44; - uint8_t sense2 = 0x00; - uint8_t selr = 0x20; // SAK - - if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) - { - printf1(TAG_NFC,"Writing config block 0\r\n"); - block[0] = sense1; - block[1] = sense2; - block[2] = selr; - block[3] = 0x00; - - ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - UNSELECT(); - delay(10); - SELECT(); - delay(10); - - ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); - } - - ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); - printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); - - uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; - uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; - - if (block[0] != ic_cfg1 || block[1] != ic_cfg2) - { - printf1(TAG_NFC,"Writing config block 1\r\n"); - // set IC_CFG1 - block[0] = ic_cfg1; - - // set IC_CFG2 - block[1] = ic_cfg2; - - // mask interrupt bits - block[2] = 0x80; - block[3] = 0; - - ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); - - UNSELECT(); - delay(10); - SELECT(); - delay(10); - - ams_read_eeprom_block(0x7F, block); - printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); - } - + nfc_state_init(); + ams_init(); } void nfc_write_frame(uint8_t * data, uint8_t len) @@ -396,16 +91,183 @@ int answer_rats(uint8_t parameter) return 0; } +void rblock_acknowledge() +{ + uint8_t buf[32]; + NFC_STATE.block_num = !NFC_STATE.block_num; + buf[0] = NFC_CMD_RBLOCK | NFC_STATE.block_num; + nfc_write_frame(buf,1); +} + +// Selects application. Returns 1 if success, 0 otherwise +int select_applet(uint8_t * aid, int len) +{ + if (memcmp(aid,AID_NDEF_TYPE_4,sizeof(AID_NDEF_TYPE_4)) == 0) + { + NFC_STATE.selected_applet = APP_NDEF_TYPE_4; + return 1; + } else if (memcmp(aid,AID_NDEF_MIFARE_TYPE_4,sizeof(AID_NDEF_MIFARE_TYPE_4)) == 0) + { + NFC_STATE.selected_applet = APP_MIFARE_TYPE_4; + return 1; + } else if (memcmp(aid,AID_CAPABILITY_CONTAINER,sizeof(AID_CAPABILITY_CONTAINER)) == 0) + { + NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER; + return 1; + } else if (memcmp(aid,AID_NDEF_TAG,sizeof(AID_NDEF_TAG)) == 0) + { + NFC_STATE.selected_applet = APP_NDEF_TAG; + return 1; + } + + return 0; +} + +void nfc_process_iblock(uint8_t * buf, int len) +{ + APDU_HEADER * apdu = (APDU_HEADER *)(buf+1); + uint8_t * payload = buf + 1 + 5; + uint8_t plen = apdu->lc; + int selected; + uint8_t res[32]; + + printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC,buf,len); + + + // TODO this needs to be organized better + switch(apdu->ins) + { + case APDU_INS_SELECT: + if (plen > len - 6) + { + printf1(TAG_ERR, "Truncating APDU length %d\r\n", apdu->lc); + plen = len-6; + } + // if (apdu->p1 == 0 && apdu->p2 == 0x0c) + // { + // printf1(TAG_NFC,"Select NDEF\r\n"); + // + // NFC_STATE.selected_applet = APP_NDEF_TAG; + // // Select NDEF file! + // res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); + // res[1] = APDU_STATUS_SUCCESS>>8; + // res[2] = APDU_STATUS_SUCCESS & 0xff; + // nfc_write_frame(res, 3); + // printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3); + // } + // else + { + selected = select_applet(payload, plen); + if (selected) + { + + // block = buf[0] & 1; + // block = NFC_STATE.block_num; + // block = !block; + // NFC_STATE.block_num = block; + res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); + res[1] = APDU_STATUS_SUCCESS>>8; + res[2] = APDU_STATUS_SUCCESS & 0xff; + nfc_write_frame(res, 3); + printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3); + } + else + { + printf1(TAG_NFC, "NOT selected\r\n"); + } + } + break; + case APDU_INS_READ_BINARY: + + + switch(NFC_STATE.selected_applet) + { + case APP_CAPABILITY_CONTAINER: + printf1(TAG_NFC,"APP_CAPABILITY_CONTAINER\r\n"); + if (plen > 15) + { + printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); + plen = 15; + } + memmove(res+1, &NFC_CC, plen); + break; + case APP_NDEF_TAG: + printf1(TAG_NFC,"APP_NDEF_TAG\r\n"); + if (plen > (sizeof(NDEF_SAMPLE) - 1)) + { + printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); + plen = sizeof(NDEF_SAMPLE) - 1; + } + memmove(res+1, NDEF_SAMPLE, plen); + break; + default: + printf1(TAG_ERR, "No binary applet selected!\r\n"); + return; + break; + } + res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); + + res[1+plen] = APDU_STATUS_SUCCESS>>8; + res[2+plen] = APDU_STATUS_SUCCESS & 0xff; + nfc_write_frame(res, 3+plen); + printf1(TAG_NFC,"APDU_INS_READ_BINARY\r\n"); + printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3+plen); + break; + default: + printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu->ins); + break; + } + + +} + +void nfc_process_block(uint8_t * buf, int len) +{ + if (IS_PPSS_CMD(buf[0])) + { + printf1(TAG_NFC, "NFC_CMD_PPSS\r\n"); + } + else if (IS_IBLOCK(buf[0])) + { + nfc_process_iblock(buf,len); + printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + } + else if (IS_RBLOCK(buf[0])) + { + rblock_acknowledge(); + printf1(TAG_NFC, "NFC_CMD_RBLOCK\r\n"); + } + else if (IS_SBLOCK(buf[0])) + { + + if ((buf[0] & NFC_SBLOCK_DESELECT) == 0) + { + nfc_write_frame(buf, 1); + printf1(TAG_NFC, "NFC_CMD_SBLOCK, DESELECTED\r\n"); + nfc_state_init(); + } + else + { + printf1(TAG_NFC, "NFC_CMD_SBLOCK, Unknown\r\n"); + } + dump_hex1(TAG_NFC, buf, len); + } + else + { + printf1(TAG_NFC, "unknown NFC request\r\n len[%d]:", len); + dump_hex1(TAG_NFC, buf, len); + } +} + void nfc_loop() { - - const uint32_t interval = 200; static uint32_t t1 = 0; - static uint32_t c = 0; uint8_t buf[32]; - AMS_DEVICE ams,ams2; + AMS_DEVICE ams; int len = 0; - uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00"; + // uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00"; + + // if (millis() - t1 > interval) if (1) { @@ -417,17 +279,14 @@ void nfc_loop() // } if (ams.regs.rfid_status) { - uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; + // uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; // if (state != AMS_STATE_SENSE) // printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis()); } - if (ams.regs.int0) + if (ams.regs.int0 & AMS_INT_INIT) { - // ams_print_int0(ams.regs.int0); - if (ams.regs.int0 & AMS_INT_XRF) - { - printf1(TAG_NFC," %d\r\n", millis()); - } + // Initialize chip! + nfc_state_init(); } if (ams.regs.int1) { @@ -443,15 +302,13 @@ void nfc_loop() { len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; ams_read_buffer(buf, len); - // printf1(TAG_NFC,"%d bytes in buffer\r\n", len); - // dump_hex1(TAG_NFC, buf, len); } } if (len) { - // printf1(TAG_NFC,"RATS %d\r\n",c++); - // ams_write_command(AMS_CMD_TRANSMIT_ACK); + + // ISO 14443-3 switch(buf[0]) { case NFC_CMD_REQA: @@ -466,31 +323,14 @@ void nfc_loop() case NFC_CMD_RATS: t1 = millis(); answer_rats(buf[1]); + NFC_STATE.block_num = 1; printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: - if (IS_PPSS_CMD(buf[0])) - { - printf1(TAG_NFC, "NFC_CMD_PPSS\r\n"); - } - else if (IS_IBLOCK(buf[0])) - { - printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); - } - else if (IS_RBLOCK(buf[0])) - { - printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); - } - else if (IS_SBLOCK(buf[0])) - { - printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); - } - else - { - printf1(TAG_NFC, "unknown NFC request\r\n len[%d]:", len); - dump_hex1(TAG_NFC, buf, len); - } + // ISO 14443-4 + nfc_process_block(buf,len); + break; } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 7cc9556..8a91803 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -6,109 +6,26 @@ void nfc_loop(); void nfc_init(); -typedef union +typedef struct { - uint8_t buf[0x20]; - struct { - uint8_t io_conf; // 0x00 - uint8_t ic_conf0; // 0x01 - uint8_t ic_conf1; // 0x02 - uint8_t ic_conf2; // 0x03 - uint8_t rfid_status; // 0x04 - uint8_t ic_status; // 0x05 - uint8_t _nc0[2]; // 0x06 - 0x07 - uint8_t mask_int0; // 0x08 - uint8_t mask_int1; // 0x09 - uint8_t int0; // 0x0a - uint8_t int1; // 0x0b - uint8_t buffer_status2; // 0x0c - uint8_t buffer_status1; // 0x0d - uint8_t last_nfc_addr; // 0x0e - uint8_t _nc1[0x1b - 0x0f + 1]; // 0x0f - 0x1b - uint8_t product_type; // 0x1c - uint8_t product_subtype; // 0x1d - uint8_t version_maj; // 0x1e - uint8_t version_min; // 0x1f - } regs; -} __attribute__((packed)) AMS_DEVICE; + uint8_t cclen_hi; + uint8_t cclen_lo; + uint8_t version; + uint8_t MLe_hi; + uint8_t MLe_lo; + uint8_t MLc_hi; + uint8_t MLc_lo; + uint8_t tlv[8]; +} __attribute__((packed)) CAPABILITY_CONTAINER; typedef struct { - uint8_t start; - uint8_t parameter; -} __attribute__((packed)) RATS_REQUEST; - -#define AMS_REG_IO_CONF 0x00 -#define AMS_REG_IC_CONF0 0x01 -#define AMS_REG_IC_CONF1 0x02 -#define AMS_REG_IC_CONF2 0x03 - #define AMS_RFCFG_EN 0x80 - #define AMS_TUN_MOD 0x40 -#define AMS_REG_RFID_STATUS 0x04 - #define AMS_HF_PON 0x80 - #define AMS_STATE_MASK 0x78 - #define AMS_STATE_INVALID 0x04 - #define AMS_STATE_OFF (0 << 3) - #define AMS_STATE_SENSE (1 << 3) - #define AMS_STATE_RESOLUTION (3 << 3) - #define AMS_STATE_RESOLUTION_L2 (2 << 3) - #define AMS_STATE_SELECTED (6 << 3) - #define AMS_STATE_SECTOR2 (7 << 3) - #define AMS_STATE_SECTORX_2 (0xf << 3) - #define AMS_STATE_SELECTEDX (0xd << 3) - #define AMS_STATE_SENSEX_L2 (0xa << 3) - #define AMS_STATE_SENSEX (0xb << 3) - #define AMS_STATE_SLEEP (0x9 << 3) -// ... // -#define AMS_REG_INT0 0x0a - #define AMS_INT_XRF (1<<0) - #define AMS_INT_TXE (1<<1) - #define AMS_INT_RXE (1<<2) - #define AMS_INT_EER_RF (1<<3) - #define AMS_INT_EEW_RF (1<<4) - #define AMS_INT_SLP (1<<5) - #define AMS_INT_WU_A (1<<6) - #define AMS_INT_INIT (1<<7) -#define AMS_REG_INT1 0x0b - #define AMS_INT_ACC_ERR (1<<0) - #define AMS_INT_EEAC_ERR (1<<1) - #define AMS_INT_IO_EEWR (1<<2) - #define AMS_INT_BF_ERR (1<<3) - #define AMS_INT_CRC_ERR (1<<4) - #define AMS_INT_PAR_ERR (1<<5) - #define AMS_INT_FRM_ERR (1<<6) - #define AMS_INT_RXS (1<<7) -#define AMS_REG_BUF2 0x0c - #define AMS_BUF_LEN_MASK 0x1f - #define AMS_BUF_INVALID 0x80 - -#define AMS_CONFIG_BLOCK0_ADDR 0x7e -#define AMS_CONFIG_BLOCK1_ADDR 0x7f - -#define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2) -#define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2) - -#define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00 -#define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01 -#define AMS_CFG1_OUTPUT_RESISTANCE_50 0x02 -#define AMS_CFG1_OUTPUT_RESISTANCE_25 0x03 - -#define AMS_CFG2_RFCFG_EN (1<<7) -#define AMS_CFG2_TUN_MOD (1<<6) - -#define AMS_CMD_DEFAULT 0x02 -#define AMS_CMD_CLEAR_BUFFER 0x04 -#define AMS_CMD_RESTART_TRANSCEIVER 0x06 -#define AMS_CMD_DIS_EN_TRANSCEIVER 0x07 -#define AMS_CMD_TRANSMIT_BUFFER 0x08 -#define AMS_CMD_TRANSMIT_ACK 0x09 -#define AMS_CMD_TRANSMIT_NACK0 0x0A -#define AMS_CMD_TRANSMIT_NACK1 0x0B -#define AMS_CMD_TRANSMIT_NACK4 0x0D -#define AMS_CMD_TRANSMIT_NACK5 0x0C -#define AMS_CMD_SLEEP 0x10 -#define AMS_CMD_SENSE 0x11 -#define AMS_CMD_SENSE_SLEEP 0x12 + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t lc; +} __attribute__((packed)) APDU_HEADER; #define NFC_CMD_REQA 0x26 #define NFC_CMD_WUPA 0x52 @@ -117,11 +34,31 @@ typedef struct #define NFC_CMD_PPSS 0xd0 #define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS) -#define NFC_CMD_IBLOCK 0x00 -#define IS_IBLOCK(x) (((x) & 0xe0) == NFC_CMD_IBLOCK) -#define NFC_CMD_RBLOCK 0xa0 -#define IS_RBLOCK(x) (((x) & 0xe0) == NFC_CMD_RBLOCK) -#define NFC_CMD_SBLOCK 0xc0 -#define IS_SBLOCK(x) (((x) & 0xc0) == NFC_CMD_SBLOCK) +#define NFC_CMD_IBLOCK 0x02 +#define IS_IBLOCK(x) (((x) & 0xe2) == NFC_CMD_IBLOCK) +#define NFC_CMD_RBLOCK 0xa2 +#define IS_RBLOCK(x) (((x) & 0xe6) == NFC_CMD_RBLOCK) +#define NFC_CMD_SBLOCK 0xc2 +#define IS_SBLOCK(x) (((x) & 0xc7) == NFC_CMD_SBLOCK) + +#define NFC_SBLOCK_DESELECT 0x30 + +#define APDU_INS_SELECT 0xA4 +#define APDU_INS_READ_BINARY 0xB0 + +#define AID_NDEF_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x01" +#define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00" +#define AID_CAPABILITY_CONTAINER "\xE1\x03" +#define AID_NDEF_TAG "\x11\x11" + +typedef enum +{ + APP_NDEF_TYPE_4 = 1, + APP_MIFARE_TYPE_4, + APP_CAPABILITY_CONTAINER, + APP_NDEF_TAG, +} APPLETS; + +#define APDU_STATUS_SUCCESS 0x9000 #endif diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index 431bc18..d3d5e5d 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -53,7 +53,7 @@ int _write (int fd, const void *buf, long int len) // Send out UART serial while(len--) { - _putchar(*data++); + // _putchar(*data++); } return 0; } From 4e0dc15dfd19c2919e229759f51361692edae3a0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 16:56:38 +0200 Subject: [PATCH 16/96] add historical bytes --- targets/stm32l432/src/nfc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index ed3e9d8..936f979 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -74,8 +74,8 @@ int answer_rats(uint8_t parameter) else NFC_STATE.max_frame_size = 32; - uint8_t res[3]; - res[0] = 3; + uint8_t res[3 + 11]; + res[0] = sizeof(res); res[1] = 2 | (1<<5); // 2 FSCI == 32 byte frame size, TB is enabled // frame wait time = (256 * 16 / 13.56MHz) * 2^FWI @@ -86,8 +86,10 @@ int answer_rats(uint8_t parameter) // FWI=14, FMT=4949ms (max) res[2] = (12<<4) | (0); // TB (FWI << 4) | (SGTI) - - nfc_write_frame(res,3); + // historical bytes + memcpy(&res[3], (uint8_t *)"SoloKey tap", 11); + + nfc_write_frame(res, sizeof(res)); return 0; } From ad9186c13baf8a0cb0de740dc3855bba542aac89 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 17:57:42 +0200 Subject: [PATCH 17/96] SELECT works --- targets/stm32l432/src/nfc.c | 30 ++++++++---------------------- targets/stm32l432/src/nfc.h | 17 ++++++++++------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 936f979..d4f01e3 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -104,37 +104,24 @@ void rblock_acknowledge() // Selects application. Returns 1 if success, 0 otherwise int select_applet(uint8_t * aid, int len) { - if (memcmp(aid,AID_NDEF_TYPE_4,sizeof(AID_NDEF_TYPE_4)) == 0) + if (memcmp(aid,AID_FIDO,sizeof(AID_FIDO)) == 0) { - NFC_STATE.selected_applet = APP_NDEF_TYPE_4; - return 1; - } else if (memcmp(aid,AID_NDEF_MIFARE_TYPE_4,sizeof(AID_NDEF_MIFARE_TYPE_4)) == 0) - { - NFC_STATE.selected_applet = APP_MIFARE_TYPE_4; - return 1; - } else if (memcmp(aid,AID_CAPABILITY_CONTAINER,sizeof(AID_CAPABILITY_CONTAINER)) == 0) - { - NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER; - return 1; - } else if (memcmp(aid,AID_NDEF_TAG,sizeof(AID_NDEF_TAG)) == 0) - { - NFC_STATE.selected_applet = APP_NDEF_TAG; + NFC_STATE.selected_applet = APP_FIDO; return 1; } - return 0; } void nfc_process_iblock(uint8_t * buf, int len) { - APDU_HEADER * apdu = (APDU_HEADER *)(buf+1); + APDU_HEADER * apdu = (APDU_HEADER *)(buf + 1); uint8_t * payload = buf + 1 + 5; uint8_t plen = apdu->lc; int selected; uint8_t res[32]; - printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC,buf,len); - + printf1(TAG_NFC,">> "); + dump_hex1(TAG_NFC, buf, len); // TODO this needs to be organized better switch(apdu->ins) @@ -162,13 +149,12 @@ void nfc_process_iblock(uint8_t * buf, int len) selected = select_applet(payload, plen); if (selected) { - // block = buf[0] & 1; // block = NFC_STATE.block_num; // block = !block; // NFC_STATE.block_num = block; - res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); - res[1] = APDU_STATUS_SUCCESS>>8; + res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); + res[1] = APDU_STATUS_SUCCESS >> 8; res[2] = APDU_STATUS_SUCCESS & 0xff; nfc_write_frame(res, 3); printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3); @@ -231,8 +217,8 @@ void nfc_process_block(uint8_t * buf, int len) } else if (IS_IBLOCK(buf[0])) { - nfc_process_iblock(buf,len); printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + nfc_process_iblock(buf, len); } else if (IS_RBLOCK(buf[0])) { diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 8a91803..457b686 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -34,14 +34,15 @@ typedef struct #define NFC_CMD_PPSS 0xd0 #define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS) -#define NFC_CMD_IBLOCK 0x02 -#define IS_IBLOCK(x) (((x) & 0xe2) == NFC_CMD_IBLOCK) -#define NFC_CMD_RBLOCK 0xa2 -#define IS_RBLOCK(x) (((x) & 0xe6) == NFC_CMD_RBLOCK) -#define NFC_CMD_SBLOCK 0xc2 -#define IS_SBLOCK(x) (((x) & 0xc7) == NFC_CMD_SBLOCK) +#define NFC_CMD_IBLOCK 0x00 +#define IS_IBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_IBLOCK) && (((x) & 0x02) == 0x02) ) +#define NFC_CMD_RBLOCK 0x80 +#define IS_RBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_RBLOCK) && (((x) & 0x02) == 0x02) ) +#define NFC_CMD_SBLOCK 0xc0 +#define IS_SBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_SBLOCK) && (((x) & 0x02) == 0x02) ) -#define NFC_SBLOCK_DESELECT 0x30 +#define NFC_SBLOCK_DESELECT 0x32 +#define NFC_SBLOCK_WTX 0xf2 #define APDU_INS_SELECT 0xA4 #define APDU_INS_READ_BINARY 0xB0 @@ -50,6 +51,7 @@ typedef struct #define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00" #define AID_CAPABILITY_CONTAINER "\xE1\x03" #define AID_NDEF_TAG "\x11\x11" +#define AID_FIDO "\xa0\x00\x00\x06\x47\x2f\x00\x01" typedef enum { @@ -57,6 +59,7 @@ typedef enum APP_MIFARE_TYPE_4, APP_CAPABILITY_CONTAINER, APP_NDEF_TAG, + APP_FIDO, } APPLETS; #define APDU_STATUS_SUCCESS 0x9000 From d02206ba09387a8a414bdbd2e7dff5e20fc4374f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 18:19:23 +0200 Subject: [PATCH 18/96] SELECT works as expected and U2F GetVersion command done --- targets/stm32l432/src/nfc.c | 32 +++++++++++++++++++++++++++----- targets/stm32l432/src/nfc.h | 4 ++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index d4f01e3..5030ae5 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -154,17 +154,39 @@ void nfc_process_iblock(uint8_t * buf, int len) // block = !block; // NFC_STATE.block_num = block; res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); - res[1] = APDU_STATUS_SUCCESS >> 8; - res[2] = APDU_STATUS_SUCCESS & 0xff; - nfc_write_frame(res, 3); - printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3); + memcpy(&res[1], (uint8_t *)"U2F_V2", 6); + res[7] = APDU_STATUS_SUCCESS >> 8; + res[8] = APDU_STATUS_SUCCESS & 0xff; + nfc_write_frame(res, 3 + 6); + printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3 + 6); } else { - printf1(TAG_NFC, "NOT selected\r\n"); + res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); + res[1] = 0x6a; + res[2] = 0x82; + nfc_write_frame(res, 3); + printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC,res, 3); } } break; + + case APDU_FIDO_U2F_VERSION: + printf1(TAG_NFC, "GetVersion command.\r\n"); + res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); + memcpy(&res[1], (uint8_t *)"U2F_V2", 6); + res[7] = APDU_STATUS_SUCCESS >> 8; + res[8] = APDU_STATUS_SUCCESS & 0xff; + nfc_write_frame(res, 3 + 6); + printf1(TAG_NFC, "<< "); dump_hex1(TAG_NFC,res, 3 + 6); + break; + + case APDU_FIDO_U2F_REGISTER: + break; + + case APDU_FIDO_U2F_AUTHENTICATE: + break; + case APDU_INS_READ_BINARY: diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 457b686..d42e1ce 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -44,6 +44,10 @@ typedef struct #define NFC_SBLOCK_DESELECT 0x32 #define NFC_SBLOCK_WTX 0xf2 +#define APDU_FIDO_U2F_REGISTER 0x01 +#define APDU_FIDO_U2F_AUTHENTICATE 0x02 +#define APDU_FIDO_U2F_VERSION 0x03 +#define APDU_FIDO_EXCHANGE 0x10 #define APDU_INS_SELECT 0xA4 #define APDU_INS_READ_BINARY 0xB0 From 45888c9a25adb4f918825b3005e5f6074596c82b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 18:22:58 +0200 Subject: [PATCH 19/96] ins check is ok --- targets/stm32l432/src/nfc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 5030ae5..a5b1124 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -172,7 +172,7 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_U2F_VERSION: - printf1(TAG_NFC, "GetVersion command.\r\n"); + printf1(TAG_NFC, "U2F GetVersion command.\r\n"); res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); memcpy(&res[1], (uint8_t *)"U2F_V2", 6); res[7] = APDU_STATUS_SUCCESS >> 8; @@ -182,9 +182,15 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_U2F_REGISTER: + printf1(TAG_NFC, "U2F Register command.\r\n"); break; case APDU_FIDO_U2F_AUTHENTICATE: + printf1(TAG_NFC, "U2F Authenticate command.\r\n"); + break; + + case APDU_FIDO_EXCHANGE: + printf1(TAG_NFC, "FIDO2 Exchange command.\r\n"); break; case APDU_INS_READ_BINARY: From d713167ec4a8e2349e2963c3f9ef58c05e9e1683 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 19:21:31 +0200 Subject: [PATCH 20/96] works. needs to add chaining --- targets/stm32l432/src/nfc.c | 18 +++++++++++++++--- targets/stm32l432/src/nfc.h | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index a5b1124..6640179 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -120,6 +120,9 @@ void nfc_process_iblock(uint8_t * buf, int len) int selected; uint8_t res[32]; + CTAP_RESPONSE ctap_resp; + int status; + printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC, buf, len); @@ -173,24 +176,33 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_VERSION: printf1(TAG_NFC, "U2F GetVersion command.\r\n"); + res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); memcpy(&res[1], (uint8_t *)"U2F_V2", 6); res[7] = APDU_STATUS_SUCCESS >> 8; res[8] = APDU_STATUS_SUCCESS & 0xff; nfc_write_frame(res, 3 + 6); - printf1(TAG_NFC, "<< "); dump_hex1(TAG_NFC,res, 3 + 6); + printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3 + 6); break; case APDU_FIDO_U2F_REGISTER: printf1(TAG_NFC, "U2F Register command.\r\n"); + break; case APDU_FIDO_U2F_AUTHENTICATE: printf1(TAG_NFC, "U2F Authenticate command.\r\n"); break; - case APDU_FIDO_EXCHANGE: - printf1(TAG_NFC, "FIDO2 Exchange command.\r\n"); + case APDU_FIDO_NFCCTAP_MSG: + printf1(TAG_NFC, "FIDO2 CTAP message.\r\n"); + + ctap_response_init(&ctap_resp); + status = ctap_request(payload, plen, &ctap_resp); + printf1(TAG_NFC, "status: %d\r\n", status); + + nfc_write_frame(ctap_resp.data, ctap_resp.length); + printf1(TAG_NFC, "<< "); dump_hex1(TAG_NFC, ctap_resp.data, ctap_resp.length); break; case APDU_INS_READ_BINARY: diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index d42e1ce..2eca2e8 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -47,7 +47,7 @@ typedef struct #define APDU_FIDO_U2F_REGISTER 0x01 #define APDU_FIDO_U2F_AUTHENTICATE 0x02 #define APDU_FIDO_U2F_VERSION 0x03 -#define APDU_FIDO_EXCHANGE 0x10 +#define APDU_FIDO_NFCCTAP_MSG 0x10 #define APDU_INS_SELECT 0xA4 #define APDU_INS_READ_BINARY 0xB0 From 67b0abde4bd609cd3eaa90bab334dc92a3cf5e13 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 19:56:18 +0200 Subject: [PATCH 21/96] some refactoring --- targets/stm32l432/src/nfc.c | 69 +++++++++++++++++++++++++------------ targets/stm32l432/src/nfc.h | 5 ++- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 6640179..0c2b3a6 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -8,6 +8,9 @@ #include "util.h" #include "device.h" +#include "ctap_errors.h" + + // Capability container @@ -57,6 +60,36 @@ void nfc_write_frame(uint8_t * data, uint8_t len) ams_write_buffer(data,len); ams_write_command(AMS_CMD_TRANSMIT_BUFFER); + printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC, data, len); +} + +void nfc_write_response_chaining(uint8_t req0, uint8_t * data, uint8_t len) +{ + nfc_write_frame(data, len); +} + +bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t resp) +{ + uint8_t res[32]; + + if (len > 32 - 3) + return false; + + res[0] = NFC_CMD_IBLOCK | (req0 & 3); + + if (len) + memcpy(&res[1], data, len); + + res[len + 1] = resp >> 8; + res[len + 2] = resp & 0xff; + nfc_write_frame(res, 3 + len); + + return true; +} + +bool nfc_write_response(uint8_t req0, uint16_t resp) +{ + return nfc_write_response_ex(req0, NULL, 0, resp); } int answer_rats(uint8_t parameter) @@ -142,8 +175,8 @@ void nfc_process_iblock(uint8_t * buf, int len) // NFC_STATE.selected_applet = APP_NDEF_TAG; // // Select NDEF file! // res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); - // res[1] = APDU_STATUS_SUCCESS>>8; - // res[2] = APDU_STATUS_SUCCESS & 0xff; + // res[1] = SW_SUCCESS>>8; + // res[2] = SW_SUCCESS & 0xff; // nfc_write_frame(res, 3); // printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3); // } @@ -156,19 +189,11 @@ void nfc_process_iblock(uint8_t * buf, int len) // block = NFC_STATE.block_num; // block = !block; // NFC_STATE.block_num = block; - res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); - memcpy(&res[1], (uint8_t *)"U2F_V2", 6); - res[7] = APDU_STATUS_SUCCESS >> 8; - res[8] = APDU_STATUS_SUCCESS & 0xff; - nfc_write_frame(res, 3 + 6); - printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3 + 6); + nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); } else { - res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); - res[1] = 0x6a; - res[2] = 0x82; - nfc_write_frame(res, 3); + nfc_write_response(buf[0], SW_FILE_NOT_FOUND); printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC,res, 3); } } @@ -177,12 +202,7 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_VERSION: printf1(TAG_NFC, "U2F GetVersion command.\r\n"); - res[0] = NFC_CMD_IBLOCK | (buf[0] & 3); - memcpy(&res[1], (uint8_t *)"U2F_V2", 6); - res[7] = APDU_STATUS_SUCCESS >> 8; - res[8] = APDU_STATUS_SUCCESS & 0xff; - nfc_write_frame(res, 3 + 6); - printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3 + 6); + nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); break; case APDU_FIDO_U2F_REGISTER: @@ -201,8 +221,12 @@ void nfc_process_iblock(uint8_t * buf, int len) status = ctap_request(payload, plen, &ctap_resp); printf1(TAG_NFC, "status: %d\r\n", status); - nfc_write_frame(ctap_resp.data, ctap_resp.length); - printf1(TAG_NFC, "<< "); dump_hex1(TAG_NFC, ctap_resp.data, ctap_resp.length); + if (status == CTAP1_ERR_SUCCESS) + { + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + } else { + nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION | status); + } break; case APDU_INS_READ_BINARY: @@ -235,14 +259,15 @@ void nfc_process_iblock(uint8_t * buf, int len) } res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); - res[1+plen] = APDU_STATUS_SUCCESS>>8; - res[2+plen] = APDU_STATUS_SUCCESS & 0xff; + res[1+plen] = SW_SUCCESS>>8; + res[2+plen] = SW_SUCCESS & 0xff; nfc_write_frame(res, 3+plen); printf1(TAG_NFC,"APDU_INS_READ_BINARY\r\n"); printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3+plen); break; default: printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu->ins); + nfc_write_response(buf[0], SW_INS_INVALID); break; } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 2eca2e8..803bf26 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -66,6 +66,9 @@ typedef enum APP_FIDO, } APPLETS; -#define APDU_STATUS_SUCCESS 0x9000 +#define SW_SUCCESS 0x9000 +#define SW_FILE_NOT_FOUND 0x6a82 +#define SW_INS_INVALID 0x6d00 +#define SW_INTERNAL_EXCEPTION 0x6f00 #endif From e8634a2d615a5224f72a745e0cdaf5653ddb026b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 20:04:44 +0200 Subject: [PATCH 22/96] add u2f errors --- targets/stm32l432/src/nfc.c | 3 +++ targets/stm32l432/src/nfc.h | 1 + 2 files changed, 4 insertions(+) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 0c2b3a6..3590d5d 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -208,10 +208,13 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_REGISTER: printf1(TAG_NFC, "U2F Register command.\r\n"); + nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); break; case APDU_FIDO_U2F_AUTHENTICATE: printf1(TAG_NFC, "U2F Authenticate command.\r\n"); + + nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); break; case APDU_FIDO_NFCCTAP_MSG: diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 803bf26..d80155a 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -67,6 +67,7 @@ typedef enum } APPLETS; #define SW_SUCCESS 0x9000 +#define SW_COND_USE_NOT_SATISFIED 0x6985 #define SW_FILE_NOT_FOUND 0x6a82 #define SW_INS_INVALID 0x6d00 #define SW_INTERNAL_EXCEPTION 0x6f00 From 94fe58d020424f88d613c0a98dd0fbbf6ca84f29 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 24 Jan 2019 20:09:57 +0200 Subject: [PATCH 23/96] small fix --- targets/stm32l432/src/nfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 3590d5d..b4f26f0 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -77,7 +77,7 @@ bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t r res[0] = NFC_CMD_IBLOCK | (req0 & 3); - if (len) + if (len && data) memcpy(&res[1], data, len); res[len + 1] = resp >> 8; @@ -222,7 +222,7 @@ void nfc_process_iblock(uint8_t * buf, int len) ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); - printf1(TAG_NFC, "status: %d\r\n", status); + printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) { From 15de8dc4a6db920458c4efb29e3803e0702a260e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 25 Jan 2019 19:32:42 +0200 Subject: [PATCH 24/96] send response from key to pc in chaining mode. partially works. GetVersion must work with pc (proxmark have errors) --- targets/stm32l432/src/nfc.c | 135 +++++++++++++++++++++++++++++++++--- targets/stm32l432/src/nfc.h | 1 + 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index b4f26f0..d78b0ed 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -44,11 +44,66 @@ void nfc_state_init() void nfc_init() { - - nfc_state_init(); ams_init(); } +void process_int0(uint8_t int0) +{ + +} + +bool ams_wait_for_tx(uint32_t timeout_ms) +{ + uint32_t tstart = millis(); + while (tstart + timeout_ms > millis()) + { + uint8_t int0 = ams_read_reg(AMS_REG_INT0); + if (int0) process_int0(int0); + if (int0 & AMS_INT_TXE) + return true; + + delay(1); + } + + return false; +} + +//bool ams_receive_with_timeout(10, recbuf, sizeof(recbuf), &reclen)) +bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, int *dlen) +{ + uint8_t buf[32]; + *dlen = 0; + + uint32_t tstart = millis(); + while (tstart + timeout_ms > millis()) + { + uint8_t int0 = ams_read_reg(AMS_REG_INT0); + uint8_t buffer_status2 = ams_read_reg(AMS_REG_BUF2); + + if (buffer_status2 && (int0 & AMS_INT_RXE)) + { + if (buffer_status2 & AMS_BUF_INVALID) + { + printf1(TAG_NFC,"Buffer being updated!\r\n"); + } + else + { + uint8_t len = buffer_status2 & AMS_BUF_LEN_MASK; + ams_read_buffer(buf, len); + printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC, buf, len); + + *dlen = MIN(32, MIN(maxlen, len)); + memcpy(data, buf, *dlen); + + return true; + } + } + + delay(1); + } + + return false; +} void nfc_write_frame(uint8_t * data, uint8_t len) { @@ -63,11 +118,6 @@ void nfc_write_frame(uint8_t * data, uint8_t len) printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC, data, len); } -void nfc_write_response_chaining(uint8_t req0, uint8_t * data, uint8_t len) -{ - nfc_write_frame(data, len); -} - bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t resp) { uint8_t res[32]; @@ -92,6 +142,72 @@ bool nfc_write_response(uint8_t req0, uint16_t resp) return nfc_write_response_ex(req0, NULL, 0, resp); } +void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len, uint16_t resp) +{ + uint8_t res[32 + 2]; + int sendlen = 0; + uint8_t iBlock = NFC_CMD_IBLOCK | (req0 & 3); +printf1(TAG_NFC,"-- chain \r\n"); + if (len <= 32) + { + nfc_write_response_ex(req0, data, len, resp); + } else { + do { + // transmit I block + int vlen = MIN(31, len - sendlen); + res[0] = iBlock; + memcpy(&res[1], &data[sendlen], vlen); + if (vlen + sendlen < len) + { + res[0] |= 0x10; + } else { + // here may be buffer overflow!!! + res[vlen + 1] = resp >> 8; + res[vlen + 2] = resp & 0xff; + vlen += 2; + } + + nfc_write_frame(res, vlen + 1); + sendlen += vlen; + + printf1(TAG_NFC,"-- slen: %d res0: %02x\r\n", sendlen, res[0]); + + // wait for transmit (32 bytes aprox 2,5ms) + if (!ams_wait_for_tx(10)) + { + printf1(TAG_NFC, "TX timeout. slen: %d \r\n", sendlen); + break; + } + + // receive R block + if (res[0] & 0x10) + { + uint8_t recbuf[32] = {0}; + int reclen; + if (!ams_receive_with_timeout(100, recbuf, sizeof(recbuf), &reclen)) + { + printf1(TAG_NFC, "R block RX timeout.\r\n"); + break; + } + + if (reclen != 1) + { + printf1(TAG_NFC, "R block length error. len: %d \r\n", reclen); + break; + } + + if (((recbuf[0] & 0x01) != (res[0] & 1)) && ((recbuf[0] & 0xf6) == 0xa2)) + { + printf1(TAG_NFC, "R block error. txdata: %02x rxdata: %02x \r\n", res[0], recbuf[0]); + //break; + } + } + + iBlock ^= 0x01; + } while (sendlen < len); + } +} + int answer_rats(uint8_t parameter) { @@ -226,7 +342,7 @@ void nfc_process_iblock(uint8_t * buf, int len) if (status == CTAP1_ERR_SUCCESS) { - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, SW_SUCCESS); } else { nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION | status); } @@ -329,6 +445,9 @@ void nfc_loop() { t1 = millis(); read_reg_block(&ams); + + process_int0(ams.regs.int0); + // if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0) // { // printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index d80155a..16257a7 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -67,6 +67,7 @@ typedef enum } APPLETS; #define SW_SUCCESS 0x9000 +#define SW_GET_RESPONSE 0x6100 //Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. #define SW_COND_USE_NOT_SATISFIED 0x6985 #define SW_FILE_NOT_FOUND 0x6a82 #define SW_INS_INVALID 0x6d00 From cde6bc107a153b98b44b3e6f0a69daa572395273 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 25 Jan 2019 19:54:02 +0200 Subject: [PATCH 25/96] GetVersion works. not so clean. needs additional memory.... --- targets/stm32l432/src/nfc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index d78b0ed..3a6658f 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -342,7 +342,10 @@ void nfc_process_iblock(uint8_t * buf, int len) if (status == CTAP1_ERR_SUCCESS) { - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, SW_SUCCESS); + uint8_t ctapdata[1024] = {0}; + ctapdata[0] = status; + memcpy(&ctapdata[1], ctap_resp.data, ctap_resp.length); + nfc_write_response_chaining(buf[0], ctapdata, ctap_resp.length + 1, SW_SUCCESS); } else { nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION | status); } From ffa42258274490f4872e0f4d0fb63dda3f9da269 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 19:07:12 +0200 Subject: [PATCH 26/96] chip have too less memory. so reusing ctap_resp buffer. --- targets/stm32l432/src/nfc.c | 42 +++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 3a6658f..e8f04ef 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -142,31 +142,33 @@ bool nfc_write_response(uint8_t req0, uint16_t resp) return nfc_write_response_ex(req0, NULL, 0, resp); } -void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len, uint16_t resp) +void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) { uint8_t res[32 + 2]; int sendlen = 0; uint8_t iBlock = NFC_CMD_IBLOCK | (req0 & 3); -printf1(TAG_NFC,"-- chain \r\n"); - if (len <= 32) + + if (len <= 31) { - nfc_write_response_ex(req0, data, len, resp); + uint8_t res[32] = {0}; + res[0] = iBlock; + if (len && data) + memcpy(&res[1], data, len); + nfc_write_frame(res, len + 1); } else { do { // transmit I block int vlen = MIN(31, len - sendlen); res[0] = iBlock; memcpy(&res[1], &data[sendlen], vlen); + + // if not a last block if (vlen + sendlen < len) { res[0] |= 0x10; - } else { - // here may be buffer overflow!!! - res[vlen + 1] = resp >> 8; - res[vlen + 2] = resp & 0xff; - vlen += 2; } + // send data nfc_write_frame(res, vlen + 1); sendlen += vlen; @@ -179,7 +181,7 @@ printf1(TAG_NFC,"-- chain \r\n"); break; } - // receive R block + // if needs to receive R block (not a last block) if (res[0] & 0x10) { uint8_t recbuf[32] = {0}; @@ -196,10 +198,10 @@ printf1(TAG_NFC,"-- chain \r\n"); break; } - if (((recbuf[0] & 0x01) != (res[0] & 1)) && ((recbuf[0] & 0xf6) == 0xa2)) + if (((recbuf[0] & 0x01) == (res[0] & 1)) && ((recbuf[0] & 0xf6) == 0xa2)) { printf1(TAG_NFC, "R block error. txdata: %02x rxdata: %02x \r\n", res[0], recbuf[0]); - //break; + break; } } @@ -340,15 +342,19 @@ void nfc_process_iblock(uint8_t * buf, int len) status = ctap_request(payload, plen, &ctap_resp); printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); - if (status == CTAP1_ERR_SUCCESS) + int ctaplen = ctap_resp.length + 3; + if (status == CTAP1_ERR_SUCCESS) { - uint8_t ctapdata[1024] = {0}; - ctapdata[0] = status; - memcpy(&ctapdata[1], ctap_resp.data, ctap_resp.length); - nfc_write_response_chaining(buf[0], ctapdata, ctap_resp.length + 1, SW_SUCCESS); + memmove(&ctap_resp.data[1], &ctap_resp.data[0], ctap_resp.length); + ctap_resp.length += 3; } else { - nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION | status); + ctap_resp.length = 3; } + ctap_resp.data[0] = status; + ctap_resp.data[ctap_resp.length - 2] = SW_SUCCESS >> 8; + ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff; + + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); break; case APDU_INS_READ_BINARY: From 3ba83f64079a923caa19b392a83ecf3e022e1a17 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 19:11:51 +0200 Subject: [PATCH 27/96] remove debug msg --- targets/stm32l432/src/nfc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index e8f04ef..ee8d4a0 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -171,9 +171,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) // send data nfc_write_frame(res, vlen + 1); sendlen += vlen; - - printf1(TAG_NFC,"-- slen: %d res0: %02x\r\n", sendlen, res[0]); - + // wait for transmit (32 bytes aprox 2,5ms) if (!ams_wait_for_tx(10)) { From df671775ba33ef69c3caa85ac3e5dce7b8c72419 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 19:30:03 +0200 Subject: [PATCH 28/96] add some profiling. looks good. --- targets/stm32l432/src/nfc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index ee8d4a0..aee0bb9 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -239,6 +239,7 @@ int answer_rats(uint8_t parameter) memcpy(&res[3], (uint8_t *)"SoloKey tap", 11); nfc_write_frame(res, sizeof(res)); + ams_wait_for_tx(10); return 0; } @@ -268,6 +269,7 @@ void nfc_process_iblock(uint8_t * buf, int len) uint8_t plen = apdu->lc; int selected; uint8_t res[32]; + uint32_t t1; CTAP_RESPONSE ctap_resp; int status; @@ -306,7 +308,8 @@ void nfc_process_iblock(uint8_t * buf, int len) // block = !block; // NFC_STATE.block_num = block; nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); - } + printf1(TAG_NFC, "FIDO applet selected.\r\n"); + } else { nfc_write_response(buf[0], SW_FILE_NOT_FOUND); @@ -334,13 +337,13 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_NFCCTAP_MSG: - printf1(TAG_NFC, "FIDO2 CTAP message.\r\n"); + t1 = millis(); + printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); - int ctaplen = ctap_resp.length + 3; if (status == CTAP1_ERR_SUCCESS) { memmove(&ctap_resp.data[1], &ctap_resp.data[0], ctap_resp.length); @@ -352,7 +355,9 @@ void nfc_process_iblock(uint8_t * buf, int len) ctap_resp.data[ctap_resp.length - 2] = SW_SUCCESS >> 8; ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff; + printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), millis() - t1); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), millis() - t1); break; case APDU_INS_READ_BINARY: @@ -503,6 +508,7 @@ void nfc_loop() printf1(TAG_NFC, "HLTA/Halt\r\n"); break; case NFC_CMD_RATS: + printf1(TAG_NFC,"RATS\r\n"); t1 = millis(); answer_rats(buf[1]); NFC_STATE.block_num = 1; From 6ca9f1946badb77239cd7e3e642657b12e9c9fc0 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 21:08:18 +0200 Subject: [PATCH 29/96] I block on receive --- targets/stm32l432/src/nfc.c | 55 +++++++++++++++++++++++++++++++++++-- targets/stm32l432/src/nfc.h | 5 ++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index aee0bb9..df0f9f3 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -407,14 +407,65 @@ void nfc_process_iblock(uint8_t * buf, int len) void nfc_process_block(uint8_t * buf, int len) { + static uint8_t ibuf[1024]; + static int ibuflen = 0; + + if (!len) + return; + if (IS_PPSS_CMD(buf[0])) { printf1(TAG_NFC, "NFC_CMD_PPSS\r\n"); } else if (IS_IBLOCK(buf[0])) { - printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); - nfc_process_iblock(buf, len); + if (buf[0] & 0x10) + { + printf1(TAG_NFC, "NFC_CMD_IBLOCK chaining blen=%d len=%d\r\n", ibuflen, len); + if (ibuflen + len > sizeof(ibuf)) + { + printf1(TAG_NFC, "I block memory error! must have %d but have only %d\r\n", ibuflen + len, sizeof(ibuf)); + nfc_write_response(buf[0], SW_INTERNAL_EXCEPTION); + return; + } + + printf1(TAG_NFC,"i> "); + dump_hex1(TAG_NFC, buf, len); + + if (len) + { + memcpy(&ibuf[ibuflen], &buf[1], len - 1); + ibuflen += len - 1; + } + + // send R block + uint8_t rb = NFC_CMD_RBLOCK | NFC_CMD_RBLOCK_ACK | (buf[0] & 3); + nfc_write_frame(&rb, 1); + } else { + if (ibuflen) + { + if (len) + { + memcpy(&ibuf[ibuflen], &buf[1], len - 1); + ibuflen += len - 1; + } + + memmove(&ibuf[1], ibuf, ibuflen); + ibuf[0] = buf[0]; + ibuflen++; + + printf1(TAG_NFC, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len); + + printf1(TAG_NFC,"i> "); + dump_hex1(TAG_NFC, buf, len); + + nfc_process_iblock(ibuf, ibuflen); + } else { + printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + nfc_process_iblock(buf, len); + } + ibuflen = 0; + } } else if (IS_RBLOCK(buf[0])) { diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 16257a7..c1c3042 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -37,6 +37,7 @@ typedef struct #define NFC_CMD_IBLOCK 0x00 #define IS_IBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_IBLOCK) && (((x) & 0x02) == 0x02) ) #define NFC_CMD_RBLOCK 0x80 +#define NFC_CMD_RBLOCK_ACK 0x20 #define IS_RBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_RBLOCK) && (((x) & 0x02) == 0x02) ) #define NFC_CMD_SBLOCK 0xc0 #define IS_SBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_SBLOCK) && (((x) & 0x02) == 0x02) ) @@ -67,10 +68,10 @@ typedef enum } APPLETS; #define SW_SUCCESS 0x9000 -#define SW_GET_RESPONSE 0x6100 //Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. +#define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. #define SW_COND_USE_NOT_SATISFIED 0x6985 #define SW_FILE_NOT_FOUND 0x6a82 -#define SW_INS_INVALID 0x6d00 +#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid #define SW_INTERNAL_EXCEPTION 0x6f00 #endif From e235402fb8b1d86528a90b2022e6582506946362 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 21:34:53 +0200 Subject: [PATCH 30/96] u2f register --- targets/stm32l432/src/app.h | 2 +- targets/stm32l432/src/nfc.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index dadafc1..6afe0bb 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -38,7 +38,7 @@ //#define ENABLE_U2F_EXTENSIONS -// #define ENABLE_U2F +#define ENABLE_U2F #define DISABLE_CTAPHID_PING #define DISABLE_CTAPHID_WINK diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index df0f9f3..4551c28 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -326,8 +326,13 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_REGISTER: printf1(TAG_NFC, "U2F Register command.\r\n"); + ctap_response_init(&ctap_resp); + u2f_request(apdu, &ctap_resp); + status = ctap_resp.data[0]; + printf1(TAG_NFC, "U2F resp: %d len: %d\r\n", status, ctap_resp.length); - nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); +// nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); break; case APDU_FIDO_U2F_AUTHENTICATE: From 1a656d60e4d6660533a2584994bdd169b7a0dd69 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 23:35:45 +0200 Subject: [PATCH 31/96] register works. but it needs to press a button.... --- targets/stm32l432/src/nfc.c | 22 +++++++++++++++++----- targets/stm32l432/src/nfc.h | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 4551c28..ea2c985 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -7,6 +7,7 @@ #include "log.h" #include "util.h" #include "device.h" +#include "u2f.h" #include "ctap_errors.h" @@ -326,12 +327,23 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_REGISTER: printf1(TAG_NFC, "U2F Register command.\r\n"); + + if (plen != 64) + { + printf1(TAG_NFC, "U2F Register request length error. len=%d.\r\n", plen); + nfc_write_response(buf[0], SW_WRONG_LENGTH); + return; + } + + uint8_t u2fbuffer[7 + 64 + 1] = {0}; + memcpy(u2fbuffer, &buf[1], 4); + memcpy(&u2fbuffer[6], &buf[5], plen + 1); + dump_hex1(TAG_NFC,u2fbuffer, 7 + 64 + 1); + ctap_response_init(&ctap_resp); - u2f_request(apdu, &ctap_resp); - status = ctap_resp.data[0]; - printf1(TAG_NFC, "U2F resp: %d len: %d\r\n", status, ctap_resp.length); - -// nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); + u2f_request((struct u2f_request_apdu *)u2fbuffer, &ctap_resp); + + printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); break; diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index c1c3042..195804f 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -69,6 +69,7 @@ typedef enum #define SW_SUCCESS 0x9000 #define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. +#define SW_WRONG_LENGTH 0x6700 #define SW_COND_USE_NOT_SATISFIED 0x6985 #define SW_FILE_NOT_FOUND 0x6a82 #define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid From a662a9a6192116c8bd3864bc7526cde43128eb2f Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 23:36:45 +0200 Subject: [PATCH 32/96] remove dump --- targets/stm32l432/src/nfc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index ea2c985..419808a 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -338,7 +338,6 @@ void nfc_process_iblock(uint8_t * buf, int len) uint8_t u2fbuffer[7 + 64 + 1] = {0}; memcpy(u2fbuffer, &buf[1], 4); memcpy(&u2fbuffer[6], &buf[5], plen + 1); - dump_hex1(TAG_NFC,u2fbuffer, 7 + 64 + 1); ctap_response_init(&ctap_resp); u2f_request((struct u2f_request_apdu *)u2fbuffer, &ctap_resp); From 3eddfbf8a989a5005e0d40f540fee49aff2404a0 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 23:44:51 +0200 Subject: [PATCH 33/96] u2f register works --- fido2/ctaphid.c | 2 +- fido2/u2f.c | 19 +++++++++++-------- fido2/u2f.h | 2 +- targets/stm32l432/src/nfc.c | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 3e6d5f1..f46b1be 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -670,7 +670,7 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) } is_busy = 1; ctap_response_init(&ctap_resp); - u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp); + u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp, false); ctaphid_write_buffer_init(&wb); wb.cid = cid; diff --git a/fido2/u2f.c b/fido2/u2f.c index 2d79228..99c9abb 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -29,7 +29,7 @@ #include APP_CONFIG // void u2f_response_writeback(uint8_t * buf, uint8_t len); -static int16_t u2f_register(struct u2f_register_request * req); +static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC); static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control); int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); void u2f_reset_response(); @@ -37,7 +37,7 @@ void u2f_reset_response(); static CTAP_RESPONSE * _u2f_resp = NULL; -void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) +void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp, bool fromNFC) { uint16_t rcode = 0; uint64_t t1,t2; @@ -69,7 +69,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) else { t1 = millis(); - rcode = u2f_register((struct u2f_register_request*)req->payload); + rcode = u2f_register((struct u2f_register_request*)req->payload, fromNFC); t2 = millis(); printf1(TAG_TIME,"u2f_register time: %d ms\n", t2-t1); } @@ -254,7 +254,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c return U2F_SW_NO_ERROR; } -static int16_t u2f_register(struct u2f_register_request * req) +static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) { uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED}; @@ -266,10 +266,13 @@ static int16_t u2f_register(struct u2f_register_request * req) const uint16_t attest_size = attestation_cert_der_size; - if ( ! ctap_user_presence_test()) - { - return U2F_SW_CONDITIONS_NOT_SATISFIED; - } + if(!fromNFC) + { + if ( ! ctap_user_presence_test()) + { + return U2F_SW_CONDITIONS_NOT_SATISFIED; + } + } if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1) { diff --git a/fido2/u2f.h b/fido2/u2f.h index 94dbbb8..76c0ad0 100644 --- a/fido2/u2f.h +++ b/fido2/u2f.h @@ -111,7 +111,7 @@ struct u2f_authenticate_request // u2f_request send a U2F message to U2F protocol // @req U2F message -void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp); +void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp, bool fromNFC); int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 419808a..e3f06ac 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -340,7 +340,7 @@ void nfc_process_iblock(uint8_t * buf, int len) memcpy(&u2fbuffer[6], &buf[5], plen + 1); ctap_response_init(&ctap_resp); - u2f_request((struct u2f_request_apdu *)u2fbuffer, &ctap_resp); + u2f_request((struct u2f_request_apdu *)u2fbuffer, &ctap_resp, true); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); From 2feef8b043a8c00e45428c8fa52c2371ebf17712 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 26 Jan 2019 23:53:13 +0200 Subject: [PATCH 34/96] add some profiling... --- targets/stm32l432/src/nfc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index e3f06ac..f8bd7fd 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -335,6 +335,7 @@ void nfc_process_iblock(uint8_t * buf, int len) return; } + t1 = millis(); uint8_t u2fbuffer[7 + 64 + 1] = {0}; memcpy(u2fbuffer, &buf[1], 4); memcpy(&u2fbuffer[6], &buf[5], plen + 1); @@ -343,8 +344,10 @@ void nfc_process_iblock(uint8_t * buf, int len) u2f_request((struct u2f_request_apdu *)u2fbuffer, &ctap_resp, true); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); + printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); - break; + printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), millis() - t1); + break; case APDU_FIDO_U2F_AUTHENTICATE: printf1(TAG_NFC, "U2F Authenticate command.\r\n"); From 1857482617051cd48c439278cfd1cfb9dede93e3 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sun, 27 Jan 2019 00:01:04 +0200 Subject: [PATCH 35/96] add some len check --- targets/stm32l432/src/nfc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index f8bd7fd..5139218 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -352,6 +352,13 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_AUTHENTICATE: printf1(TAG_NFC, "U2F Authenticate command.\r\n"); + if (plen != 1 + 64 + 1 + buf[65]) + { + printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", plen, buf[65]); + nfc_write_response(buf[0], SW_WRONG_LENGTH); + return; + } + nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); break; From 2049020b927b2770a4624cd1372d778a04ebb34e Mon Sep 17 00:00:00 2001 From: merlokk Date: Sun, 27 Jan 2019 11:44:33 +0200 Subject: [PATCH 36/96] refactoring --- fido2/apdu.h | 30 ++++++++++++++++++++++++++++++ fido2/ctaphid.c | 2 +- fido2/main.c | 2 +- fido2/u2f.c | 25 +++++++++++++++++++++---- fido2/u2f.h | 9 +++++++-- targets/stm32l432/Makefile | 2 +- targets/stm32l432/src/nfc.c | 11 +++-------- targets/stm32l432/src/nfc.h | 25 +------------------------ 8 files changed, 65 insertions(+), 41 deletions(-) create mode 100644 fido2/apdu.h diff --git a/fido2/apdu.h b/fido2/apdu.h new file mode 100644 index 0000000..d9687c7 --- /dev/null +++ b/fido2/apdu.h @@ -0,0 +1,30 @@ +#ifndef _APDU_H_ +#define _APDU_H_ + +#include + +typedef struct +{ + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t lc; +} __attribute__((packed)) APDU_HEADER; + +#define APDU_FIDO_U2F_REGISTER 0x01 +#define APDU_FIDO_U2F_AUTHENTICATE 0x02 +#define APDU_FIDO_U2F_VERSION 0x03 +#define APDU_FIDO_NFCCTAP_MSG 0x10 +#define APDU_INS_SELECT 0xA4 +#define APDU_INS_READ_BINARY 0xB0 + +#define SW_SUCCESS 0x9000 +#define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. +#define SW_WRONG_LENGTH 0x6700 +#define SW_COND_USE_NOT_SATISFIED 0x6985 +#define SW_FILE_NOT_FOUND 0x6a82 +#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid +#define SW_INTERNAL_EXCEPTION 0x6f00 + +#endif //_APDU_H_ diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index f46b1be..3e6d5f1 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -670,7 +670,7 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) } is_busy = 1; ctap_response_init(&ctap_resp); - u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp, false); + u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp); ctaphid_write_buffer_init(&wb); wb.cid = cid; diff --git a/fido2/main.c b/fido2/main.c index 51e15ec..35c4c6f 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -50,7 +50,7 @@ int main(int argc, char * argv[]) // TAG_CP | // TAG_CTAP| // TAG_HID| - /*TAG_U2F|*/ + //TAG_U2F| // TAG_PARSE | // TAG_TIME| // TAG_DUMP| diff --git a/fido2/u2f.c b/fido2/u2f.c index 99c9abb..eb24ae5 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -26,6 +26,7 @@ #include "log.h" #include "device.h" #include "wallet.h" +#include "apdu.h" #include APP_CONFIG // void u2f_response_writeback(uint8_t * buf, uint8_t len); @@ -37,13 +38,13 @@ void u2f_reset_response(); static CTAP_RESPONSE * _u2f_resp = NULL; -void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp, bool fromNFC) +void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPONSE * resp, bool fromNFC) { uint16_t rcode = 0; uint64_t t1,t2; - uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16)); uint8_t byte; + ctap_response_init(resp); u2f_set_writeback_buffer(resp); if (req->cla != 0) @@ -69,7 +70,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp, bool fromNF else { t1 = millis(); - rcode = u2f_register((struct u2f_register_request*)req->payload, fromNFC); + rcode = u2f_register((struct u2f_register_request*)payload, fromNFC); t2 = millis(); printf1(TAG_TIME,"u2f_register time: %d ms\n", t2-t1); } @@ -77,7 +78,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp, bool fromNF case U2F_AUTHENTICATE: printf1(TAG_U2F, "U2F_AUTHENTICATE\n"); t1 = millis(); - rcode = u2f_authenticate((struct u2f_authenticate_request*)req->payload, req->p1); + rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1); t2 = millis(); printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", t2-t1); break; @@ -120,6 +121,22 @@ end: printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length); } +void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp) +{ + if (len < 5 || !req) + return; + + uint32_t alen = req[4]; + + u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp, true); +} + +void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) +{ + uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16)); + + u2f_request_ex((APDU_HEADER *)req, &req[7], len, resp, false); +} int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len) { diff --git a/fido2/u2f.h b/fido2/u2f.h index 76c0ad0..3f4f689 100644 --- a/fido2/u2f.h +++ b/fido2/u2f.h @@ -110,8 +110,13 @@ struct u2f_authenticate_request }; // u2f_request send a U2F message to U2F protocol -// @req U2F message -void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp, bool fromNFC); +// @req U2F message +void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp); + +// u2f_request send a U2F message to NFC protocol +// @req data with iso7816 apdu message +// @len data length +void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp); int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); diff --git a/targets/stm32l432/Makefile b/targets/stm32l432/Makefile index 017998f..9df352c 100644 --- a/targets/stm32l432/Makefile +++ b/targets/stm32l432/Makefile @@ -8,7 +8,7 @@ all: $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DFLASH_ROP=1' all-hacker: - $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' + $(MAKE) -f application.mk solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' all-locked: $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DFLASH_ROP=2' diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 5139218..1e2bfbf 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -336,12 +336,7 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); - uint8_t u2fbuffer[7 + 64 + 1] = {0}; - memcpy(u2fbuffer, &buf[1], 4); - memcpy(&u2fbuffer[6], &buf[5], plen + 1); - - ctap_response_init(&ctap_resp); - u2f_request((struct u2f_request_apdu *)u2fbuffer, &ctap_resp, true); + u2f_request_nfc(&buf[1], len, &ctap_resp); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -356,10 +351,10 @@ void nfc_process_iblock(uint8_t * buf, int len) { printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", plen, buf[65]); nfc_write_response(buf[0], SW_WRONG_LENGTH); - return; + //return; } - nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED); + u2f_request_nfc(&buf[1], len, &ctap_resp); break; case APDU_FIDO_NFCCTAP_MSG: diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 195804f..0079ea4 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -2,6 +2,7 @@ #define _NFC_H_ #include +#include "apdu.h" void nfc_loop(); void nfc_init(); @@ -18,15 +19,6 @@ typedef struct uint8_t tlv[8]; } __attribute__((packed)) CAPABILITY_CONTAINER; -typedef struct -{ - uint8_t cla; - uint8_t ins; - uint8_t p1; - uint8_t p2; - uint8_t lc; -} __attribute__((packed)) APDU_HEADER; - #define NFC_CMD_REQA 0x26 #define NFC_CMD_WUPA 0x52 #define NFC_CMD_HLTA 0x50 @@ -45,13 +37,6 @@ typedef struct #define NFC_SBLOCK_DESELECT 0x32 #define NFC_SBLOCK_WTX 0xf2 -#define APDU_FIDO_U2F_REGISTER 0x01 -#define APDU_FIDO_U2F_AUTHENTICATE 0x02 -#define APDU_FIDO_U2F_VERSION 0x03 -#define APDU_FIDO_NFCCTAP_MSG 0x10 -#define APDU_INS_SELECT 0xA4 -#define APDU_INS_READ_BINARY 0xB0 - #define AID_NDEF_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x01" #define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00" #define AID_CAPABILITY_CONTAINER "\xE1\x03" @@ -67,12 +52,4 @@ typedef enum APP_FIDO, } APPLETS; -#define SW_SUCCESS 0x9000 -#define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE. -#define SW_WRONG_LENGTH 0x6700 -#define SW_COND_USE_NOT_SATISFIED 0x6985 -#define SW_FILE_NOT_FOUND 0x6a82 -#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid -#define SW_INTERNAL_EXCEPTION 0x6f00 - #endif From 4c941997b429a67982b9e60210d263c2d3354db2 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sun, 27 Jan 2019 23:35:20 +0200 Subject: [PATCH 37/96] check as3956 on startup --- fido2/main.c | 2 -- fido2/u2f.c | 2 +- targets/stm32l432/src/ams.c | 21 ++++++++++++++------- targets/stm32l432/src/ams.h | 15 +++++++++++++-- targets/stm32l432/src/device.c | 10 +++++++++- targets/stm32l432/src/nfc.c | 5 +++-- targets/stm32l432/src/nfc.h | 3 ++- 7 files changed, 42 insertions(+), 16 deletions(-) diff --git a/fido2/main.c b/fido2/main.c index 35c4c6f..3849633 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -65,8 +65,6 @@ int main(int argc, char * argv[]) usbhid_init(); printf1(TAG_GEN,"init usb\n"); - nfc_init(); - ctaphid_init(); printf1(TAG_GEN,"init ctaphid\n"); diff --git a/fido2/u2f.c b/fido2/u2f.c index eb24ae5..6d5e6eb 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -135,7 +135,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) { uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16)); - u2f_request_ex((APDU_HEADER *)req, &req[7], len, resp, false); + u2f_request_ex((APDU_HEADER *)req, req->payload, len, resp, false); } int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 1b2c87a..a342513 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -28,7 +28,7 @@ static void wait_for_rx() } -static void ams_print_device(AMS_DEVICE * dev) +void ams_print_device(AMS_DEVICE * dev) { printf1(TAG_NFC, "AMS_DEVICE:\r\n"); printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); @@ -252,7 +252,7 @@ void ams_print_int1(uint8_t int0) printf1(tag,"\r\n"); } -void ams_init() +bool ams_init() { uint8_t block[4]; @@ -273,13 +273,19 @@ void ams_init() ams_write_command(AMS_CMD_DEFAULT); ams_write_command(AMS_CMD_CLEAR_BUFFER); + // check connection + uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); + if (!productType) + { + printf1(TAG_NFC,"Have no product type. Connection error."); + return false; + } + printf1(TAG_NFC,"Product type 0x%02x.", productType); + // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); - ams_read_eeprom_block(0, block); - printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); - - ams_read_eeprom_block(0, block); + ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); @@ -336,5 +342,6 @@ void ams_init() ams_read_eeprom_block(0x7F, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); } - + + return true; } diff --git a/targets/stm32l432/src/ams.h b/targets/stm32l432/src/ams.h index 361cb0d..ad3b94f 100644 --- a/targets/stm32l432/src/ams.h +++ b/targets/stm32l432/src/ams.h @@ -1,8 +1,12 @@ +// AS3956 interface +// https://ams.com/as3956 +// https://ams.com/documents/20143/36005/AS3956_DS000546_7-00.pdf + #ifndef _AMS_H_ #define _AMS_H_ #include -#include +#include #include "stm32l4xx_ll_gpio.h" @@ -35,7 +39,7 @@ typedef union #define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) #define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) -void ams_init(); +bool ams_init(); void ams_read_buffer(uint8_t * data, int len); void ams_write_buffer(uint8_t * data, int len); @@ -92,7 +96,14 @@ void ams_write_reg(uint8_t addr, uint8_t tx); #define AMS_REG_BUF2 0x0c #define AMS_BUF_LEN_MASK 0x1f #define AMS_BUF_INVALID 0x80 +#define AMS_REG_BUF1 0x0d +// ... // +#define AMS_REG_PRODUCT_TYPE 0x1c +#define AMS_REG_PRODUCT_SUBTYPE 0x1d +#define AMS_REG_VERSION_MAJOR 0x1e +#define AMS_REG_VERSION_MINOR 0x1f +#define AMS_CONFIG_UID_ADDR 0x00 #define AMS_CONFIG_BLOCK0_ADDR 0x7e #define AMS_CONFIG_BLOCK1_ADDR 0x7f diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 33d9113..b3fd58f 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -48,6 +48,7 @@ uint32_t __90_ms = 0; uint32_t __device_status = 0; uint32_t __last_update = 0; extern PCD_HandleTypeDef hpcd; +bool haveNFC = false; #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) @@ -118,6 +119,12 @@ void device_init() #else flash_option_bytes_init(0); #endif + printf1(TAG_GEN,"init nfc\n"); + haveNFC = nfc_init(); + if (haveNFC) + printf1(TAG_GEN,"NFC OK.\n"); + else + printf1(TAG_GEN,"NFC not found.\n"); #endif printf1(TAG_GEN,"hello solo\r\n"); @@ -397,7 +404,8 @@ void device_manage() } #endif #ifndef IS_BOOTLOADER - nfc_loop(); + if(haveNFC) + nfc_loop(); #endif } diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 1e2bfbf..75ba0bf 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -43,11 +43,12 @@ void nfc_state_init() NFC_STATE.block_num = 1; } -void nfc_init() +bool nfc_init() { nfc_state_init(); - ams_init(); + return ams_init(); } + void process_int0(uint8_t int0) { diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 0079ea4..b425b28 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -2,10 +2,11 @@ #define _NFC_H_ #include +#include #include "apdu.h" void nfc_loop(); -void nfc_init(); +bool nfc_init(); typedef struct { From f24058d2e8e140c4c8a2195d27900828fb28bd62 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 27 Jan 2019 23:58:35 +0200 Subject: [PATCH 38/96] u2f authenticate wrong length fix --- targets/stm32l432/src/nfc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 75ba0bf..5d9feaf 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -348,11 +348,12 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_AUTHENTICATE: printf1(TAG_NFC, "U2F Authenticate command.\r\n"); - if (plen != 1 + 64 + 1 + buf[65]) + if (plen != 64 + 1 + buf[6 + 64]) { - printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", plen, buf[65]); + delay(5); + printf1(TAG_NFC, "U2F Authenticate request length error. len=%d keyhlen=%d.\r\n", plen, buf[6 + 64]); nfc_write_response(buf[0], SW_WRONG_LENGTH); - //return; + return; } u2f_request_nfc(&buf[1], len, &ctap_resp); From cce25b2a1c04e882c59f43e466bb8d0bc1d08dd2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 28 Jan 2019 00:04:17 +0200 Subject: [PATCH 39/96] u2f auth works --- fido2/u2f.c | 17 ++++++++++------- targets/stm32l432/src/nfc.c | 6 ++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/fido2/u2f.c b/fido2/u2f.c index 6d5e6eb..edc4451 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -31,7 +31,7 @@ // void u2f_response_writeback(uint8_t * buf, uint8_t len); static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC); -static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control); +static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control, bool fromNFC); int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); void u2f_reset_response(); @@ -78,7 +78,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO case U2F_AUTHENTICATE: printf1(TAG_U2F, "U2F_AUTHENTICATE\n"); t1 = millis(); - rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1); + rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1, fromNFC); t2 = millis(); printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", t2-t1); break; @@ -213,7 +213,7 @@ static int8_t u2f_appid_eq(struct u2f_key_handle * kh, uint8_t * appid) -static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control) +static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control, bool fromNFC) { uint8_t up = 1; @@ -245,10 +245,13 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c - if (ctap_user_presence_test() == 0) - { - return U2F_SW_CONDITIONS_NOT_SATISFIED; - } + if(!fromNFC) + { + if (ctap_user_presence_test() == 0) + { + return U2F_SW_CONDITIONS_NOT_SATISFIED; + } + } count = ctap_atomic_count(0); diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 5d9feaf..0b4cf5c 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -356,7 +356,13 @@ void nfc_process_iblock(uint8_t * buf, int len) return; } + t1 = millis(); u2f_request_nfc(&buf[1], len, &ctap_resp); + + printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); + printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + printf1(TAG_NFC,"U2F Authenticate answered %d (took %d)\r\n", millis(), millis() - t1); break; case APDU_FIDO_NFCCTAP_MSG: From 91d092a27a6faf7b8be6bdd87dc6a9e52f37524a Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sun, 27 Jan 2019 23:55:11 -0500 Subject: [PATCH 40/96] tell AMS to go to sleep if deselected --- targets/stm32l432/src/nfc.c | 2 ++ targets/stm32l432/src/nfc.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 0b4cf5c..61d8845 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -508,6 +508,8 @@ void nfc_process_block(uint8_t * buf, int len) { nfc_write_frame(buf, 1); printf1(TAG_NFC, "NFC_CMD_SBLOCK, DESELECTED\r\n"); + ams_wait_for_tx(2); + ams_write_command(AMS_CMD_SLEEP); nfc_state_init(); } else diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index b425b28..ced5975 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -35,8 +35,8 @@ typedef struct #define NFC_CMD_SBLOCK 0xc0 #define IS_SBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_SBLOCK) && (((x) & 0x02) == 0x02) ) -#define NFC_SBLOCK_DESELECT 0x32 -#define NFC_SBLOCK_WTX 0xf2 +#define NFC_SBLOCK_DESELECT 0x30 +#define NFC_SBLOCK_WTX 0x30 #define AID_NDEF_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x01" #define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00" @@ -46,6 +46,7 @@ typedef struct typedef enum { + APP_NOTHING = 0, APP_NDEF_TYPE_4 = 1, APP_MIFARE_TYPE_4, APP_CAPABILITY_CONTAINER, From 5f637992b1837b0e0ccc14523050a66a53f11e72 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 29 Jan 2019 22:12:38 -0500 Subject: [PATCH 41/96] implement capability container and ndef tag to work with nexus 6 --- targets/stm32l432/src/nfc.c | 142 ++++++++++++++++++++---------------- targets/stm32l432/src/nfc.h | 2 +- 2 files changed, 80 insertions(+), 64 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 61d8845..a648a94 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -17,13 +17,13 @@ const CAPABILITY_CONTAINER NFC_CC = { .cclen_hi = 0x00, .cclen_lo = 0x0f, - .version = 0x01, - .MLe_hi = 0x00, .MLe_lo = 0xff, - .MLc_hi = 0x00, .MLc_lo = 0xff, + .version = 0x20, + .MLe_hi = 0x00, .MLe_lo = 0x7f, + .MLc_hi = 0x00, .MLc_lo = 0x7f, .tlv = { 0x04,0x06, - 0x11,0x11, - 0x00,0xff, - 0x00,0xff } + 0xe1,0x04, + 0x00,0x7f, + 0x00,0x00 } }; uint8_t NDEF_SAMPLE[] = "\x00\x13\xD1\x01\x0ET\x02enHello World"; @@ -51,7 +51,7 @@ bool nfc_init() void process_int0(uint8_t int0) { - + } bool ams_wait_for_tx(uint32_t timeout_ms) @@ -66,7 +66,7 @@ bool ams_wait_for_tx(uint32_t timeout_ms) delay(1); } - + return false; } @@ -75,13 +75,13 @@ bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, i { uint8_t buf[32]; *dlen = 0; - + uint32_t tstart = millis(); while (tstart + timeout_ms > millis()) { uint8_t int0 = ams_read_reg(AMS_REG_INT0); uint8_t buffer_status2 = ams_read_reg(AMS_REG_BUF2); - + if (buffer_status2 && (int0 & AMS_INT_RXE)) { if (buffer_status2 & AMS_BUF_INVALID) @@ -100,10 +100,10 @@ bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, i return true; } } - + delay(1); } - + return false; } @@ -126,16 +126,16 @@ bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t r if (len > 32 - 3) return false; - + res[0] = NFC_CMD_IBLOCK | (req0 & 3); - + if (len && data) memcpy(&res[1], data, len); - + res[len + 1] = resp >> 8; res[len + 2] = resp & 0xff; nfc_write_frame(res, 3 + len); - + return true; } @@ -163,9 +163,9 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) int vlen = MIN(31, len - sendlen); res[0] = iBlock; memcpy(&res[1], &data[sendlen], vlen); - + // if not a last block - if (vlen + sendlen < len) + if (vlen + sendlen < len) { res[0] |= 0x10; } @@ -173,14 +173,14 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) // send data nfc_write_frame(res, vlen + 1); sendlen += vlen; - + // wait for transmit (32 bytes aprox 2,5ms) if (!ams_wait_for_tx(10)) { printf1(TAG_NFC, "TX timeout. slen: %d \r\n", sendlen); break; } - + // if needs to receive R block (not a last block) if (res[0] & 0x10) { @@ -191,7 +191,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) printf1(TAG_NFC, "R block RX timeout.\r\n"); break; } - + if (reclen != 1) { printf1(TAG_NFC, "R block length error. len: %d \r\n", reclen); @@ -204,7 +204,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) break; } } - + iBlock ^= 0x01; } while (sendlen < len); } @@ -239,7 +239,7 @@ int answer_rats(uint8_t parameter) // historical bytes memcpy(&res[3], (uint8_t *)"SoloKey tap", 11); - + nfc_write_frame(res, sizeof(res)); ams_wait_for_tx(10); return 0; @@ -259,9 +259,24 @@ int select_applet(uint8_t * aid, int len) if (memcmp(aid,AID_FIDO,sizeof(AID_FIDO)) == 0) { NFC_STATE.selected_applet = APP_FIDO; - return 1; + return APP_FIDO; } - return 0; + else if (memcmp(aid,AID_NDEF_TYPE_4,sizeof(AID_NDEF_TYPE_4)) == 0) + { + NFC_STATE.selected_applet = APP_NDEF_TYPE_4; + return APP_NDEF_TYPE_4; + } + else if (memcmp(aid,AID_CAPABILITY_CONTAINER,sizeof(AID_CAPABILITY_CONTAINER)) == 0) + { + NFC_STATE.selected_applet = APP_CAPABILITY_CONTAINER; + return APP_CAPABILITY_CONTAINER; + } + else if (memcmp(aid,AID_NDEF_TAG,sizeof(AID_NDEF_TAG)) == 0) + { + NFC_STATE.selected_applet = APP_NDEF_TAG; + return APP_NDEF_TAG; + } + return APP_NOTHING; } void nfc_process_iblock(uint8_t * buf, int len) @@ -271,12 +286,12 @@ void nfc_process_iblock(uint8_t * buf, int len) uint8_t plen = apdu->lc; int selected; uint8_t res[32]; - uint32_t t1; + uint32_t t1; - CTAP_RESPONSE ctap_resp; + CTAP_RESPONSE ctap_resp; int status; - - printf1(TAG_NFC,">> "); + + printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC, buf, len); // TODO this needs to be organized better @@ -303,7 +318,7 @@ void nfc_process_iblock(uint8_t * buf, int len) // else { selected = select_applet(payload, plen); - if (selected) + if (selected == APP_FIDO) { // block = buf[0] & 1; // block = NFC_STATE.block_num; @@ -311,6 +326,11 @@ void nfc_process_iblock(uint8_t * buf, int len) // NFC_STATE.block_num = block; nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); printf1(TAG_NFC, "FIDO applet selected.\r\n"); + } + else if (selected != APP_NOTHING) + { + nfc_write_response(buf[0], SW_SUCCESS); + printf1(TAG_NFC, "SELECTED %d\r\n", selected); } else { @@ -328,17 +348,17 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_REGISTER: printf1(TAG_NFC, "U2F Register command.\r\n"); - + if (plen != 64) { printf1(TAG_NFC, "U2F Register request length error. len=%d.\r\n", plen); nfc_write_response(buf[0], SW_WRONG_LENGTH); return; } - + t1 = millis(); u2f_request_nfc(&buf[1], len, &ctap_resp); - + printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); @@ -347,7 +367,7 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_U2F_AUTHENTICATE: printf1(TAG_NFC, "U2F Authenticate command.\r\n"); - + if (plen != 64 + 1 + buf[6 + 64]) { delay(5); @@ -355,10 +375,10 @@ void nfc_process_iblock(uint8_t * buf, int len) nfc_write_response(buf[0], SW_WRONG_LENGTH); return; } - + t1 = millis(); u2f_request_nfc(&buf[1], len, &ctap_resp); - + printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); @@ -368,11 +388,11 @@ void nfc_process_iblock(uint8_t * buf, int len) case APDU_FIDO_NFCCTAP_MSG: t1 = millis(); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); - + ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); - + if (status == CTAP1_ERR_SUCCESS) { memmove(&ctap_resp.data[1], &ctap_resp.data[0], ctap_resp.length); @@ -383,7 +403,7 @@ void nfc_process_iblock(uint8_t * buf, int len) ctap_resp.data[0] = status; ctap_resp.data[ctap_resp.length - 2] = SW_SUCCESS >> 8; ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff; - + printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), millis() - t1); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), millis() - t1); @@ -401,7 +421,8 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); plen = 15; } - memmove(res+1, &NFC_CC, plen); + nfc_write_response_ex(buf[0], &NFC_CC, plen, SW_SUCCESS); + ams_wait_for_tx(10); break; case APP_NDEF_TAG: printf1(TAG_NFC,"APP_NDEF_TAG\r\n"); @@ -410,20 +431,15 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); plen = sizeof(NDEF_SAMPLE) - 1; } - memmove(res+1, NDEF_SAMPLE, plen); + nfc_write_response_ex(buf[0], NDEF_SAMPLE, plen, SW_SUCCESS); + ams_wait_for_tx(10); break; default: printf1(TAG_ERR, "No binary applet selected!\r\n"); return; break; } - res[0] = NFC_CMD_IBLOCK | (buf[0] & 1); - res[1+plen] = SW_SUCCESS>>8; - res[2+plen] = SW_SUCCESS & 0xff; - nfc_write_frame(res, 3+plen); - printf1(TAG_NFC,"APDU_INS_READ_BINARY\r\n"); - printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC,res, 3+plen); break; default: printf1(TAG_NFC, "Unknown INS %02x\r\n", apdu->ins); @@ -438,10 +454,10 @@ void nfc_process_block(uint8_t * buf, int len) { static uint8_t ibuf[1024]; static int ibuflen = 0; - + if (!len) return; - + if (IS_PPSS_CMD(buf[0])) { printf1(TAG_NFC, "NFC_CMD_PPSS\r\n"); @@ -458,15 +474,15 @@ void nfc_process_block(uint8_t * buf, int len) return; } - printf1(TAG_NFC,"i> "); - dump_hex1(TAG_NFC, buf, len); - + printf1(TAG_NFC,"i> "); + dump_hex1(TAG_NFC, buf, len); + if (len) { memcpy(&ibuf[ibuflen], &buf[1], len - 1); ibuflen += len - 1; } - + // send R block uint8_t rb = NFC_CMD_RBLOCK | NFC_CMD_RBLOCK_ACK | (buf[0] & 3); nfc_write_frame(&rb, 1); @@ -478,19 +494,19 @@ void nfc_process_block(uint8_t * buf, int len) memcpy(&ibuf[ibuflen], &buf[1], len - 1); ibuflen += len - 1; } - + memmove(&ibuf[1], ibuf, ibuflen); ibuf[0] = buf[0]; ibuflen++; - + printf1(TAG_NFC, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len); - - printf1(TAG_NFC,"i> "); - dump_hex1(TAG_NFC, buf, len); - + + printf1(TAG_NFC,"i> "); + dump_hex1(TAG_NFC, buf, len); + nfc_process_iblock(ibuf, ibuflen); } else { - printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); + // printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); nfc_process_iblock(buf, len); } ibuflen = 0; @@ -506,8 +522,8 @@ void nfc_process_block(uint8_t * buf, int len) if ((buf[0] & NFC_SBLOCK_DESELECT) == 0) { - nfc_write_frame(buf, 1); printf1(TAG_NFC, "NFC_CMD_SBLOCK, DESELECTED\r\n"); + nfc_write_frame(buf, 1); ams_wait_for_tx(2); ams_write_command(AMS_CMD_SLEEP); nfc_state_init(); @@ -539,9 +555,9 @@ void nfc_loop() { t1 = millis(); read_reg_block(&ams); - + process_int0(ams.regs.int0); - + // if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0) // { // printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index ced5975..b66b43e 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -41,7 +41,7 @@ typedef struct #define AID_NDEF_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x01" #define AID_NDEF_MIFARE_TYPE_4 "\xD2\x76\x00\x00\x85\x01\x00" #define AID_CAPABILITY_CONTAINER "\xE1\x03" -#define AID_NDEF_TAG "\x11\x11" +#define AID_NDEF_TAG "\xE1\x04" #define AID_FIDO "\xa0\x00\x00\x06\x47\x2f\x00\x01" typedef enum From e2e29492e635ace8a7a3a4c339703d610510713e Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 29 Jan 2019 22:39:49 -0500 Subject: [PATCH 42/96] point to website --- targets/stm32l432/src/nfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index a648a94..0b34d34 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -26,7 +26,7 @@ const CAPABILITY_CONTAINER NFC_CC = { 0x00,0x00 } }; -uint8_t NDEF_SAMPLE[] = "\x00\x13\xD1\x01\x0ET\x02enHello World"; +uint8_t NDEF_SAMPLE[] = "\x00\x14\xd1\x01\x0eU\x04solokeys.com/"; static struct { From e996d470f9c5e2815a00b1b4988099177caeffd8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 19:15:48 +0200 Subject: [PATCH 43/96] small fixes --- targets/stm32l432/src/nfc.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 0b34d34..f98d53a 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -341,12 +341,22 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_U2F_VERSION: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + printf1(TAG_NFC, "U2F GetVersion command.\r\n"); nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); break; case APDU_FIDO_U2F_REGISTER: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + printf1(TAG_NFC, "U2F Register command.\r\n"); if (plen != 64) @@ -366,6 +376,11 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_U2F_AUTHENTICATE: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + printf1(TAG_NFC, "U2F Authenticate command.\r\n"); if (plen != 64 + 1 + buf[6 + 64]) @@ -386,6 +401,11 @@ void nfc_process_iblock(uint8_t * buf, int len) break; case APDU_FIDO_NFCCTAP_MSG: + if (NFC_STATE.selected_applet != APP_FIDO) { + nfc_write_response(buf[0], SW_INS_INVALID); + break; + } + t1 = millis(); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); @@ -421,7 +441,7 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_ERR, "Truncating requested CC length %d\r\n", apdu->lc); plen = 15; } - nfc_write_response_ex(buf[0], &NFC_CC, plen, SW_SUCCESS); + nfc_write_response_ex(buf[0], (uint8_t *)&NFC_CC, plen, SW_SUCCESS); ams_wait_for_tx(10); break; case APP_NDEF_TAG: @@ -450,10 +470,17 @@ void nfc_process_iblock(uint8_t * buf, int len) } +static uint8_t ibuf[1024]; +static int ibuflen = 0; + +void clear_ibuf() +{ + ibuflen = 0; + memset(ibuf, 0, sizeof(ibuf)); +} + void nfc_process_block(uint8_t * buf, int len) { - static uint8_t ibuf[1024]; - static int ibuflen = 0; if (!len) return; @@ -509,7 +536,7 @@ void nfc_process_block(uint8_t * buf, int len) // printf1(TAG_NFC, "NFC_CMD_IBLOCK\r\n"); nfc_process_iblock(buf, len); } - ibuflen = 0; + clear_ibuf(); } } else if (IS_RBLOCK(buf[0])) @@ -527,6 +554,7 @@ void nfc_process_block(uint8_t * buf, int len) ams_wait_for_tx(2); ams_write_command(AMS_CMD_SLEEP); nfc_state_init(); + clear_ibuf(); } else { @@ -610,6 +638,7 @@ void nfc_loop() t1 = millis(); answer_rats(buf[1]); NFC_STATE.block_num = 1; + clear_ibuf(); printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: From 5c8acdd66607f6f464f7f4bcbf16dffc926730e8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 20:00:13 +0200 Subject: [PATCH 44/96] fix u2f user presence check, added `dont-enforce-user-presence-and-sign`, fix counter --- fido2/u2f.c | 29 ++++++++++++++++++----------- fido2/u2f.h | 1 + 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/fido2/u2f.c b/fido2/u2f.c index edc4451..1eb7e60 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -233,8 +233,8 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c } } if ( - control != U2F_AUTHENTICATE_SIGN || - req->khl != U2F_KEY_HANDLE_SIZE || + (control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) || + req->khl != U2F_KEY_HANDLE_SIZE || u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important u2f_load_key(&req->kh, req->app) != 0 @@ -243,9 +243,11 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c return U2F_SW_WRONG_PAYLOAD; } + // dont-enforce-user-presence-and-sign + if (control == U2F_AUTHENTICATE_SIGN_NO_USER) + up = 0; - - if(!fromNFC) + if(!fromNFC && up) { if (ctap_user_presence_test() == 0) { @@ -254,21 +256,26 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c } count = ctap_atomic_count(0); + uint8_t vcount[4]; + vcount[3] = (count) & 0xff; + vcount[2] = (count >> 8) & 0xff; + vcount[1] = (count >> 16) & 0xff; + vcount[0] = (count >> 24) & 0xff; crypto_sha256_init(); - crypto_sha256_update(req->app,32); - crypto_sha256_update(&up,1); - crypto_sha256_update((uint8_t *)&count,4); - crypto_sha256_update(req->chal,32); + crypto_sha256_update(req->app, 32); + crypto_sha256_update(&up, 1); + crypto_sha256_update(vcount, 4); + crypto_sha256_update(req->chal, 32); crypto_sha256_final(hash); - printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F,hash,32); + printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F, hash, 32); crypto_ecc256_sign(hash, 32, sig); - u2f_response_writeback(&up,1); - u2f_response_writeback((uint8_t *)&count,4); + u2f_response_writeback(&up, 1); + u2f_response_writeback(vcount, 4); dump_signature_der(sig); return U2F_SW_NO_ERROR; diff --git a/fido2/u2f.h b/fido2/u2f.h index 3f4f689..88975a1 100644 --- a/fido2/u2f.h +++ b/fido2/u2f.h @@ -53,6 +53,7 @@ // U2F Authenticate #define U2F_AUTHENTICATE_CHECK 0x7 #define U2F_AUTHENTICATE_SIGN 0x3 +#define U2F_AUTHENTICATE_SIGN_NO_USER 0x8 // Command status responses From f6e2bfa6837ccec165c623ad50c027ffa10aca68 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 20:06:19 +0200 Subject: [PATCH 45/96] yubikey answers U2F_SW_WRONG_PAYLOAD instead of U2F_SW_WRONG_DATA --- fido2/u2f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fido2/u2f.c b/fido2/u2f.c index 1eb7e60..ac84205 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -229,7 +229,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c } else { - return U2F_SW_WRONG_DATA; + return U2F_SW_WRONG_PAYLOAD; } } if ( From 0ef42b2df716fdb5d5845f18804d38945bc3b846 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 20:45:36 +0200 Subject: [PATCH 46/96] added WTX sending sketch --- targets/stm32l432/src/nfc.c | 21 +++++++++++++++++++++ targets/stm32l432/src/nfc.h | 3 +++ 2 files changed, 24 insertions(+) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index f98d53a..fc9ed3c 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -54,6 +54,21 @@ void process_int0(uint8_t int0) } +// WTX on/off: +// sends/receives WTX frame to reader every `WTX_time` time in ms +// works via timer interrupts +// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> +bool WTX_on(int WTX_time) +{ + return true; +} + +bool WTX_off() +{ + return true; +} + + bool ams_wait_for_tx(uint32_t timeout_ms) { uint32_t tstart = millis(); @@ -367,7 +382,9 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); + WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); + WTX_off(); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -392,7 +409,9 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); + WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); + WTX_off(); printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); @@ -409,8 +428,10 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); + WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); + WTX_off(); printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index b66b43e..4859570 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -20,6 +20,9 @@ typedef struct uint8_t tlv[8]; } __attribute__((packed)) CAPABILITY_CONTAINER; +// WTX time in ms +#define WTX_TIME_DEFAULT 300 + #define NFC_CMD_REQA 0x26 #define NFC_CMD_WUPA 0x52 #define NFC_CMD_HLTA 0x50 From ab01d0c73dd493dbb06c234cb60180fab0ed6f80 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:02:02 +0200 Subject: [PATCH 47/96] delete comment --- targets/stm32l432/src/nfc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index fc9ed3c..bfa8a87 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -68,7 +68,6 @@ bool WTX_off() return true; } - bool ams_wait_for_tx(uint32_t timeout_ms) { uint32_t tstart = millis(); @@ -85,7 +84,6 @@ bool ams_wait_for_tx(uint32_t timeout_ms) return false; } -//bool ams_receive_with_timeout(10, recbuf, sizeof(recbuf), &reclen)) bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, int *dlen) { uint8_t buf[32]; From c6daa4acc9e2ed5499533efeb7be7241a4f3e5cb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:27:43 +0200 Subject: [PATCH 48/96] more WTX sketch --- targets/stm32l432/src/nfc.c | 70 +++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index bfa8a87..c03261e 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -54,20 +54,6 @@ void process_int0(uint8_t int0) } -// WTX on/off: -// sends/receives WTX frame to reader every `WTX_time` time in ms -// works via timer interrupts -// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> -bool WTX_on(int WTX_time) -{ - return true; -} - -bool WTX_off() -{ - return true; -} - bool ams_wait_for_tx(uint32_t timeout_ms) { uint32_t tstart = millis(); @@ -223,6 +209,62 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) } } +// WTX on/off: +// sends/receives WTX frame to reader every `WTX_time` time in ms +// works via timer interrupts +// WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> +static bool WTX_sent; +static bool WTX_fail; +bool WTX_on(int WTX_time) +{ + WTX_sent = false; + WTX_fail = false; + + return true; +} + +bool WTX_off() +{ + if (WTX_fail) + return false; + + return true; +} + +// executes twice a period. 1st for send WTX, 2nd for check the result +bool WTX_process() +{ + uint8_t wtx[] = {0xf2, 0x01}; + if (WTX_fail) + return false; + + if (!WTX_sent) + { + nfc_write_frame(wtx, sizeof(wtx)); + WTX_sent = true; + return true; + } + else + { + uint8_t data[32]; + int len; + if (ams_receive_with_timeout(0, data, sizeof(data), &len)) + { + WTX_fail = true; + return false; + } + + if (len != 2 || data[0] != 0xf2 || data[1] != 0x01) + { + WTX_fail = true; + return false; + } + + WTX_sent = false; + return true; + } +} + int answer_rats(uint8_t parameter) { From 6e5de7bd6b2d1942ba75b402dc8b849954287360 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:31:20 +0200 Subject: [PATCH 49/96] read data if we sent WTX --- targets/stm32l432/src/nfc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index c03261e..b1d8bf1 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -223,16 +223,26 @@ bool WTX_on(int WTX_time) return true; } +bool WTX_process(int read_timeout); + bool WTX_off() { if (WTX_fail) return false; + // read data if we sent WTX + if (WTX_sent) + { + if (!WTX_process(10)) + return false; + } + return true; } // executes twice a period. 1st for send WTX, 2nd for check the result -bool WTX_process() +// read timeout must be 0 to call from int +bool WTX_process(int read_timeout) { uint8_t wtx[] = {0xf2, 0x01}; if (WTX_fail) @@ -248,7 +258,7 @@ bool WTX_process() { uint8_t data[32]; int len; - if (ams_receive_with_timeout(0, data, sizeof(data), &len)) + if (ams_receive_with_timeout(read_timeout, data, sizeof(data), &len)) { WTX_fail = true; return false; From 429e4b2a771222ce236d27d81afbd6073e6dbdd7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:33:57 +0200 Subject: [PATCH 50/96] add WTX_clear(); --- targets/stm32l432/src/nfc.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index b1d8bf1..a7819cb 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -215,11 +215,16 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) // WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> static bool WTX_sent; static bool WTX_fail; -bool WTX_on(int WTX_time) + +void WTX_clear() { WTX_sent = false; WTX_fail = false; - +} + +bool WTX_on(int WTX_time) +{ + WTX_clear(); return true; } @@ -434,7 +439,8 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - WTX_off(); + if (!WTX_off()) + return; printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -461,7 +467,8 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - WTX_off(); + if (!WTX_off()) + return; printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); @@ -481,7 +488,8 @@ void nfc_process_iblock(uint8_t * buf, int len) WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); - WTX_off(); + if (!WTX_off()) + return; printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) @@ -626,6 +634,7 @@ void nfc_process_block(uint8_t * buf, int len) ams_write_command(AMS_CMD_SLEEP); nfc_state_init(); clear_ibuf(); + WTX_clear(); } else { @@ -710,6 +719,7 @@ void nfc_loop() answer_rats(buf[1]); NFC_STATE.block_num = 1; clear_ibuf(); + WTX_clear(); printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: From 19627a959a8bf465c29f1e0fab8398321af8522c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 21:35:45 +0200 Subject: [PATCH 51/96] some TODOs --- targets/stm32l432/src/nfc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index a7819cb..eb07440 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -225,6 +225,9 @@ void WTX_clear() bool WTX_on(int WTX_time) { WTX_clear(); + + // TODO: start interrupt + return true; } @@ -232,8 +235,7 @@ bool WTX_process(int read_timeout); bool WTX_off() { - if (WTX_fail) - return false; + // TODO: stop interrupt // read data if we sent WTX if (WTX_sent) @@ -241,6 +243,9 @@ bool WTX_off() if (!WTX_process(10)) return false; } + + if (WTX_fail) + return false; return true; } From c3bddee814da45c90e4f15b69f0548978e45cbbb Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:21:26 -0500 Subject: [PATCH 52/96] dont do this when powered by nfc --- targets/stm32l432/src/ams.c | 131 ++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index a342513..d52da58 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -265,83 +265,86 @@ bool ams_init() LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); LL_SPI_Enable(SPI1); - delay(10); + // delay(10); SELECT(); - delay(10); + // delay(10); - - ams_write_command(AMS_CMD_DEFAULT); - ams_write_command(AMS_CMD_CLEAR_BUFFER); - - // check connection - uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); - if (!productType) - { - printf1(TAG_NFC,"Have no product type. Connection error."); - return false; - } - printf1(TAG_NFC,"Product type 0x%02x.", productType); - - // enable tunneling mode and RF configuration - ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); - - ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); - printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); - - ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); - - uint8_t sense1 = 0x44; - uint8_t sense2 = 0x00; - uint8_t selr = 0x20; // SAK - - if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) + // + if (1) { - printf1(TAG_NFC,"Writing config block 0\r\n"); - block[0] = sense1; - block[1] = sense2; - block[2] = selr; - block[3] = 0x00; + ams_write_command(AMS_CMD_DEFAULT); + ams_write_command(AMS_CMD_CLEAR_BUFFER); - ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - UNSELECT(); - delay(10); - SELECT(); - delay(10); + // check connection + uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); + if (!productType) + { + printf1(TAG_NFC,"Have no product type. Connection error."); + return false; + } + printf1(TAG_NFC,"Product type 0x%02x.", productType); + + // enable tunneling mode and RF configuration + ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); + + ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); + printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); - } - ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); - printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + uint8_t sense1 = 0x44; + uint8_t sense2 = 0x00; + uint8_t selr = 0x20; // SAK - uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; - uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; + if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) + { + printf1(TAG_NFC,"Writing config block 0\r\n"); + block[0] = sense1; + block[1] = sense2; + block[2] = selr; + block[3] = 0x00; - if (block[0] != ic_cfg1 || block[1] != ic_cfg2) - { - printf1(TAG_NFC,"Writing config block 1\r\n"); - // set IC_CFG1 - block[0] = ic_cfg1; + ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + UNSELECT(); + delay(10); + SELECT(); + delay(10); - // set IC_CFG2 - block[1] = ic_cfg2; + ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + } - // mask interrupt bits - block[2] = 0x80; - block[3] = 0; - - ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); - - UNSELECT(); - delay(10); - SELECT(); - delay(10); - - ams_read_eeprom_block(0x7F, block); + ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + + uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; + uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; + + if (block[0] != ic_cfg1 || block[1] != ic_cfg2) + { + printf1(TAG_NFC,"Writing config block 1\r\n"); + // set IC_CFG1 + block[0] = ic_cfg1; + + // set IC_CFG2 + block[1] = ic_cfg2; + + // mask interrupt bits + block[2] = 0x80; + block[3] = 0; + + ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + + UNSELECT(); + delay(10); + SELECT(); + delay(10); + + ams_read_eeprom_block(0x7F, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + } } - + return true; } From 4ba57ccc85f3db1384a7d7a9f45d9ac5fc72847d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:23:01 -0500 Subject: [PATCH 53/96] refactor init functions --- targets/stm32l432/bootloader/bootloader.h | 12 +- targets/stm32l432/bootloader/main.c | 23 +- targets/stm32l432/src/init.c | 467 ++++++++++------------ targets/stm32l432/src/init.h | 37 ++ 4 files changed, 276 insertions(+), 263 deletions(-) create mode 100644 targets/stm32l432/src/init.h diff --git a/targets/stm32l432/bootloader/bootloader.h b/targets/stm32l432/bootloader/bootloader.h index 22e5db3..4cd23be 100644 --- a/targets/stm32l432/bootloader/bootloader.h +++ b/targets/stm32l432/bootloader/bootloader.h @@ -1,21 +1,21 @@ /* * Copyright (C) 2018 SoloKeys, Inc. - * + * * This file is part of Solo. - * + * * Solo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * Solo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Solo. If not, see - * + * * This code is available under licenses for commercial use. * Please contact SoloKeys for more information. */ @@ -66,7 +66,7 @@ #define SKIP_BUTTON_CHECK_FAST 1 void printing_init(); -void hw_init(void); +void hw_init(int lf); // Trigger software reset void device_reboot(); diff --git a/targets/stm32l432/bootloader/main.c b/targets/stm32l432/bootloader/main.c index afdc15f..d1325af 100644 --- a/targets/stm32l432/bootloader/main.c +++ b/targets/stm32l432/bootloader/main.c @@ -23,6 +23,9 @@ #include #include +#include "stm32l4xx_ll_rcc.h" +#include "stm32l4xx.h" + #include "cbor.h" #include "device.h" #include "ctaphid.h" @@ -32,9 +35,8 @@ #include "ctap.h" #include "app.h" #include "memory_layout.h" -#include "stm32l4xx_ll_rcc.h" +#include "init.h" -#include "stm32l4xx.h" uint8_t REBOOT_FLAG = 0; @@ -82,7 +84,15 @@ int main(int argc, char * argv[]) TAG_ERR ); - device_init(); + // device_init(); + SystemClock_Config_LF(); + init_gpio(); + init_millisecond_timer(1); + +#if DEBUG_LEVEL > 0 + init_debug_uart(); +#endif + printf1(TAG_GEN,"init device\n"); t1 = millis(); @@ -118,7 +128,14 @@ int main(int argc, char * argv[]) printf1(TAG_RED,"Not authorized to boot (%08x == %08lx)\r\n", AUTH_WORD_ADDR, *(uint32_t*)AUTH_WORD_ADDR); } start_bootloader: + + SystemClock_Config(); + init_gpio(); + init_millisecond_timer(0); + init_pwm(); + init_rng(); usbhid_init(); + printf1(TAG_GEN,"init usb\n"); ctaphid_init(); diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index 056a7ba..3c33c56 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -45,31 +45,20 @@ #include "usbd_composite.h" #include "usbd_cdc_if.h" #include "device.h" +#include "init.h" #include APP_CONFIG -/* USER CODE BEGIN Includes */ -/* USER CODE END Includes */ - -/* Private variables ---------------------------------------------------------*/ USBD_HandleTypeDef Solo_USBD_Device; -/* Private function prototypes -----------------------------------------------*/ static void LL_Init(void); -void SystemClock_Config(void); -static void MX_GPIO_Init(void); -static void MX_USART1_UART_Init(void); -static void MX_TIM2_Init(void); -static void MX_TIM6_Init(void); -static void MX_RNG_Init(void); -static void MX_SPI1_Init(void); #define Error_Handler() _Error_Handler(__FILE__,__LINE__) void _Error_Handler(char *file, int line); -void hw_init(void) +void hw_init(int lowfreq) { #ifdef IS_BOOTLOADER SCB->VTOR = FLASH_BASE; @@ -77,25 +66,33 @@ void hw_init(void) #endif LL_Init(); - SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + if (lowfreq) + { + SystemClock_Config_LF(); + } + else + { + SystemClock_Config(); + } - SystemClock_Config(); // TODO bootloader should not change clk freq. - MX_GPIO_Init(); - MX_TIM2_Init(); // PWM for LEDs + init_gpio(); - MX_TIM6_Init(); // ~1 ms timer + if (!lowfreq) + { + init_pwm(); + } + + init_millisecond_timer(lowfreq); #if DEBUG_LEVEL > 0 - MX_USART1_UART_Init();// debug uart + init_debug_uart(); #endif - MX_RNG_Init(); - MX_SPI1_Init(); - TIM6->SR = 0; - __enable_irq(); - NVIC_EnableIRQ(TIM6_IRQn); + init_rng(); + init_spi(); + } static void LL_Init(void) @@ -122,259 +119,253 @@ static void LL_Init(void) NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); } -static int NFC = 0; + /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { - if (!NFC) - { + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); - LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); - if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) - { - Error_Handler(); - } - LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); - LL_RCC_HSI48_Enable(); + LL_RCC_HSI48_Enable(); - /* Wait till HSI48 is ready */ - while(LL_RCC_HSI48_IsReady() != 1) - { + /* Wait till HSI48 is ready */ + while(LL_RCC_HSI48_IsReady() != 1) + { - } + } - LL_RCC_LSI_Enable(); + LL_RCC_LSI_Enable(); - /* Wait till LSI is ready */ - while(LL_RCC_LSI_IsReady() != 1) - { + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { - } - LL_RCC_MSI_Enable(); - /* Wait till MSI is ready */ - while(LL_RCC_MSI_IsReady() != 1) - { + } + LL_RCC_MSI_Enable(); + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { - } - LL_RCC_MSI_EnableRangeSelection(); + } + LL_RCC_MSI_EnableRangeSelection(); - LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11); + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11); - LL_RCC_MSI_SetCalibTrimming(0); + LL_RCC_MSI_SetCalibTrimming(0); - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); - /* Wait till System clock is ready */ - while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) - { + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { - } - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16); - LL_Init1msTick(48000000); + LL_Init1msTick(48000000); - LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); - LL_SetSystemCoreClock(48000000); + LL_SetSystemCoreClock(48000000); - LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); - LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_HSI48); + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_HSI48); - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS); + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS); - LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_CRS); + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_CRS); - LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_CRS); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_CRS); - LL_CRS_SetSyncDivider(LL_CRS_SYNC_DIV_1); + LL_CRS_SetSyncDivider(LL_CRS_SYNC_DIV_1); - LL_CRS_SetSyncPolarity(LL_CRS_SYNC_POLARITY_RISING); + LL_CRS_SetSyncPolarity(LL_CRS_SYNC_POLARITY_RISING); - LL_CRS_SetSyncSignalSource(LL_CRS_SYNC_SOURCE_USB); + LL_CRS_SetSyncSignalSource(LL_CRS_SYNC_SOURCE_USB); - LL_CRS_SetReloadCounter(__LL_CRS_CALC_CALCULATE_RELOADVALUE(48000000,1000)); + LL_CRS_SetReloadCounter(__LL_CRS_CALC_CALCULATE_RELOADVALUE(48000000,1000)); - LL_CRS_SetFreqErrorLimit(34); + LL_CRS_SetFreqErrorLimit(34); - LL_CRS_SetHSI48SmoothTrimming(32); - - /* SysTick_IRQn interrupt configuration */ - NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); - } - else - { - LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); - - if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) - { - Error_Handler(); - } - LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); - - LL_RCC_LSI_Enable(); - - /* Wait till LSI is ready */ - while(LL_RCC_LSI_IsReady() != 1) - { - - } - LL_RCC_MSI_Enable(); - - /* Wait till MSI is ready */ - while(LL_RCC_MSI_IsReady() != 1) - { - - } - LL_RCC_MSI_EnableRangeSelection(); - - LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6); - - LL_RCC_MSI_SetCalibTrimming(0); - - LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); - - /* Wait till System clock is ready */ - while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) - { - - } - LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); - - LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); - - LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); - - LL_Init1msTick(4000000); - - LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); - - LL_SetSystemCoreClock(4000000); - - LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); - - LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); - - /* SysTick_IRQn interrupt configuration */ - NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); - } + LL_CRS_SetHSI48SmoothTrimming(32); + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); } -void usb_init() +void SystemClock_Config_LF(void) { - if (!NFC) + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) { - // enable USB power - SET_BIT(PWR->CR2, PWR_CR2_USV); - - // Enable USB Clock - SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); - - - USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC); - in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0; - out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0; - - in_endpoint_to_class[CDC_IN_EP & 0x7F] = 1; - out_endpoint_to_class[CDC_OUT_EP & 0x7F] = 1; - - USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0); - USBD_RegisterClass(&Solo_USBD_Device, &USBD_Composite); - // USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID); - // - // USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC); - USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS); - - USBD_Start(&Solo_USBD_Device); + Error_Handler(); } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(4000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(4000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + } -/* TIM2 init function */ -static void MX_TIM2_Init(void) +void init_usb() { - // if(!NFC) - { - LL_TIM_InitTypeDef TIM_InitStruct; - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; + // enable USB power + SET_BIT(PWR->CR2, PWR_CR2_USV); - LL_GPIO_InitTypeDef GPIO_InitStruct; + // Enable USB Clock + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); - /* Peripheral clock enable */ - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); - TIM2->SR = 0 ; + USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC); + in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0; + out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0; - TIM_InitStruct.Prescaler = 0; - TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; - TIM_InitStruct.Autoreload = 1000; - TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; - LL_TIM_Init(TIM2, &TIM_InitStruct); + in_endpoint_to_class[CDC_IN_EP & 0x7F] = 1; + out_endpoint_to_class[CDC_OUT_EP & 0x7F] = 1; - LL_TIM_EnableARRPreload(TIM2); + USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0); + USBD_RegisterClass(&Solo_USBD_Device, &USBD_Composite); + // USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID); + // + // USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC); + USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS); - LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); + USBD_Start(&Solo_USBD_Device); +} - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 1000; - TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; - LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct); +void init_pwm(void) +{ - LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2); + LL_TIM_InitTypeDef TIM_InitStruct; + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; - LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct); + LL_GPIO_InitTypeDef GPIO_InitStruct; - LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3); + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; - LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct); + TIM2->SR = 0 ; - LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH4); + TIM_InitStruct.Prescaler = 0; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 1000; + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; + LL_TIM_Init(TIM2, &TIM_InitStruct); - LL_TIM_SetOCRefClearInputSource(TIM2, LL_TIM_OCREF_CLR_INT_NC); + LL_TIM_EnableARRPreload(TIM2); - LL_TIM_DisableExternalClock(TIM2); + LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); - LL_TIM_ConfigETR(TIM2, LL_TIM_ETR_POLARITY_NONINVERTED, LL_TIM_ETR_PRESCALER_DIV1, LL_TIM_ETR_FILTER_FDIV1); + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.CompareValue = 1000; + TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct); - LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2); - LL_TIM_DisableMasterSlaveMode(TIM2); + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct); - /**TIM2 GPIO Configuration - PA1 ------> TIM2_CH2 - PA2 ------> TIM2_CH3 - PA3 ------> TIM2_CH4 - */ - GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_3; - GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; - GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - GPIO_InitStruct.Alternate = LL_GPIO_AF_1; - LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3); - LL_TIM_EnableCounter(TIM2); - } + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct); + + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH4); + + LL_TIM_SetOCRefClearInputSource(TIM2, LL_TIM_OCREF_CLR_INT_NC); + + LL_TIM_DisableExternalClock(TIM2); + + LL_TIM_ConfigETR(TIM2, LL_TIM_ETR_POLARITY_NONINVERTED, LL_TIM_ETR_PRESCALER_DIV1, LL_TIM_ETR_FILTER_FDIV1); + + LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); + + LL_TIM_DisableMasterSlaveMode(TIM2); + + /**TIM2 GPIO Configuration + PA1 ------> TIM2_CH2 + PA2 ------> TIM2_CH3 + PA3 ------> TIM2_CH4 + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_3; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_1; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + LL_TIM_EnableCounter(TIM2); } -/* USART1 init function */ -static void MX_USART1_UART_Init(void) +void init_debug_uart(void) { LL_USART_InitTypeDef USART_InitStruct; @@ -411,20 +402,18 @@ static void MX_USART1_UART_Init(void) } -/** Pinout Configuration -*/ -static void MX_GPIO_Init(void) +void init_gpio(void) { /* GPIO Ports Clock Enable */ LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); + LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); } - -/* TIM6 init function */ -static void MX_TIM6_Init(void) +void init_millisecond_timer(int lf) { LL_TIM_InitTypeDef TIM_InitStruct; @@ -434,7 +423,7 @@ static void MX_TIM6_Init(void) // 48 MHz sys clock --> 6 MHz timer clock // 48 MHz / 48000 == 1000 Hz - if (!NFC) + if (!lf) TIM_InitStruct.Prescaler = 48000; else TIM_InitStruct.Prescaler = 4000; @@ -454,39 +443,14 @@ static void MX_TIM6_Init(void) // Start immediately LL_TIM_EnableCounter(TIM6); + + TIM6->SR = 0; + __enable_irq(); + NVIC_EnableIRQ(TIM6_IRQn); } -/* TIM7 init function */ -// static void MX_TIM7_Init(void) -// { -// -// LL_TIM_InitTypeDef TIM_InitStruct; -// -// /* Peripheral clock enable */ -// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7); -// -// // 48 MHz sys clock --> 6 MHz timer clock -// // 6 MHz / 6000 == 1000 Hz -// TIM_InitStruct.Prescaler = 48000; -// TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; -// TIM_InitStruct.Autoreload = 0xffff; -// LL_TIM_Init(TIM6, &TIM_InitStruct); -// -// LL_TIM_DisableARRPreload(TIM7); -// -// LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_RESET); -// -// LL_TIM_DisableMasterSlaveMode(TIM7); -// -// // enable interrupt -// TIM7->DIER |= 1; -// -// // Start immediately -// LL_TIM_EnableCounter(TIM7); -// } -/* RNG init function */ -static void MX_RNG_Init(void) +void init_rng(void) { /* Peripheral clock enable */ @@ -497,7 +461,7 @@ static void MX_RNG_Init(void) } /* SPI1 init function */ -static void MX_SPI1_Init(void) +void init_spi(void) { LL_SPI_InitTypeDef SPI_InitStruct; @@ -527,10 +491,7 @@ static void MX_SPI1_Init(void) SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; - // if (!NFC) - // SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64; - // else - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct.CRCPoly = 7; @@ -538,7 +499,5 @@ static void MX_SPI1_Init(void) LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA); - // LL_SPI_EnableNSSPulseMgt(SPI1); - } diff --git a/targets/stm32l432/src/init.h b/targets/stm32l432/src/init.h new file mode 100644 index 0000000..1319a1e --- /dev/null +++ b/targets/stm32l432/src/init.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 SoloKeys, Inc. + * + * This file is part of Solo. + * + * Solo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Solo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Solo. If not, see + * + * This code is available under licenses for commercial use. + * Please contact SoloKeys for more information. + */ +#ifndef _INIT_H_ +#define _INIT_H_ + +void SystemClock_Config(void); +void SystemClock_Config_LF(void); + +void init_usb(); +void init_gpio(void); +void init_debug_uart(void); +void init_pwm(void); +void init_millisecond_timer(int lf); +void init_rng(void); +void init_spi(void); + + +#endif From 38171dba06ed8d35efca783cd3d7c2c1496283a4 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:23:51 -0500 Subject: [PATCH 54/96] low freq init --- targets/stm32l432/src/device.c | 53 +++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index b3fd58f..888a2a6 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -43,12 +43,17 @@ #include "stm32l4xx_ll_iwdg.h" #include "usbd_cdc_if.h" #include "nfc.h" +#include "init.h" + +#define LOW_FREQUENCY 1 +#define HIGH_FREQUENCY 0 uint32_t __90_ms = 0; uint32_t __device_status = 0; uint32_t __last_update = 0; extern PCD_HandleTypeDef hpcd; bool haveNFC = false; +bool isLowFreq = 0; #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) @@ -108,10 +113,8 @@ void device_reboot() } void device_init() { - hw_init(); - - LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); - LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); + hw_init(LOW_FREQUENCY); + isLowFreq = 1; #ifndef IS_BOOTLOADER #if BOOT_TO_DFU @@ -121,38 +124,40 @@ void device_init() #endif printf1(TAG_GEN,"init nfc\n"); haveNFC = nfc_init(); - if (haveNFC) - printf1(TAG_GEN,"NFC OK.\n"); - else - printf1(TAG_GEN,"NFC not found.\n"); + // if (haveNFC) + // printf1(TAG_GEN,"NFC OK.\n"); + // else + // printf1(TAG_GEN,"NFC not found.\n"); #endif - printf1(TAG_GEN,"hello solo\r\n"); + // printf1(TAG_GEN,"hello solo\r\n"); } -void usb_init(void); -void usbhid_init() -{ - usb_init(); - -#if DEBUG_LEVEL>1 - wait_for_usb_tether(); -#endif -} - - - void wait_for_usb_tether() { - while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) ) + while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) ) ; - while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) ) + while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) ) ; delay(10); - while (USBD_OK != CDC_Transmit_FS("tethered\r\n", 10) ) + while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) ) ; } +void usbhid_init() +{ + if (!isLowFreq) + { + init_usb(); + +#if DEBUG_LEVEL>1 + wait_for_usb_tether(); +#endif + } +} + + + int usbhid_recv(uint8_t * msg) { if (fifo_hidmsg_size()) From 3d0d91fa5c2efdc3a3fc42dc8eee79870d261acf Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:24:11 -0500 Subject: [PATCH 55/96] lf param --- targets/stm32l432/src/app.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index 6afe0bb..e3f8ee0 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -45,7 +45,7 @@ #define DISABLE_CTAPHID_CBOR void printing_init(); -void hw_init(void); +void hw_init(int lf); //#define TEST //#define TEST_POWER From ee98340a0393195100435717af358144b59e1931 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:24:42 -0500 Subject: [PATCH 56/96] temporarily remove prints at start --- fido2/main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fido2/main.c b/fido2/main.c index 3849633..27b68a4 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -41,7 +41,7 @@ int main(int argc, char * argv[]) set_logging_mask( /*0*/ - // TAG_GEN| + TAG_GEN| // TAG_MC | // TAG_GA | // TAG_WALLET | @@ -60,20 +60,20 @@ int main(int argc, char * argv[]) ); device_init(); - printf1(TAG_GEN,"init device\n"); + // printf1(TAG_GEN,"init device\n"); usbhid_init(); - printf1(TAG_GEN,"init usb\n"); + // printf1(TAG_GEN,"init usb\n"); ctaphid_init(); - printf1(TAG_GEN,"init ctaphid\n"); + // printf1(TAG_GEN,"init ctaphid\n"); - ctap_init(); - printf1(TAG_GEN,"init ctap\n"); + // ctap_init(); + // printf1(TAG_GEN,"init ctap\n"); memset(hidmsg,0,sizeof(hidmsg)); - printf1(TAG_GEN,"recv'ing hid msg \n"); + // printf1(TAG_GEN,"recv'ing hid msg \n"); while(1) From ca2074de3674b34e3f79d45174f12bb546195d6d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:25:01 -0500 Subject: [PATCH 57/96] Update Makefile --- targets/stm32l432/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/targets/stm32l432/Makefile b/targets/stm32l432/Makefile index 9df352c..aeae209 100644 --- a/targets/stm32l432/Makefile +++ b/targets/stm32l432/Makefile @@ -56,8 +56,7 @@ flash_dfu: solo.hex bootloader.hex # STM32_Programmer_CLI -c port=usb1 -halt -e all --readunprotect STM32_Programmer_CLI -c port=usb1 -halt -rdu -d all.hex -flashboot: solo.hex bootloader.hex - $(merge_hex) solo.hex bootloader.hex all.hex +flashboot: STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst From 81a89ed6aaa8ce0b8dc572dbef782e3623ada1b1 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 2 Feb 2019 00:29:32 -0500 Subject: [PATCH 58/96] go back to high freq --- targets/stm32l432/src/device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 888a2a6..8ed047f 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -113,8 +113,8 @@ void device_reboot() } void device_init() { - hw_init(LOW_FREQUENCY); - isLowFreq = 1; + hw_init(HIGH_FREQUENCY); + // isLowFreq = 1; #ifndef IS_BOOTLOADER #if BOOT_TO_DFU From 3ffcc473748b6c7f14ec5ed55c12cc921c09703f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 14:11:49 +0200 Subject: [PATCH 59/96] fix logger --- targets/stm32l432/src/redirect.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index d3d5e5d..ee587d0 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -43,11 +43,22 @@ static int NFC = 0; int _write (int fd, const void *buf, long int len) { uint8_t * data = (uint8_t *) buf; + static uint8_t logbuf[1000] = {0}; + static int logbuflen = 0; + if (logbuflen + len > 1000) { + int mlen = logbuflen + len - 1000; + memmove(logbuf, &logbuf[mlen], mlen); + logbuflen -= mlen; + } + memcpy(&logbuf[logbuflen], data, len); + logbuflen += len; if (!NFC) { // Send out USB serial - CDC_Transmit_FS(data, len); + uint8_t res = CDC_Transmit_FS(logbuf, logbuflen); + if (res == USBD_OK) + logbuflen = 0; } // Send out UART serial From e657e26886993bc7489f19d5ac6b84cb1f6eb788 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 15:15:37 +0200 Subject: [PATCH 60/96] check AMS product type --- targets/stm32l432/src/ams.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index a342513..4a7a2f7 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -275,12 +275,12 @@ bool ams_init() // check connection uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); - if (!productType) + if (productType != 0x14) { - printf1(TAG_NFC,"Have no product type. Connection error."); + printf1(TAG_NFC,"Have no product type [0x%02x]. Connection error.\n", productType); return false; } - printf1(TAG_NFC,"Product type 0x%02x.", productType); + printf1(TAG_NFC,"Product type 0x%02x.\n", productType); // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); From 4611f05051dfe6a17fb85f801c7fca65635ed041 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 15:17:52 +0200 Subject: [PATCH 61/96] small fix in AMS3956 debug texts --- targets/stm32l432/src/ams.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 4a7a2f7..76a256c 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -277,10 +277,10 @@ bool ams_init() uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); if (productType != 0x14) { - printf1(TAG_NFC,"Have no product type [0x%02x]. Connection error.\n", productType); + printf1(TAG_NFC, "Have no product type [0x%02x]. AMS3956 connection error.\n", productType); return false; } - printf1(TAG_NFC,"Product type 0x%02x.\n", productType); + printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); From 771fffe329746be23278c674ea43cfe1759adffa Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 17:12:22 +0200 Subject: [PATCH 62/96] WTX works. todo: clean debug unneeded messages --- targets/stm32l432/src/device.c | 6 +++++ targets/stm32l432/src/nfc.c | 41 ++++++++++++++++++++++++++-------- targets/stm32l432/src/nfc.h | 2 ++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index b3fd58f..725727d 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -65,6 +65,12 @@ void TIM6_DAC_IRQHandler() ctaphid_update_status(__device_status); } } + + // NFC sending WTX if needs + if (haveNFC) + { + WTX_timer_exec(); + } } // Global USB interrupt handler diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index eb07440..9369487 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -215,41 +215,55 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) // WTX: f2 01 91 40 === f2(S-block + WTX, frame without CID) 01(from iso - multiply WTX from ATS by 1) <2b crc16> static bool WTX_sent; static bool WTX_fail; +static uint32_t WTX_timer; + +bool WTX_process(int read_timeout); void WTX_clear() { WTX_sent = false; WTX_fail = false; + WTX_timer = 0; } bool WTX_on(int WTX_time) { WTX_clear(); - // TODO: start interrupt + WTX_timer = millis(); return true; } -bool WTX_process(int read_timeout); - bool WTX_off() { - // TODO: stop interrupt + WTX_timer = 0; // read data if we sent WTX if (WTX_sent) { - if (!WTX_process(10)) +printf1(TAG_NFC, "WTX_process from WTX_off\n"); + if (!WTX_process(100)) return false; } if (WTX_fail) return false; + WTX_clear(); return true; } +void WTX_timer_exec() +{ + // timer on and expired (300ms) + if ((WTX_timer <= 0) || WTX_timer + 300 > millis()) + return; + + WTX_process(10); + WTX_timer = millis(); +} + // executes twice a period. 1st for send WTX, 2nd for check the result // read timeout must be 0 to call from int bool WTX_process(int read_timeout) @@ -262,24 +276,28 @@ bool WTX_process(int read_timeout) { nfc_write_frame(wtx, sizeof(wtx)); WTX_sent = true; +printf1(TAG_NFC, "+ %d\n", millis()); return true; } else { uint8_t data[32]; int len; - if (ams_receive_with_timeout(read_timeout, data, sizeof(data), &len)) + if (!ams_receive_with_timeout(read_timeout, data, sizeof(data), &len)) { +printf1(TAG_NFC, "ft len=%d ms=%d\n", len, millis()); WTX_fail = true; return false; } if (len != 2 || data[0] != 0xf2 || data[1] != 0x01) { +printf1(TAG_NFC, "fl %d [%02x]\n", len, data[0]); WTX_fail = true; return false; } +printf1(TAG_NFC, "- %d\n", millis()); WTX_sent = false; return true; } @@ -398,6 +416,7 @@ void nfc_process_iblock(uint8_t * buf, int len) // block = buf[0] & 1; // block = NFC_STATE.block_num; // block = !block; + // NFC_STATE.block_num = block; // NFC_STATE.block_num = block; nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); printf1(TAG_NFC, "FIDO applet selected.\r\n"); @@ -444,8 +463,10 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - if (!WTX_off()) + if (!WTX_off()) { +printf1(TAG_NFC, "WRX-off err\n"); return; + } printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -493,8 +514,10 @@ void nfc_process_iblock(uint8_t * buf, int len) WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp); - if (!WTX_off()) + if (!WTX_off()){ +printf1(TAG_NFC, "WTX-off err\n"); return; + } printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) @@ -643,7 +666,7 @@ void nfc_process_block(uint8_t * buf, int len) } else { - printf1(TAG_NFC, "NFC_CMD_SBLOCK, Unknown\r\n"); + printf1(TAG_NFC, "NFC_CMD_SBLOCK, Unknown. len[%d]\r\n", len); } dump_hex1(TAG_NFC, buf, len); } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 4859570..2388018 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -57,4 +57,6 @@ typedef enum APP_FIDO, } APPLETS; +void WTX_timer_exec(); + #endif From 375db69e3a2e6d836e4ccce118ecd95a2b70d875 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 19:06:49 +0200 Subject: [PATCH 63/96] fido2 works --- fido2/ctap.c | 25 +++++++++++++++---------- fido2/ctap.h | 2 +- targets/stm32l432/src/nfc.c | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/fido2/ctap.c b/fido2/ctap.c index 6b644f3..b84f9b7 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -324,7 +324,7 @@ static int is_matching_rk(CTAP_residentKey * rk, CTAP_residentKey * rk2) } -static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store) +static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store, bool fromNFC) { CborEncoder cose_key; int auth_data_sz, ret; @@ -350,8 +350,13 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au count = auth_data_update_count(&authData->head); device_set_status(CTAPHID_STATUS_UPNEEDED); - int but = ctap_user_presence_test(); - + // if NFC - not need to click a button + int but = 1; + if(!fromNFC) + { + but = ctap_user_presence_test(); + } + if (!but) { return CTAP2_ERR_OPERATION_DENIED; @@ -551,7 +556,7 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d -uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) +uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length, bool fromNFC) { CTAP_makeCredential MC; int ret, i; @@ -621,7 +626,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt int32_t auth_data_sz; ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf), - &MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz, MC.rk); + &MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz, MC.rk, fromNFC); check_retr(ret); @@ -940,7 +945,7 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder) return 0; } -uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) +uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length, bool fromNFC) { CTAP_getAssertion GA; uint8_t auth_data_buf[sizeof(CTAP_authDataHeader)]; @@ -992,7 +997,7 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) ret = cbor_encoder_create_map(encoder, &map, map_size); check_ret(ret); - ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0); + ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0, fromNFC); check_retr(ret); /*for (int j = 0; j < GA.credLen; j++)*/ @@ -1358,7 +1363,7 @@ void ctap_response_init(CTAP_RESPONSE * resp) } -uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) +uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool fromNFC) { CborEncoder encoder; uint8_t status = 0; @@ -1398,7 +1403,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) device_set_status(CTAPHID_STATUS_PROCESSING); printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n"); t1 = millis(); - status = ctap_make_credential(&encoder, pkt_raw, length); + status = ctap_make_credential(&encoder, pkt_raw, length, fromNFC); t2 = millis(); printf1(TAG_TIME,"make_credential time: %d ms\n", t2-t1); @@ -1410,7 +1415,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) device_set_status(CTAPHID_STATUS_PROCESSING); printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n"); t1 = millis(); - status = ctap_get_assertion(&encoder, pkt_raw, length); + status = ctap_get_assertion(&encoder, pkt_raw, length, fromNFC); t2 = millis(); printf1(TAG_TIME,"get_assertion time: %d ms\n", t2-t1); diff --git a/fido2/ctap.h b/fido2/ctap.h index 7448b44..2df795b 100644 --- a/fido2/ctap.h +++ b/fido2/ctap.h @@ -275,7 +275,7 @@ typedef struct void ctap_response_init(CTAP_RESPONSE * resp); -uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp); +uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool fromNFC); // Encodes R,S signature to 2 der sequence of two integers. Sigder must be at least 72 bytes. // @return length of der signature diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 9369487..892a853 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -513,12 +513,12 @@ printf1(TAG_NFC, "WRX-off err\n"); WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); - status = ctap_request(payload, plen, &ctap_resp); + status = ctap_request(payload, plen, &ctap_resp, true); if (!WTX_off()){ printf1(TAG_NFC, "WTX-off err\n"); return; } - printf1(TAG_NFC, "CTAP resp: %d len: %d\r\n", status, ctap_resp.length); + printf1(TAG_NFC, "CTAP resp: 0x%02õ len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) { From bc1bb3509f202e26fcaf111c2d58075bb65cdc7e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 19:21:06 +0200 Subject: [PATCH 64/96] move APDU dumps to separate log channel --- fido2/log.c | 1 + fido2/log.h | 45 +++++++++++++++++++------------------ fido2/main.c | 37 +++++++++++++++--------------- targets/stm32l432/src/nfc.c | 16 +++++++------ 4 files changed, 52 insertions(+), 47 deletions(-) diff --git a/fido2/log.c b/fido2/log.c index 01514db..e070a23 100644 --- a/fido2/log.c +++ b/fido2/log.c @@ -63,6 +63,7 @@ struct logtag tagtable[] = { {TAG_BOOT,"BOOT"}, {TAG_EXT,"EXT"}, {TAG_NFC,"NFC"}, + {TAG_NFC_APDU, "NAPDU"}, }; diff --git a/fido2/log.h b/fido2/log.h index a6f5097..ea056ad 100644 --- a/fido2/log.h +++ b/fido2/log.h @@ -38,29 +38,30 @@ void set_logging_tag(uint32_t tag); typedef enum { - TAG_GEN = (1 << 0), - TAG_MC = (1 << 1), - TAG_GA = (1 << 2), - TAG_CP = (1 << 3), - TAG_ERR = (1 << 4), - TAG_PARSE= (1 << 5), - TAG_CTAP = (1 << 6), - TAG_U2F = (1 << 7), - TAG_DUMP = (1 << 8), - TAG_GREEN = (1 << 9), - TAG_RED= (1 << 10), - TAG_TIME= (1 << 11), - TAG_HID = (1 << 12), - TAG_USB = (1 << 13), - TAG_WALLET = (1 << 14), - TAG_STOR = (1 << 15), - TAG_DUMP2 = (1 << 16), - TAG_BOOT = (1 << 17), - TAG_EXT = (1 << 17), - TAG_NFC = (1 << 18), + TAG_GEN = (1 << 0), + TAG_MC = (1 << 1), + TAG_GA = (1 << 2), + TAG_CP = (1 << 3), + TAG_ERR = (1 << 4), + TAG_PARSE = (1 << 5), + TAG_CTAP = (1 << 6), + TAG_U2F = (1 << 7), + TAG_DUMP = (1 << 8), + TAG_GREEN = (1 << 9), + TAG_RED = (1 << 10), + TAG_TIME = (1 << 11), + TAG_HID = (1 << 12), + TAG_USB = (1 << 13), + TAG_WALLET = (1 << 14), + TAG_STOR = (1 << 15), + TAG_DUMP2 = (1 << 16), + TAG_BOOT = (1 << 17), + TAG_EXT = (1 << 18), + TAG_NFC = (1 << 19), + TAG_NFC_APDU = (1 << 20), - TAG_NO_TAG = (1UL<<30), - TAG_FILENO = (1UL<<31) + TAG_NO_TAG = (1UL << 30), + TAG_FILENO = (1UL << 31) } LOG_TAG; #if DEBUG_LEVEL > 0 diff --git a/fido2/main.c b/fido2/main.c index 3849633..19111e6 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -40,24 +40,25 @@ int main(int argc, char * argv[]) uint32_t t1 = 0; set_logging_mask( - /*0*/ - // TAG_GEN| - // TAG_MC | - // TAG_GA | - // TAG_WALLET | - TAG_STOR | - TAG_NFC | - // TAG_CP | - // TAG_CTAP| - // TAG_HID| - //TAG_U2F| - // TAG_PARSE | - // TAG_TIME| - // TAG_DUMP| - TAG_GREEN| - TAG_RED| - TAG_ERR - ); + /*0*/ + //TAG_GEN| + //TAG_MC | + //TAG_GA | + //TAG_WALLET | + TAG_STOR | + //TAG_NFC_APDU | + TAG_NFC | + //TAG_CP | + //TAG_CTAP| + //TAG_HID| + //TAG_U2F| + //TAG_PARSE | + //TAG_TIME| + //TAG_DUMP| + TAG_GREEN| + TAG_RED| + TAG_ERR + ); device_init(); printf1(TAG_GEN,"init device\n"); diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 892a853..c1d6024 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -91,7 +91,8 @@ bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, i { uint8_t len = buffer_status2 & AMS_BUF_LEN_MASK; ams_read_buffer(buf, len); - printf1(TAG_NFC,">> "); dump_hex1(TAG_NFC, buf, len); + printf1(TAG_NFC_APDU, ">> "); + dump_hex1(TAG_NFC_APDU, buf, len); *dlen = MIN(32, MIN(maxlen, len)); memcpy(data, buf, *dlen); @@ -116,7 +117,8 @@ void nfc_write_frame(uint8_t * data, uint8_t len) ams_write_buffer(data,len); ams_write_command(AMS_CMD_TRANSMIT_BUFFER); - printf1(TAG_NFC,"<< "); dump_hex1(TAG_NFC, data, len); + printf1(TAG_NFC_APDU, "<< "); + dump_hex1(TAG_NFC_APDU, data, len); } bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t resp) @@ -600,7 +602,7 @@ void nfc_process_block(uint8_t * buf, int len) { if (buf[0] & 0x10) { - printf1(TAG_NFC, "NFC_CMD_IBLOCK chaining blen=%d len=%d\r\n", ibuflen, len); + printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining blen=%d len=%d\r\n", ibuflen, len); if (ibuflen + len > sizeof(ibuf)) { printf1(TAG_NFC, "I block memory error! must have %d but have only %d\r\n", ibuflen + len, sizeof(ibuf)); @@ -608,8 +610,8 @@ void nfc_process_block(uint8_t * buf, int len) return; } - printf1(TAG_NFC,"i> "); - dump_hex1(TAG_NFC, buf, len); + printf1(TAG_NFC_APDU,"i> "); + dump_hex1(TAG_NFC_APDU, buf, len); if (len) { @@ -635,8 +637,8 @@ void nfc_process_block(uint8_t * buf, int len) printf1(TAG_NFC, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len); - printf1(TAG_NFC,"i> "); - dump_hex1(TAG_NFC, buf, len); + printf1(TAG_NFC_APDU,"i> "); + dump_hex1(TAG_NFC_APDU, buf, len); nfc_process_iblock(ibuf, ibuflen); } else { From 5328610ff14225e571ada1bd67fb2a9e9ca8175f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 19:51:32 +0200 Subject: [PATCH 65/96] delete debug messages --- targets/stm32l432/src/nfc.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index c1d6024..6a9b3ad 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -244,13 +244,18 @@ bool WTX_off() // read data if we sent WTX if (WTX_sent) { -printf1(TAG_NFC, "WTX_process from WTX_off\n"); if (!WTX_process(100)) + { + printf1(TAG_NFC, "WTX-off get last WTX error\n"); return false; + } } if (WTX_fail) + { + printf1(TAG_NFC, "WTX-off fail\n"); return false; + } WTX_clear(); return true; @@ -258,7 +263,7 @@ printf1(TAG_NFC, "WTX_process from WTX_off\n"); void WTX_timer_exec() { - // timer on and expired (300ms) + // condition: (timer on) or (not expired[300ms]) if ((WTX_timer <= 0) || WTX_timer + 300 > millis()) return; @@ -267,7 +272,7 @@ void WTX_timer_exec() } // executes twice a period. 1st for send WTX, 2nd for check the result -// read timeout must be 0 to call from int +// read timeout must be 10 ms to call from interrupt bool WTX_process(int read_timeout) { uint8_t wtx[] = {0xf2, 0x01}; @@ -278,7 +283,6 @@ bool WTX_process(int read_timeout) { nfc_write_frame(wtx, sizeof(wtx)); WTX_sent = true; -printf1(TAG_NFC, "+ %d\n", millis()); return true; } else @@ -287,19 +291,16 @@ printf1(TAG_NFC, "+ %d\n", millis()); int len; if (!ams_receive_with_timeout(read_timeout, data, sizeof(data), &len)) { -printf1(TAG_NFC, "ft len=%d ms=%d\n", len, millis()); WTX_fail = true; return false; } if (len != 2 || data[0] != 0xf2 || data[1] != 0x01) { -printf1(TAG_NFC, "fl %d [%02x]\n", len, data[0]); WTX_fail = true; return false; } -printf1(TAG_NFC, "- %d\n", millis()); WTX_sent = false; return true; } @@ -386,7 +387,7 @@ void nfc_process_iblock(uint8_t * buf, int len) CTAP_RESPONSE ctap_resp; int status; - printf1(TAG_NFC,">> "); + printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); // TODO this needs to be organized better @@ -465,10 +466,8 @@ void nfc_process_iblock(uint8_t * buf, int len) t1 = millis(); WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - if (!WTX_off()) { -printf1(TAG_NFC, "WRX-off err\n"); + if (!WTX_off()) return; - } printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); @@ -516,10 +515,9 @@ printf1(TAG_NFC, "WRX-off err\n"); WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); status = ctap_request(payload, plen, &ctap_resp, true); - if (!WTX_off()){ -printf1(TAG_NFC, "WTX-off err\n"); + if (!WTX_off()) return; - } + printf1(TAG_NFC, "CTAP resp: 0x%02õ len: %d\r\n", status, ctap_resp.length); if (status == CTAP1_ERR_SUCCESS) @@ -635,7 +633,7 @@ void nfc_process_block(uint8_t * buf, int len) ibuf[0] = buf[0]; ibuflen++; - printf1(TAG_NFC, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len); + printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining last block. blen=%d len=%d\r\n", ibuflen, len); printf1(TAG_NFC_APDU,"i> "); dump_hex1(TAG_NFC_APDU, buf, len); From ca0538551334b564d995bec42d022bdc6c4f4c08 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Feb 2019 20:06:46 +0200 Subject: [PATCH 66/96] log fixing --- targets/stm32l432/src/redirect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index ee587d0..8e55b9a 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -45,9 +45,9 @@ int _write (int fd, const void *buf, long int len) uint8_t * data = (uint8_t *) buf; static uint8_t logbuf[1000] = {0}; static int logbuflen = 0; - if (logbuflen + len > 1000) { - int mlen = logbuflen + len - 1000; - memmove(logbuf, &logbuf[mlen], mlen); + if (logbuflen + len > sizeof(logbuf)) { + int mlen = logbuflen + len - sizeof(logbuf); + memmove(logbuf, &logbuf[mlen], sizeof(logbuf) - mlen); logbuflen -= mlen; } memcpy(&logbuf[logbuflen], data, len); From 765d532f82d8bc6bc6310e20c659d68b0a702337 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 17:54:52 -0500 Subject: [PATCH 67/96] add low freq clocking options 4,8,16MHz --- targets/stm32l432/src/init.c | 148 ++++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index 5185aeb..371e181 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -65,6 +65,7 @@ void hw_init(int lowfreq) #else #endif LL_Init(); + init_gpio(); if (lowfreq) { @@ -76,7 +77,6 @@ void hw_init(int lowfreq) } - init_gpio(); if (!lowfreq) { @@ -85,7 +85,6 @@ void hw_init(int lowfreq) init_millisecond_timer(lowfreq); - #if DEBUG_LEVEL > 0 init_debug_uart(); #endif @@ -208,7 +207,7 @@ void SystemClock_Config(void) NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); } -void SystemClock_Config_LF(void) +void SystemClock_Config_LF4(void) { SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); @@ -266,6 +265,130 @@ void SystemClock_Config_LF(void) /* SysTick_IRQn interrupt configuration */ NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + + +} + +// 8MHz +void SystemClock_Config_LF(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + // while(LL_RCC_LSI_IsReady() != 1) + // { + // + // } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + // while(LL_RCC_MSI_IsReady() != 1) + // { + // + // } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_7); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + // while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + // { + // + // } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(8000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(8000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + +} + +// 16MHz +void SystemClock_Config_LF16(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_8); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(16000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(16000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + } void init_usb() @@ -413,8 +536,25 @@ void init_gpio(void) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + + LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT); LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); + +#ifdef SOLO_AMS_IRQ_PORT + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + /**/ + LL_GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = SOLO_AMS_IRQ_PIN; + GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(SOLO_AMS_IRQ_PORT, &GPIO_InitStruct); + + + LL_GPIO_SetPinMode(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_MODE_INPUT); + LL_GPIO_SetPinPull(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_PULL_UP); +#endif + } void init_millisecond_timer(int lf) @@ -430,7 +570,7 @@ void init_millisecond_timer(int lf) if (!lf) TIM_InitStruct.Prescaler = 48000; else - TIM_InitStruct.Prescaler = 4000; + TIM_InitStruct.Prescaler = 8000; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 90; From 2ed8667f1822221141828804eb9e7fb1803a53fc Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 17:55:27 -0500 Subject: [PATCH 68/96] immedately change clock rate to load data sections faster --- targets/stm32l432/src/startup_stm32l432xx.s | 55 +++++++++++---------- targets/stm32l432/src/system_stm32l4xx.c | 3 ++ 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/targets/stm32l432/src/startup_stm32l432xx.s b/targets/stm32l432/src/startup_stm32l432xx.s index 32d257f..7599702 100644 --- a/targets/stm32l432/src/startup_stm32l432xx.s +++ b/targets/stm32l432/src/startup_stm32l432xx.s @@ -7,7 +7,7 @@ * - Set the initial SP * - Set the initial PC == Reset_Handler, * - Set the vector table entries with the exceptions ISR address, - * - Configure the clock system + * - Configure the clock system * - Branches to main in the C library (which eventually * calls main()). * After Reset the Cortex-M4 processor is in Thread mode, @@ -79,6 +79,8 @@ Reset_Handler: ldr sp, =_estack /* Atollic update: set stack pointer */ /* Copy the data segment initializers from flash to SRAM */ +/* Call the clock system intitialization function.*/ + bl SystemInit movs r1, #0 b LoopCopyDataInit @@ -106,8 +108,7 @@ LoopFillZerobss: cmp r2, r3 bcc FillZerobss -/* Call the clock system intitialization function.*/ - bl SystemInit + /* Call static constructors */ bl __libc_init_array /* Call the application's entry point.*/ @@ -115,7 +116,7 @@ LoopFillZerobss: LoopForever: b LoopForever - + .size Reset_Handler, .-Reset_Handler /** @@ -414,49 +415,49 @@ g_pfnVectors: .weak COMP_IRQHandler .thumb_set COMP_IRQHandler,Default_Handler - + .weak LPTIM1_IRQHandler .thumb_set LPTIM1_IRQHandler,Default_Handler - + .weak LPTIM2_IRQHandler - .thumb_set LPTIM2_IRQHandler,Default_Handler - + .thumb_set LPTIM2_IRQHandler,Default_Handler + .weak USB_IRQHandler - .thumb_set USB_IRQHandler,Default_Handler - + .thumb_set USB_IRQHandler,Default_Handler + .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + .weak LPUART1_IRQHandler - .thumb_set LPUART1_IRQHandler,Default_Handler - + .thumb_set LPUART1_IRQHandler,Default_Handler + .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - + .thumb_set QUADSPI_IRQHandler,Default_Handler + .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - + .thumb_set I2C3_EV_IRQHandler,Default_Handler + .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - + .thumb_set I2C3_ER_IRQHandler,Default_Handler + .weak SAI1_IRQHandler .thumb_set SAI1_IRQHandler,Default_Handler - + .weak SWPMI1_IRQHandler .thumb_set SWPMI1_IRQHandler,Default_Handler - + .weak TSC_IRQHandler .thumb_set TSC_IRQHandler,Default_Handler - + .weak RNG_IRQHandler .thumb_set RNG_IRQHandler,Default_Handler - + .weak FPU_IRQHandler .thumb_set FPU_IRQHandler,Default_Handler - + .weak CRS_IRQHandler .thumb_set CRS_IRQHandler,Default_Handler /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l432/src/system_stm32l4xx.c b/targets/stm32l432/src/system_stm32l4xx.c index 44f5432..bb12cc3 100644 --- a/targets/stm32l432/src/system_stm32l4xx.c +++ b/targets/stm32l432/src/system_stm32l4xx.c @@ -106,6 +106,7 @@ */ #include "stm32l4xx.h" +#include "init.h" #if !defined (HSE_VALUE) #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ @@ -219,6 +220,8 @@ void SystemInit(void) /* Disable all interrupts */ RCC->CIER = 0x00000000U; + SystemClock_Config_LF(); + } /** From e3971a5e0f524d29c609a9bc98fe49609635592d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 17:56:53 -0500 Subject: [PATCH 69/96] change ams init, read less regs --- targets/stm32l432/src/ams.c | 47 ++++++++++++++++++++++++------------- targets/stm32l432/src/ams.h | 20 +++++++++++++++- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index d52da58..b0ab7d0 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -79,27 +79,16 @@ uint8_t ams_read_reg(uint8_t addr) return data; } -// data must be 14 bytes long -void read_reg_block2(AMS_DEVICE * dev) -{ - int i; - - for (i = 0; i < 0x20; i++) - { - dev->buf[i] = ams_read_reg(i); - } -} - // data must be 14 bytes long void read_reg_block(AMS_DEVICE * dev) { int i; - uint8_t mode = 0x20 | (0 ); + uint8_t mode = 0x20 | (4 ); flush_rx(); send_recv(mode); - for (i = 0; i < 0x20; i++) + for (i = 0x04; i < 0x0d; i++) { dev->buf[i] = send_recv(0); } @@ -204,6 +193,30 @@ const char * ams_get_state_string(uint8_t regval) return "STATE_WRONG"; } +int ams_state_is_valid(uint8_t regval) +{ + if (regval & AMS_STATE_INVALID) + { + return 0; + } + switch (regval & AMS_STATE_MASK) + { + case AMS_STATE_OFF: + case AMS_STATE_SENSE: + case AMS_STATE_RESOLUTION: + case AMS_STATE_RESOLUTION_L2: + case AMS_STATE_SELECTED: + case AMS_STATE_SECTOR2: + case AMS_STATE_SECTORX_2: + case AMS_STATE_SELECTEDX: + case AMS_STATE_SENSEX_L2: + case AMS_STATE_SENSEX: + case AMS_STATE_SLEEP: + return 1; + } + return 0; +} + void ams_print_int0(uint8_t int0) { uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); @@ -252,6 +265,7 @@ void ams_print_int1(uint8_t int0) printf1(tag,"\r\n"); } + bool ams_init() { @@ -270,7 +284,7 @@ bool ams_init() // delay(10); // - if (1) + if (0) { ams_write_command(AMS_CMD_DEFAULT); ams_write_command(AMS_CMD_CLEAR_BUFFER); @@ -287,6 +301,7 @@ bool ams_init() // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); + ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); @@ -295,7 +310,7 @@ bool ams_init() uint8_t sense1 = 0x44; uint8_t sense2 = 0x00; - uint8_t selr = 0x20; // SAK + uint8_t selr = 0x20; // SAK if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) { @@ -318,7 +333,7 @@ bool ams_init() ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); - uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; + uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V1; uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; if (block[0] != ic_cfg1 || block[1] != ic_cfg2) diff --git a/targets/stm32l432/src/ams.h b/targets/stm32l432/src/ams.h index ad3b94f..1f2e3a5 100644 --- a/targets/stm32l432/src/ams.h +++ b/targets/stm32l432/src/ams.h @@ -52,6 +52,9 @@ uint8_t ams_read_reg(uint8_t addr); void ams_write_reg(uint8_t addr, uint8_t tx); +const char * ams_get_state_string(uint8_t regval); +int ams_state_is_valid(uint8_t regval); + #define AMS_REG_IO_CONF 0x00 #define AMS_REG_IC_CONF0 0x01 @@ -70,11 +73,21 @@ void ams_write_reg(uint8_t addr, uint8_t tx); #define AMS_STATE_SELECTED (6 << 3) #define AMS_STATE_SECTOR2 (7 << 3) #define AMS_STATE_SECTORX_2 (0xf << 3) - #define AMS_STATE_SELECTEDX (0xd << 3) + #define AMS_STATE_SELECTEDX (0xe << 3) #define AMS_STATE_SENSEX_L2 (0xa << 3) #define AMS_STATE_SENSEX (0xb << 3) #define AMS_STATE_SLEEP (0x9 << 3) // ... // +#define AMS_REG_MASK_INT0 0x08 + #define AMS_MASK0_PU (1<<7) // power up + #define AMS_MASK0_WU_A (1<<6) // selected INT + #define AMS_MASK0_SLP (1<<5) + #define AMS_MASK0_EEW_RF (1<<4) + #define AMS_MASK0_EER_RF (1<<3) + #define AMS_MASK0_RXE (1<<2) + #define AMS_MASK0_TXE (1<<1) + #define AMS_MASK0_XRF (1<<0) +#define AMS_REG_MASK_INT1 0x09 #define AMS_REG_INT0 0x0a #define AMS_INT_XRF (1<<0) #define AMS_INT_TXE (1<<1) @@ -109,6 +122,11 @@ void ams_write_reg(uint8_t addr, uint8_t tx); #define AMS_CFG1_VOLTAGE_LEVEL_1V9 (0x00<<2) #define AMS_CFG1_VOLTAGE_LEVEL_2V0 (0x01<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V1 (0x02<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V2 (0x03<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V3 (0x04<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V4 (0x05<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V5 (0x06<<2) #define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00 #define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01 From f470e9a9cd8f39c742a11216563f1d88aa6023b9 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 18:05:22 -0500 Subject: [PATCH 70/96] dont need to init clock at first in bootloader --- targets/stm32l432/bootloader/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/bootloader/main.c b/targets/stm32l432/bootloader/main.c index d1325af..2c419a7 100644 --- a/targets/stm32l432/bootloader/main.c +++ b/targets/stm32l432/bootloader/main.c @@ -24,6 +24,7 @@ #include #include "stm32l4xx_ll_rcc.h" +#include "stm32l4xx_ll_gpio.h" #include "stm32l4xx.h" #include "cbor.h" @@ -85,8 +86,9 @@ int main(int argc, char * argv[]) ); // device_init(); - SystemClock_Config_LF(); + init_gpio(); + init_millisecond_timer(1); #if DEBUG_LEVEL > 0 From 3005a63938b4bcefafa27d6ca22cb872e32ce5ab Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 18:07:09 -0500 Subject: [PATCH 71/96] re-arrange some logic for better passive operation --- targets/stm32l432/src/app.h | 3 ++ targets/stm32l432/src/device.c | 13 ++++- targets/stm32l432/src/nfc.c | 92 +++++++++++++++++++------------- targets/stm32l432/src/redirect.c | 10 ++-- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index e3f8ee0..b37296b 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -73,6 +73,9 @@ void hw_init(int lf); #define SOLO_AMS_CS_PORT GPIOB #define SOLO_AMS_CS_PIN LL_GPIO_PIN_0 +#define SOLO_AMS_IRQ_PORT GPIOC +#define SOLO_AMS_IRQ_PIN LL_GPIO_PIN_15 + #define SKIP_BUTTON_CHECK_WITH_DELAY 0 #define SKIP_BUTTON_CHECK_FAST 0 diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 8ed047f..b0002ad 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -111,11 +111,16 @@ void device_reboot() { NVIC_SystemReset(); } + void device_init() { - hw_init(HIGH_FREQUENCY); + + // hw_init(LOW_FREQUENCY); // isLowFreq = 1; + hw_init(HIGH_FREQUENCY); + isLowFreq = 0; + #ifndef IS_BOOTLOADER #if BOOT_TO_DFU flash_option_bytes_init(1); @@ -153,6 +158,12 @@ void usbhid_init() #if DEBUG_LEVEL>1 wait_for_usb_tether(); #endif + } + else + { + + + } } diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index eb07440..2442d38 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -11,10 +11,9 @@ #include "ctap_errors.h" +#define IS_IRQ_ACTIVE() (1 == (LL_GPIO_ReadInputPort(SOLO_AMS_IRQ_PORT) & SOLO_AMS_IRQ_PIN)) // Capability container - - const CAPABILITY_CONTAINER NFC_CC = { .cclen_hi = 0x00, .cclen_lo = 0x0f, .version = 0x20, @@ -26,8 +25,19 @@ const CAPABILITY_CONTAINER NFC_CC = { 0x00,0x00 } }; +// 13 chars uint8_t NDEF_SAMPLE[] = "\x00\x14\xd1\x01\x0eU\x04solokeys.com/"; +#include +void nprintf(const char *format, ...) +{ + memmove((char*)NDEF_SAMPLE + sizeof(NDEF_SAMPLE) - 1 - 13," ", 13); + va_list args; + va_start (args, format); + vsnprintf ((char*)NDEF_SAMPLE + sizeof(NDEF_SAMPLE) - 1 - 13, 13, format, args); + va_end (args); +} + static struct { uint8_t max_frame_size; @@ -225,9 +235,9 @@ void WTX_clear() bool WTX_on(int WTX_time) { WTX_clear(); - + // TODO: start interrupt - + return true; } @@ -236,7 +246,7 @@ bool WTX_process(int read_timeout); bool WTX_off() { // TODO: stop interrupt - + // read data if we sent WTX if (WTX_sent) { @@ -246,7 +256,7 @@ bool WTX_off() if (WTX_fail) return false; - + return true; } @@ -257,7 +267,7 @@ bool WTX_process(int read_timeout) uint8_t wtx[] = {0xf2, 0x01}; if (WTX_fail) return false; - + if (!WTX_sent) { nfc_write_frame(wtx, sizeof(wtx)); @@ -273,16 +283,16 @@ bool WTX_process(int read_timeout) WTX_fail = true; return false; } - + if (len != 2 || data[0] != 0xf2 || data[1] != 0x01) { WTX_fail = true; return false; } - + WTX_sent = false; return true; - } + } } int answer_rats(uint8_t parameter) @@ -315,8 +325,11 @@ int answer_rats(uint8_t parameter) // historical bytes memcpy(&res[3], (uint8_t *)"SoloKey tap", 11); + nfc_write_frame(res, sizeof(res)); ams_wait_for_tx(10); + + return 0; } @@ -420,7 +433,7 @@ void nfc_process_iblock(uint8_t * buf, int len) nfc_write_response(buf[0], SW_INS_INVALID); break; } - + printf1(TAG_NFC, "U2F GetVersion command.\r\n"); nfc_write_response_ex(buf[0], (uint8_t *)"U2F_V2", 6, SW_SUCCESS); @@ -657,49 +670,51 @@ void nfc_process_block(uint8_t * buf, int len) void nfc_loop() { static uint32_t t1 = 0; + static uint32_t t2 = 0; uint8_t buf[32]; AMS_DEVICE ams; int len = 0; - // uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00"; - // if (millis() - t1 > interval) if (1) { - t1 = millis(); read_reg_block(&ams); + uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; - process_int0(ams.regs.int0); + if (state != AMS_STATE_SELECTED && state != AMS_STATE_SELECTEDX) + { + // delay(1); // sleep ? + return; + } - // if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0) - // { - // printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); - // } if (ams.regs.rfid_status) { - // uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; // if (state != AMS_STATE_SENSE) - // printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis()); + // printf1(TAG_NFC," %s x%02x\r\n", ams_get_state_string(ams.regs.rfid_status), state); } if (ams.regs.int0 & AMS_INT_INIT) { - // Initialize chip! nfc_state_init(); + t1 = millis(); } if (ams.regs.int1) { // ams_print_int1(ams.regs.int1); } - if (ams.regs.buffer_status2 && (ams.regs.int0 & AMS_INT_RXE)) + + if ((ams.regs.int0 & AMS_INT_RXE)) { - if (ams.regs.buffer_status2 & AMS_BUF_INVALID) + if (ams.regs.buffer_status2) { - printf1(TAG_NFC,"Buffer being updated!\r\n"); - } - else - { - len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; - ams_read_buffer(buf, len); + if (ams.regs.buffer_status2 & AMS_BUF_INVALID) + { + printf1(TAG_NFC,"Buffer being updated!\r\n"); + } + else + { + len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; + ams_read_buffer(buf, len); + } } } @@ -719,12 +734,17 @@ void nfc_loop() printf1(TAG_NFC, "HLTA/Halt\r\n"); break; case NFC_CMD_RATS: - printf1(TAG_NFC,"RATS\r\n"); - t1 = millis(); + t2 = millis(); + answer_rats(buf[1]); + nprintf("R:%x-%x:%d:%d",firstbuf[0],firstbuf[1],t2-t1,inits); + /// + LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_12); + /// + NFC_STATE.block_num = 1; - clear_ibuf(); - WTX_clear(); + clear_ibuf(); + WTX_clear(); printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: @@ -736,10 +756,8 @@ void nfc_loop() break; } - - } + } - } diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index d3d5e5d..12e47b5 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -37,18 +37,16 @@ void _putchar(char c) LL_USART_TransmitData8(DEBUG_UART,c); #endif } -static int NFC = 0; int _write (int fd, const void *buf, long int len) { uint8_t * data = (uint8_t *) buf; - if (!NFC) - { - // Send out USB serial - CDC_Transmit_FS(data, len); - } + + // Send out USB serial + CDC_Transmit_FS(data, len); + // Send out UART serial while(len--) From c624a32ef693f76ae29d3e9c18367e47a08d5fc9 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 18:07:38 -0500 Subject: [PATCH 72/96] default 8 thread build --- targets/stm32l432/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/targets/stm32l432/Makefile b/targets/stm32l432/Makefile index aeae209..b4be621 100644 --- a/targets/stm32l432/Makefile +++ b/targets/stm32l432/Makefile @@ -8,7 +8,7 @@ all: $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DFLASH_ROP=1' all-hacker: - $(MAKE) -f application.mk solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' + $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) DEBUG=$(DEBUG) EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' all-locked: $(MAKE) -f application.mk -j8 solo.hex PREFIX=$(PREFIX) EXTRA_DEFINES='-DFLASH_ROP=2' @@ -45,7 +45,6 @@ clean2: $(MAKE) -f application.mk clean $(MAKE) -f bootloader.mk clean - flash: solo.hex bootloader.hex $(merge_hex) solo.hex bootloader.hex all.hex STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect From 587c9aad1488c54eca0bb305a65ba5b80484405d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Wed, 6 Feb 2019 18:09:53 -0500 Subject: [PATCH 73/96] refactor --- targets/stm32l432/src/nfc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 2442d38..53c77e2 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -28,6 +28,7 @@ const CAPABILITY_CONTAINER NFC_CC = { // 13 chars uint8_t NDEF_SAMPLE[] = "\x00\x14\xd1\x01\x0eU\x04solokeys.com/"; +// Poor way to get some info while in passive operation #include void nprintf(const char *format, ...) { @@ -737,7 +738,7 @@ void nfc_loop() t2 = millis(); answer_rats(buf[1]); - nprintf("R:%x-%x:%d:%d",firstbuf[0],firstbuf[1],t2-t1,inits); + nprintf("R:%d",t2-t1); /// LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_12); /// From c6d946136e31bb183425a55f7772a85cf0b2f110 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 7 Feb 2019 16:05:08 +0200 Subject: [PATCH 74/96] small fix --- targets/stm32l432/src/ams.c | 9 +++------ targets/stm32l432/src/redirect.c | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 8d43148..e218f34 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -268,7 +268,6 @@ void ams_print_int1(uint8_t int0) bool ams_init() { - uint8_t block[4]; LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); @@ -290,7 +289,7 @@ bool ams_init() uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); if (productType != 0x14) { - printf1(TAG_NFC, "Have no product type [0x%02x]. AMS3956 connection error.\n", productType); + printf1(TAG_NFC, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType); return false; } printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); @@ -298,10 +297,8 @@ bool ams_init() // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); - // enable tunneling mode and RF configuration - ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); - - + if (1) + { ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index 8f40035..ff03c1e 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -52,7 +52,7 @@ int _write (int fd, const void *buf, long int len) memcpy(&logbuf[logbuflen], data, len); logbuflen += len; - // Send out USB serial + // Send out USB serial uint8_t res = CDC_Transmit_FS(logbuf, logbuflen); if (res == USBD_OK) logbuflen = 0; From 9054736e0eb5fcc14fe9308438bf427dd1ac65c3 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 7 Feb 2019 19:03:45 -0500 Subject: [PATCH 75/96] delete debugging code --- targets/stm32l432/src/nfc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 53c77e2..a42b156 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -738,10 +738,6 @@ void nfc_loop() t2 = millis(); answer_rats(buf[1]); - nprintf("R:%d",t2-t1); - /// - LL_GPIO_SetOutputPin(GPIOA,LL_GPIO_PIN_12); - /// NFC_STATE.block_num = 1; clear_ibuf(); From be9bd941c85f68d5ff4f30c3df61bde5f2956ad1 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 7 Feb 2019 19:45:02 -0500 Subject: [PATCH 76/96] simplify ams init --- targets/stm32l432/src/ams.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index e218f34..74a24cf 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -280,25 +280,22 @@ bool ams_init() // delay(10); SELECT(); - // delay(10); + // delay(1); - ams_write_command(AMS_CMD_DEFAULT); - ams_write_command(AMS_CMD_CLEAR_BUFFER); - - // check connection - uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); - if (productType != 0x14) + // Needs to be disabled for passive operation + // if (0) + if (1) { - printf1(TAG_NFC, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType); - return false; - } - printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); - - // enable tunneling mode and RF configuration - ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); + // check connection + uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); + if (productType != 0x14) + { + printf1(TAG_NFC, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType); + return false; + } + + printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); - if (1) - { ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); @@ -335,7 +332,12 @@ bool ams_init() if (block[0] != ic_cfg1 || block[1] != ic_cfg2) { + printf1(TAG_NFC,"Writing config block 1\r\n"); + + ams_write_reg(AMS_REG_IC_CONF1,ic_cfg1); + ams_write_reg(AMS_REG_IC_CONF2,ic_cfg2); + // set IC_CFG1 block[0] = ic_cfg1; From 342af18b1f351723afd5b42ab600fb944e016dd4 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 7 Feb 2019 20:09:00 -0500 Subject: [PATCH 77/96] initialize ctap --- fido2/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fido2/main.c b/fido2/main.c index ad34ed8..6f4e729 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -69,7 +69,7 @@ int main(int argc, char * argv[]) ctaphid_init(); // printf1(TAG_GEN,"init ctaphid\n"); - // ctap_init(); + ctap_init(); // printf1(TAG_GEN,"init ctap\n"); memset(hidmsg,0,sizeof(hidmsg)); From e230a9464ec66ab36097b8e8fd2b095304848537 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 7 Feb 2019 20:09:13 -0500 Subject: [PATCH 78/96] enable ctap from usb --- fido2/ctaphid.c | 12 ++++++------ targets/stm32l432/src/app.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 3e6d5f1..3e5306f 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -1,21 +1,21 @@ /* * Copyright (C) 2018 SoloKeys, Inc. - * + * * This file is part of Solo. - * + * * Solo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * Solo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Solo. If not, see - * + * * This code is available under licenses for commercial use. * Please contact SoloKeys for more information. */ @@ -636,7 +636,7 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) } is_busy = 1; ctap_response_init(&ctap_resp); - status = ctap_request(ctap_buffer, len, &ctap_resp); + status = ctap_request(ctap_buffer, len, &ctap_resp, 0); ctaphid_write_buffer_init(&wb); wb.cid = cid; diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index b37296b..f4d333a 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -40,9 +40,9 @@ #define ENABLE_U2F -#define DISABLE_CTAPHID_PING -#define DISABLE_CTAPHID_WINK -#define DISABLE_CTAPHID_CBOR +// #define DISABLE_CTAPHID_PING +// #define DISABLE_CTAPHID_WINK +// #define DISABLE_CTAPHID_CBOR void printing_init(); void hw_init(int lf); From 13d9885da441154244779512cad7aa40215768cc Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 8 Feb 2019 13:08:28 -0500 Subject: [PATCH 79/96] initialize at 16MHz, add 24 and 32 options --- targets/stm32l432/src/init.c | 130 ++++++++++++++++++++++- targets/stm32l432/src/init.h | 1 + targets/stm32l432/src/system_stm32l4xx.c | 2 +- 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index 371e181..cb4c4e6 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -69,7 +69,7 @@ void hw_init(int lowfreq) if (lowfreq) { - SystemClock_Config_LF(); + SystemClock_Config_LF16(); } else { @@ -270,7 +270,7 @@ void SystemClock_Config_LF4(void) } // 8MHz -void SystemClock_Config_LF(void) +void SystemClock_Config_LF8(void) { SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); @@ -391,6 +391,130 @@ void SystemClock_Config_LF16(void) } + + +// 24 MHz +void SystemClock_Config_LF24(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_1); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_9); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_8); + + LL_Init1msTick(24000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(24000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + +} + +// 32 MHz +void SystemClock_Config_LF32(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_1); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_10); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16); + + LL_Init1msTick(32000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(32000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + +} + void init_usb() { // enable USB power @@ -570,7 +694,7 @@ void init_millisecond_timer(int lf) if (!lf) TIM_InitStruct.Prescaler = 48000; else - TIM_InitStruct.Prescaler = 8000; + TIM_InitStruct.Prescaler = 24000; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 90; diff --git a/targets/stm32l432/src/init.h b/targets/stm32l432/src/init.h index 1319a1e..a9920ad 100644 --- a/targets/stm32l432/src/init.h +++ b/targets/stm32l432/src/init.h @@ -24,6 +24,7 @@ void SystemClock_Config(void); void SystemClock_Config_LF(void); +void SystemClock_Config_LF16(void); void init_usb(); void init_gpio(void); diff --git a/targets/stm32l432/src/system_stm32l4xx.c b/targets/stm32l432/src/system_stm32l4xx.c index bb12cc3..262e883 100644 --- a/targets/stm32l432/src/system_stm32l4xx.c +++ b/targets/stm32l432/src/system_stm32l4xx.c @@ -220,7 +220,7 @@ void SystemInit(void) /* Disable all interrupts */ RCC->CIER = 0x00000000U; - SystemClock_Config_LF(); + SystemClock_Config_LF16(); } From 665e84d183c7d564dcabd9cfcb26fbfb78096ed5 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 8 Feb 2019 13:09:12 -0500 Subject: [PATCH 80/96] delay to allow spi interface to initialize --- targets/stm32l432/src/ams.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 74a24cf..505103e 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -280,7 +280,7 @@ bool ams_init() // delay(10); SELECT(); - // delay(1); + delay(2); // Needs to be disabled for passive operation // if (0) @@ -293,7 +293,7 @@ bool ams_init() printf1(TAG_NFC, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType); return false; } - + printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); From 120fb9554161cbc1b165090f38bf07cd503595f4 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 8 Feb 2019 13:09:32 -0500 Subject: [PATCH 81/96] compile for bootloader --- targets/stm32l432/src/device.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 6d86a1d..dbb2a09 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -70,12 +70,13 @@ void TIM6_DAC_IRQHandler() ctaphid_update_status(__device_status); } } - +#ifndef IS_BOOTLOADER // NFC sending WTX if needs - if (haveNFC) + if (haveNFC) { WTX_timer_exec(); } +#endif } // Global USB interrupt handler @@ -127,6 +128,7 @@ void device_init() hw_init(HIGH_FREQUENCY); isLowFreq = 0; + #ifndef IS_BOOTLOADER #if BOOT_TO_DFU flash_option_bytes_init(1); @@ -135,13 +137,8 @@ void device_init() #endif printf1(TAG_GEN,"init nfc\n"); haveNFC = nfc_init(); - // if (haveNFC) - // printf1(TAG_GEN,"NFC OK.\n"); - // else - // printf1(TAG_GEN,"NFC not found.\n"); #endif - // printf1(TAG_GEN,"hello solo\r\n"); } void wait_for_usb_tether() From 2893cd7ce369aed907c9ceaff7969bbac87b8792 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 11 Feb 2019 22:00:18 -0500 Subject: [PATCH 82/96] move inits to device_init --- fido2/ctap.c | 13 ++++++++----- fido2/ctap.h | 12 ++++++------ fido2/main.c | 8 -------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/fido2/ctap.c b/fido2/ctap.c index b84f9b7..de43385 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -351,12 +351,12 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au device_set_status(CTAPHID_STATUS_UPNEEDED); // if NFC - not need to click a button - int but = 1; + int but = 1; if(!fromNFC) { but = ctap_user_presence_test(); - } - + } + if (!but) { return CTAP2_ERR_OPERATION_DENIED; @@ -1509,7 +1509,7 @@ static void ctap_state_init() ctap_reset_rk(); } -void ctap_init() +void ctap_init(int init_pin) { crypto_ecc256_init(); @@ -1564,7 +1564,10 @@ void ctap_init() exit(1); } - crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); + if (init_pin) + { + crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); + } #ifdef BRIDGE_TO_WALLET wallet_init(); diff --git a/fido2/ctap.h b/fido2/ctap.h index 2df795b..d43e637 100644 --- a/fido2/ctap.h +++ b/fido2/ctap.h @@ -1,21 +1,21 @@ /* * Copyright (C) 2018 SoloKeys, Inc. - * + * * This file is part of Solo. - * + * * Solo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * Solo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with Solo. If not, see - * + * * This code is available under licenses for commercial use. * Please contact SoloKeys for more information. */ @@ -282,7 +282,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool f int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder); // Run ctap related power-up procedures (init pinToken, generate shared secret) -void ctap_init(); +void ctap_init(int init_pin); // Resets state between different accesses of different applications void ctap_reset_state(); diff --git a/fido2/main.c b/fido2/main.c index 6f4e729..6c92394 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -61,16 +61,8 @@ int main(int argc, char * argv[]) ); device_init(); - // printf1(TAG_GEN,"init device\n"); - usbhid_init(); - // printf1(TAG_GEN,"init usb\n"); - ctaphid_init(); - // printf1(TAG_GEN,"init ctaphid\n"); - - ctap_init(); - // printf1(TAG_GEN,"init ctap\n"); memset(hidmsg,0,sizeof(hidmsg)); From 529b879c083720746e26cd3004b6b9cbcd42be5e Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 11 Feb 2019 22:02:41 -0500 Subject: [PATCH 83/96] init in device_init --- targets/stm32l432/src/device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index dbb2a09..7600f34 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -128,6 +128,11 @@ void device_init() hw_init(HIGH_FREQUENCY); isLowFreq = 0; + usbhid_init(); + + ctaphid_init(); + + ctap_init( 1 ); #ifndef IS_BOOTLOADER #if BOOT_TO_DFU From 3b320e0aebf117a5a0e38167c4711f38cddb7b88 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 12 Feb 2019 18:34:13 -0500 Subject: [PATCH 84/96] initialize at 24 MHz at very start instead of 16 --- targets/stm32l432/src/system_stm32l4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/src/system_stm32l4xx.c b/targets/stm32l432/src/system_stm32l4xx.c index 262e883..7332d63 100644 --- a/targets/stm32l432/src/system_stm32l4xx.c +++ b/targets/stm32l432/src/system_stm32l4xx.c @@ -220,7 +220,7 @@ void SystemInit(void) /* Disable all interrupts */ RCC->CIER = 0x00000000U; - SystemClock_Config_LF16(); + SystemClock_Config_LF24(); } From fed9f473aadfc49fe5eefda684f72a89ba9ce684 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 18:12:01 +0200 Subject: [PATCH 85/96] added hardware part of UID --- targets/stm32l432/src/ams.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 505103e..d3ec927 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -297,7 +297,7 @@ bool ams_init() printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); - printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); + printf1(TAG_NFC,"UID: 3F 14 02 - "); dump_hex1(TAG_NFC,block,4); ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); From 54b7f4205691ea5ea47253f4f371f071c3976e62 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 01:19:35 -0500 Subject: [PATCH 86/96] passive operation works as is (refactor needed) --- .gitignore | 2 + fido2/u2f.c | 8 +- targets/stm32l432/src/ams.c | 6 +- targets/stm32l432/src/ams.h | 5 + targets/stm32l432/src/device.c | 14 +- targets/stm32l432/src/init.c | 196 +++++++++++++++++++++-- targets/stm32l432/src/nfc.c | 69 ++++---- targets/stm32l432/src/redirect.c | 5 +- targets/stm32l432/src/system_stm32l4xx.c | 2 +- 9 files changed, 250 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index 4e3c5c5..9613abd 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,5 @@ env3/ .tags* targets/*/docs/ main + +builds/* diff --git a/fido2/u2f.c b/fido2/u2f.c index 5213ea8..1ae395d 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -160,7 +160,7 @@ void u2f_set_writeback_buffer(CTAP_RESPONSE * resp) _u2f_resp = resp; } -static void dump_signature_der(uint8_t * sig) +void dump_signature_der(uint8_t * sig) { uint8_t sigder[72]; int len; @@ -183,7 +183,7 @@ static void u2f_make_auth_tag(struct u2f_key_handle * kh, uint8_t * appid, uint8 memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE); } -static int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey) +int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey) { ctap_generate_rng(kh->key, U2F_KEY_HANDLE_KEY_SIZE); u2f_make_auth_tag(kh, appid, kh->tag); @@ -286,6 +286,7 @@ static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED}; struct u2f_key_handle key_handle; + static uint32_t count = 0; uint8_t pubkey[64]; uint8_t hash[32]; uint8_t * sig = (uint8_t*)req; @@ -300,11 +301,12 @@ static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) return U2F_SW_CONDITIONS_NOT_SATISFIED; } } - + uint32_t t1 = millis(); if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1) { return U2F_SW_INSUFFICIENT_MEMORY; } + printf1(TAG_NFC, "keygen time: %d ms\r\n", millis()-t1); crypto_sha256_init(); crypto_sha256_update(i,1); diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index d3ec927..629c68d 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -283,8 +283,8 @@ bool ams_init() delay(2); // Needs to be disabled for passive operation - // if (0) - if (1) + if (0) + // if (1) { // check connection uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); @@ -327,7 +327,7 @@ bool ams_init() ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); - uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V1; + uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; if (block[0] != ic_cfg1 || block[1] != ic_cfg2) diff --git a/targets/stm32l432/src/ams.h b/targets/stm32l432/src/ams.h index 1f2e3a5..d8e3cad 100644 --- a/targets/stm32l432/src/ams.h +++ b/targets/stm32l432/src/ams.h @@ -127,6 +127,11 @@ int ams_state_is_valid(uint8_t regval); #define AMS_CFG1_VOLTAGE_LEVEL_2V3 (0x04<<2) #define AMS_CFG1_VOLTAGE_LEVEL_2V4 (0x05<<2) #define AMS_CFG1_VOLTAGE_LEVEL_2V5 (0x06<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V6 (0x07<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V7 (0x08<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V8 (0x09<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_2V9 (0x0a<<2) +#define AMS_CFG1_VOLTAGE_LEVEL_3V0 (0x0b<<2) #define AMS_CFG1_OUTPUT_RESISTANCE_ZZ 0x00 #define AMS_CFG1_OUTPUT_RESISTANCE_100 0x01 diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 7600f34..ae35a3d 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -25,7 +25,7 @@ #include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_tim.h" #include "stm32l4xx_ll_usart.h" - +#include "stm32l4xx_ll_pwr.h" #include "usbd_hid.h" #include APP_CONFIG @@ -122,17 +122,19 @@ void device_reboot() void device_init() { - // hw_init(LOW_FREQUENCY); - // isLowFreq = 1; + hw_init(LOW_FREQUENCY); + isLowFreq = 1; - hw_init(HIGH_FREQUENCY); - isLowFreq = 0; + printf1(TAG_NFC,"PWR->CR1: %04x\r\n", LL_PWR_GetRegulVoltageScaling()); + + // hw_init(HIGH_FREQUENCY); + // isLowFreq = 0; usbhid_init(); ctaphid_init(); - ctap_init( 1 ); + ctap_init( 0 ); #ifndef IS_BOOTLOADER #if BOOT_TO_DFU diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index cb4c4e6..c7dfcb5 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -48,7 +48,8 @@ #include "init.h" #include APP_CONFIG - +// KHz +#define CLOCK_RATE 24000 USBD_HandleTypeDef Solo_USBD_Device; @@ -56,7 +57,8 @@ static void LL_Init(void); #define Error_Handler() _Error_Handler(__FILE__,__LINE__) void _Error_Handler(char *file, int line); - +void SystemClock_Config_LF28(void); +void SystemClock_Config_LF48(void); void hw_init(int lowfreq) { @@ -69,7 +71,24 @@ void hw_init(int lowfreq) if (lowfreq) { + // Under voltage + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); +#if CLOCK_RATE == 48000 + SystemClock_Config_LF48(); +#elif CLOCK_RATE == 32000 + SystemClock_Config_LF32(); +#elif CLOCK_RATE == 28000 + SystemClock_Config_LF28(); +#elif CLOCK_RATE == 24000 + SystemClock_Config_LF24(); +#elif CLOCK_RATE == 20000 + SystemClock_Config_LF20(); +#elif CLOCK_RATE == 16000 SystemClock_Config_LF16(); +#else +#error "Invalid clock rate selected" +#endif + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); } else { @@ -515,6 +534,154 @@ void SystemClock_Config_LF32(void) } +// 28 MHz +void SystemClock_Config_LF28(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + LL_FLASH_SetLatency(LL_FLASH_LATENCY_1); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_1) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_HSI_Enable(); + + /* Wait till HSI is ready */ + while(LL_RCC_HSI_IsReady() != 1) + { + + } + LL_RCC_HSI_SetCalibTrimming(16); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_2, 28, LL_RCC_PLLR_DIV_8); + + LL_RCC_PLL_EnableDomain_SYS(); + + LL_RCC_PLL_Enable(); + + /* Wait till PLL is ready */ + while(LL_RCC_PLL_IsReady() != 1) + { + + } + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_8); + + LL_Init1msTick(28000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(28000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); +} + +// 48 MHz +void SystemClock_Config_LF48(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); + + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + + if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) + { + Error_Handler(); + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + LL_RCC_LSI_Enable(); + + /* Wait till LSI is ready */ + while(LL_RCC_LSI_IsReady() != 1) + { + + } + LL_RCC_MSI_Enable(); + + /* Wait till MSI is ready */ + while(LL_RCC_MSI_IsReady() != 1) + { + + } + LL_RCC_MSI_EnableRangeSelection(); + + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11); + + LL_RCC_MSI_SetCalibTrimming(0); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + + /* Wait till System clock is ready */ + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) + { + + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16); + + LL_Init1msTick(48000000); + + LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); + + LL_SetSystemCoreClock(48000000); + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_MSI); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + + +} + +// 20 MHz +void SystemClock_Config_LF20(void) +{ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); +} + void init_usb() { // enable USB power @@ -666,17 +833,18 @@ void init_gpio(void) LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP); #ifdef SOLO_AMS_IRQ_PORT - LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); - /**/ - LL_GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Pin = SOLO_AMS_IRQ_PIN; - GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; - LL_GPIO_Init(SOLO_AMS_IRQ_PORT, &GPIO_InitStruct); - - - LL_GPIO_SetPinMode(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_MODE_INPUT); - LL_GPIO_SetPinPull(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_PULL_UP); +// SAVE POWER + // LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + // /**/ + // LL_GPIO_InitTypeDef GPIO_InitStruct; + // GPIO_InitStruct.Pin = SOLO_AMS_IRQ_PIN; + // GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; + // GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + // LL_GPIO_Init(SOLO_AMS_IRQ_PORT, &GPIO_InitStruct); + // + // + // LL_GPIO_SetPinMode(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_MODE_INPUT); + // LL_GPIO_SetPinPull(SOLO_AMS_IRQ_PORT,SOLO_AMS_IRQ_PIN,LL_GPIO_PULL_UP); #endif } @@ -694,7 +862,7 @@ void init_millisecond_timer(int lf) if (!lf) TIM_InitStruct.Prescaler = 48000; else - TIM_InitStruct.Prescaler = 24000; + TIM_InitStruct.Prescaler = CLOCK_RATE; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 90; diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 1ef554c..2eb76d5 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -8,6 +8,7 @@ #include "util.h" #include "device.h" #include "u2f.h" +#include "crypto.h" #include "ctap_errors.h" @@ -102,7 +103,7 @@ bool ams_receive_with_timeout(uint32_t timeout_ms, uint8_t * data, int maxlen, i { uint8_t len = buffer_status2 & AMS_BUF_LEN_MASK; ams_read_buffer(buf, len); - printf1(TAG_NFC_APDU, ">> "); + printf1(TAG_NFC_APDU, ">> "); dump_hex1(TAG_NFC_APDU, buf, len); *dlen = MIN(32, MIN(maxlen, len)); @@ -128,7 +129,7 @@ void nfc_write_frame(uint8_t * data, uint8_t len) ams_write_buffer(data,len); ams_write_command(AMS_CMD_TRANSMIT_BUFFER); - printf1(TAG_NFC_APDU, "<< "); + printf1(TAG_NFC_APDU, "<< "); dump_hex1(TAG_NFC_APDU, data, len); } @@ -156,7 +157,7 @@ bool nfc_write_response(uint8_t req0, uint16_t resp) return nfc_write_response_ex(req0, NULL, 0, resp); } -void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) +void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len, int keepgoing) { uint8_t res[32 + 2]; int sendlen = 0; @@ -177,7 +178,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) memcpy(&res[1], &data[sendlen], vlen); // if not a last block - if (vlen + sendlen < len) + if ((vlen + sendlen < len) || keepgoing) { res[0] |= 0x10; } @@ -187,11 +188,11 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) sendlen += vlen; // wait for transmit (32 bytes aprox 2,5ms) - if (!ams_wait_for_tx(10)) - { - printf1(TAG_NFC, "TX timeout. slen: %d \r\n", sendlen); - break; - } + // if (!ams_wait_for_tx(10)) + // { + // printf1(TAG_NFC, "TX timeout. slen: %d \r\n", sendlen); + // break; + // } // if needs to receive R block (not a last block) if (res[0] & 0x10) @@ -200,13 +201,14 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) int reclen; if (!ams_receive_with_timeout(100, recbuf, sizeof(recbuf), &reclen)) { - printf1(TAG_NFC, "R block RX timeout.\r\n"); + printf1(TAG_NFC, "R block RX timeout %d/%d.\r\n",sendlen,len); break; } if (reclen != 1) { - printf1(TAG_NFC, "R block length error. len: %d \r\n", reclen); + printf1(TAG_NFC, "R block length error. len: %d. %d/%d \r\n", reclen,sendlen,len); + dump_hex1(TAG_NFC, recbuf, reclen); break; } @@ -243,14 +245,14 @@ bool WTX_on(int WTX_time) { WTX_clear(); WTX_timer = millis(); - + return true; } bool WTX_off() { WTX_timer = 0; - + // read data if we sent WTX if (WTX_sent) { @@ -266,7 +268,7 @@ bool WTX_off() printf1(TAG_NFC, "WTX-off fail\n"); return false; } - + WTX_clear(); return true; } @@ -276,7 +278,7 @@ void WTX_timer_exec() // condition: (timer on) or (not expired[300ms]) if ((WTX_timer <= 0) || WTX_timer + 300 > millis()) return; - + WTX_process(10); WTX_timer = millis(); } @@ -396,9 +398,10 @@ void nfc_process_iblock(uint8_t * buf, int len) int selected; uint8_t res[32]; uint32_t t1; - + int l1; CTAP_RESPONSE ctap_resp; int status; + struct u2f_register_request * u2freq = (struct u2f_register_request *)payload; printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); @@ -477,14 +480,24 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); - WTX_on(WTX_TIME_DEFAULT); - u2f_request_nfc(&buf[1], len, &ctap_resp); - if (!WTX_off()) - return; - printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); - printf1(TAG_NFC,"U2F Register processing %d (took %d)\r\n", millis(), millis() - t1); - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + + // WTX_on(WTX_TIME_DEFAULT); + // SystemClock_Config_LF32(); + // delay(300); + u2f_request_nfc(&buf[1], len, &ctap_resp); + // SystemClock_Config_LF16(); + // if (!WTX_off()) + // return; + + printf1(TAG_NFC,"U2F Register P2 took %d\r\n", millis() - t1); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0 ); + + // printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); + + + + printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), millis() - t1); break; @@ -505,14 +518,14 @@ void nfc_process_iblock(uint8_t * buf, int len) } t1 = millis(); - WTX_on(WTX_TIME_DEFAULT); + // WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); - if (!WTX_off()) - return; + // if (!WTX_off()) + // return; printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0); printf1(TAG_NFC,"U2F Authenticate answered %d (took %d)\r\n", millis(), millis() - t1); break; @@ -545,7 +558,7 @@ void nfc_process_iblock(uint8_t * buf, int len) ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff; printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), millis() - t1); - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0); printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), millis() - t1); break; diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index ff03c1e..bc06282 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -42,6 +42,7 @@ void _putchar(char c) int _write (int fd, const void *buf, long int len) { uint8_t * data = (uint8_t *) buf; +#if DEBUG_LEVEL>1 static uint8_t logbuf[1000] = {0}; static int logbuflen = 0; if (logbuflen + len > sizeof(logbuf)) { @@ -56,11 +57,11 @@ int _write (int fd, const void *buf, long int len) uint8_t res = CDC_Transmit_FS(logbuf, logbuflen); if (res == USBD_OK) logbuflen = 0; - +#endif // Send out UART serial while(len--) { - // _putchar(*data++); + _putchar(*data++); } return 0; } diff --git a/targets/stm32l432/src/system_stm32l4xx.c b/targets/stm32l432/src/system_stm32l4xx.c index 7332d63..262e883 100644 --- a/targets/stm32l432/src/system_stm32l4xx.c +++ b/targets/stm32l432/src/system_stm32l4xx.c @@ -220,7 +220,7 @@ void SystemInit(void) /* Disable all interrupts */ RCC->CIER = 0x00000000U; - SystemClock_Config_LF24(); + SystemClock_Config_LF16(); } From a195408a11d72f57783aea21bd78ab047d668cc8 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 01:51:07 -0500 Subject: [PATCH 87/96] scale up to 24 MHz only for register --- targets/stm32l432/src/init.c | 8 ++++---- targets/stm32l432/src/nfc.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index c7dfcb5..6272f97 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -49,7 +49,7 @@ #include APP_CONFIG // KHz -#define CLOCK_RATE 24000 +#define CLOCK_RATE 16000 USBD_HandleTypeDef Solo_USBD_Device; @@ -360,7 +360,7 @@ void SystemClock_Config_LF16(void) { Error_Handler(); } - LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); LL_RCC_LSI_Enable(); @@ -423,7 +423,7 @@ void SystemClock_Config_LF24(void) { Error_Handler(); } - LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); LL_RCC_LSI_Enable(); @@ -927,7 +927,7 @@ void init_spi(void) SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct.CRCPoly = 7; diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 2eb76d5..0299d13 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -485,8 +485,9 @@ void nfc_process_iblock(uint8_t * buf, int len) // WTX_on(WTX_TIME_DEFAULT); // SystemClock_Config_LF32(); // delay(300); + SystemClock_Config_LF24(); u2f_request_nfc(&buf[1], len, &ctap_resp); - // SystemClock_Config_LF16(); + SystemClock_Config_LF16(); // if (!WTX_off()) // return; From 57930aaa13ae8cc867252a317fbcada331566d2d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 13:27:25 -0500 Subject: [PATCH 88/96] fix compilation errors --- fido2/u2f.c | 12 ++++++------ targets/stm32l432/build/common.mk | 2 +- targets/stm32l432/src/ams.c | 4 ++++ targets/stm32l432/src/init.c | 1 - 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/fido2/u2f.c b/fido2/u2f.c index 3d10d41..471e828 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -10,6 +10,7 @@ #include "crypto.h" #include "log.h" #include "device.h" +#include "apdu.h" #include "wallet.h" #ifdef ENABLE_U2F_EXTENSIONS #include "extensions.h" @@ -42,7 +43,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO goto end; } #ifdef ENABLE_U2F_EXTENSIONS - rcode = extend_u2f(req, len); + rcode = extend_u2f(req, len); // FIXME #endif if (rcode != U2F_SW_NO_ERROR && rcode != U2F_SW_CONDITIONS_NOT_SATISFIED) // If the extension didn't do anything... { @@ -59,7 +60,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO { timestamp(); - rcode = u2f_register((struct u2f_register_request*)req->payload, fromNFC); + rcode = u2f_register((struct u2f_register_request*)payload, fromNFC); printf1(TAG_TIME,"u2f_register time: %d ms\n", timestamp()); } @@ -67,7 +68,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO case U2F_AUTHENTICATE: printf1(TAG_U2F, "U2F_AUTHENTICATE\n"); timestamp(); - rcode = u2f_authenticate((struct u2f_authenticate_request*)req->payload, req->p1, fromNFC); + rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1, fromNFC); printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", timestamp()); break; case U2F_VERSION: @@ -253,7 +254,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c crypto_sha256_update(req->app, 32); crypto_sha256_update(&up, 1); - crypto_sha256_update(vcount, 4); + crypto_sha256_update(hash, 4); crypto_sha256_update(req->chal, 32); crypto_sha256_final(hash); @@ -292,12 +293,11 @@ static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) return U2F_SW_CONDITIONS_NOT_SATISFIED; } } - uint32_t t1 = millis(); + if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1) { return U2F_SW_INSUFFICIENT_MEMORY; } - printf1(TAG_NFC, "keygen time: %d ms\r\n", millis()-t1); crypto_sha256_init(); crypto_sha256_update(i,1); diff --git a/targets/stm32l432/build/common.mk b/targets/stm32l432/build/common.mk index 4170e51..7c0ae32 100644 --- a/targets/stm32l432/build/common.mk +++ b/targets/stm32l432/build/common.mk @@ -6,7 +6,7 @@ AR=$(PREFIX)arm-none-eabi-ar DRIVER_LIBS := lib/stm32l4xx_hal_pcd.c lib/stm32l4xx_hal_pcd_ex.c lib/stm32l4xx_ll_gpio.c \ lib/stm32l4xx_ll_rcc.c lib/stm32l4xx_ll_rng.c lib/stm32l4xx_ll_tim.c \ lib/stm32l4xx_ll_usb.c lib/stm32l4xx_ll_utils.c lib/stm32l4xx_ll_pwr.c \ - lib/stm32l4xx_ll_usart.c + lib/stm32l4xx_ll_usart.c lib/stm32l4xx_ll_spi.c USB_LIB := lib/usbd/usbd_cdc.c lib/usbd/usbd_cdc_if.c lib/usbd/usbd_composite.c \ lib/usbd/usbd_conf.c lib/usbd/usbd_core.c lib/usbd/usbd_ioreq.c \ diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 629c68d..7b2438a 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -219,6 +219,7 @@ int ams_state_is_valid(uint8_t regval) void ams_print_int0(uint8_t int0) { +#if DEBUG_LEVEL uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); printf1(TAG_NFC," "); if (int0 & AMS_INT_XRF) @@ -239,10 +240,12 @@ void ams_print_int0(uint8_t int0) printf1(tag," INIT"); printf1(tag,"\r\n"); +#endif } void ams_print_int1(uint8_t int0) { +#if DEBUG_LEVEL uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); printf1(TAG_NFC," "); if (int0 & AMS_INT_ACC_ERR) @@ -263,6 +266,7 @@ void ams_print_int1(uint8_t int0) printf1(tag," RXS"); printf1(tag,"\r\n"); +#endif } diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index e0730c7..fd4bb61 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -804,7 +804,6 @@ void init_debug_uart(void) LL_USART_Enable(USART1); } -#endif void init_gpio(void) { From ff0d42c8d54574b0bee35b4812528f1b0802e4d7 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 13:56:06 -0500 Subject: [PATCH 89/96] refactor clock rates, fix warnings --- fido2/device.h | 12 +++++ fido2/u2f.c | 3 +- targets/stm32l432/src/init.c | 68 +++++++++++++++++------- targets/stm32l432/src/init.h | 4 -- targets/stm32l432/src/nfc.c | 31 ++++------- targets/stm32l432/src/system_stm32l4xx.c | 3 +- 6 files changed, 75 insertions(+), 46 deletions(-) diff --git a/fido2/device.h b/fido2/device.h index e75f250..a9ee118 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -86,5 +86,17 @@ void boot_st_bootloader(); // HID wink command void device_wink(); +typedef enum { + DEVICE_LOW_POWER_IDLE = 0, + DEVICE_LOW_POWER_FAST = 1, + DEVICE_FAST = 2, +} DEVICE_CLOCK_RATE; + +// Set the clock rate for the device. +// Three modes are targetted for Solo. +// 0: Lowest clock rate for NFC. +// 1: fastest clock rate supported at a low power setting for NFC FIDO. +// 2: fastest clock rate. Generally for USB interface. +void device_set_clock_rate(DEVICE_CLOCK_RATE param); #endif diff --git a/fido2/u2f.c b/fido2/u2f.c index 471e828..9731572 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -278,7 +278,6 @@ static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED}; struct u2f_key_handle key_handle; - static uint32_t count = 0; uint8_t pubkey[64]; uint8_t hash[32]; uint8_t * sig = (uint8_t*)req; @@ -293,7 +292,7 @@ static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) return U2F_SW_CONDITIONS_NOT_SATISFIED; } } - + if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1) { return U2F_SW_INSUFFICIENT_MEMORY; diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index fd4bb61..4834e5d 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -34,7 +34,31 @@ #include APP_CONFIG // KHz -#define CLOCK_RATE 16000 +#define MAX_CLOCK_RATE 24000 + +#define SET_CLOCK_RATE2() SystemClock_Config() + +#if MAX_CLOCK_RATE == 48000 + #define SET_CLOCK_RATE0() SystemClock_Config_LF32() + #define SET_CLOCK_RATE1() SystemClock_Config_LF48() +#elif MAX_CLOCK_RATE == 32000 + #define SET_CLOCK_RATE0() SystemClock_Config_LF24() + #define SET_CLOCK_RATE1() SystemClock_Config_LF32() +#elif MAX_CLOCK_RATE == 28000 + #define SET_CLOCK_RATE0() SystemClock_Config_LF24() + #define SET_CLOCK_RATE1() SystemClock_Config_LF28() +#elif MAX_CLOCK_RATE == 24000 + #define SET_CLOCK_RATE0() SystemClock_Config_LF16() + #define SET_CLOCK_RATE1() SystemClock_Config_LF24() +#elif MAX_CLOCK_RATE == 20000 + #define SET_CLOCK_RATE0() SystemClock_Config_LF16() + #define SET_CLOCK_RATE1() SystemClock_Config_LF20() +#elif MAX_CLOCK_RATE == 16000 + #define SET_CLOCK_RATE0() SystemClock_Config_LF8() + #define SET_CLOCK_RATE1() SystemClock_Config_LF16() +#else +#error "Invalid clock rate selected" +#endif USBD_HandleTypeDef Solo_USBD_Device; @@ -42,6 +66,11 @@ static void LL_Init(void); #define Error_Handler() _Error_Handler(__FILE__,__LINE__) void _Error_Handler(char *file, int line); + +void SystemClock_Config(void); +void SystemClock_Config_LF16(void); +void SystemClock_Config_LF20(void); +void SystemClock_Config_LF24(void); void SystemClock_Config_LF28(void); void SystemClock_Config_LF48(void); @@ -56,23 +85,8 @@ void hw_init(int lowfreq) if (lowfreq) { - // Under voltage - LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); -#if CLOCK_RATE == 48000 - SystemClock_Config_LF48(); -#elif CLOCK_RATE == 32000 - SystemClock_Config_LF32(); -#elif CLOCK_RATE == 28000 - SystemClock_Config_LF28(); -#elif CLOCK_RATE == 24000 - SystemClock_Config_LF24(); -#elif CLOCK_RATE == 20000 - SystemClock_Config_LF20(); -#elif CLOCK_RATE == 16000 - SystemClock_Config_LF16(); -#else -#error "Invalid clock rate selected" -#endif + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); // Under voltage + device_set_clock_rate(DEVICE_LOW_POWER_IDLE); LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); } else @@ -123,6 +137,22 @@ static void LL_Init(void) } +void device_set_clock_rate(DEVICE_CLOCK_RATE param) +{ + switch(param) + { + case DEVICE_LOW_POWER_IDLE: + SET_CLOCK_RATE0(); + break; + case DEVICE_LOW_POWER_FAST: + SET_CLOCK_RATE1(); + break; + case DEVICE_FAST: + SET_CLOCK_RATE2(); + break; + } +} + /** * @brief System Clock Configuration * @retval None @@ -847,7 +877,7 @@ void init_millisecond_timer(int lf) if (!lf) TIM_InitStruct.Prescaler = 48000; else - TIM_InitStruct.Prescaler = CLOCK_RATE; + TIM_InitStruct.Prescaler = MAX_CLOCK_RATE; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 90; diff --git a/targets/stm32l432/src/init.h b/targets/stm32l432/src/init.h index a9920ad..729e898 100644 --- a/targets/stm32l432/src/init.h +++ b/targets/stm32l432/src/init.h @@ -22,10 +22,6 @@ #ifndef _INIT_H_ #define _INIT_H_ -void SystemClock_Config(void); -void SystemClock_Config_LF(void); -void SystemClock_Config_LF16(void); - void init_usb(); void init_gpio(void); void init_debug_uart(void); diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 0299d13..cf526df 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -396,12 +396,8 @@ void nfc_process_iblock(uint8_t * buf, int len) uint8_t * payload = buf + 1 + 5; uint8_t plen = apdu->lc; int selected; - uint8_t res[32]; - uint32_t t1; - int l1; CTAP_RESPONSE ctap_resp; int status; - struct u2f_register_request * u2freq = (struct u2f_register_request *)payload; printf1(TAG_NFC,"Iblock: "); dump_hex1(TAG_NFC, buf, len); @@ -479,19 +475,19 @@ void nfc_process_iblock(uint8_t * buf, int len) return; } - t1 = millis(); + timestamp(); // WTX_on(WTX_TIME_DEFAULT); // SystemClock_Config_LF32(); // delay(300); - SystemClock_Config_LF24(); + device_set_clock_rate(DEVICE_LOW_POWER_FAST);; u2f_request_nfc(&buf[1], len, &ctap_resp); - SystemClock_Config_LF16(); + device_set_clock_rate(DEVICE_LOW_POWER_IDLE);; // if (!WTX_off()) // return; - printf1(TAG_NFC,"U2F Register P2 took %d\r\n", millis() - t1); + printf1(TAG_NFC,"U2F Register P2 took %d\r\n", timestamp()); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0 ); // printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); @@ -518,16 +514,16 @@ void nfc_process_iblock(uint8_t * buf, int len) return; } - t1 = millis(); + timestamp(); // WTX_on(WTX_TIME_DEFAULT); u2f_request_nfc(&buf[1], len, &ctap_resp); // if (!WTX_off()) // return; printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); - printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), millis() - t1); + printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), timestamp()); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0); - printf1(TAG_NFC,"U2F Authenticate answered %d (took %d)\r\n", millis(), millis() - t1); + printf1(TAG_NFC,"U2F Authenticate answered %d (took %d)\r\n", millis(), timestamp); break; case APDU_FIDO_NFCCTAP_MSG: @@ -536,7 +532,7 @@ void nfc_process_iblock(uint8_t * buf, int len) break; } - t1 = millis(); + timestamp(); printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); WTX_on(WTX_TIME_DEFAULT); @@ -558,9 +554,9 @@ void nfc_process_iblock(uint8_t * buf, int len) ctap_resp.data[ctap_resp.length - 2] = SW_SUCCESS >> 8; ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff; - printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), millis() - t1); + printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), timestamp()); nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0); - printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), millis() - t1); + printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), timestamp()); break; case APDU_INS_READ_BINARY: @@ -613,7 +609,7 @@ void clear_ibuf() memset(ibuf, 0, sizeof(ibuf)); } -void nfc_process_block(uint8_t * buf, int len) +void nfc_process_block(uint8_t * buf, unsigned int len) { if (!len) @@ -706,8 +702,6 @@ void nfc_process_block(uint8_t * buf, int len) void nfc_loop() { - static uint32_t t1 = 0; - static uint32_t t2 = 0; uint8_t buf[32]; AMS_DEVICE ams; int len = 0; @@ -732,7 +726,6 @@ void nfc_loop() if (ams.regs.int0 & AMS_INT_INIT) { nfc_state_init(); - t1 = millis(); } if (ams.regs.int1) { @@ -771,14 +764,12 @@ void nfc_loop() printf1(TAG_NFC, "HLTA/Halt\r\n"); break; case NFC_CMD_RATS: - t2 = millis(); answer_rats(buf[1]); NFC_STATE.block_num = 1; clear_ibuf(); WTX_clear(); - printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); break; default: diff --git a/targets/stm32l432/src/system_stm32l4xx.c b/targets/stm32l432/src/system_stm32l4xx.c index 262e883..a903c1c 100644 --- a/targets/stm32l432/src/system_stm32l4xx.c +++ b/targets/stm32l432/src/system_stm32l4xx.c @@ -106,6 +106,7 @@ */ #include "stm32l4xx.h" +#include "device.h" #include "init.h" #if !defined (HSE_VALUE) @@ -220,7 +221,7 @@ void SystemInit(void) /* Disable all interrupts */ RCC->CIER = 0x00000000U; - SystemClock_Config_LF16(); + device_set_clock_rate(DEVICE_LOW_POWER_IDLE); } From 347d0942b1021d3d96b6f6beb2c28c5588f4375c Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 14:07:27 -0500 Subject: [PATCH 90/96] refactor fromNFC --- fido2/ctap.c | 18 +++++++++--------- fido2/ctap.h | 2 +- fido2/ctaphid.c | 2 +- fido2/device.h | 5 +++++ fido2/u2f.c | 22 +++++++++++----------- targets/stm32l432/src/device.c | 9 +++++++-- targets/stm32l432/src/nfc.c | 12 ++++++------ 7 files changed, 40 insertions(+), 30 deletions(-) diff --git a/fido2/ctap.c b/fido2/ctap.c index 02d1d5c..553b20e 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -310,7 +310,7 @@ static int is_matching_rk(CTAP_residentKey * rk, CTAP_residentKey * rk2) } -static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, unsigned int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store, bool fromNFC) +static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, unsigned int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store) { CborEncoder cose_key; int auth_data_sz, ret; @@ -338,7 +338,7 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au device_set_status(CTAPHID_STATUS_UPNEEDED); // if NFC - not need to click a button int but = 1; - if(!fromNFC) + if(!device_is_nfc()) { but = ctap_user_presence_test(); } @@ -552,7 +552,7 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d -uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length, bool fromNFC) +uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length) { CTAP_makeCredential MC; int ret; @@ -623,7 +623,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt int32_t auth_data_sz; ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf), - &MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz, MC.rk, fromNFC); + &MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz, MC.rk); check_retr(ret); @@ -963,7 +963,7 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder) return 0; } -uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length, bool fromNFC) +uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length) { CTAP_getAssertion GA; uint8_t auth_data_buf[sizeof(CTAP_authDataHeader)]; @@ -1027,7 +1027,7 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length, else #endif { - ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0, fromNFC); + ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0); check_retr(ret); } @@ -1394,7 +1394,7 @@ void ctap_response_init(CTAP_RESPONSE * resp) } -uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool fromNFC) +uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp) { CborEncoder encoder; uint8_t status = 0; @@ -1432,7 +1432,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool f device_set_status(CTAPHID_STATUS_PROCESSING); printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n"); timestamp(); - status = ctap_make_credential(&encoder, pkt_raw, length, fromNFC); + status = ctap_make_credential(&encoder, pkt_raw, length); printf1(TAG_TIME,"make_credential time: %d ms\n", timestamp()); resp->length = cbor_encoder_get_buffer_size(&encoder, buf); @@ -1443,7 +1443,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool f device_set_status(CTAPHID_STATUS_PROCESSING); printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n"); timestamp(); - status = ctap_get_assertion(&encoder, pkt_raw, length, fromNFC); + status = ctap_get_assertion(&encoder, pkt_raw, length); printf1(TAG_TIME,"get_assertion time: %d ms\n", timestamp()); resp->length = cbor_encoder_get_buffer_size(&encoder, buf); diff --git a/fido2/ctap.h b/fido2/ctap.h index 1996468..a6db27d 100644 --- a/fido2/ctap.h +++ b/fido2/ctap.h @@ -260,7 +260,7 @@ typedef struct void ctap_response_init(CTAP_RESPONSE * resp); -uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp, bool fromNFC); +uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp); // Encodes R,S signature to 2 der sequence of two integers. Sigder must be at least 72 bytes. // @return length of der signature diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index d6d3a54..5ddc260 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -621,7 +621,7 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) } is_busy = 1; ctap_response_init(&ctap_resp); - status = ctap_request(ctap_buffer, len, &ctap_resp, 0); + status = ctap_request(ctap_buffer, len, &ctap_resp); ctaphid_write_buffer_init(&wb); wb.cid = cid; diff --git a/fido2/device.h b/fido2/device.h index a9ee118..109d25a 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -99,4 +99,9 @@ typedef enum { // 2: fastest clock rate. Generally for USB interface. void device_set_clock_rate(DEVICE_CLOCK_RATE param); +// Returns 1 if operating in NFC mode. +// 0 otherwise. +bool device_is_nfc(); + + #endif diff --git a/fido2/u2f.c b/fido2/u2f.c index 9731572..9b2d766 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -19,8 +19,8 @@ // void u2f_response_writeback(uint8_t * buf, uint8_t len); #ifdef ENABLE_U2F -static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC); -static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control, bool fromNFC); +static int16_t u2f_register(struct u2f_register_request * req); +static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control); #endif int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len); void u2f_reset_response(); @@ -28,7 +28,7 @@ void u2f_reset_response(); static CTAP_RESPONSE * _u2f_resp = NULL; -void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPONSE * resp, bool fromNFC) +void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPONSE * resp) { uint16_t rcode = 0; uint8_t byte; @@ -60,7 +60,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO { timestamp(); - rcode = u2f_register((struct u2f_register_request*)payload, fromNFC); + rcode = u2f_register((struct u2f_register_request*)payload); printf1(TAG_TIME,"u2f_register time: %d ms\n", timestamp()); } @@ -68,7 +68,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO case U2F_AUTHENTICATE: printf1(TAG_U2F, "U2F_AUTHENTICATE\n"); timestamp(); - rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1, fromNFC); + rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1); printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", timestamp()); break; case U2F_VERSION: @@ -117,14 +117,14 @@ void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp) uint32_t alen = req[4]; - u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp, true); + u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp); } void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp) { uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16)); - u2f_request_ex((APDU_HEADER *)req, req->payload, len, resp, false); + u2f_request_ex((APDU_HEADER *)req, req->payload, len, resp); } int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len) @@ -203,7 +203,7 @@ static int8_t u2f_appid_eq(struct u2f_key_handle * kh, uint8_t * appid) -static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control, bool fromNFC) +static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control) { uint8_t up = 1; @@ -237,7 +237,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c if (control == U2F_AUTHENTICATE_SIGN_NO_USER) up = 0; - if(!fromNFC && up) + if(!device_is_nfc() && up) { if (ctap_user_presence_test() == 0) { @@ -273,7 +273,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c return U2F_SW_NO_ERROR; } -static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) +static int16_t u2f_register(struct u2f_register_request * req) { uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED}; @@ -285,7 +285,7 @@ static int16_t u2f_register(struct u2f_register_request * req, bool fromNFC) const uint16_t attest_size = attestation_cert_der_size; - if(!fromNFC) + if(!device_is_nfc()) { if ( ! ctap_user_presence_test()) { diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index c389b65..7562c75 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -40,8 +40,8 @@ uint32_t __90_ms = 0; uint32_t __device_status = 0; uint32_t __last_update = 0; extern PCD_HandleTypeDef hpcd; -bool haveNFC = false; -bool isLowFreq = 0; +static bool haveNFC = 0; +static bool isLowFreq = 0; #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN)) @@ -136,6 +136,11 @@ void device_init() } +bool device_is_nfc() +{ + return haveNFC; +} + void wait_for_usb_tether() { while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) ) diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index cf526df..85da81a 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -157,7 +157,7 @@ bool nfc_write_response(uint8_t req0, uint16_t resp) return nfc_write_response_ex(req0, NULL, 0, resp); } -void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len, int keepgoing) +void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len) { uint8_t res[32 + 2]; int sendlen = 0; @@ -178,7 +178,7 @@ void nfc_write_response_chaining(uint8_t req0, uint8_t * data, int len, int keep memcpy(&res[1], &data[sendlen], vlen); // if not a last block - if ((vlen + sendlen < len) || keepgoing) + if (vlen + sendlen < len) { res[0] |= 0x10; } @@ -488,7 +488,7 @@ void nfc_process_iblock(uint8_t * buf, int len) // return; printf1(TAG_NFC,"U2F Register P2 took %d\r\n", timestamp()); - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0 ); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); // printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); @@ -522,7 +522,7 @@ void nfc_process_iblock(uint8_t * buf, int len) printf1(TAG_NFC, "U2F resp len: %d\r\n", ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate processing %d (took %d)\r\n", millis(), timestamp()); - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); printf1(TAG_NFC,"U2F Authenticate answered %d (took %d)\r\n", millis(), timestamp); break; @@ -537,7 +537,7 @@ void nfc_process_iblock(uint8_t * buf, int len) WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); - status = ctap_request(payload, plen, &ctap_resp, true); + status = ctap_request(payload, plen, &ctap_resp); if (!WTX_off()) return; @@ -555,7 +555,7 @@ void nfc_process_iblock(uint8_t * buf, int len) ctap_resp.data[ctap_resp.length - 1] = SW_SUCCESS & 0xff; printf1(TAG_NFC,"CTAP processing %d (took %d)\r\n", millis(), timestamp()); - nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length, 0); + nfc_write_response_chaining(buf[0], ctap_resp.data, ctap_resp.length); printf1(TAG_NFC,"CTAP answered %d (took %d)\r\n", millis(), timestamp()); break; From ecf994b647ddf65624c494ba1aacd85e5091877d Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 14:13:29 -0500 Subject: [PATCH 91/96] fix warnings and compile errors --- targets/stm32l432/src/app.h | 1 + targets/stm32l432/src/nfc.c | 7 +++---- targets/stm32l432/src/redirect.c | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index c0353a0..5753d14 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -30,6 +30,7 @@ // #define DISABLE_CTAPHID_WINK // #define DISABLE_CTAPHID_CBOR +// #define ENABLE_SERIAL_PRINTING #if defined(SOLO_HACKER) #define SOLO_PRODUCT_NAME "Solo Hacker " SOLO_VERSION diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index 85da81a..dc66235 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -444,7 +444,7 @@ void nfc_process_iblock(uint8_t * buf, int len) else { nfc_write_response(buf[0], SW_FILE_NOT_FOUND); - printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC,res, 3); + printf1(TAG_NFC, "NOT selected\r\n"); dump_hex1(TAG_NFC,payload, plen); } } break; @@ -495,7 +495,7 @@ void nfc_process_iblock(uint8_t * buf, int len) - printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), millis() - t1); + printf1(TAG_NFC,"U2F Register answered %d (took %d)\r\n", millis(), timestamp()); break; case APDU_FIDO_U2F_AUTHENTICATE: @@ -532,8 +532,7 @@ void nfc_process_iblock(uint8_t * buf, int len) break; } - timestamp(); - printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", t1); + printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp()); WTX_on(WTX_TIME_DEFAULT); ctap_response_init(&ctap_resp); diff --git a/targets/stm32l432/src/redirect.c b/targets/stm32l432/src/redirect.c index f601ad8..ed4147f 100644 --- a/targets/stm32l432/src/redirect.c +++ b/targets/stm32l432/src/redirect.c @@ -24,7 +24,7 @@ void _putchar(char c) } -int _write (int fd, const void *buf, long int len) +int _write (int fd, const void *buf, unsigned long int len) { uint8_t * data = (uint8_t *) buf; #if DEBUG_LEVEL>1 @@ -43,11 +43,14 @@ int _write (int fd, const void *buf, long int len) if (res == USBD_OK) logbuflen = 0; #endif +#ifdef ENABLE_SERIAL_PRINTING // Send out UART serial while(len--) { _putchar(*data++); } +#endif return 0; + } #endif From e2ca7f52db1b98d6f632f7357b3f0cafc3de4cd2 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 14:19:07 -0500 Subject: [PATCH 92/96] optimize ecc for arm --- targets/stm32l432/build/application.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/stm32l432/build/application.mk b/targets/stm32l432/build/application.mk index 1d2419e..576e029 100644 --- a/targets/stm32l432/build/application.mk +++ b/targets/stm32l432/build/application.mk @@ -41,7 +41,7 @@ DEBUG=0 endif DEFINES = -DDEBUG_LEVEL=$(DEBUG) -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER -DAPP_CONFIG=\"app.h\" $(EXTRA_DEFINES) -# DEFINES += -DTEST_SOLO_STM32 -DTEST -DTEST_FIFO=1 +DEFINES += -DuECC_PLATFORM=5 -DuECC_OPTIMIZATION_LEVEL=4 -DuECC_SQUARE_FUNC=1 -DuECC_SUPPORT_COMPRESSED_POINT=0 CFLAGS=$(INC) -c $(DEFINES) -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fdata-sections -ffunction-sections $(HW) -g $(VERSION_FLAGS) LDFLAGS_LIB=$(HW) $(SEARCH) -specs=nano.specs -specs=nosys.specs -Wl,--gc-sections -u _printf_float -lnosys From e8d0ad5e7cf2f8bd5a57aae8e5e8b69d3816474c Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 15:04:23 -0500 Subject: [PATCH 93/96] autodetect passive nfc operation or usb operation --- fido2/ctap.c | 4 +- fido2/ctap.h | 2 +- targets/stm32l432/src/ams.c | 150 ++++++++++++++++----------------- targets/stm32l432/src/ams.h | 3 +- targets/stm32l432/src/app.h | 2 +- targets/stm32l432/src/device.c | 26 +++--- targets/stm32l432/src/init.c | 2 + targets/stm32l432/src/nfc.c | 135 +++++++++++++++-------------- targets/stm32l432/src/nfc.h | 4 +- 9 files changed, 175 insertions(+), 153 deletions(-) diff --git a/fido2/ctap.c b/fido2/ctap.c index 553b20e..ecdff80 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -1536,7 +1536,7 @@ static void ctap_state_init() ctap_reset_rk(); } -void ctap_init(int init_pin) +void ctap_init() { crypto_ecc256_init(); @@ -1591,7 +1591,7 @@ void ctap_init(int init_pin) exit(1); } - if (init_pin) + if (! device_is_nfc()) { crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); } diff --git a/fido2/ctap.h b/fido2/ctap.h index a6db27d..a3a8783 100644 --- a/fido2/ctap.h +++ b/fido2/ctap.h @@ -267,7 +267,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp); int ctap_encode_der_sig(uint8_t const * const in_sigbuf, uint8_t * const out_sigder); // Run ctap related power-up procedures (init pinToken, generate shared secret) -void ctap_init(int init_pin); +void ctap_init(); // Resets state between different accesses of different applications void ctap_reset_state(); diff --git a/targets/stm32l432/src/ams.c b/targets/stm32l432/src/ams.c index 7b2438a..335758f 100644 --- a/targets/stm32l432/src/ams.c +++ b/targets/stm32l432/src/ams.c @@ -6,6 +6,7 @@ #include "log.h" #include "util.h" #include "device.h" +#include "nfc.h" static void flush_rx() { @@ -269,11 +270,8 @@ void ams_print_int1(uint8_t int0) #endif } - -bool ams_init() +void ams_init() { - uint8_t block[4]; - LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); @@ -284,85 +282,85 @@ bool ams_init() // delay(10); SELECT(); - delay(2); + delay(1); +} - // Needs to be disabled for passive operation - if (0) - // if (1) +void ams_configure() +{ + // Should not be used during passive operation. + uint8_t block[4]; + + // check connection + uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); + if (productType != 0x14) { - // check connection - uint8_t productType = ams_read_reg(AMS_REG_PRODUCT_TYPE); - if (productType != 0x14) - { - printf1(TAG_NFC, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType); - return false; - } + printf1(TAG_ERR, "Have wrong product type [0x%02x]. AMS3956 connection error.\n", productType); + } - printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); + printf1(TAG_NFC,"AMS3956 product type 0x%02x.\n", productType); - ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); - printf1(TAG_NFC,"UID: 3F 14 02 - "); dump_hex1(TAG_NFC,block,4); + ams_read_eeprom_block(AMS_CONFIG_UID_ADDR, block); + printf1(TAG_NFC,"UID: 3F 14 02 - "); dump_hex1(TAG_NFC,block,4); + + ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); + + uint8_t sense1 = 0x44; + uint8_t sense2 = 0x00; + uint8_t selr = 0x20; // SAK + + if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) + { + printf1(TAG_NFC,"Writing config block 0\r\n"); + block[0] = sense1; + block[1] = sense2; + block[2] = selr; + block[3] = 0x00; + + ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); + UNSELECT(); + delay(10); + SELECT(); + delay(10); ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); - - uint8_t sense1 = 0x44; - uint8_t sense2 = 0x00; - uint8_t selr = 0x20; // SAK - - if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) - { - printf1(TAG_NFC,"Writing config block 0\r\n"); - block[0] = sense1; - block[1] = sense2; - block[2] = selr; - block[3] = 0x00; - - ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - UNSELECT(); - delay(10); - SELECT(); - delay(10); - - ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); - printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); - } - - ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); - printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); - - uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; - uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; - - if (block[0] != ic_cfg1 || block[1] != ic_cfg2) - { - - printf1(TAG_NFC,"Writing config block 1\r\n"); - - ams_write_reg(AMS_REG_IC_CONF1,ic_cfg1); - ams_write_reg(AMS_REG_IC_CONF2,ic_cfg2); - - // set IC_CFG1 - block[0] = ic_cfg1; - - // set IC_CFG2 - block[1] = ic_cfg2; - - // mask interrupt bits - block[2] = 0x80; - block[3] = 0; - - ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); - - UNSELECT(); - delay(10); - SELECT(); - delay(10); - - ams_read_eeprom_block(0x7F, block); - printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); - } } - return true; + ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + + uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; + uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; + + if (block[0] != ic_cfg1 || block[1] != ic_cfg2) + { + + printf1(TAG_NFC,"Writing config block 1\r\n"); + + ams_write_reg(AMS_REG_IC_CONF1,ic_cfg1); + ams_write_reg(AMS_REG_IC_CONF2,ic_cfg2); + + // set IC_CFG1 + block[0] = ic_cfg1; + + // set IC_CFG2 + block[1] = ic_cfg2; + + // mask interrupt bits + block[2] = 0x80; + block[3] = 0; + + ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); + + UNSELECT(); + delay(10); + SELECT(); + delay(10); + + ams_read_eeprom_block(0x7F, block); + printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); + } + + } diff --git a/targets/stm32l432/src/ams.h b/targets/stm32l432/src/ams.h index d8e3cad..ef701bf 100644 --- a/targets/stm32l432/src/ams.h +++ b/targets/stm32l432/src/ams.h @@ -39,7 +39,8 @@ typedef union #define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) #define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) -bool ams_init(); +void ams_init(); +void ams_configure(); void ams_read_buffer(uint8_t * data, int len); void ams_write_buffer(uint8_t * data, int len); diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h index 5753d14..8570d24 100644 --- a/targets/stm32l432/src/app.h +++ b/targets/stm32l432/src/app.h @@ -30,7 +30,7 @@ // #define DISABLE_CTAPHID_WINK // #define DISABLE_CTAPHID_CBOR -// #define ENABLE_SERIAL_PRINTING +#define ENABLE_SERIAL_PRINTING #if defined(SOLO_HACKER) #define SOLO_PRODUCT_NAME "Solo Hacker " SOLO_VERSION diff --git a/targets/stm32l432/src/device.c b/targets/stm32l432/src/device.c index 7562c75..d65b7f8 100644 --- a/targets/stm32l432/src/device.c +++ b/targets/stm32l432/src/device.c @@ -60,7 +60,7 @@ void TIM6_DAC_IRQHandler() } #ifndef IS_BOOTLOADER // NFC sending WTX if needs - if (haveNFC) + if (device_is_nfc()) { WTX_timer_exec(); } @@ -113,26 +113,32 @@ void device_init() hw_init(LOW_FREQUENCY); isLowFreq = 1; - printf1(TAG_NFC,"PWR->CR1: %04x\r\n", LL_PWR_GetRegulVoltageScaling()); + haveNFC = nfc_init(); - // hw_init(HIGH_FREQUENCY); - // isLowFreq = 0; + if (haveNFC) + { + printf1(TAG_NFC, "Have NFC\r\n"); + } + else + { + printf1(TAG_NFC, "Have NO NFC\r\n"); + hw_init(HIGH_FREQUENCY); + + isLowFreq = 0; + } usbhid_init(); ctaphid_init(); - ctap_init( 0 ); + ctap_init( !haveNFC ); -#ifndef IS_BOOTLOADER #if BOOT_TO_DFU flash_option_bytes_init(1); #else flash_option_bytes_init(0); #endif - printf1(TAG_GEN,"init nfc\n"); - haveNFC = nfc_init(); -#endif + } @@ -430,7 +436,7 @@ void device_manage() } #endif #ifndef IS_BOOTLOADER - if(haveNFC) + // if(device_is_nfc()) nfc_loop(); #endif } diff --git a/targets/stm32l432/src/init.c b/targets/stm32l432/src/init.c index 4834e5d..3e704ea 100644 --- a/targets/stm32l432/src/init.c +++ b/targets/stm32l432/src/init.c @@ -808,6 +808,8 @@ void init_debug_uart(void) /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); + + LL_USART_DeInit(USART1); /**USART1 GPIO Configuration PB6 ------> USART1_TX PB7 ------> USART1_RX diff --git a/targets/stm32l432/src/nfc.c b/targets/stm32l432/src/nfc.c index dc66235..ab0ddf3 100644 --- a/targets/stm32l432/src/nfc.c +++ b/targets/stm32l432/src/nfc.c @@ -57,8 +57,23 @@ void nfc_state_init() bool nfc_init() { + uint32_t t1; nfc_state_init(); - return ams_init(); + ams_init(); + + // Detect if we are powered by NFC field by listening for a message for + // first 25 ms. + t1 = millis(); + while ((millis() - t1) < 25) + { + if (nfc_loop() > 0) + return 1; + } + + // Under USB power. Configure AMS chip. + ams_configure(); + + return 0; } void process_int0(uint8_t int0) @@ -699,88 +714,86 @@ void nfc_process_block(uint8_t * buf, unsigned int len) } } -void nfc_loop() +int nfc_loop() { uint8_t buf[32]; AMS_DEVICE ams; int len = 0; - if (1) + read_reg_block(&ams); + uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; + + if (state != AMS_STATE_SELECTED && state != AMS_STATE_SELECTEDX) { - read_reg_block(&ams); - uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; + // delay(1); // sleep ? + return 0; + } - if (state != AMS_STATE_SELECTED && state != AMS_STATE_SELECTEDX) - { - // delay(1); // sleep ? - return; - } + if (ams.regs.rfid_status) + { + // if (state != AMS_STATE_SENSE) + // printf1(TAG_NFC," %s x%02x\r\n", ams_get_state_string(ams.regs.rfid_status), state); + } + if (ams.regs.int0 & AMS_INT_INIT) + { + nfc_state_init(); + } + if (ams.regs.int1) + { + // ams_print_int1(ams.regs.int1); + } - if (ams.regs.rfid_status) + if ((ams.regs.int0 & AMS_INT_RXE)) + { + if (ams.regs.buffer_status2) { - // if (state != AMS_STATE_SENSE) - // printf1(TAG_NFC," %s x%02x\r\n", ams_get_state_string(ams.regs.rfid_status), state); - } - if (ams.regs.int0 & AMS_INT_INIT) - { - nfc_state_init(); - } - if (ams.regs.int1) - { - // ams_print_int1(ams.regs.int1); - } - - if ((ams.regs.int0 & AMS_INT_RXE)) - { - if (ams.regs.buffer_status2) + if (ams.regs.buffer_status2 & AMS_BUF_INVALID) { - if (ams.regs.buffer_status2 & AMS_BUF_INVALID) - { - printf1(TAG_NFC,"Buffer being updated!\r\n"); - } - else - { - len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; - ams_read_buffer(buf, len); - } + printf1(TAG_NFC,"Buffer being updated!\r\n"); + } + else + { + len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; + ams_read_buffer(buf, len); } } + } - if (len) + if (len) + { + + // ISO 14443-3 + switch(buf[0]) { + case NFC_CMD_REQA: + printf1(TAG_NFC, "NFC_CMD_REQA\r\n"); + break; + case NFC_CMD_WUPA: + printf1(TAG_NFC, "NFC_CMD_WUPA\r\n"); + break; + case NFC_CMD_HLTA: + printf1(TAG_NFC, "HLTA/Halt\r\n"); + break; + case NFC_CMD_RATS: - // ISO 14443-3 - switch(buf[0]) - { - case NFC_CMD_REQA: - printf1(TAG_NFC, "NFC_CMD_REQA\r\n"); - break; - case NFC_CMD_WUPA: - printf1(TAG_NFC, "NFC_CMD_WUPA\r\n"); - break; - case NFC_CMD_HLTA: - printf1(TAG_NFC, "HLTA/Halt\r\n"); - break; - case NFC_CMD_RATS: + answer_rats(buf[1]); - answer_rats(buf[1]); + NFC_STATE.block_num = 1; + clear_ibuf(); + WTX_clear(); + break; + default: - NFC_STATE.block_num = 1; - clear_ibuf(); - WTX_clear(); - break; - default: - - // ISO 14443-4 - nfc_process_block(buf,len); + // ISO 14443-4 + nfc_process_block(buf,len); - break; - } - + break; } } + return len; + } diff --git a/targets/stm32l432/src/nfc.h b/targets/stm32l432/src/nfc.h index 2388018..a8627a2 100644 --- a/targets/stm32l432/src/nfc.h +++ b/targets/stm32l432/src/nfc.h @@ -5,7 +5,9 @@ #include #include "apdu.h" -void nfc_loop(); +// Return number of bytes read if any. +int nfc_loop(); + bool nfc_init(); typedef struct From 1ed7833c9f481188f61adfd3124569e9fdda6c0f Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 15:08:09 -0500 Subject: [PATCH 94/96] fix pc build --- pc/device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pc/device.c b/pc/device.c index b4d5379..69a2509 100644 --- a/pc/device.c +++ b/pc/device.c @@ -461,3 +461,8 @@ void device_wink() { printf("*WINK*\n"); } + +bool device_is_nfc() +{ + return 0; +} From 14974e0ebe493e3f62d7b01208c50d766f8055cd Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 15:30:57 -0500 Subject: [PATCH 95/96] fix compile issues --- fido2/extensions/extensions.c | 4 ++-- fido2/extensions/extensions.h | 3 ++- fido2/u2f.c | 2 +- targets/stm32l432/bootloader/main.c | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fido2/extensions/extensions.c b/fido2/extensions/extensions.c index d14cab8..f8160df 100644 --- a/fido2/extensions/extensions.c +++ b/fido2/extensions/extensions.c @@ -91,10 +91,10 @@ int16_t extend_fido2(CredentialId * credid, uint8_t * output) } } -int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len) +int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len) { - struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) req->payload; + struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) payload; uint16_t rcode; if (req->ins == U2F_AUTHENTICATE) diff --git a/fido2/extensions/extensions.h b/fido2/extensions/extensions.h index ea871a5..2d602c1 100644 --- a/fido2/extensions/extensions.h +++ b/fido2/extensions/extensions.h @@ -7,8 +7,9 @@ #ifndef EXTENSIONS_H_ #define EXTENSIONS_H_ #include "u2f.h" +#include "apdu.h" -int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len); +int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len); int16_t extend_fido2(CredentialId * credid, uint8_t * output); diff --git a/fido2/u2f.c b/fido2/u2f.c index 9b2d766..3e968a8 100644 --- a/fido2/u2f.c +++ b/fido2/u2f.c @@ -43,7 +43,7 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO goto end; } #ifdef ENABLE_U2F_EXTENSIONS - rcode = extend_u2f(req, len); // FIXME + rcode = extend_u2f(req, payload, len); #endif if (rcode != U2F_SW_NO_ERROR && rcode != U2F_SW_CONDITIONS_NOT_SATISFIED) // If the extension didn't do anything... { diff --git a/targets/stm32l432/bootloader/main.c b/targets/stm32l432/bootloader/main.c index aec4d61..ef057ed 100644 --- a/targets/stm32l432/bootloader/main.c +++ b/targets/stm32l432/bootloader/main.c @@ -27,7 +27,7 @@ uint8_t REBOOT_FLAG = 0; -void BOOT_boot(void) +void BOOT_boot(void) { typedef void (*pFunction)(void); @@ -79,7 +79,7 @@ int main() init_millisecond_timer(1); #if DEBUG_LEVEL > 0 - init_debug_uart(); + init_debug_uart(); #endif printf1(TAG_GEN,"init device\n"); @@ -118,7 +118,7 @@ int main() } #ifdef SOLO_HACKER start_bootloader: - +#endif SystemClock_Config(); init_gpio(); init_millisecond_timer(0); From 0eac67259da6b8c12c5d7e99e3047ca27f65cf41 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Tue, 26 Feb 2019 18:24:40 -0500 Subject: [PATCH 96/96] remove stm32l442 target --- targets/stm32l442/lib/stm32l4xx_ll_spi.c | 307 ----- targets/stm32l442/lib/stm32l4xx_ll_spi.h | 1436 ---------------------- 2 files changed, 1743 deletions(-) delete mode 100644 targets/stm32l442/lib/stm32l4xx_ll_spi.c delete mode 100644 targets/stm32l442/lib/stm32l4xx_ll_spi.h diff --git a/targets/stm32l442/lib/stm32l4xx_ll_spi.c b/targets/stm32l442/lib/stm32l4xx_ll_spi.c deleted file mode 100644 index 99e28de..0000000 --- a/targets/stm32l442/lib/stm32l4xx_ll_spi.c +++ /dev/null @@ -1,307 +0,0 @@ -/** - ****************************************************************************** - * @file stm32l4xx_ll_spi.c - * @author MCD Application Team - * @brief SPI LL module driver. - ****************************************************************************** - * @attention - * - *

© 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. - * - ****************************************************************************** - */ -#if defined(USE_FULL_LL_DRIVER) - -/* Includes ------------------------------------------------------------------*/ -#include "stm32l4xx_ll_spi.h" -#include "stm32l4xx_ll_bus.h" - -#ifdef USE_FULL_ASSERT -#include "stm32_assert.h" -#else -#define assert_param(expr) ((void)0U) -#endif - -/** @addtogroup STM32L4xx_LL_Driver - * @{ - */ - -#if defined (SPI1) || defined (SPI2) || defined (SPI3) - -/** @addtogroup SPI_LL - * @{ - */ - -/* Private types -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ - -/* Private constants ---------------------------------------------------------*/ -/** @defgroup SPI_LL_Private_Constants SPI Private Constants - * @{ - */ -/* SPI registers Masks */ -#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \ - SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \ - SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_CRCL | \ - SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \ - SPI_CR1_BIDIMODE) -/** - * @} - */ - -/* Private macros ------------------------------------------------------------*/ -/** @defgroup SPI_LL_Private_Macros SPI Private Macros - * @{ - */ -#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \ - || ((__VALUE__) == LL_SPI_SIMPLEX_RX) \ - || ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \ - || ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX)) - -#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \ - || ((__VALUE__) == LL_SPI_MODE_SLAVE)) - -#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \ - || ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT)) - -#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \ - || ((__VALUE__) == LL_SPI_POLARITY_HIGH)) - -#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \ - || ((__VALUE__) == LL_SPI_PHASE_2EDGE)) - -#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \ - || ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \ - || ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT)) - -#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \ - || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256)) - -#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \ - || ((__VALUE__) == LL_SPI_MSB_FIRST)) - -#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \ - || ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE)) - -#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U) - -/** - * @} - */ - -/* Private function prototypes -----------------------------------------------*/ - -/* Exported functions --------------------------------------------------------*/ -/** @addtogroup SPI_LL_Exported_Functions - * @{ - */ - -/** @addtogroup SPI_LL_EF_Init - * @{ - */ - -/** - * @brief De-initialize the SPI registers to their default reset values. - * @param SPIx SPI Instance - * @retval An ErrorStatus enumeration value: - * - SUCCESS: SPI registers are de-initialized - * - ERROR: SPI registers are not de-initialized - */ -ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx) -{ - ErrorStatus status = ERROR; - - /* Check the parameters */ - assert_param(IS_SPI_ALL_INSTANCE(SPIx)); - -#if defined(SPI1) - if (SPIx == SPI1) - { - /* Force reset of SPI clock */ - LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); - - /* Release reset of SPI clock */ - LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); - - status = SUCCESS; - } -#endif /* SPI1 */ -#if defined(SPI2) - if (SPIx == SPI2) - { - /* Force reset of SPI clock */ - LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); - - /* Release reset of SPI clock */ - LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); - - status = SUCCESS; - } -#endif /* SPI2 */ -#if defined(SPI3) - if (SPIx == SPI3) - { - /* Force reset of SPI clock */ - LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3); - - /* Release reset of SPI clock */ - LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3); - - status = SUCCESS; - } -#endif /* SPI3 */ - - return status; -} - -/** - * @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct. - * @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0), - * SPI IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. - * @param SPIx SPI Instance - * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure - * @retval An ErrorStatus enumeration value. (Return always SUCCESS) - */ -ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct) -{ - ErrorStatus status = ERROR; - - /* Check the SPI Instance SPIx*/ - assert_param(IS_SPI_ALL_INSTANCE(SPIx)); - - /* Check the SPI parameters from SPI_InitStruct*/ - assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection)); - assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode)); - assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth)); - assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity)); - assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase)); - assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS)); - assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate)); - assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder)); - assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation)); - - if (LL_SPI_IsEnabled(SPIx) == 0x00000000U) - { - /*---------------------------- SPIx CR1 Configuration ------------------------ - * Configure SPIx CR1 with parameters: - * - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits - * - Master/Slave Mode: SPI_CR1_MSTR bit - * - ClockPolarity: SPI_CR1_CPOL bit - * - ClockPhase: SPI_CR1_CPHA bit - * - NSS management: SPI_CR1_SSM bit - * - BaudRate prescaler: SPI_CR1_BR[2:0] bits - * - BitOrder: SPI_CR1_LSBFIRST bit - * - CRCCalculation: SPI_CR1_CRCEN bit - */ - MODIFY_REG(SPIx->CR1, - SPI_CR1_CLEAR_MASK, - SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode | - SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase | - SPI_InitStruct->NSS | SPI_InitStruct->BaudRate | - SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation); - - /*---------------------------- SPIx CR2 Configuration ------------------------ - * Configure SPIx CR2 with parameters: - * - DataWidth: DS[3:0] bits - * - NSS management: SSOE bit - */ - MODIFY_REG(SPIx->CR2, - SPI_CR2_DS | SPI_CR2_SSOE, - SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U)); - - /*---------------------------- SPIx CRCPR Configuration ---------------------- - * Configure SPIx CRCPR with parameters: - * - CRCPoly: CRCPOLY[15:0] bits - */ - if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE) - { - assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly)); - LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly); - } - status = SUCCESS; - } - - return status; -} - -/** - * @brief Set each @ref LL_SPI_InitTypeDef field to default value. - * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure - * whose fields will be set to default values. - * @retval None - */ -void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct) -{ - /* Set SPI_InitStruct fields to default values */ - SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX; - SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE; - SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT; - SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW; - SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE; - SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT; - SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; - SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST; - SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; - SPI_InitStruct->CRCPoly = 7U; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ - -/** - * @} - */ - -#endif /* USE_FULL_LL_DRIVER */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/targets/stm32l442/lib/stm32l4xx_ll_spi.h b/targets/stm32l442/lib/stm32l4xx_ll_spi.h deleted file mode 100644 index b5bc17a..0000000 --- a/targets/stm32l442/lib/stm32l4xx_ll_spi.h +++ /dev/null @@ -1,1436 +0,0 @@ -/** - ****************************************************************************** - * @file stm32l4xx_ll_spi.h - * @author MCD Application Team - * @brief Header file of SPI LL module. - ****************************************************************************** - * @attention - * - *

© 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. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef STM32L4xx_LL_SPI_H -#define STM32L4xx_LL_SPI_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "stm32l4xx.h" - -/** @addtogroup STM32L4xx_LL_Driver - * @{ - */ - -#if defined (SPI1) || defined (SPI2) || defined (SPI3) - -/** @defgroup SPI_LL SPI - * @{ - */ - -/* Private types -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private macros ------------------------------------------------------------*/ - -/* Exported types ------------------------------------------------------------*/ -#if defined(USE_FULL_LL_DRIVER) -/** @defgroup SPI_LL_ES_INIT SPI Exported Init structure - * @{ - */ - -/** - * @brief SPI Init structures definition - */ -typedef struct -{ - uint32_t TransferDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. - This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferDirection().*/ - - uint32_t Mode; /*!< Specifies the SPI mode (Master/Slave). - This parameter can be a value of @ref SPI_LL_EC_MODE. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetMode().*/ - - uint32_t DataWidth; /*!< Specifies the SPI data width. - This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetDataWidth().*/ - - uint32_t ClockPolarity; /*!< Specifies the serial clock steady state. - This parameter can be a value of @ref SPI_LL_EC_POLARITY. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPolarity().*/ - - uint32_t ClockPhase; /*!< Specifies the clock active edge for the bit capture. - This parameter can be a value of @ref SPI_LL_EC_PHASE. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPhase().*/ - - uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) or by software using the SSI bit. - This parameter can be a value of @ref SPI_LL_EC_NSS_MODE. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetNSSMode().*/ - - uint32_t BaudRate; /*!< Specifies the BaudRate prescaler value which will be used to configure the transmit and receive SCK clock. - This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER. - @note The communication clock is derived from the master clock. The slave clock does not need to be set. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetBaudRatePrescaler().*/ - - uint32_t BitOrder; /*!< Specifies whether data transfers start from MSB or LSB bit. - This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferBitOrder().*/ - - uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. - This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION. - - This feature can be modified afterwards using unitary functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/ - - uint32_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. - This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF. - - This feature can be modified afterwards using unitary function @ref LL_SPI_SetCRCPolynomial().*/ - -} LL_SPI_InitTypeDef; - -/** - * @} - */ -#endif /* USE_FULL_LL_DRIVER */ - -/* Exported constants --------------------------------------------------------*/ -/** @defgroup SPI_LL_Exported_Constants SPI Exported Constants - * @{ - */ - -/** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines - * @brief Flags defines which can be used with LL_SPI_ReadReg function - * @{ - */ -#define LL_SPI_SR_RXNE SPI_SR_RXNE /*!< Rx buffer not empty flag */ -#define LL_SPI_SR_TXE SPI_SR_TXE /*!< Tx buffer empty flag */ -#define LL_SPI_SR_BSY SPI_SR_BSY /*!< Busy flag */ -#define LL_SPI_SR_CRCERR SPI_SR_CRCERR /*!< CRC error flag */ -#define LL_SPI_SR_MODF SPI_SR_MODF /*!< Mode fault flag */ -#define LL_SPI_SR_OVR SPI_SR_OVR /*!< Overrun flag */ -#define LL_SPI_SR_FRE SPI_SR_FRE /*!< TI mode frame format error flag */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_IT IT Defines - * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions - * @{ - */ -#define LL_SPI_CR2_RXNEIE SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ -#define LL_SPI_CR2_TXEIE SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ -#define LL_SPI_CR2_ERRIE SPI_CR2_ERRIE /*!< Error interrupt enable */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_MODE Operation Mode - * @{ - */ -#define LL_SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /*!< Master configuration */ -#define LL_SPI_MODE_SLAVE 0x00000000U /*!< Slave configuration */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_PROTOCOL Serial Protocol - * @{ - */ -#define LL_SPI_PROTOCOL_MOTOROLA 0x00000000U /*!< Motorola mode. Used as default value */ -#define LL_SPI_PROTOCOL_TI (SPI_CR2_FRF) /*!< TI mode */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_PHASE Clock Phase - * @{ - */ -#define LL_SPI_PHASE_1EDGE 0x00000000U /*!< First clock transition is the first data capture edge */ -#define LL_SPI_PHASE_2EDGE (SPI_CR1_CPHA) /*!< Second clock transition is the first data capture edge */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_POLARITY Clock Polarity - * @{ - */ -#define LL_SPI_POLARITY_LOW 0x00000000U /*!< Clock to 0 when idle */ -#define LL_SPI_POLARITY_HIGH (SPI_CR1_CPOL) /*!< Clock to 1 when idle */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler - * @{ - */ -#define LL_SPI_BAUDRATEPRESCALER_DIV2 0x00000000U /*!< BaudRate control equal to fPCLK/2 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV4 (SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/4 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV8 (SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/8 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/16 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV32 (SPI_CR1_BR_2) /*!< BaudRate control equal to fPCLK/32 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/64 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/128 */ -#define LL_SPI_BAUDRATEPRESCALER_DIV256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/256 */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order - * @{ - */ -#define LL_SPI_LSB_FIRST (SPI_CR1_LSBFIRST) /*!< Data is transmitted/received with the LSB first */ -#define LL_SPI_MSB_FIRST 0x00000000U /*!< Data is transmitted/received with the MSB first */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode - * @{ - */ -#define LL_SPI_FULL_DUPLEX 0x00000000U /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */ -#define LL_SPI_SIMPLEX_RX (SPI_CR1_RXONLY) /*!< Simplex Rx mode. Rx transfer only on 1 line */ -#define LL_SPI_HALF_DUPLEX_RX (SPI_CR1_BIDIMODE) /*!< Half-Duplex Rx mode. Rx transfer on 1 line */ -#define LL_SPI_HALF_DUPLEX_TX (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE) /*!< Half-Duplex Tx mode. Tx transfer on 1 line */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode - * @{ - */ -#define LL_SPI_NSS_SOFT (SPI_CR1_SSM) /*!< NSS managed internally. NSS pin not used and free */ -#define LL_SPI_NSS_HARD_INPUT 0x00000000U /*!< NSS pin used in Input. Only used in Master mode */ -#define LL_SPI_NSS_HARD_OUTPUT (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_DATAWIDTH Datawidth - * @{ - */ -#define LL_SPI_DATAWIDTH_4BIT (SPI_CR2_DS_0 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 4 bits */ -#define LL_SPI_DATAWIDTH_5BIT (SPI_CR2_DS_2) /*!< Data length for SPI transfer: 5 bits */ -#define LL_SPI_DATAWIDTH_6BIT (SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 6 bits */ -#define LL_SPI_DATAWIDTH_7BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 7 bits */ -#define LL_SPI_DATAWIDTH_8BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 8 bits */ -#define LL_SPI_DATAWIDTH_9BIT (SPI_CR2_DS_3) /*!< Data length for SPI transfer: 9 bits */ -#define LL_SPI_DATAWIDTH_10BIT (SPI_CR2_DS_3 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 10 bits */ -#define LL_SPI_DATAWIDTH_11BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 11 bits */ -#define LL_SPI_DATAWIDTH_12BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 12 bits */ -#define LL_SPI_DATAWIDTH_13BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2) /*!< Data length for SPI transfer: 13 bits */ -#define LL_SPI_DATAWIDTH_14BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 14 bits */ -#define LL_SPI_DATAWIDTH_15BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 15 bits */ -#define LL_SPI_DATAWIDTH_16BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 16 bits */ -/** - * @} - */ -#if defined(USE_FULL_LL_DRIVER) - -/** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation - * @{ - */ -#define LL_SPI_CRCCALCULATION_DISABLE 0x00000000U /*!< CRC calculation disabled */ -#define LL_SPI_CRCCALCULATION_ENABLE (SPI_CR1_CRCEN) /*!< CRC calculation enabled */ -/** - * @} - */ -#endif /* USE_FULL_LL_DRIVER */ - -/** @defgroup SPI_LL_EC_CRC_LENGTH CRC Length - * @{ - */ -#define LL_SPI_CRC_8BIT 0x00000000U /*!< 8-bit CRC length */ -#define LL_SPI_CRC_16BIT (SPI_CR1_CRCL) /*!< 16-bit CRC length */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_RX_FIFO_TH RX FIFO Threshold - * @{ - */ -#define LL_SPI_RX_FIFO_TH_HALF 0x00000000U /*!< RXNE event is generated if FIFO level is greater than or equel to 1/2 (16-bit) */ -#define LL_SPI_RX_FIFO_TH_QUARTER (SPI_CR2_FRXTH) /*!< RXNE event is generated if FIFO level is greater than or equel to 1/4 (8-bit) */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_RX_FIFO RX FIFO Level - * @{ - */ -#define LL_SPI_RX_FIFO_EMPTY 0x00000000U /*!< FIFO reception empty */ -#define LL_SPI_RX_FIFO_QUARTER_FULL (SPI_SR_FRLVL_0) /*!< FIFO reception 1/4 */ -#define LL_SPI_RX_FIFO_HALF_FULL (SPI_SR_FRLVL_1) /*!< FIFO reception 1/2 */ -#define LL_SPI_RX_FIFO_FULL (SPI_SR_FRLVL_1 | SPI_SR_FRLVL_0) /*!< FIFO reception full */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_TX_FIFO TX FIFO Level - * @{ - */ -#define LL_SPI_TX_FIFO_EMPTY 0x00000000U /*!< FIFO transmission empty */ -#define LL_SPI_TX_FIFO_QUARTER_FULL (SPI_SR_FTLVL_0) /*!< FIFO transmission 1/4 */ -#define LL_SPI_TX_FIFO_HALF_FULL (SPI_SR_FTLVL_1) /*!< FIFO transmission 1/2 */ -#define LL_SPI_TX_FIFO_FULL (SPI_SR_FTLVL_1 | SPI_SR_FTLVL_0) /*!< FIFO transmission full */ -/** - * @} - */ - -/** @defgroup SPI_LL_EC_DMA_PARITY DMA Parity - * @{ - */ -#define LL_SPI_DMA_PARITY_EVEN 0x00000000U /*!< Select DMA parity Even */ -#define LL_SPI_DMA_PARITY_ODD 0x00000001U /*!< Select DMA parity Odd */ - -/** - * @} - */ - -/** - * @} - */ - -/* Exported macro ------------------------------------------------------------*/ -/** @defgroup SPI_LL_Exported_Macros SPI Exported Macros - * @{ - */ - -/** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros - * @{ - */ - -/** - * @brief Write a value in SPI register - * @param __INSTANCE__ SPI Instance - * @param __REG__ Register to be written - * @param __VALUE__ Value to be written in the register - * @retval None - */ -#define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) - -/** - * @brief Read a value in SPI register - * @param __INSTANCE__ SPI Instance - * @param __REG__ Register to be read - * @retval Register value - */ -#define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) -/** - * @} - */ - -/** - * @} - */ - -/* Exported functions --------------------------------------------------------*/ -/** @defgroup SPI_LL_Exported_Functions SPI Exported Functions - * @{ - */ - -/** @defgroup SPI_LL_EF_Configuration Configuration - * @{ - */ - -/** - * @brief Enable SPI peripheral - * @rmtoll CR1 SPE LL_SPI_Enable - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR1, SPI_CR1_SPE); -} - -/** - * @brief Disable SPI peripheral - * @note When disabling the SPI, follow the procedure described in the Reference Manual. - * @rmtoll CR1 SPE LL_SPI_Disable - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); -} - -/** - * @brief Check if SPI peripheral is enabled - * @rmtoll CR1 SPE LL_SPI_IsEnabled - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabled(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL); -} - -/** - * @brief Set SPI operation mode to Master or Slave - * @note This bit should not be changed when communication is ongoing. - * @rmtoll CR1 MSTR LL_SPI_SetMode\n - * CR1 SSI LL_SPI_SetMode - * @param SPIx SPI Instance - * @param Mode This parameter can be one of the following values: - * @arg @ref LL_SPI_MODE_MASTER - * @arg @ref LL_SPI_MODE_SLAVE - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode); -} - -/** - * @brief Get SPI operation mode (Master or Slave) - * @rmtoll CR1 MSTR LL_SPI_GetMode\n - * CR1 SSI LL_SPI_GetMode - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_MODE_MASTER - * @arg @ref LL_SPI_MODE_SLAVE - */ -__STATIC_INLINE uint32_t LL_SPI_GetMode(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI)); -} - -/** - * @brief Set serial protocol used - * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. - * @rmtoll CR2 FRF LL_SPI_SetStandard - * @param SPIx SPI Instance - * @param Standard This parameter can be one of the following values: - * @arg @ref LL_SPI_PROTOCOL_MOTOROLA - * @arg @ref LL_SPI_PROTOCOL_TI - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) -{ - MODIFY_REG(SPIx->CR2, SPI_CR2_FRF, Standard); -} - -/** - * @brief Get serial protocol used - * @rmtoll CR2 FRF LL_SPI_GetStandard - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_PROTOCOL_MOTOROLA - * @arg @ref LL_SPI_PROTOCOL_TI - */ -__STATIC_INLINE uint32_t LL_SPI_GetStandard(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRF)); -} - -/** - * @brief Set clock phase - * @note This bit should not be changed when communication is ongoing. - * This bit is not used in SPI TI mode. - * @rmtoll CR1 CPHA LL_SPI_SetClockPhase - * @param SPIx SPI Instance - * @param ClockPhase This parameter can be one of the following values: - * @arg @ref LL_SPI_PHASE_1EDGE - * @arg @ref LL_SPI_PHASE_2EDGE - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase); -} - -/** - * @brief Get clock phase - * @rmtoll CR1 CPHA LL_SPI_GetClockPhase - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_PHASE_1EDGE - * @arg @ref LL_SPI_PHASE_2EDGE - */ -__STATIC_INLINE uint32_t LL_SPI_GetClockPhase(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA)); -} - -/** - * @brief Set clock polarity - * @note This bit should not be changed when communication is ongoing. - * This bit is not used in SPI TI mode. - * @rmtoll CR1 CPOL LL_SPI_SetClockPolarity - * @param SPIx SPI Instance - * @param ClockPolarity This parameter can be one of the following values: - * @arg @ref LL_SPI_POLARITY_LOW - * @arg @ref LL_SPI_POLARITY_HIGH - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity); -} - -/** - * @brief Get clock polarity - * @rmtoll CR1 CPOL LL_SPI_GetClockPolarity - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_POLARITY_LOW - * @arg @ref LL_SPI_POLARITY_HIGH - */ -__STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL)); -} - -/** - * @brief Set baud rate prescaler - * @note These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler. - * @rmtoll CR1 BR LL_SPI_SetBaudRatePrescaler - * @param SPIx SPI Instance - * @param BaudRate This parameter can be one of the following values: - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate); -} - -/** - * @brief Get baud rate prescaler - * @rmtoll CR1 BR LL_SPI_GetBaudRatePrescaler - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 - * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 - */ -__STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR)); -} - -/** - * @brief Set transfer bit order - * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. - * @rmtoll CR1 LSBFIRST LL_SPI_SetTransferBitOrder - * @param SPIx SPI Instance - * @param BitOrder This parameter can be one of the following values: - * @arg @ref LL_SPI_LSB_FIRST - * @arg @ref LL_SPI_MSB_FIRST - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder); -} - -/** - * @brief Get transfer bit order - * @rmtoll CR1 LSBFIRST LL_SPI_GetTransferBitOrder - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_LSB_FIRST - * @arg @ref LL_SPI_MSB_FIRST - */ -__STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST)); -} - -/** - * @brief Set transfer direction mode - * @note For Half-Duplex mode, Rx Direction is set by default. - * In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex. - * @rmtoll CR1 RXONLY LL_SPI_SetTransferDirection\n - * CR1 BIDIMODE LL_SPI_SetTransferDirection\n - * CR1 BIDIOE LL_SPI_SetTransferDirection - * @param SPIx SPI Instance - * @param TransferDirection This parameter can be one of the following values: - * @arg @ref LL_SPI_FULL_DUPLEX - * @arg @ref LL_SPI_SIMPLEX_RX - * @arg @ref LL_SPI_HALF_DUPLEX_RX - * @arg @ref LL_SPI_HALF_DUPLEX_TX - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection); -} - -/** - * @brief Get transfer direction mode - * @rmtoll CR1 RXONLY LL_SPI_GetTransferDirection\n - * CR1 BIDIMODE LL_SPI_GetTransferDirection\n - * CR1 BIDIOE LL_SPI_GetTransferDirection - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_FULL_DUPLEX - * @arg @ref LL_SPI_SIMPLEX_RX - * @arg @ref LL_SPI_HALF_DUPLEX_RX - * @arg @ref LL_SPI_HALF_DUPLEX_TX - */ -__STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)); -} - -/** - * @brief Set frame data width - * @rmtoll CR2 DS LL_SPI_SetDataWidth - * @param SPIx SPI Instance - * @param DataWidth This parameter can be one of the following values: - * @arg @ref LL_SPI_DATAWIDTH_4BIT - * @arg @ref LL_SPI_DATAWIDTH_5BIT - * @arg @ref LL_SPI_DATAWIDTH_6BIT - * @arg @ref LL_SPI_DATAWIDTH_7BIT - * @arg @ref LL_SPI_DATAWIDTH_8BIT - * @arg @ref LL_SPI_DATAWIDTH_9BIT - * @arg @ref LL_SPI_DATAWIDTH_10BIT - * @arg @ref LL_SPI_DATAWIDTH_11BIT - * @arg @ref LL_SPI_DATAWIDTH_12BIT - * @arg @ref LL_SPI_DATAWIDTH_13BIT - * @arg @ref LL_SPI_DATAWIDTH_14BIT - * @arg @ref LL_SPI_DATAWIDTH_15BIT - * @arg @ref LL_SPI_DATAWIDTH_16BIT - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) -{ - MODIFY_REG(SPIx->CR2, SPI_CR2_DS, DataWidth); -} - -/** - * @brief Get frame data width - * @rmtoll CR2 DS LL_SPI_GetDataWidth - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_DATAWIDTH_4BIT - * @arg @ref LL_SPI_DATAWIDTH_5BIT - * @arg @ref LL_SPI_DATAWIDTH_6BIT - * @arg @ref LL_SPI_DATAWIDTH_7BIT - * @arg @ref LL_SPI_DATAWIDTH_8BIT - * @arg @ref LL_SPI_DATAWIDTH_9BIT - * @arg @ref LL_SPI_DATAWIDTH_10BIT - * @arg @ref LL_SPI_DATAWIDTH_11BIT - * @arg @ref LL_SPI_DATAWIDTH_12BIT - * @arg @ref LL_SPI_DATAWIDTH_13BIT - * @arg @ref LL_SPI_DATAWIDTH_14BIT - * @arg @ref LL_SPI_DATAWIDTH_15BIT - * @arg @ref LL_SPI_DATAWIDTH_16BIT - */ -__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_DS)); -} - -/** - * @brief Set threshold of RXFIFO that triggers an RXNE event - * @rmtoll CR2 FRXTH LL_SPI_SetRxFIFOThreshold - * @param SPIx SPI Instance - * @param Threshold This parameter can be one of the following values: - * @arg @ref LL_SPI_RX_FIFO_TH_HALF - * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetRxFIFOThreshold(SPI_TypeDef *SPIx, uint32_t Threshold) -{ - MODIFY_REG(SPIx->CR2, SPI_CR2_FRXTH, Threshold); -} - -/** - * @brief Get threshold of RXFIFO that triggers an RXNE event - * @rmtoll CR2 FRXTH LL_SPI_GetRxFIFOThreshold - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_RX_FIFO_TH_HALF - * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER - */ -__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOThreshold(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRXTH)); -} - -/** - * @} - */ - -/** @defgroup SPI_LL_EF_CRC_Management CRC Management - * @{ - */ - -/** - * @brief Enable CRC - * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. - * @rmtoll CR1 CRCEN LL_SPI_EnableCRC - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR1, SPI_CR1_CRCEN); -} - -/** - * @brief Disable CRC - * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. - * @rmtoll CR1 CRCEN LL_SPI_DisableCRC - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN); -} - -/** - * @brief Check if CRC is enabled - * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. - * @rmtoll CR1 CRCEN LL_SPI_IsEnabledCRC - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL); -} - -/** - * @brief Set CRC Length - * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. - * @rmtoll CR1 CRCL LL_SPI_SetCRCWidth - * @param SPIx SPI Instance - * @param CRCLength This parameter can be one of the following values: - * @arg @ref LL_SPI_CRC_8BIT - * @arg @ref LL_SPI_CRC_16BIT - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetCRCWidth(SPI_TypeDef *SPIx, uint32_t CRCLength) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_CRCL, CRCLength); -} - -/** - * @brief Get CRC Length - * @rmtoll CR1 CRCL LL_SPI_GetCRCWidth - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_CRC_8BIT - * @arg @ref LL_SPI_CRC_16BIT - */ -__STATIC_INLINE uint32_t LL_SPI_GetCRCWidth(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CRCL)); -} - -/** - * @brief Set CRCNext to transfer CRC on the line - * @note This bit has to be written as soon as the last data is written in the SPIx_DR register. - * @rmtoll CR1 CRCNEXT LL_SPI_SetCRCNext - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT); -} - -/** - * @brief Set polynomial for CRC calculation - * @rmtoll CRCPR CRCPOLY LL_SPI_SetCRCPolynomial - * @param SPIx SPI Instance - * @param CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly) -{ - WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly); -} - -/** - * @brief Get polynomial for CRC calculation - * @rmtoll CRCPR CRCPOLY LL_SPI_GetCRCPolynomial - * @param SPIx SPI Instance - * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF - */ -__STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_REG(SPIx->CRCPR)); -} - -/** - * @brief Get Rx CRC - * @rmtoll RXCRCR RXCRC LL_SPI_GetRxCRC - * @param SPIx SPI Instance - * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF - */ -__STATIC_INLINE uint32_t LL_SPI_GetRxCRC(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_REG(SPIx->RXCRCR)); -} - -/** - * @brief Get Tx CRC - * @rmtoll TXCRCR TXCRC LL_SPI_GetTxCRC - * @param SPIx SPI Instance - * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF - */ -__STATIC_INLINE uint32_t LL_SPI_GetTxCRC(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_REG(SPIx->TXCRCR)); -} - -/** - * @} - */ - -/** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management - * @{ - */ - -/** - * @brief Set NSS mode - * @note LL_SPI_NSS_SOFT Mode is not used in SPI TI mode. - * @rmtoll CR1 SSM LL_SPI_SetNSSMode\n - * @rmtoll CR2 SSOE LL_SPI_SetNSSMode - * @param SPIx SPI Instance - * @param NSS This parameter can be one of the following values: - * @arg @ref LL_SPI_NSS_SOFT - * @arg @ref LL_SPI_NSS_HARD_INPUT - * @arg @ref LL_SPI_NSS_HARD_OUTPUT - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS) -{ - MODIFY_REG(SPIx->CR1, SPI_CR1_SSM, NSS); - MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U))); -} - -/** - * @brief Get NSS mode - * @rmtoll CR1 SSM LL_SPI_GetNSSMode\n - * @rmtoll CR2 SSOE LL_SPI_GetNSSMode - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_NSS_SOFT - * @arg @ref LL_SPI_NSS_HARD_INPUT - * @arg @ref LL_SPI_NSS_HARD_OUTPUT - */ -__STATIC_INLINE uint32_t LL_SPI_GetNSSMode(SPI_TypeDef *SPIx) -{ - register uint32_t Ssm = (READ_BIT(SPIx->CR1, SPI_CR1_SSM)); - register uint32_t Ssoe = (READ_BIT(SPIx->CR2, SPI_CR2_SSOE) << 16U); - return (Ssm | Ssoe); -} - -/** - * @brief Enable NSS pulse management - * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. - * @rmtoll CR2 NSSP LL_SPI_EnableNSSPulseMgt - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableNSSPulseMgt(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR2, SPI_CR2_NSSP); -} - -/** - * @brief Disable NSS pulse management - * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. - * @rmtoll CR2 NSSP LL_SPI_DisableNSSPulseMgt - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableNSSPulseMgt(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR2, SPI_CR2_NSSP); -} - -/** - * @brief Check if NSS pulse is enabled - * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. - * @rmtoll CR2 NSSP LL_SPI_IsEnabledNSSPulse - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledNSSPulse(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR2, SPI_CR2_NSSP) == (SPI_CR2_NSSP)) ? 1UL : 0UL); -} - -/** - * @} - */ - -/** @defgroup SPI_LL_EF_FLAG_Management FLAG Management - * @{ - */ - -/** - * @brief Check if Rx buffer is not empty - * @rmtoll SR RXNE LL_SPI_IsActiveFlag_RXNE - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL); -} - -/** - * @brief Check if Tx buffer is empty - * @rmtoll SR TXE LL_SPI_IsActiveFlag_TXE - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL); -} - -/** - * @brief Get CRC error flag - * @rmtoll SR CRCERR LL_SPI_IsActiveFlag_CRCERR - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL); -} - -/** - * @brief Get mode fault error flag - * @rmtoll SR MODF LL_SPI_IsActiveFlag_MODF - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL); -} - -/** - * @brief Get overrun error flag - * @rmtoll SR OVR LL_SPI_IsActiveFlag_OVR - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL); -} - -/** - * @brief Get busy flag - * @note The BSY flag is cleared under any one of the following conditions: - * -When the SPI is correctly disabled - * -When a fault is detected in Master mode (MODF bit set to 1) - * -In Master mode, when it finishes a data transmission and no new data is ready to be - * sent - * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between - * each data transfer. - * @rmtoll SR BSY LL_SPI_IsActiveFlag_BSY - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL); -} - -/** - * @brief Get frame format error flag - * @rmtoll SR FRE LL_SPI_IsActiveFlag_FRE - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_FRE(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->SR, SPI_SR_FRE) == (SPI_SR_FRE)) ? 1UL : 0UL); -} - -/** - * @brief Get FIFO reception Level - * @rmtoll SR FRLVL LL_SPI_GetRxFIFOLevel - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_RX_FIFO_EMPTY - * @arg @ref LL_SPI_RX_FIFO_QUARTER_FULL - * @arg @ref LL_SPI_RX_FIFO_HALF_FULL - * @arg @ref LL_SPI_RX_FIFO_FULL - */ -__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOLevel(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FRLVL)); -} - -/** - * @brief Get FIFO Transmission Level - * @rmtoll SR FTLVL LL_SPI_GetTxFIFOLevel - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_TX_FIFO_EMPTY - * @arg @ref LL_SPI_TX_FIFO_QUARTER_FULL - * @arg @ref LL_SPI_TX_FIFO_HALF_FULL - * @arg @ref LL_SPI_TX_FIFO_FULL - */ -__STATIC_INLINE uint32_t LL_SPI_GetTxFIFOLevel(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FTLVL)); -} - -/** - * @brief Clear CRC error flag - * @rmtoll SR CRCERR LL_SPI_ClearFlag_CRCERR - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR); -} - -/** - * @brief Clear mode fault error flag - * @note Clearing this flag is done by a read access to the SPIx_SR - * register followed by a write access to the SPIx_CR1 register - * @rmtoll SR MODF LL_SPI_ClearFlag_MODF - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx) -{ - __IO uint32_t tmpreg_sr; - tmpreg_sr = SPIx->SR; - (void) tmpreg_sr; - CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); -} - -/** - * @brief Clear overrun error flag - * @note Clearing this flag is done by a read access to the SPIx_DR - * register followed by a read access to the SPIx_SR register - * @rmtoll SR OVR LL_SPI_ClearFlag_OVR - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx) -{ - __IO uint32_t tmpreg; - tmpreg = SPIx->DR; - (void) tmpreg; - tmpreg = SPIx->SR; - (void) tmpreg; -} - -/** - * @brief Clear frame format error flag - * @note Clearing this flag is done by reading SPIx_SR register - * @rmtoll SR FRE LL_SPI_ClearFlag_FRE - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx) -{ - __IO uint32_t tmpreg; - tmpreg = SPIx->SR; - (void) tmpreg; -} - -/** - * @} - */ - -/** @defgroup SPI_LL_EF_IT_Management Interrupt Management - * @{ - */ - -/** - * @brief Enable error interrupt - * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). - * @rmtoll CR2 ERRIE LL_SPI_EnableIT_ERR - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR2, SPI_CR2_ERRIE); -} - -/** - * @brief Enable Rx buffer not empty interrupt - * @rmtoll CR2 RXNEIE LL_SPI_EnableIT_RXNE - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE); -} - -/** - * @brief Enable Tx buffer empty interrupt - * @rmtoll CR2 TXEIE LL_SPI_EnableIT_TXE - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR2, SPI_CR2_TXEIE); -} - -/** - * @brief Disable error interrupt - * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). - * @rmtoll CR2 ERRIE LL_SPI_DisableIT_ERR - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE); -} - -/** - * @brief Disable Rx buffer not empty interrupt - * @rmtoll CR2 RXNEIE LL_SPI_DisableIT_RXNE - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE); -} - -/** - * @brief Disable Tx buffer empty interrupt - * @rmtoll CR2 TXEIE LL_SPI_DisableIT_TXE - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE); -} - -/** - * @brief Check if error interrupt is enabled - * @rmtoll CR2 ERRIE LL_SPI_IsEnabledIT_ERR - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL); -} - -/** - * @brief Check if Rx buffer not empty interrupt is enabled - * @rmtoll CR2 RXNEIE LL_SPI_IsEnabledIT_RXNE - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL); -} - -/** - * @brief Check if Tx buffer empty interrupt - * @rmtoll CR2 TXEIE LL_SPI_IsEnabledIT_TXE - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL); -} - -/** - * @} - */ - -/** @defgroup SPI_LL_EF_DMA_Management DMA Management - * @{ - */ - -/** - * @brief Enable DMA Rx - * @rmtoll CR2 RXDMAEN LL_SPI_EnableDMAReq_RX - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); -} - -/** - * @brief Disable DMA Rx - * @rmtoll CR2 RXDMAEN LL_SPI_DisableDMAReq_RX - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); -} - -/** - * @brief Check if DMA Rx is enabled - * @rmtoll CR2 RXDMAEN LL_SPI_IsEnabledDMAReq_RX - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL); -} - -/** - * @brief Enable DMA Tx - * @rmtoll CR2 TXDMAEN LL_SPI_EnableDMAReq_TX - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) -{ - SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); -} - -/** - * @brief Disable DMA Tx - * @rmtoll CR2 TXDMAEN LL_SPI_DisableDMAReq_TX - * @param SPIx SPI Instance - * @retval None - */ -__STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx) -{ - CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); -} - -/** - * @brief Check if DMA Tx is enabled - * @rmtoll CR2 TXDMAEN LL_SPI_IsEnabledDMAReq_TX - * @param SPIx SPI Instance - * @retval State of bit (1 or 0). - */ -__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(SPI_TypeDef *SPIx) -{ - return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL); -} - -/** - * @brief Set parity of Last DMA reception - * @rmtoll CR2 LDMARX LL_SPI_SetDMAParity_RX - * @param SPIx SPI Instance - * @param Parity This parameter can be one of the following values: - * @arg @ref LL_SPI_DMA_PARITY_ODD - * @arg @ref LL_SPI_DMA_PARITY_EVEN - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetDMAParity_RX(SPI_TypeDef *SPIx, uint32_t Parity) -{ - MODIFY_REG(SPIx->CR2, SPI_CR2_LDMARX, (Parity << SPI_CR2_LDMARX_Pos)); -} - -/** - * @brief Get parity configuration for Last DMA reception - * @rmtoll CR2 LDMARX LL_SPI_GetDMAParity_RX - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_DMA_PARITY_ODD - * @arg @ref LL_SPI_DMA_PARITY_EVEN - */ -__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_RX(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMARX) >> SPI_CR2_LDMARX_Pos); -} - -/** - * @brief Set parity of Last DMA transmission - * @rmtoll CR2 LDMATX LL_SPI_SetDMAParity_TX - * @param SPIx SPI Instance - * @param Parity This parameter can be one of the following values: - * @arg @ref LL_SPI_DMA_PARITY_ODD - * @arg @ref LL_SPI_DMA_PARITY_EVEN - * @retval None - */ -__STATIC_INLINE void LL_SPI_SetDMAParity_TX(SPI_TypeDef *SPIx, uint32_t Parity) -{ - MODIFY_REG(SPIx->CR2, SPI_CR2_LDMATX, (Parity << SPI_CR2_LDMATX_Pos)); -} - -/** - * @brief Get parity configuration for Last DMA transmission - * @rmtoll CR2 LDMATX LL_SPI_GetDMAParity_TX - * @param SPIx SPI Instance - * @retval Returned value can be one of the following values: - * @arg @ref LL_SPI_DMA_PARITY_ODD - * @arg @ref LL_SPI_DMA_PARITY_EVEN - */ -__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_TX(SPI_TypeDef *SPIx) -{ - return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMATX) >> SPI_CR2_LDMATX_Pos); -} - -/** - * @brief Get the data register address used for DMA transfer - * @rmtoll DR DR LL_SPI_DMA_GetRegAddr - * @param SPIx SPI Instance - * @retval Address of data register - */ -__STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(SPI_TypeDef *SPIx) -{ - return (uint32_t) & (SPIx->DR); -} - -/** - * @} - */ - -/** @defgroup SPI_LL_EF_DATA_Management DATA Management - * @{ - */ - -/** - * @brief Read 8-Bits in the data register - * @rmtoll DR DR LL_SPI_ReceiveData8 - * @param SPIx SPI Instance - * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF - */ -__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx) -{ - return (uint8_t)(READ_REG(SPIx->DR)); -} - -/** - * @brief Read 16-Bits in the data register - * @rmtoll DR DR LL_SPI_ReceiveData16 - * @param SPIx SPI Instance - * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF - */ -__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx) -{ - return (uint16_t)(READ_REG(SPIx->DR)); -} - -/** - * @brief Write 8-Bits in the data register - * @rmtoll DR DR LL_SPI_TransmitData8 - * @param SPIx SPI Instance - * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF - * @retval None - */ -__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData) -{ -#if defined (__GNUC__) - __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR); - *spidr = TxData; -#else - *((__IO uint8_t *)&SPIx->DR) = TxData; -#endif -} - -/** - * @brief Write 16-Bits in the data register - * @rmtoll DR DR LL_SPI_TransmitData16 - * @param SPIx SPI Instance - * @param TxData Value between Min_Data=0x00 and Max_Data=0xFFFF - * @retval None - */ -__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) -{ -#if defined (__GNUC__) - __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR); - *spidr = TxData; -#else - SPIx->DR = TxData; -#endif -} - -/** - * @} - */ -#if defined(USE_FULL_LL_DRIVER) -/** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions - * @{ - */ - -ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx); -ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct); -void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct); - -/** - * @} - */ -#endif /* USE_FULL_LL_DRIVER */ -/** - * @} - */ - -/** - * @} - */ - -#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* STM32L4xx_LL_SPI_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/