From 648adb8d87572ef2a2f6284e9f43bb400cc46b70 Mon Sep 17 00:00:00 2001 From: "Peter D. Gray" Date: Wed, 12 May 2021 10:02:58 -0400 Subject: [PATCH] working psram --- stm32/mk4-bootloader/.gitignore | 3 +- stm32/mk4-bootloader/Makefile | 29 +- stm32/mk4-bootloader/ae.c | 4 + stm32/mk4-bootloader/console.c | 495 +++ stm32/mk4-bootloader/dispatch.c | 14 - stm32/mk4-bootloader/faster_sha256.c | 16 +- stm32/mk4-bootloader/hal | 1 + stm32/mk4-bootloader/hal_glue.c | 45 + stm32/mk4-bootloader/psram.c | 144 +- stm32/mk4-bootloader/psram.h | 3 + stm32/mk4-bootloader/sflash.c | 1 + stm32/mk4-bootloader/stm32l4xx_hal_conf.h | 367 +- stm32/mk4-bootloader/stm32l4xx_hal_hash.c | 1795 +++++++--- stm32/mk4-bootloader/stm32l4xx_hal_hash_ex.c | 939 ----- stm32/mk4-bootloader/stm32l4xx_hal_ospi.c | 3213 ++++++++++++++++++ stm32/mk4-bootloader/stm32l4xx_hal_qspi.c | 2356 ------------- stm32/mk4-bootloader/stm32l4xx_hal_rcc.c | 999 ++++-- stm32/mk4-bootloader/stm32l4xx_hal_rcc_ex.c | 2146 ++++++++---- stm32/mk4-bootloader/stm32l4xx_hal_usart.c | 2769 +++++++++++---- stm32/mk4-bootloader/storage.c | 18 +- 20 files changed, 9699 insertions(+), 5658 deletions(-) create mode 160000 stm32/mk4-bootloader/hal create mode 100644 stm32/mk4-bootloader/hal_glue.c delete mode 100644 stm32/mk4-bootloader/stm32l4xx_hal_hash_ex.c create mode 100644 stm32/mk4-bootloader/stm32l4xx_hal_ospi.c delete mode 100644 stm32/mk4-bootloader/stm32l4xx_hal_qspi.c diff --git a/stm32/mk4-bootloader/.gitignore b/stm32/mk4-bootloader/.gitignore index 40462d73..3a8b172d 100644 --- a/stm32/mk4-bootloader/.gitignore +++ b/stm32/mk4-bootloader/.gitignore @@ -8,4 +8,5 @@ version-full.txt version.txt # dev shortcut -hal +H +I diff --git a/stm32/mk4-bootloader/Makefile b/stm32/mk4-bootloader/Makefile index 9e9cf55a..3982feea 100644 --- a/stm32/mk4-bootloader/Makefile +++ b/stm32/mk4-bootloader/Makefile @@ -27,11 +27,14 @@ TARGET_NAME = bootloader OBJS += startup.o assets/screens.o OBJS += enable.o dispatch.o verify.o oled.o clocks.o storage.o constant_time.o rng.o ae.o OBJS += delay.o gpio.o pins.o version.o sflash.o console.o psram.o +OBJS += faster_sha256.o micro-ecc/uECC.o hal_glue.o + +# Have to have copies of these because the DMA and interrupt stuff +# needs to be commented-out. OBJS += stm32l4xx_hal_firewall.o stm32l4xx_hal_gpio.o stm32l4xx_hal_spi.o OBJS += stm32l4xx_hal_rcc.o stm32l4xx_hal_rcc_ex.o -OBJS += faster_sha256.o micro-ecc/uECC.o -OBJS += stm32l4xx_hal_hash.o stm32l4xx_hal_hash_ex.o stm32l4xx_hal_usart.o -OBJS += stm32l4xx_hal_qspi.o +OBJS += stm32l4xx_hal_hash.o # stm32l4xx_hal_usart.o +OBJS += stm32l4xx_hal_ospi.o #OBJS = $(addsuffix .o, $(basename $(C_SRCS) $(ASM_SRCS))) @@ -39,7 +42,7 @@ OBJS += stm32l4xx_hal_qspi.o micro-ecc/uECC.o: c_flags += -Wno-undef -Wno-redundant-decls # Headers for chip stuff (assumes STM32L476 chip) -STM32LIB_PATH = ../../external/micropython/lib +#STM32LIB_PATH = ../../external/micropython/lib # Where we will end up in the memory map (at start of flash) # - reserve last 8k flash page for other purposes @@ -62,7 +65,7 @@ BL_SRAM_SIZE = 0x00001c00 CFLAGS = -I. -Wall --std=gnu99 -Os -g3 \ -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mtune=cortex-m4 \ -ffunction-sections -fdata-sections \ - -mcpu=cortex-m4 -DMCU_SERIES_L4 -DSTM32L4A6xx + -mcpu=cortex-m4 -DMCU_SERIES_L4 -DSTM32L4S5xx # -flto -fdata-sections -ffunction-sections -funsigned-char -funsigned-bitfields @@ -72,9 +75,12 @@ CFLAGS += -D BL_NVROM_BASE=$(BL_NVROM_BASE) -D BL_NVROM_SIZE=$(BL_NVROM_SIZE) CFLAGS += -D BL_SRAM_BASE=$(BL_SRAM_BASE) -D BL_SRAM_SIZE=$(BL_SRAM_SIZE) # Header file search path -INC_PATHS = $(STM32LIB_PATH)/stm32lib/CMSIS/STM32L4xx/Include \ - $(STM32LIB_PATH)/stm32lib/STM32L4xx_HAL_Driver/Inc \ - $(STM32LIB_PATH)/cmsis/inc +#INC_PATHS = $(STM32LIB_PATH)/stm32lib/CMSIS/STM32L4xx/Include \ +# $(STM32LIB_PATH)/stm32lib/STM32L4xx_HAL_Driver/Inc \ +# $(STM32LIB_PATH)/cmsis/inc +INC_PATHS = hal/Drivers/CMSIS/Device/ST/STM32L4xx/Include \ + hal/Drivers/STM32L4xx_HAL_Driver/Inc \ + hal/Drivers/CMSIS/Include CFLAGS += $(foreach INC,$(INC_PATHS),-I$(INC)) @@ -218,5 +224,10 @@ xxx: @echo OBJS = $(OBJS) tags: - ctags -f .tags *.[ch] -R $(INC_PATHS) $(STM32LIB_PATH)/stm32lib/STM32L4xx_HAL_Driver/*/*.h + ctags -f .tags *.[ch] -R $(INC_PATHS) \ + hal/Drivers/STM32L4xx_HAL_Driver/Src/*.c + + #$(STM32LIB_PATH)/stm32lib/STM32L4xx_HAL_Driver/*/*.h + +# EOF diff --git a/stm32/mk4-bootloader/ae.c b/stm32/mk4-bootloader/ae.c index 6f657a1e..b262b80d 100644 --- a/stm32/mk4-bootloader/ae.c +++ b/stm32/mk4-bootloader/ae.c @@ -353,9 +353,13 @@ ae_setup(void) MY_UART->CR1 = 0; MY_UART->CR1 = 0x1000002d & ~(0 | USART_CR1_PEIE +#ifdef USART_CR1_TXEIE | USART_CR1_TXEIE +#endif | USART_CR1_TCIE +#ifdef USART_CR1_RXNEIE | USART_CR1_RXNEIE +#endif | USART_CR1_IDLEIE | USART_CR1_OVER8 | USART_CR1_UE); diff --git a/stm32/mk4-bootloader/console.c b/stm32/mk4-bootloader/console.c index 16fa87bf..c0908809 100644 --- a/stm32/mk4-bootloader/console.c +++ b/stm32/mk4-bootloader/console.c @@ -179,4 +179,499 @@ hex_dump(const void *d, int len) } } +// Copied parts of stm32l4xx_hal_usart.c + +#if defined(USART_CR1_FIFOEN) +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8 | \ + USART_CR1_FIFOEN )) /*!< USART CR1 fields of parameters set by USART_SetConfig API */ + +#define USART_CR2_FIELDS ((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ + USART_CR2_LBCL | USART_CR2_STOP | USART_CR2_SLVEN | \ + USART_CR2_DIS_NSS)) /*!< USART CR2 fields of parameters set by USART_SetConfig API */ + +#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< USART or USART CR3 fields of parameters set by USART_SetConfig API */ +#else +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) /*!< USART CR1 fields of parameters set by USART_SetConfig API */ +#define USART_CR2_FIELDS ((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | \ + USART_CR2_CLKEN | USART_CR2_LBCL | USART_CR2_STOP)) /*!< USART CR2 fields of parameters set by USART_SetConfig API */ +#endif /* USART_CR1_FIFOEN */ + +#define USART_BRR_MIN 0x10U /* USART BRR minimum authorized value */ +#define USART_BRR_MAX 0xFFFFU /* USART BRR maximum authorized value */ +#define USART_TEACK_REACK_TIMEOUT 1000U /*!< USART TX or RX enable acknowledge time-out value */ +#define USART_DUMMY_DATA ((uint16_t) 0xFFFF) /*!< USART transmitted dummy data */ + +/** + * @brief Handle USART Communication Timeout. + * @param husart USART handle. + * @param Flag Specifies the USART flag to check. + * @param Status the Flag status (SET or RESET). + * @param Tickstart Tick start value + * @param Timeout timeout duration. + * @retval HAL status + */ +static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief Configure the USART peripheral. + * @param husart USART handle. + * @retval HAL status + */ +static HAL_StatusTypeDef USART_SetConfig(USART_HandleTypeDef *husart) +{ + uint32_t tmpreg; + USART_ClockSourceTypeDef clocksource; + HAL_StatusTypeDef ret = HAL_OK; + uint16_t brrtemp; + uint32_t usartdiv = 0x00000000; + uint32_t pclk; + + /* Check the parameters */ + assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity)); + assert_param(IS_USART_PHASE(husart->Init.CLKPhase)); + assert_param(IS_USART_LASTBIT(husart->Init.CLKLastBit)); + assert_param(IS_USART_BAUDRATE(husart->Init.BaudRate)); + assert_param(IS_USART_WORD_LENGTH(husart->Init.WordLength)); + assert_param(IS_USART_STOPBITS(husart->Init.StopBits)); + assert_param(IS_USART_PARITY(husart->Init.Parity)); + assert_param(IS_USART_MODE(husart->Init.Mode)); +#if defined(USART_PRESC_PRESCALER) + assert_param(IS_USART_PRESCALER(husart->Init.ClockPrescaler)); +#endif /* USART_PRESC_PRESCALER */ + + /*-------------------------- USART CR1 Configuration -----------------------*/ + /* Clear M, PCE, PS, TE and RE bits and configure + * the USART Word Length, Parity and Mode: + * set the M bits according to husart->Init.WordLength value + * set PCE and PS bits according to husart->Init.Parity value + * set TE and RE bits according to husart->Init.Mode value + * force OVER8 to 1 to allow to reach the maximum speed (Fclock/8) */ + tmpreg = (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode | USART_CR1_OVER8; + MODIFY_REG(husart->Instance->CR1, USART_CR1_FIELDS, tmpreg); + + /*---------------------------- USART CR2 Configuration ---------------------*/ + /* Clear and configure the USART Clock, CPOL, CPHA, LBCL STOP and SLVEN bits: + * set CPOL bit according to husart->Init.CLKPolarity value + * set CPHA bit according to husart->Init.CLKPhase value + * set LBCL bit according to husart->Init.CLKLastBit value (used in SPI master mode only) + * set STOP[13:12] bits according to husart->Init.StopBits value */ + tmpreg = (uint32_t)(USART_CLOCK_ENABLE); + tmpreg |= (uint32_t)husart->Init.CLKLastBit; + tmpreg |= ((uint32_t)husart->Init.CLKPolarity | (uint32_t)husart->Init.CLKPhase); + tmpreg |= (uint32_t)husart->Init.StopBits; + MODIFY_REG(husart->Instance->CR2, USART_CR2_FIELDS, tmpreg); + +#if defined(USART_PRESC_PRESCALER) + /*-------------------------- USART PRESC Configuration -----------------------*/ + /* Configure + * - USART Clock Prescaler : set PRESCALER according to husart->Init.ClockPrescaler value */ + MODIFY_REG(husart->Instance->PRESC, USART_PRESC_PRESCALER, husart->Init.ClockPrescaler); +#endif /* USART_PRESC_PRESCALER */ + + /*-------------------------- USART BRR Configuration -----------------------*/ + /* BRR is filled-up according to OVER8 bit setting which is forced to 1 */ + USART_GETCLOCKSOURCE(husart, clocksource); + + switch (clocksource) + { + case USART_CLOCKSOURCE_PCLK1: + pclk = HAL_RCC_GetPCLK1Freq(); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + break; + case USART_CLOCKSOURCE_PCLK2: + pclk = HAL_RCC_GetPCLK2Freq(); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + break; + case USART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(HSI_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(HSI_VALUE, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + break; + case USART_CLOCKSOURCE_SYSCLK: + pclk = HAL_RCC_GetSysClockFreq(); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + break; + case USART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(LSE_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(LSE_VALUE, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + break; + default: + ret = HAL_ERROR; + break; + } + + /* USARTDIV must be greater than or equal to 0d16 and smaller than or equal to ffff */ + if ((usartdiv >= USART_BRR_MIN) && (usartdiv <= USART_BRR_MAX)) + { + brrtemp = (uint16_t)(usartdiv & 0xFFF0U); + brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); + husart->Instance->BRR = brrtemp; + } + else + { + ret = HAL_ERROR; + } + +#if defined(USART_CR1_FIFOEN) + /* Initialize the number of data to process during RX/TX ISR execution */ + husart->NbTxDataToProcess = 1U; + husart->NbRxDataToProcess = 1U; +#endif /* USART_CR1_FIFOEN */ + + /* Clear ISR function pointers */ + husart->RxISR = NULL; + husart->TxISR = NULL; + + return ret; +} + +/** + * @brief Check the USART Idle State. + * @param husart USART handle. + * @retval HAL status + */ +static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart) +{ + uint32_t tickstart; + + /* Initialize the USART ErrorCode */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + /* Check if the Transmitter is enabled */ + if ((husart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) + { + /* Wait until TEACK flag is set */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_ISR_TEACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + /* Check if the Receiver is enabled */ + if ((husart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) + { + /* Wait until REACK flag is set */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_ISR_REACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + + /* Initialize the USART state*/ + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; +} + + + +/** + * @brief Initialize the USART mode according to the specified + * parameters in the USART_InitTypeDef and initialize the associated handle. + * @param husart USART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart) +{ + /* Check the USART handle allocation */ + if (husart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_USART_INSTANCE(husart->Instance)); + + if (husart->State == HAL_USART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + husart->Lock = HAL_UNLOCKED; + } + + husart->State = HAL_USART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_USART_DISABLE(husart); + + /* Set the Usart Communication parameters */ + if (USART_SetConfig(husart) == HAL_ERROR) + { + return HAL_ERROR; + } + + /* In Synchronous mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register + - HDSEL, SCEN and IREN bits in the USART_CR3 register.*/ + husart->Instance->CR2 &= ~USART_CR2_LINEN; + husart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN); + + /* Enable the Peripheral */ + __HAL_USART_ENABLE(husart); + + /* TEACK and/or REACK to check before moving husart->State to Ready */ + return (USART_CheckIdleState(husart)); +} + +/** + * @brief Simplex send an amount of data in blocking mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pTxData. + * @param husart USART handle. + * @param pTxData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent. + * @param Timeout Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size, uint32_t Timeout) +{ + uint8_t *ptxdata8bits; + uint16_t *ptxdata16bits; + uint32_t tickstart; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(husart); + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_TX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + husart->TxXferSize = Size; + husart->TxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + ptxdata8bits = NULL; + ptxdata16bits = (uint16_t *) pTxData; + } + else + { + ptxdata8bits = pTxData; + ptxdata16bits = NULL; + } + + /* Check the remaining data to be sent */ + while (husart->TxXferCount > 0U) + { + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if (ptxdata8bits == NULL) + { + husart->Instance->TDR = (uint16_t)(*ptxdata16bits & 0x01FFU); + ptxdata16bits++; + } + else + { + husart->Instance->TDR = (uint8_t)(*ptxdata8bits & 0xFFU); + ptxdata8bits++; + } + + husart->TxXferCount--; + } + + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear Transmission Complete Flag */ + __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF); + + /* Clear overrun flag and discard the received data */ + __HAL_USART_CLEAR_OREFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + + /* At end of Tx process, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + + +/** + * @brief Receive an amount of data in blocking mode. + * @note To receive synchronous data, dummy data are simultaneously transmitted. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pRxData. + * @param husart USART handle. + * @param pRxData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @param Timeout Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout) +{ + uint8_t *prxdata8bits; + uint16_t *prxdata16bits; + uint16_t uhMask; + uint32_t tickstart; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(husart); + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_RX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + husart->RxXferSize = Size; + husart->RxXferCount = Size; + + /* Computation of USART mask to apply to RDR register */ + USART_MASK_COMPUTATION(husart); + uhMask = husart->Mask; + + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + prxdata8bits = NULL; + prxdata16bits = (uint16_t *) pRxData; + } + else + { + prxdata8bits = pRxData; + prxdata16bits = NULL; + } + + /* as long as data have to be received */ + while (husart->RxXferCount > 0U) + { +#if defined(USART_CR2_SLVEN) + if (husart->SlaveMode == USART_SLAVEMODE_DISABLE) +#endif /* USART_CR2_SLVEN */ + { + /* Wait until TXE flag is set to send dummy byte in order to generate the + * clock for the slave to send data. + * Whatever the frame length (7, 8 or 9-bit long), the same dummy value + * can be written for all the cases. */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x0FF); + } + + /* Wait for RXNE Flag */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (prxdata8bits == NULL) + { + *prxdata16bits = (uint16_t)(husart->Instance->RDR & uhMask); + prxdata16bits++; + } + else + { + *prxdata8bits = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU)); + prxdata8bits++; + } + + husart->RxXferCount--; + + } + +#if defined(USART_CR2_SLVEN) + /* Clear SPI slave underrun flag and discard transmit data */ + if (husart->SlaveMode == USART_SLAVEMODE_ENABLE) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR2_SLVEN */ + + /* At end of Rx process, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + + + // EOF diff --git a/stm32/mk4-bootloader/dispatch.c b/stm32/mk4-bootloader/dispatch.c index c92ffcb3..3edc39c9 100644 --- a/stm32/mk4-bootloader/dispatch.c +++ b/stm32/mk4-bootloader/dispatch.c @@ -102,10 +102,6 @@ wipe_all_sram(void) { const uint32_t noise = 0xdeadbeef; -// strange omission from HAL headers -#define SRAM3_BASE ((uint32_t)0x20040000U) -#define SRAM3_SIZE ((uint32_t)0x00060000U) - // wipe all of SRAM (except our own memory, which was already wiped) memset4((void *)(SRAM1_BASE+BL_SRAM_SIZE), noise, SRAM1_SIZE_MAX - BL_SRAM_SIZE); memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE); @@ -802,14 +798,4 @@ fail: return rv; } -// HAL support garbage -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; -const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \ - 4000000, 8000000, 16000000, 24000000, 32000000, 48000000}; -uint32_t SystemCoreClock; - -// TODO: cleanup HAL stuff to not use this -uint32_t HAL_GetTick(void) { return 53; } - // EOF diff --git a/stm32/mk4-bootloader/faster_sha256.c b/stm32/mk4-bootloader/faster_sha256.c index 78adaf75..4e6fe8c3 100644 --- a/stm32/mk4-bootloader/faster_sha256.c +++ b/stm32/mk4-bootloader/faster_sha256.c @@ -7,6 +7,16 @@ #include "stm32l4xx_hal.h" #include +// so we don't need stm32l4xx_hal_hash_ex.c +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA256); +} +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256); +} + void sha256_init(SHA256_CTX *ctx) { memset(ctx, 0, sizeof(SHA256_CTX)); @@ -88,14 +98,13 @@ sha256_single(const uint8_t data[], uint32_t len, uint8_t digest[32]) //#pragma GCC push_options //#pragma GCC optimize ("O0") - void sha256_selftest(void) { SHA256_CTX ctx; uint8_t md[32], md2[32]; - puts("sha256 selftest start"); + puts2("sha256 selftest: "); sha256_single((uint8_t *)"a", 1, md); ASSERT(md[0] == 0xca); @@ -129,9 +138,8 @@ sha256_selftest(void) } } - puts("sha256 selftest PASS"); + puts("PASS"); } - #endif // EOF diff --git a/stm32/mk4-bootloader/hal b/stm32/mk4-bootloader/hal new file mode 160000 index 00000000..5e1553e0 --- /dev/null +++ b/stm32/mk4-bootloader/hal @@ -0,0 +1 @@ +Subproject commit 5e1553e07706491bd11f4edd304e093b6e4b83a4 diff --git a/stm32/mk4-bootloader/hal_glue.c b/stm32/mk4-bootloader/hal_glue.c new file mode 100644 index 00000000..3be4cdf4 --- /dev/null +++ b/stm32/mk4-bootloader/hal_glue.c @@ -0,0 +1,45 @@ +#include "stm32l4xx_hal.h" + +// HAL support garbage +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; +const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \ + 4000000, 8000000, 16000000, 24000000, 32000000, 48000000}; +uint32_t SystemCoreClock; + +// TODO: cleanup HAL stuff to not use this +uint32_t HAL_GetTick(void) { return 53; } +uint32_t uwTickPrio = 0; /* (1UL << __NVIC_PRIO_BITS); * Invalid priority */ + +// unwanted junk from stm32l4xx_hal_rcc.c +HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) { return 0; } + + +/** + * @brief Return Voltage Scaling Range. + * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_SCALE1 or PWR_REGULATOR_VOLTAGE_SCALE2 + * or PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when applicable) + */ +uint32_t HAL_PWREx_GetVoltageRange(void) +{ +#if defined(PWR_CR5_R1MODE) + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + return PWR_REGULATOR_VOLTAGE_SCALE2; + } + else if (READ_BIT(PWR->CR5, PWR_CR5_R1MODE) == PWR_CR5_R1MODE) + { + /* PWR_CR5_R1MODE bit set means that Range 1 Boost is disabled */ + return PWR_REGULATOR_VOLTAGE_SCALE1; + } + else + { + return PWR_REGULATOR_VOLTAGE_SCALE1_BOOST; + } +#else + return (PWR->CR1 & PWR_CR1_VOS); +#endif +} + + + diff --git a/stm32/mk4-bootloader/psram.c b/stm32/mk4-bootloader/psram.c index 0255befc..a948ab3d 100644 --- a/stm32/mk4-bootloader/psram.c +++ b/stm32/mk4-bootloader/psram.c @@ -6,23 +6,29 @@ * */ #include "psram.h" +#include "oled.h" +#include "assets/screens.h" #include #include "delay.h" #include "stm32l4xx_hal.h" #include "console.h" -static QSPI_HandleTypeDef qh; +uint8_t psram_chip_eid[8]; + +static OSPI_HandleTypeDef qh; void psram_setup(void) { + // Using OSPI1 block + // enable clocks - __HAL_RCC_QSPI_CLK_ENABLE(); + __HAL_RCC_OSPI1_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); // reset module - __HAL_RCC_QSPI_FORCE_RESET(); - __HAL_RCC_QSPI_RELEASE_RESET(); + __HAL_RCC_OSPI1_FORCE_RESET(); + __HAL_RCC_OSPI1_RELEASE_RESET(); // configure pins: Port E PE10-PE15 GPIO_InitTypeDef setup = { @@ -30,74 +36,124 @@ psram_setup(void) .Mode = GPIO_MODE_AF_PP, // not sure .Pull = GPIO_NOPULL, // not sure .Speed = GPIO_SPEED_FREQ_VERY_HIGH, - .Alternate = GPIO_AF10_QUADSPI, + .Alternate = GPIO_AF10_OCTOSPIM_P1, }; HAL_GPIO_Init(GPIOE, &setup); #if 0 - QUADSPI_TypeDef *Instance; /* QSPI registers base address */ - QSPI_InitTypeDef Init; /* QSPI communication parameters */ - uint8_t *pTxBuffPtr; /* Pointer to QSPI Tx transfer Buffer */ - __IO uint32_t TxXferSize; /* QSPI Tx Transfer size */ - __IO uint32_t TxXferCount; /* QSPI Tx Transfer Counter */ - uint8_t *pRxBuffPtr; /* Pointer to QSPI Rx transfer Buffer */ - __IO uint32_t RxXferSize; /* QSPI Rx Transfer size */ - __IO uint32_t RxXferCount; /* QSPI Rx Transfer Counter */ - DMA_HandleTypeDef *hdma; /* QSPI Rx/Tx DMA Handle parameters */ - __IO HAL_LockTypeDef Lock; /* Locking object */ - __IO HAL_QSPI_StateTypeDef State; /* QSPI communication state */ - __IO uint32_t ErrorCode; /* QSPI Error code */ - uint32_t Timeout; /* Timeout for the QSPI memory access */ + uint32_t FifoThreshold; /*!< This is the threshold used by the Peripheral to generate the interrupt + indicating that data are available in reception or free place + is available in transmission. + This parameter can be a value between 1 and 32 */ + uint32_t DualQuad; /*!< It enables or not the dual-quad mode which allow to access up to + quad mode on two different devices to increase the throughput. + This parameter can be a value of @ref OSPI_DualQuad */ + uint32_t MemoryType; /*!< It indicates the external device type connected to the OSPI. + This parameter can be a value of @ref OSPI_MemoryType */ + uint32_t DeviceSize; /*!< It defines the size of the external device connected to the OSPI, + it corresponds to the number of address bits required to access + the external device. + This parameter can be a value between 1 and 32 */ + uint32_t ChipSelectHighTime; /*!< It defines the minimun number of clocks which the chip select + must remain high between commands. + This parameter can be a value between 1 and 8 */ + uint32_t FreeRunningClock; /*!< It enables or not the free running clock. + This parameter can be a value of @ref OSPI_FreeRunningClock */ + uint32_t ClockMode; /*!< It indicates the level of clock when the chip select is released. + This parameter can be a value of @ref OSPI_ClockMode */ + uint32_t ClockPrescaler; /*!< It specifies the prescaler factor used for generating + the external clock based on the AHB clock. + This parameter can be a value between 1 and 256 */ + uint32_t SampleShifting; /*!< It allows to delay to 1/2 cycle the data sampling in order + to take in account external signal delays. + This parameter can be a value of @ref OSPI_SampleShifting */ + uint32_t DelayHoldQuarterCycle; /*!< It allows to hold to 1/4 cycle the data. + This parameter can be a value of @ref OSPI_DelayHoldQuarterCycle */ + uint32_t ChipSelectBoundary; /*!< It enables the transaction boundary feature and + defines the boundary of bytes to release the chip select. + This parameter can be a value between 0 and 31 */ + uint32_t DelayBlockBypass; /*!< It enables the delay block bypass, so the sampling is not affected + by the delay block. + This parameter can be a value of @ref OSPI_DelayBlockBypass */ +#if defined (OCTOSPI_DCR3_MAXTRAN) + uint32_t MaxTran; /*!< It enables the communication regulation feature. The chip select is + released every MaxTran+1 bytes when the other OctoSPI request the access + to the bus. + This parameter can be a value between 0 and 255 */ +#endif +#if defined (OCTOSPI_DCR4_REFRESH) + uint32_t Refresh; /*!< It enables the refresh rate feature. The chip select is released every + Refresh+1 clock cycles. + This parameter can be a value between 0 and 0xFFFFFFFF */ +#endif #endif memset(&qh, 0, sizeof(qh)); - qh.Instance = QUADSPI; - qh.Init.ClockPrescaler = 64; // conservative starting value - qh.Init.FifoThreshold = 4; // indirect mode only - qh.Init.FlashSize = 23; - qh.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_8_CYCLE; // maxed for now - qh.Init.ClockMode = QSPI_CLOCK_MODE_0; // low clock between ops - qh.Init.FlashID = QSPI_FLASH_ID_1; - qh.Init.DualFlash = QSPI_DUALFLASH_DISABLE; + qh.Instance = OCTOSPI1; + qh.Init.FifoThreshold = 4; // ?? + qh.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE; + qh.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON; // seems like 8-bit mode stuff? + qh.Init.DeviceSize = 23; + qh.Init.ChipSelectHighTime = 8; // maxed out to start + qh.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE; + qh.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0; // low clock between ops + qh.Init.ClockPrescaler = 16; // prescaller, decrease me + + qh.Init.ChipSelectBoundary = 0; // set for 1024-byte block size? + // module init - HAL_StatusTypeDef rv = HAL_QSPI_Init(&qh); + HAL_StatusTypeDef rv = HAL_OSPI_Init(&qh); ASSERT(rv == HAL_OK); // do some SPI commands first - QSPI_CommandTypeDef cmd = { + // Read Electronic ID + // - length not clear from datasheet, but bits repeat after 8 bytes + + OSPI_RegularCmdTypeDef cmd = { + .OperationType = HAL_OSPI_OPTYPE_COMMON_CFG, .Instruction = 0x9f, // "read ID" command - .InstructionMode = QSPI_INSTRUCTION_1_LINE, + .InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE, .Address = 0, // dont care - .AddressSize = QSPI_ADDRESS_24_BITS, - .AddressMode = QSPI_ADDRESS_1_LINE, - .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE, + .AddressSize = HAL_OSPI_ADDRESS_24_BITS, + .AddressMode = HAL_OSPI_ADDRESS_1_LINE, + .AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE, .DummyCycles = 0, - .DataMode = QSPI_DATA_1_LINE, - .NbData = 8, // how much to read in bytes - .DdrMode = QSPI_DDR_MODE_DISABLE, // normal - .SIOOMode = QSPI_SIOO_INST_EVERY_CMD, // normal + .DataMode = HAL_OSPI_DATA_1_LINE, + .NbData = sizeof(psram_chip_eid), // how much to read in bytes }; // Start "Indirection functional mode" - uint8_t buf[8]; - rv = HAL_QSPI_Command(&qh, &cmd, HAL_MAX_DELAY); - ASSERT(rv == HAL_OK); + rv = HAL_OSPI_Command(&qh, &cmd, HAL_MAX_DELAY); + if(rv != HAL_OK) goto fail; - rv = HAL_QSPI_Receive(&qh, buf, HAL_MAX_DELAY); + rv = HAL_OSPI_Receive(&qh, psram_chip_eid, HAL_MAX_DELAY); + if(rv != HAL_OK) goto fail; - puts2("HAL_QSPI_Receive "); puthex2(rv); putchar('\n'); - hex_dump(buf, sizeof(buf)); + puts2("PSRAM EID: "); + hex_dump(psram_chip_eid, sizeof(psram_chip_eid)); + ASSERT(psram_chip_eid[0] == 0x0d); + ASSERT(psram_chip_eid[1] == 0x5d); #if 0 - QSPI_MemoryMappedTypeDef mmap = { + OSPI_MemoryMappedTypeDef mmap = { }; - rv = HAL_QSPI_MemoryMapped(&qh, &cmd, &mmap); + rv = HAL_OSPI_MemoryMapped(&qh, &cmd, &mmap); ASSERT(rv == HAL_OK); #endif + + return; + +fail: + puts("PSRAM fail"); + + oled_setup(); + oled_show(screen_fatal); + + LOCKUP_FOREVER(); } // EOF diff --git a/stm32/mk4-bootloader/psram.h b/stm32/mk4-bootloader/psram.h index 59f48a86..b1e67977 100644 --- a/stm32/mk4-bootloader/psram.h +++ b/stm32/mk4-bootloader/psram.h @@ -4,6 +4,9 @@ #pragma once #include "basics.h" +// 8 bytes of unique data from chip +extern uint8_t psram_chip_eid[8]; + extern void psram_setup(void); // EOF diff --git a/stm32/mk4-bootloader/sflash.c b/stm32/mk4-bootloader/sflash.c index 7e413045..221351ee 100644 --- a/stm32/mk4-bootloader/sflash.c +++ b/stm32/mk4-bootloader/sflash.c @@ -5,6 +5,7 @@ * */ #include "sflash.h" +#include "console.h" #include #include "delay.h" #include "stm32l4xx_hal.h" diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_conf.h b/stm32/mk4-bootloader/stm32l4xx_hal_conf.h index a2f226e0..c24a6c95 100644 --- a/stm32/mk4-bootloader/stm32l4xx_hal_conf.h +++ b/stm32/mk4-bootloader/stm32l4xx_hal_conf.h @@ -2,50 +2,31 @@ ****************************************************************************** * @file stm32l4xx_hal_conf.h * @author MCD Application Team - * @version V1.2.0 - * @date 25-November-2015 * @brief HAL configuration template file. * This file should be copied to the application folder and renamed * to stm32l4xx_hal_conf.h. ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2015 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * 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. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H +#ifndef STM32L4xx_HAL_CONF_H +#define STM32L4xx_HAL_CONF_H #ifdef __cplusplus extern "C" { #endif -#define USE_USB_FS /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ @@ -56,59 +37,69 @@ #define HAL_MODULE_ENABLED //#define HAL_ADC_MODULE_ENABLED //#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ +//#define HAL_CAN_LEGACY_MODULE_ENABLED +//#define HAL_COMP_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ +//#define HAL_CRC_MODULE_ENABLED +//#define HAL_CRYP_MODULE_ENABLED //#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DFSDM_MODULE_ENABLED */ +//#define HAL_DCMI_MODULE_ENABLED +//#define HAL_DFSDM_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED +//#define HAL_DMA2D_MODULE_ENABLED +//#define HAL_DSI_MODULE_ENABLED +//#define HAL_EXTI_MODULE_ENABLED #define HAL_FIREWALL_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ +//#define HAL_GFXMMU_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +//#define HAL_HCD_MODULE_ENABLED //#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LCD_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ +//#define HAL_IRDA_MODULE_ENABLED +//#define HAL_IWDG_MODULE_ENABLED +//#define HAL_LCD_MODULE_ENABLED +//#define HAL_LPTIM_MODULE_ENABLED +//#define HAL_LTDC_MODULE_ENABLED +//#define HAL_MMC_MODULE_ENABLED +//#define HAL_NAND_MODULE_ENABLED +//#define HAL_NOR_MODULE_ENABLED +//#define HAL_OPAMP_MODULE_ENABLED +#define HAL_OSPI_MODULE_ENABLED //#define HAL_PCD_MODULE_ENABLED +//#define HAL_PKA_MODULE_ENABLED +//#define HAL_PSSI_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED -#define HAL_QSPI_MODULE_ENABLED +//#define HAL_QSPI_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED #define HAL_RNG_MODULE_ENABLED //#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ +//#define HAL_SAI_MODULE_ENABLED //#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ +//#define HAL_SMARTCARD_MODULE_ENABLED +//#define HAL_SMBUS_MODULE_ENABLED #define HAL_SPI_MODULE_ENABLED -/* #define HAL_SWPMI_MODULE_ENABLED */ +//#define HAL_SRAM_MODULE_ENABLED +//#define HAL_SWPMI_MODULE_ENABLED //#define HAL_TIM_MODULE_ENABLED //#define HAL_TSC_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED -/* #define HAL_WWDG_MODULE_ENABLED */ - -#define HAL_HASH_MODULE_ENABLED +//#define HAL_WWDG_MODULE_ENABLED /* ########################## Oscillator Values adaptation ####################*/ /** * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). + * (when HSE is used as system clock source, directly or through the PLL). */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ #endif /* HSE_STARTUP_TIMEOUT */ /** @@ -116,54 +107,66 @@ * This value is the default MSI range value after Reset. */ #if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ #endif /* MSI_VALUE */ /** * @brief Internal High Speed oscillator (HSI) value. * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). + * (when HSI is used as system clock source, directly or through the PLL). */ #if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ #endif /* HSI_VALUE */ +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + /** * @brief Internal Low Speed oscillator (LSI) value. */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ + The real value may vary depending on the variations + in voltage and temperature.*/ /** * @brief External Low Speed oscillator (LSE) value. * This value is used by the UART, RTC HAL module to compute the system frequency */ #if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ #endif /* LSE_VALUE */ #if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ #endif /* HSE_STARTUP_TIMEOUT */ /** * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source * frequency. */ #if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ + #define EXTERNAL_SAI1_CLOCK_VALUE 48000U /*!< Value of the SAI1 External clock source in Hz*/ #endif /* EXTERNAL_SAI1_CLOCK_VALUE */ /** * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source * frequency. */ #if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ + #define EXTERNAL_SAI2_CLOCK_VALUE 48000U /*!< Value of the SAI2 External clock source in Hz*/ #endif /* EXTERNAL_SAI2_CLOCK_VALUE */ /* Tip: To avoid modifying this file each time you need to use different HSE, @@ -173,19 +176,73 @@ /** * @brief This is the HAL system configuration section */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U /* ########################## Assert Selection ############################## */ /** * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -/* #define USE_FULL_ASSERT 1 */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/deregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32l4xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U +#define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U +#define USE_HAL_OSPI_REGISTER_CALLBACKS 0U +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U +#define USE_HAL_SD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U +#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U +#define USE_HAL_TSC_REGISTER_CALLBACKS 0U +#define USE_HAL_UART_REGISTER_CALLBACKS 0U +#define USE_HAL_USART_REGISTER_CALLBACKS 0U +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U /* Includes ------------------------------------------------------------------*/ /** @@ -220,6 +277,10 @@ #include "stm32l4xx_hal_can.h" #endif /* HAL_CAN_MODULE_ENABLED */ +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "Legacy/stm32l4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + #ifdef HAL_COMP_MODULE_ENABLED #include "stm32l4xx_hal_comp.h" #endif /* HAL_COMP_MODULE_ENABLED */ @@ -236,6 +297,26 @@ #include "stm32l4xx_hal_dac.h" #endif /* HAL_DAC_MODULE_ENABLED */ +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32l4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32l4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32l4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32l4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GFXMMU_MODULE_ENABLED + #include "stm32l4xx_hal_gfxmmu.h" +#endif /* HAL_GFXMMU_MODULE_ENABLED */ + #ifdef HAL_FIREWALL_MODULE_ENABLED #include "stm32l4xx_hal_firewall.h" #endif /* HAL_FIREWALL_MODULE_ENABLED */ @@ -244,136 +325,156 @@ #include "stm32l4xx_hal_flash.h" #endif /* HAL_FLASH_MODULE_ENABLED */ -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32l4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32l4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32l4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32l4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32l4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED + #include "stm32l4xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32l4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32l4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32l4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ #ifdef HAL_NAND_MODULE_ENABLED #include "stm32l4xx_hal_nand.h" #endif /* HAL_NAND_MODULE_ENABLED */ -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32l4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ #ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" + #include "stm32l4xx_hal_opamp.h" #endif /* HAL_OPAMP_MODULE_ENABLED */ +#ifdef HAL_OSPI_MODULE_ENABLED + #include "stm32l4xx_hal_ospi.h" +#endif /* HAL_OSPI_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32l4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED + #include "stm32l4xx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED + #include "stm32l4xx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + #ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" + #include "stm32l4xx_hal_pwr.h" #endif /* HAL_PWR_MODULE_ENABLED */ #ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" + #include "stm32l4xx_hal_qspi.h" #endif /* HAL_QSPI_MODULE_ENABLED */ #ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" + #include "stm32l4xx_hal_rng.h" #endif /* HAL_RNG_MODULE_ENABLED */ #ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" + #include "stm32l4xx_hal_rtc.h" #endif /* HAL_RTC_MODULE_ENABLED */ #ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" + #include "stm32l4xx_hal_sai.h" #endif /* HAL_SAI_MODULE_ENABLED */ #ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" + #include "stm32l4xx_hal_sd.h" #endif /* HAL_SD_MODULE_ENABLED */ +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32l4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + #ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" + #include "stm32l4xx_hal_smbus.h" #endif /* HAL_SMBUS_MODULE_ENABLED */ #ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" + #include "stm32l4xx_hal_spi.h" #endif /* HAL_SPI_MODULE_ENABLED */ +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32l4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + #ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" + #include "stm32l4xx_hal_swpmi.h" #endif /* HAL_SWPMI_MODULE_ENABLED */ #ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" + #include "stm32l4xx_hal_tim.h" #endif /* HAL_TIM_MODULE_ENABLED */ #ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" + #include "stm32l4xx_hal_tsc.h" #endif /* HAL_TSC_MODULE_ENABLED */ #ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" + #include "stm32l4xx_hal_uart.h" #endif /* HAL_UART_MODULE_ENABLED */ #ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" + #include "stm32l4xx_hal_usart.h" #endif /* HAL_USART_MODULE_ENABLED */ -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - #ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" + #include "stm32l4xx_hal_wwdg.h" #endif /* HAL_WWDG_MODULE_ENABLED */ -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32l4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - /* Exported macro ------------------------------------------------------------*/ #ifdef USE_FULL_ASSERT /** * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function + * @param expr If expr is false, it calls assert_failed function * which reports the name of the source file and the source * line number of the call that failed. * If expr is true, it returns no value. * @retval None */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) /* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); + void assert_failed(uint8_t *file, uint32_t line); #else - #define assert_param(expr) ((void)0) + #define assert_param(expr) ((void)0U) #endif /* USE_FULL_ASSERT */ #ifdef __cplusplus } #endif -#endif /* __STM32L4xx_HAL_CONF_H */ +#endif /* STM32L4xx_HAL_CONF_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_hash.c b/stm32/mk4-bootloader/stm32l4xx_hal_hash.c index 353b4616..4ee43afc 100644 --- a/stm32/mk4-bootloader/stm32l4xx_hal_hash.c +++ b/stm32/mk4-bootloader/stm32l4xx_hal_hash.c @@ -2,8 +2,6 @@ ****************************************************************************** * @file stm32l4xx_hal_hash.c * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 * @brief HASH HAL module driver. * This file provides firmware functions to manage the following * functionalities of the HASH peripheral: @@ -59,26 +57,29 @@ (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is initialized and processes the buffer fed in input. When the input data have all been - fed to the IP, the digest computation can start. + fed to the Peripheral, the digest computation can start. - (#)Multi-buffer processing is possible in polling and DMA mode. + (#)Multi-buffer processing is possible in polling, interrupt and DMA modes. (##) In polling mode, only multi-buffer HASH processing is possible. API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one. - User must resort to HAL_HASH_xxx_Start() to enter the last one and retrieve as + User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as + well the computed digest. + + (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer, + except for the last one. + User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as well the computed digest. (##) In DMA mode, multi-buffer HASH and HMAC processing are possible. - (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro. - From that point, each buffer can be fed to the IP thru HAL_HASH_xxx_Start_DMA() API. + From that point, each buffer can be fed to the Peripheral thru HAL_HASH_xxx_Start_DMA() API. Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT() macro then wrap-up the HASH processing in feeding the last input buffer thru the same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to API HAL_HASH_xxx_Finish(). - (+++) HMAC processing (requires to resort to extended functions): after initialization, the key and the first input buffer are entered - in the IP with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and + in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and starts step 2. The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this point, the HMAC processing is still carrying out step 2. @@ -94,43 +95,109 @@ (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA. (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows - to save in memory the IP context. This context can be restored afterwards + to save in memory the Peripheral context. This context can be restored afterwards to resume the HASH processing thanks to HAL_HASH_ContextRestoring(). - (##) Once the HASH IP has been restored to the same configuration as that at suspension + (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension time, processing can be restarted with the same API call (same API, same handle, same parameters) as done before the suspension. Relevant parameters to restart at the proper location are internally saved in the HASH handle. (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral. + *** Remarks on message length *** + =================================== + [..] + (#) HAL in interruption mode (interruptions driven) + + (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes. + This is why, for driver implementation simplicity’s sake, user is requested to enter a message the + length of which is a multiple of 4 bytes. + + (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR + to specify which bits to discard at the end of the complete message to process only the message bits + and not extra bits. + + (##) If user needs to perform a hash computation of a large input buffer that is spread around various places + in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it + becomes necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral. + It is advised to the user to + (+++) achieve the first formatting operation by software then enter the data + (+++) while the Peripheral is processing the first input set, carry out the second formatting operation by software, to be ready when DINIS occurs. + (+++) repeat step 2 until the whole message is processed. + + [..] + (#) HAL in DMA mode + + (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis. + The same field described above in HASH_STR is used to specify which bits to discard at the end of the DMA transfer + to process only the message bits and not extra bits. Due to hardware implementation, this is possible only at the + end of the complete message. When several DMA transfers are needed to enter the message, this is not applicable at + the end of the intermediary transfers. + + (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive chunks of data + by software while the DMA transfer and processing is on-going for the first parts of the message. Due to the 32-bit alignment + required for the DMA transfer, it is underlined that the software formatting operation is more complex than in the IT mode. + + *** Callback registration *** + =================================== + [..] + (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use function @ref HAL_HASH_RegisterCallback() to register a user callback. + + (#) Function @ref HAL_HASH_RegisterCallback() allows to register following callbacks: + (+) InCpltCallback : callback for input completion. + (+) DgstCpltCallback : callback for digest computation completion. + (+) ErrorCallback : callback for error. + (+) MspInitCallback : HASH MspInit. + (+) MspDeInitCallback : HASH MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + (#) Use function @ref HAL_HASH_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + @ref HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) InCpltCallback : callback for input completion. + (+) DgstCpltCallback : callback for digest computation completion. + (+) ErrorCallback : callback for error. + (+) MspInitCallback : HASH MspInit. + (+) MspDeInitCallback : HASH MspDeInit. + + (#) By default, after the @ref HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions: + examples @ref HAL_HASH_InCpltCallback(), @ref HAL_HASH_DgstCpltCallback() + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the @ref HAL_HASH_Init + and @ref HAL_HASH_DeInit only when these callbacks are null (not registered beforehand) + If not, MspInit or MspDeInit are not null, the @ref HAL_HASH_Init and @ref HAL_HASH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used + during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using @ref HAL_HASH_RegisterCallback before calling @ref HAL_HASH_DeInit + or @ref HAL_HASH_Init function. + + When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + @endverbatim ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * 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. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -138,19 +205,19 @@ /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal.h" -#ifdef HAL_HASH_MODULE_ENABLED - -#if defined (STM32L4A6xx) /** @addtogroup STM32L4xx_HAL_Driver * @{ */ +#if defined (HASH) /** @defgroup HASH HASH * @brief HASH HAL module driver. * @{ */ +#ifdef HAL_HASH_MODULE_ENABLED + /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /** @defgroup HASH_Private_Constants HASH Private Constants @@ -160,8 +227,8 @@ /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status * @{ */ -#define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000) /*!< DCAL not set after input data written in DIN register */ -#define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001) /*!< DCAL set after input data written in DIN register */ +#define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */ +#define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */ /** * @} */ @@ -169,7 +236,7 @@ /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers * @{ */ -#define HASH_NUMBER_OF_CSR_REGISTERS 54 /*!< Number of Context Swap Registers */ +#define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */ /** * @} */ @@ -177,7 +244,7 @@ /** @defgroup HASH_TimeOut_Value HASH TimeOut Value * @{ */ -#define HASH_TIMEOUTVALUE 1000 /*!< Time-out value */ +#define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */ /** * @} */ @@ -185,7 +252,7 @@ /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit * @{ */ -#define HASH_DMA_SUSPENSION_WORDS_LIMIT 20 /*!< Number of words below which DMA suspension is aborted */ +#define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */ /** * @} */ @@ -200,10 +267,10 @@ /** @defgroup HASH_Private_Functions HASH Private Functions * @{ */ -/* +#if 0 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma); static void HASH_DMAError(DMA_HandleTypeDef *hdma); -*/ +#endif static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size); static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout); static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); @@ -234,7 +301,7 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim [..] This section provides as well call back functions definitions for user code to manage: - (+) Input data transfer to IP completion + (+) Input data transfer to Peripheral completion (+) Calculated digest retrieval completion (+) Error management @@ -247,26 +314,45 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim /** * @brief Initialize the HASH according to the specified parameters in the HASH_HandleTypeDef and create the associated handle. - * @note Only MDMAT and DATATYPE bits of HASH IP are set by HAL_HASH_Init(), + * @note Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(), * other configuration bits are set by HASH or HMAC processing APIs. * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for * multi-buffer HASH processing, user needs to resort to * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the * relevant APIs manage themselves the MDMAT bit. - * @param hhash: HASH handle + * @param hhash HASH handle * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) { - /* Check the parameters */ - assert_param(IS_HASH_DATATYPE(hhash->Init.DataType)); - /* Check the hash handle allocation */ if(hhash == NULL) { return HAL_ERROR; } + + /* Check the parameters */ + assert_param(IS_HASH_DATATYPE(hhash->Init.DataType)); +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + if (hhash->State == HAL_HASH_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hhash->Lock = HAL_UNLOCKED; + + /* Reset Callback pointers in HAL_HASH_STATE_RESET only */ + hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ + hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */ + hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ + if(hhash->MspInitCallback == NULL) + { + hhash->MspInitCallback = HAL_HASH_MspInit; + } + + /* Init the low level hardware */ + hhash->MspInitCallback(hhash); + } +#else if(hhash->State == HAL_HASH_STATE_RESET) { /* Allocate lock resource and initialize it */ @@ -275,6 +361,7 @@ HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) /* Init the low level hardware */ HAL_HASH_MspInit(hhash); } +#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ /* Change the HASH state */ hhash->State = HAL_HASH_STATE_BUSY; @@ -288,23 +375,29 @@ HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) hhash->DigestCalculationDisable = RESET; /* Set phase to READY */ hhash->Phase = HAL_HASH_PHASE_READY; + /* Reset suspension request flag */ + hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; - /* Set the data type and reset MDMAT bit */ - MODIFY_REG(HASH->CR, HASH_CR_DATATYPE|HASH_CR_MDMAT, hhash->Init.DataType); - + /* Set the data type bit */ + MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType); + /* Reset MDMAT bit */ +__HAL_HASH_RESET_MDMAT(); /* Reset HASH handle status */ hhash->Status = HAL_OK; /* Set the HASH state to Ready */ hhash->State = HAL_HASH_STATE_READY; + /* Initialise the error code */ + hhash->ErrorCode = HAL_HASH_ERROR_NONE; + /* Return function status */ return HAL_OK; } /** * @brief DeInitialize the HASH peripheral. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) @@ -328,8 +421,19 @@ HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) /* Reset digest calculation bridle (MDMAT bit control) */ hhash->DigestCalculationDisable = RESET; - /* DeInit the low level hardware: CLOCK, NVIC.*/ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + if(hhash->MspDeInitCallback == NULL) + { + hhash->MspDeInitCallback = HAL_HASH_MspDeInit; + } + + /* DeInit the low level hardware */ + hhash->MspDeInitCallback(hhash); +#else + /* DeInit the low level hardware: CLOCK, NVIC */ HAL_HASH_MspDeInit(hhash); +#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ + /* Reset HASH handle status */ hhash->Status = HAL_OK; @@ -337,13 +441,19 @@ HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) /* Set the HASH state to Ready */ hhash->State = HAL_HASH_STATE_RESET; + /* Initialise the error code */ + hhash->ErrorCode = HAL_HASH_ERROR_NONE; + + /* Reset multi buffers accumulation flag */ + hhash->Accumulation = 0U; + /* Return function status */ return HAL_OK; } /** * @brief Initialize the HASH MSP. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval None */ __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash) @@ -358,7 +468,7 @@ __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash) /** * @brief DeInitialize the HASH MSP. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval None */ __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash) @@ -374,12 +484,12 @@ __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash) /** * @brief Input data transfer complete call back. * @note HAL_HASH_InCpltCallback() is called when the complete input message - * has been fed to the IP. This API is invoked only when input data are + * has been fed to the Peripheral. This API is invoked only when input data are * entered under interruption or thru DMA. * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set), * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding - * to the IP. - * @param hhash: HASH handle. + * to the Peripheral. + * @param hhash HASH handle. * @retval None */ __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash) @@ -396,7 +506,7 @@ __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash) * @brief Digest computation complete call back. * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not * relevant with DMA. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval None */ __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash) @@ -413,7 +523,7 @@ __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash) * @brief Error callback. * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...) * to retrieve the error type. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval None */ __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) @@ -426,6 +536,184 @@ __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) */ } +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User HASH Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hhash HASH handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID + * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID + * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID + * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID + * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, pHASH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hhash); + + if(HAL_HASH_STATE_READY == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_INPUTCPLT_CB_ID : + hhash->InCpltCallback = pCallback; + break; + + case HAL_HASH_DGSTCPLT_CB_ID : + hhash->DgstCpltCallback = pCallback; + break; + + case HAL_HASH_ERROR_CB_ID : + hhash->ErrorCallback = pCallback; + break; + + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = pCallback; + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(HAL_HASH_STATE_RESET == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = pCallback; + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhash); + return status; +} + +/** + * @brief Unregister a HASH Callback + * HASH Callback is redirected to the weak (surcharged) predefined callback + * @param hhash HASH handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID + * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID + * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID + * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID + * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID) +{ +HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hhash); + + if(HAL_HASH_STATE_READY == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_INPUTCPLT_CB_ID : + hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ + break; + + case HAL_HASH_DGSTCPLT_CB_ID : + hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */ + break; + + case HAL_HASH_ERROR_CB_ID : + hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ + break; + + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(HAL_HASH_STATE_RESET == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhash); + return status; +} +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ /** * @} @@ -442,17 +730,19 @@ __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) the hash value using one of the following algorithms: (+) MD5 (++) HAL_HASH_MD5_Start() - (++) HAL_HASH_MD5_Accumulate() + (++) HAL_HASH_MD5_Accmlt() + (++) HAL_HASH_MD5_Accmlt_End() (+) SHA1 (++) HAL_HASH_SHA1_Start() - (++) HAL_HASH_SHA1_Accumulate() + (++) HAL_HASH_SHA1_Accmlt() + (++) HAL_HASH_SHA1_Accmlt_End() [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start(). [..] In case of multi-buffer HASH processing (a single digest is computed while - several buffers are fed to the IP), the user can resort to successive calls + several buffers are fed to the Peripheral), the user can resort to successive calls to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call - to HAL_HASH_xxx_Start(). + to HAL_HASH_xxx_Accumulate_End(). @endverbatim * @{ @@ -462,11 +752,11 @@ __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then * read the computed digest. * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes. - * @param Timeout: Timeout value + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) @@ -477,37 +767,52 @@ HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuff /** * @brief If not already done, initialize the HASH peripheral in MD5 mode then * processes pInBuffer. - * @note Consecutive calls to HAL_HASH_MD5_Accumulate() can be used to feed - * several input buffers back-to-back to the IP that will yield a single + * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single * HASH signature once all buffers have been entered. Wrap-up of input * buffers feeding and retrieval of digest is done by a call to - * HAL_HASH_MD5_Start(). + * HAL_HASH_MD5_Accmlt_End(). * @note Field hhash->Phase of HASH handle is tested to check whether or not - * the IP has already been initialized. - * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Start() - * to read it, feeding at the same time the last input buffer to the IP. + * the Peripheral has already been initialized. + * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End() + * to read it, feeding at the same time the last input buffer to the Peripheral. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. Only HAL_HASH_MD5_Start() is able + * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able * to manage the ending buffer with a length in bytes not a multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes, must be a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. * @retval HAL status */ -HAL_StatusTypeDef HAL_HASH_MD5_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) { return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_MD5); } +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); +} + /** * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then * read the computed digest. * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes. - * @param Timeout: Timeout value + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) @@ -518,28 +823,42 @@ HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuf /** * @brief If not already done, initialize the HASH peripheral in SHA1 mode then * processes pInBuffer. - * @note Consecutive calls to HAL_HASH_SHA1_Accumulate() can be used to feed - * several input buffers back-to-back to the IP that will yield a single + * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single * HASH signature once all buffers have been entered. Wrap-up of input * buffers feeding and retrieval of digest is done by a call to - * HAL_HASH_SHA1_Start(). + * HAL_HASH_SHA1_Accmlt_End(). * @note Field hhash->Phase of HASH handle is tested to check whether or not - * the IP has already been initialized. - * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Start() - * to read it, feeding at the same time the last input buffer to the IP. + * the Peripheral has already been initialized. + * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End() + * to read it, feeding at the same time the last input buffer to the Peripheral. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Start() is able + * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able * to manage the ending buffer with a length in bytes not a multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes, must be a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. * @retval HAL status */ -HAL_StatusTypeDef HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) { return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA1); } +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); +} /** * @} @@ -556,12 +875,16 @@ HAL_StatusTypeDef HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *p the hash value using one of the following algorithms: (+) MD5 (++) HAL_HASH_MD5_Start_IT() + (++) HAL_HASH_MD5_Accmlt_IT() + (++) HAL_HASH_MD5_Accmlt_End_IT() (+) SHA1 (++) HAL_HASH_SHA1_Start_IT() + (++) HAL_HASH_SHA1_Accmlt_IT() + (++) HAL_HASH_SHA1_Accmlt_End_IT() [..] API HAL_HASH_IRQHandler() manages each HASH interruption. - [..] Note that HAL_HASH_IRQHandler() manages as well HASH IP interruptions when in + [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in HMAC processing mode. @@ -573,10 +896,10 @@ HAL_StatusTypeDef HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *p * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then * read the computed digest in interruption mode. * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) @@ -584,15 +907,51 @@ HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInB return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_MD5); } +/** + * @brief If not already done, initialize the HASH peripheral in MD5 mode then + * processes pInBuffer in interruption mode. + * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASH_MD5_Accmlt_End_IT(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate_IT(hhash, pInBuffer, Size,HASH_ALGOSELECTION_MD5); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_MD5); +} /** * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then * read the computed digest in interruption mode. * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) @@ -600,9 +959,47 @@ HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pIn return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA1); } + +/** + * @brief If not already done, initialize the HASH peripheral in SHA1 mode then + * processes pInBuffer in interruption mode. + * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASH_SHA1_Accmlt_End_IT(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate_IT(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA1); +} + /** * @brief Handle HASH interrupt request. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well. * @note In case of error reported during the HASH interruption processing, * HAL_HASH_ErrorCallback() API is called so that user code can @@ -614,7 +1011,12 @@ void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) hhash->Status = HASH_IT(hhash); if (hhash->Status != HAL_OK) { + hhash->ErrorCode |= HAL_HASH_ERROR_IT; +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->ErrorCallback(hhash); +#else HAL_HASH_ErrorCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ /* After error handling by code user, reset HASH handle HAL status */ hhash->Status = HAL_OK; } @@ -624,6 +1026,7 @@ void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) * @} */ +#if 0 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode * @brief HASH processing functions using DMA mode. * @@ -640,45 +1043,41 @@ void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) (++) HAL_HASH_SHA1_Start_DMA() (++) HAL_HASH_SHA1_Finish() - [..] When resorting to DMA mode to enter the data in the IP, user must resort + [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort to HAL_HASH_xxx_Start_DMA() then read the resulting digest with HAL_HASH_xxx_Finish(). - [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally retrieved thanks to HAL_HASH_xxx_Finish(). - @endverbatim * @{ */ -#if 0 /** * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer - * to feed the input buffer to the IP. + * to feed the input buffer to the Peripheral. * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must * be called to retrieve the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) { return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); } -#endif /** * @brief Return the computed digest in MD5 mode. * @note The API waits for DCIS to be set then reads the computed digest. * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in * HMAC MD5 mode. - * @param hhash: HASH handle. - * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes. - * @param Timeout: Timeout value. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) @@ -686,22 +1085,20 @@ HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBu return HASH_Finish(hhash, pOutBuffer, Timeout); } -#if 0 /** * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer - * to feed the input buffer to the IP. + * to feed the input buffer to the Peripheral. * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must * be called to retrieve the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) { return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); } -#endif /** @@ -709,9 +1106,9 @@ HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pI * @note The API waits for DCIS to be set then reads the computed digest. * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in * HMAC SHA1 mode. - * @param hhash: HASH handle. - * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes. - * @param Timeout: Timeout value. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) @@ -748,11 +1145,11 @@ HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutB * @note Digest is available in pOutBuffer. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes. - * @param Timeout: Timeout value. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value. * @retval HAL status */ HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) @@ -766,17 +1163,18 @@ HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuff * @note Digest is available in pOutBuffer. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes. - * @param Timeout: Timeout value. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value. * @retval HAL status */ HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) { return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); } +#endif /** * @} @@ -808,10 +1206,10 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuf * @note Digest is available in pOutBuffer. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) @@ -825,10 +1223,10 @@ HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInB * @note Digest is available in pOutBuffer. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) @@ -842,7 +1240,6 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pIn -#if 0 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode * @brief HMAC processing functions using DMA modes. * @@ -857,7 +1254,7 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pIn (+) SHA1 (++) HAL_HMAC_SHA1_Start_DMA() - [..] When resorting to DMA mode to enter the data in the IP for HMAC processing, + [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing, user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest with HAL_HASH_xxx_Finish(). @@ -866,9 +1263,10 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pIn */ +#if 0 /** * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required - * DMA transfers to feed the key and the input buffer to the IP. + * DMA transfers to feed the key and the input buffer to the Peripheral. * @note Once the DMA transfers are finished (indicated by hhash->State set back * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve * the computed digest. @@ -880,9 +1278,9 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pIn * For the processing of the last buffer of the thread, MDMAT bit must * be reset and the buffer length (in bytes) doesn't have to be a * multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) @@ -893,7 +1291,7 @@ HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pIn /** * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required - * DMA transfers to feed the key and the input buffer to the IP. + * DMA transfers to feed the key and the input buffer to the Peripheral. * @note Once the DMA transfers are finished (indicated by hhash->State set back * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve * the computed digest. @@ -905,9 +1303,9 @@ HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pIn * For the processing of the last buffer of the thread, MDMAT bit must * be reset and the buffer length (in bytes) doesn't have to be a * multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. * @retval HAL status */ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) @@ -941,9 +1339,9 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pI [..] This subsection provides functions allowing to suspend the HASH processing - (+) when input are fed to the IP by software + (+) when input are fed to the Peripheral by software (++) HAL_HASH_SwFeed_ProcessSuspend() - (+) when input are fed to the IP by DMA + (+) when input are fed to the Peripheral by DMA (++) HAL_HASH_DMAFeed_ProcessSuspend() @@ -955,7 +1353,7 @@ HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pI /** * @brief Return the HASH handle state. * @note The API yields the current state of the handle (BUSY, READY,...). - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval HAL HASH state */ HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash) @@ -968,7 +1366,7 @@ HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash) * @brief Return the HASH HAL status. * @note The API yields the HAL status of the handle: it is the result of the * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT). - * @param hhash: HASH handle. + * @param hhash HASH handle. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash) @@ -978,8 +1376,8 @@ HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash) /** * @brief Save the HASH context in case of processing suspension. - * @param hhash: HASH handle. - * @param pMemBuffer: pointer to the memory buffer where the HASH context + * @param hhash HASH handle. + * @param pMemBuffer pointer to the memory buffer where the HASH context * is saved. * @note The IMR, STR, CR then all the CSR registers are saved * in that order. Only the r/w bits are read to be restored later on. @@ -993,34 +1391,34 @@ void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer) { uint32_t mem_ptr = (uint32_t)pMemBuffer; uint32_t csr_ptr = (uint32_t)HASH->CSR; - uint32_t i = 0; + uint32_t i; /* Prevent unused argument(s) compilation warning */ UNUSED(hhash); /* Save IMR register content */ *(uint32_t*)(mem_ptr) = READ_BIT(HASH->IMR,HASH_IT_DINI|HASH_IT_DCI); - mem_ptr+=4; + mem_ptr+=4U; /* Save STR register content */ *(uint32_t*)(mem_ptr) = READ_BIT(HASH->STR,HASH_STR_NBLW); - mem_ptr+=4; + mem_ptr+=4U; /* Save CR register content */ *(uint32_t*)(mem_ptr) = READ_BIT(HASH->CR,HASH_CR_DMAE|HASH_CR_DATATYPE|HASH_CR_MODE|HASH_CR_ALGO|HASH_CR_LKEY|HASH_CR_MDMAT); - mem_ptr+=4; + mem_ptr+=4U; /* By default, save all CSRs registers */ - for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0; i--) + for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--) { *(uint32_t*)(mem_ptr) = *(uint32_t*)(csr_ptr); - mem_ptr+=4; - csr_ptr+=4; + mem_ptr+=4U; + csr_ptr+=4U; } } /** * @brief Restore the HASH context in case of processing resumption. - * @param hhash: HASH handle. - * @param pMemBuffer: pointer to the memory buffer where the HASH context + * @param hhash HASH handle. + * @param pMemBuffer pointer to the memory buffer where the HASH context * is stored. * @note The IMR, STR, CR then all the CSR registers are restored * in that order. Only the r/w bits are restored. @@ -1033,38 +1431,38 @@ void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer) { uint32_t mem_ptr = (uint32_t)pMemBuffer; uint32_t csr_ptr = (uint32_t)HASH->CSR; - uint32_t i = 0; + uint32_t i; /* Prevent unused argument(s) compilation warning */ UNUSED(hhash); /* Restore IMR register content */ WRITE_REG(HASH->IMR, (*(uint32_t*)(mem_ptr))); - mem_ptr+=4; + mem_ptr+=4U; /* Restore STR register content */ WRITE_REG(HASH->STR, (*(uint32_t*)(mem_ptr))); - mem_ptr+=4; + mem_ptr+=4U; /* Restore CR register content */ WRITE_REG(HASH->CR, (*(uint32_t*)(mem_ptr))); - mem_ptr+=4; + mem_ptr+=4U; /* Reset the HASH processor before restoring the Context Swap Registers (CSR) */ __HAL_HASH_INIT(); /* By default, restore all CSR registers */ - for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0; i--) + for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--) { WRITE_REG((*(uint32_t*)(csr_ptr)), (*(uint32_t*)(mem_ptr))); - mem_ptr+=4; - csr_ptr+=4; + mem_ptr+=4U; + csr_ptr+=4U; } } /** * @brief Initiate HASH processing suspension when in polling or interruption mode. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @note Set the handle field SuspendRequest to the appropriate value so that * the on-going HASH processing is suspended as soon as the required * conditions are met. Note that the actual suspension is carried out @@ -1081,18 +1479,18 @@ void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) #if 0 /** * @brief Suspend the HASH processing when in DMA mode. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @note When suspension attempt occurs at the very end of a DMA transfer and - * all the data have already been entered in the IP, hhash->State is + * all the data have already been entered in the Peripheral, hhash->State is * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is * recommended to wrap-up the processing in reading the digest as usual. * @retval HAL status */ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) { - uint32_t tmp_remaining_DMATransferSize_inWords = 0x0; - uint32_t tmp_initial_DMATransferSize_inWords = 0x0; - uint32_t tmp_words_already_pushed = 0x0; + uint32_t tmp_remaining_DMATransferSize_inWords; + uint32_t tmp_initial_DMATransferSize_inWords; + uint32_t tmp_words_already_pushed; if (hhash->State == HAL_HASH_STATE_READY) { @@ -1102,7 +1500,8 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) { /* Make sure there is enough time to suspend the processing */ - tmp_remaining_DMATransferSize_inWords = hhash->hdmain->Instance->CNDTR; + tmp_remaining_DMATransferSize_inWords = ((DMA_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR; + if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT) { /* No suspension attempted since almost to the end of the transferred data. */ @@ -1110,7 +1509,7 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) return HAL_ERROR; } - /* Wait for DMAS to be reset */ + /* Wait for BUSY flag to be reset */ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) { return HAL_TIMEOUT; @@ -1121,18 +1520,26 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) return HAL_ERROR; } - /* Wait for DMAS to be set */ + /* Wait for BUSY flag to be set */ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK) { return HAL_TIMEOUT; } - /* Disable DMA channel */ - HAL_DMA_Abort(hhash->hdmain); + /* Note that the Abort function will + - Clear the transfer error flags + - Unlock + - Set the State + */ + if (HAL_DMA_Abort(hhash->hdmain) !=HAL_OK) + { + return HAL_ERROR; + } /* Clear DMAE bit */ CLEAR_BIT(HASH->CR,HASH_CR_DMAE); + /* Wait for BUSY flag to be reset */ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) { return HAL_TIMEOUT; @@ -1145,9 +1552,9 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) /* At this point, DMA interface is disabled and no transfer is on-going */ /* Retrieve from the DMA handle how many words remain to be written */ - tmp_remaining_DMATransferSize_inWords = hhash->hdmain->Instance->CNDTR; + tmp_remaining_DMATransferSize_inWords = ((DMA_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR; - if (tmp_remaining_DMATransferSize_inWords == 0) + if (tmp_remaining_DMATransferSize_inWords == 0U) { /* All the DMA transfer is actually done. Suspension occurred at the very end of the transfer. Either the digest computation is about to start (HASH case) @@ -1164,23 +1571,23 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) { /* Compute how many words were supposed to be transferred by DMA */ - tmp_initial_DMATransferSize_inWords = (hhash->HashInCount%4 ? (hhash->HashInCount+3)/4: hhash->HashInCount/4); + tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount%4U)!=0U) ? ((hhash->HashInCount+3U)/4U): (hhash->HashInCount/4U)); - /* If discrepancy between the number of words reported by DMA IP and the numbers of words entered as reported - by HASH IP, correct it */ + /* If discrepancy between the number of words reported by DMA Peripheral and the numbers of words entered as reported + by HASH Peripheral, correct it */ /* tmp_words_already_pushed reflects the number of words that were already pushed before the start of DMA transfer (multi-buffer processing case) */ tmp_words_already_pushed = hhash->NbWordsAlreadyPushed; - if ((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) %16 != HASH_NBW_PUSHED()) + if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) %16U) != HASH_NBW_PUSHED()) { tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */ } - /* Accordingly, update the input pointer that points at the next word to be transferred to the IP by DMA */ - hhash->pHashInBuffPtr += 4 * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ; + /* Accordingly, update the input pointer that points at the next word to be transferred to the Peripheral by DMA */ + hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ; /* And store in HashInCount the remaining size to transfer (in bytes) */ - hhash->HashInCount = 4 * tmp_remaining_DMATransferSize_inWords; + hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords; } @@ -1191,8 +1598,18 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) } } +#endif - +/** + * @brief Return the HASH handle error code. + * @param hhash pointer to a HASH_HandleTypeDef structure. + * @retval HASH Error Code +*/ +uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash) +{ + /* Return HASH Error Code */ + return hhash->ErrorCode; +} /** * @} */ @@ -1206,9 +1623,10 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) * @{ */ +#if 0 /** * @brief DMA HASH Input Data transfer completion callback. - * @param hdma: DMA handle. + * @param hdma DMA handle. * @note In case of HMAC processing, HASH_DMAXferCplt() initiates * the next DMA transfer for the following HMAC step. * @retval None @@ -1216,105 +1634,130 @@ HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma) { HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - uint32_t inputaddr = 0x0; - uint32_t buffersize = 0x0; + uint32_t inputaddr; + uint32_t buffersize; + HAL_StatusTypeDef status ; if (hhash->State != HAL_HASH_STATE_SUSPENDED) { - /* Disable the DMA transfer */ - CLEAR_BIT(HASH->CR, HASH_CR_DMAE); + /* Disable the DMA transfer */ + CLEAR_BIT(HASH->CR, HASH_CR_DMAE); - if (READ_BIT(HASH->CR, HASH_CR_MODE) == RESET) - { - /* If no HMAC processing, input data transfer is now over */ - - /* Change the HASH state to ready */ - hhash->State = HAL_HASH_STATE_READY; - - /* Call Input data transfer complete call back */ - HAL_HASH_InCpltCallback(hhash); - } - else - { - /* HMAC processing: depending on the current HMAC step and whether or - not multi-buffer processing is on-going, the next step is initiated - and MDMAT bit is set. */ - - - if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) + if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U) { - /* This is the end of HMAC processing */ + /* If no HMAC processing, input data transfer is now over */ /* Change the HASH state to ready */ hhash->State = HAL_HASH_STATE_READY; - /* Call Input data transfer complete call back - (note that the last DMA transfer was that of the key - for the outer HASH operation). */ + /* Call Input data transfer complete call back */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ - return; } - else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) + else { - inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */ - buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */ - hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ + /* HMAC processing: depending on the current HMAC step and whether or + not multi-buffer processing is on-going, the next step is initiated + and MDMAT bit is set. */ - /* In case of suspension request, save the new starting parameters */ - hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */ - hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */ - hhash->NbWordsAlreadyPushed = 0; /* Reset number of words already pushed */ - - /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */ - if (hhash->DigestCalculationDisable != RESET) + if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) { - /* Digest calculation is disabled: Step 2 must start with MDMAT bit set, - no digest calculation will be triggered at the end of the input buffer feeding to the IP */ - __HAL_HASH_SET_MDMAT(); - } - } - else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) - { - if (hhash->DigestCalculationDisable != RESET) - { - /* No automatic move to Step 3 as a new message buffer will be fed to the IP - (case of multi-buffer HMAC processing): - DCAL must not be set. - Phase remains in Step 2, MDMAT remains set at this point. - Change the HASH state to ready and call Input data transfer complete call back. */ + /* This is the end of HMAC processing */ + + /* Change the HASH state to ready */ hhash->State = HAL_HASH_STATE_READY; - HAL_HASH_InCpltCallback(hhash); - return ; - } - else - { - /* Digest calculation is not disabled (case of single buffer input or last buffer - of multi-buffer HMAC processing) */ - inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */ - buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */ - hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ - /* In case of suspension request, save the new starting parameters */ - hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */ - hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */ - hhash->NbWordsAlreadyPushed = 0; /* Reset number of words already pushed */ + /* Call Input data transfer complete call back + (note that the last DMA transfer was that of the key + for the outer HASH operation). */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + return; } - } + else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) + { + inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */ + buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ + + /* In case of suspension request, save the new starting parameters */ + hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */ + hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */ + + hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ + /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */ + if (hhash->DigestCalculationDisable != RESET) + { + /* Digest calculation is disabled: Step 2 must start with MDMAT bit set, + no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */ + __HAL_HASH_SET_MDMAT(); + } + } + else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/ + { + if (hhash->DigestCalculationDisable != RESET) + { + /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral + (case of multi-buffer HMAC processing): + DCAL must not be set. + Phase remains in Step 2, MDMAT remains set at this point. + Change the HASH state to ready and call Input data transfer complete call back. */ + hhash->State = HAL_HASH_STATE_READY; +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + return ; + } + else + { + /* Digest calculation is not disabled (case of single buffer input or last buffer + of multi-buffer HMAC processing) */ + inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */ + buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ + /* In case of suspension request, save the new starting parameters */ + hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */ + hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */ + + hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ + } + } + /* Configure the Number of valid bits in last word of the message */ __HAL_HASH_SET_NBVALIDBITS(buffersize); - /* Set the HASH DMA transfert completion call back */ hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; - /* Enable the DMA In DMA Stream */ - HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (buffersize%4 ? (buffersize+3)/4:buffersize/4)); + /* Enable the DMA In DMA Stream */ + status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((buffersize %4U)!=0U) ? ((buffersize+(4U-(buffersize %4U)))/4U):(buffersize/4U))); /* Enable DMA requests */ SET_BIT(HASH->CR, HASH_CR_DMAE); + + /* Return function status */ + if (status != HAL_OK) + { + /* Update HASH state machine to error */ + hhash->State = HAL_HASH_STATE_ERROR; + } + else + { + /* Change HASH state */ + hhash->State = HAL_HASH_STATE_READY; + } } } @@ -1323,7 +1766,7 @@ static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma) /** * @brief DMA HASH communication error callback. - * @param hdma: DMA handle. + * @param hdma DMA handle. * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that * can contain user code to manage the error. * @retval None @@ -1332,29 +1775,34 @@ static void HASH_DMAError(DMA_HandleTypeDef *hdma) { HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - if (hhash->State != HAL_HASH_STATE_SUSPENDED) + if (hhash->State != HAL_HASH_STATE_SUSPENDED) { - /* Set HASH state to ready to prevent any blocking issue in user code - present in HAL_HASH_ErrorCallback() */ - hhash->State= HAL_HASH_STATE_READY; - /* Set HASH handle status to error */ - hhash->Status = HAL_ERROR; - HAL_HASH_ErrorCallback(hhash); - /* After error handling by code user, reset HASH handle HAL status */ - hhash->Status = HAL_OK; + hhash->ErrorCode |= HAL_HASH_ERROR_DMA; + /* Set HASH state to ready to prevent any blocking issue in user code + present in HAL_HASH_ErrorCallback() */ + hhash->State= HAL_HASH_STATE_READY; + /* Set HASH handle status to error */ + hhash->Status = HAL_ERROR; +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->ErrorCallback(hhash); +#else + HAL_HASH_ErrorCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + /* After error handling by code user, reset HASH handle HAL status */ + hhash->Status = HAL_OK; } } #endif /** - * @brief Feed the input buffer to the HASH IP. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to input buffer. - * @param Size: the size of input buffer in bytes. + * @brief Feed the input buffer to the HASH Peripheral. + * @param hhash HASH handle. + * @param pInBuffer pointer to input buffer. + * @param Size the size of input buffer in bytes. * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether * or not the HASH processing must be suspended. If this is the case, the - * processing is suspended when possible and the IP feeding point reached at + * processing is suspended when possible and the Peripheral feeding point reached at * suspension time is stored in the handle for resumption later on. * @retval HAL status */ @@ -1363,38 +1811,38 @@ static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInB uint32_t buffercounter; __IO uint32_t inputaddr = (uint32_t) pInBuffer; - for(buffercounter = 0; buffercounter < Size; buffercounter+=4) + for(buffercounter = 0U; buffercounter < Size; buffercounter+=4U) { /* Write input data 4 bytes at a time */ HASH->DIN = *(uint32_t*)inputaddr; - inputaddr+=4; + inputaddr+=4U; /* If the suspension flag has been raised and if the processing is not about - to end, suspend processing */ - if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) + to end, suspend processing */ + if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4U) < Size)) { /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free - in the input buffer */ + in the input buffer */ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) { /* Reset SuspendRequest */ hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; - /* Depending whether the key or the input data were fed to the IP, the feeding point - reached at suspension time is not saved in the same handle fields */ + /* Depending whether the key or the input data were fed to the Peripheral, the feeding point + reached at suspension time is not saved in the same handle fields */ if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)) { /* Save current reading and writing locations of Input and Output buffers */ hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Save the number of bytes that remain to be processed at this point */ - hhash->HashInCount = Size - (buffercounter + 4); + hhash->HashInCount = Size - (buffercounter + 4U); } else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) { /* Save current reading and writing locations of Input and Output buffers */ hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr; /* Save the number of bytes that remain to be processed at this point */ - hhash->HashKeyCount = Size - (buffercounter + 4); + hhash->HashKeyCount = Size - (buffercounter + 4U); } else { @@ -1412,14 +1860,14 @@ static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInB } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */ } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */ - /* At this point, all the data have been entered to the IP: exit */ + /* At this point, all the data have been entered to the Peripheral: exit */ return HAL_OK; } /** * @brief Retrieve the message digest. - * @param pMsgDigest: pointer to the computed digest. - * @param Size: message digest size in bytes. + * @param pMsgDigest pointer to the computed digest. + * @param Size message digest size in bytes. * @retval None */ static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) @@ -1431,54 +1879,54 @@ static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) /* Read the message digest */ case 16: /* MD5 */ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); break; case 20: /* SHA1 */ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]); break; case 28: /* SHA224 */ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]); break; case 32: /* SHA256 */ *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]); - msgdigest+=4; + msgdigest+=4U; *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7]); break; default: @@ -1490,10 +1938,10 @@ static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) /** * @brief Handle HASH processing Timeout. - * @param hhash: HASH handle. - * @param Flag: specifies the HASH flag to check. - * @param Status: the Flag status (SET or RESET). - * @param Timeout: Timeout duration. + * @param hhash HASH handle. + * @param Flag specifies the HASH flag to check. + * @param Status the Flag status (SET or RESET). + * @param Timeout Timeout duration. * @retval HAL status */ static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout) @@ -1508,7 +1956,7 @@ static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { - if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) + if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U)) { /* Set State to Ready to be able to restart later on */ hhash->State = HAL_HASH_STATE_READY; @@ -1530,7 +1978,7 @@ static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { - if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout)) + if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U)) { /* Set State to Ready to be able to restart later on */ hhash->State = HAL_HASH_STATE_READY; @@ -1551,10 +1999,10 @@ static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, /** * @brief HASH processing in interruption mode. - * @param hhash: HASH handle. + * @param hhash HASH handle. * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether * or not the HASH processing must be suspended. If this is the case, the - * processing is suspended when possible and the IP feeding point reached at + * processing is suspended when possible and the Peripheral feeding point reached at * suspension time is stored in the handle for resumption later on. * @retval HAL status */ @@ -1563,7 +2011,7 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) if (hhash->State == HAL_HASH_STATE_BUSY) { /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */ - if(hhash->HashITCounter == 0) + if(hhash->HashITCounter == 0U) { /* Disable Interrupts */ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI); @@ -1572,18 +2020,18 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) hhash->State = HAL_HASH_STATE_READY; return HAL_ERROR; } - else if (hhash->HashITCounter == 1) + else if (hhash->HashITCounter == 1U) { /* This is the first call to HASH_IT, the first input data are about to be - entered in the IP. A specific processing is carried out at this point to + entered in the Peripheral. A specific processing is carried out at this point to start-up the processing. */ - hhash->HashITCounter = 2; + hhash->HashITCounter = 2U; } else { /* Cruise speed reached, HashITCounter remains equal to 3 until the end of the HASH processing or the end of the current step for HMAC processing. */ - hhash->HashITCounter = 3; + hhash->HashITCounter = 3U; } /* If digest is ready */ @@ -1596,19 +2044,25 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI); /* Change the HASH state */ hhash->State = HAL_HASH_STATE_READY; + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; /* Call digest computation complete call back */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->DgstCpltCallback(hhash); +#else HAL_HASH_DgstCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ return HAL_OK; } - /* If IP ready to accept new data */ + /* If Peripheral ready to accept new data */ if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) { /* If the suspension flag has been raised and if the processing is not about to end, suspend processing */ - if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && (hhash->HashInCount != 0)) + if ( (hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND)) { /* Disable Interrupts */ __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI); @@ -1622,17 +2076,21 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) return HAL_OK; } - /* Enter input data in the IP thru HASH_Write_Block_Data() call and + /* Enter input data in the Peripheral thru HASH_Write_Block_Data() call and check whether the digest calculation has been triggered */ if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) { /* Call Input data transfer complete call back (called at the end of each step for HMAC) */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) { - /* Wait until IP is not busy anymore */ + /* Wait until Peripheral is not busy anymore */ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) { /* Disable Interrupts */ @@ -1649,7 +2107,7 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) } else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) { - /* Wait until IP is not busy anymore */ + /* Wait until Peripheral is not busy anymore */ if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) { /* Disable Interrupts */ @@ -1664,6 +2122,10 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start of a new phase */ __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ } + else + { + /* Nothing to do */ + } } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */ } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/ @@ -1678,8 +2140,8 @@ static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) /** - * @brief Write a block of data in HASH IP in interruption mode. - * @param hhash: HASH handle. + * @brief Write a block of data in HASH Peripheral in interruption mode. + * @param hhash HASH handle. * @note HASH_Write_Block_Data() is called under interruption by HASH_IT(). * @retval HAL status */ @@ -1691,34 +2153,33 @@ static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED; /* If there are more than 64 bytes remaining to be entered */ - if(hhash->HashInCount > 64) + if(hhash->HashInCount > 64U) { inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* Write the Input block in the Data IN register (16 32-bit words, or 64 bytes are entered) */ - for(buffercounter = 0; buffercounter < 64; buffercounter+=4) + for(buffercounter = 0U; buffercounter < 64U; buffercounter+=4U) { HASH->DIN = *(uint32_t*)inputaddr; - inputaddr+=4; + inputaddr+=4U; } /* If this is the start of input data entering, an additional word must be entered to start up the HASH processing */ - if(hhash->HashITCounter == 2) + if(hhash->HashITCounter == 2U) { HASH->DIN = *(uint32_t*)inputaddr; - inputaddr+=4; - if(hhash->HashInCount >= 68) + if(hhash->HashInCount >= 68U) { - /* There are still data waiting to be entered in the IP. + /* There are still data waiting to be entered in the Peripheral. Decrement buffer counter and set pointer to the proper memory location for the next data entering round. */ - hhash->HashInCount -= 68; - hhash->pHashInBuffPtr+= 68; + hhash->HashInCount -= 68U; + hhash->pHashInBuffPtr+= 68U; } else { /* All the input buffer has been fed to the HW. */ - hhash->HashInCount = 0; + hhash->HashInCount = 0U; } } else @@ -1726,8 +2187,8 @@ static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) /* 64 bytes have been entered and there are still some remaining: Decrement buffer counter and set pointer to the proper memory location for the next data entering round.*/ - hhash->HashInCount -= 64; - hhash->pHashInBuffPtr+= 64; + hhash->HashInCount -= 64U; + hhash->pHashInBuffPtr+= 64U; } } else @@ -1743,18 +2204,38 @@ static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) __HAL_HASH_DISABLE_IT(HASH_IT_DINI); /* Write the Input block in the Data IN register */ - for(buffercounter = 0; buffercounter < (inputcounter+3)/4; buffercounter++) + for(buffercounter = 0U; buffercounter < ((inputcounter+3U)/4U); buffercounter++) { HASH->DIN = *(uint32_t*)inputaddr; - inputaddr+=4; + inputaddr+=4U; + } + + if (hhash->Accumulation == 1U) + { + /* Field accumulation is set, API only feeds data to the Peripheral and under interruption. + The digest computation will be started when the last buffer data are entered. */ + + /* Reset multi buffers accumulation flag */ + hhash->Accumulation = 0U; + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + /* Call Input data transfer complete call back */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + } + else + { + /* Start the Digest calculation */ + __HAL_HASH_START_DIGEST(); + /* Return indication that digest calculation has started: + this return value triggers the call to Input data transfer + complete call back as well as the proper transition from + one step to another in HMAC mode. */ + ret = HASH_DIGEST_CALCULATION_STARTED; } - /* Start the Digest calculation */ - __HAL_HASH_START_DIGEST(); - /* Return indication that digest calculation has started: - this return value triggers the call to Input data transfer - complete call back as well as the proper transition from - one step to another in HMAC mode. */ - ret = HASH_DIGEST_CALCULATION_STARTED; /* Reset buffer counter */ hhash->HashInCount = 0; } @@ -1765,8 +2246,8 @@ static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) /** * @brief HMAC processing in polling mode. - * @param hhash: HASH handle. - * @param Timeout: Timeout value. + * @param hhash HASH handle. + * @param Timeout Timeout value. * @retval HAL status */ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout) @@ -1792,7 +2273,8 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Write input buffer in Data register */ - if ((hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount)) != HAL_OK) + hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); + if (hhash->Status != HAL_OK) { return hhash->Status; } @@ -1833,7 +2315,8 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Write input buffer in Data register */ - if ((hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount)) != HAL_OK) + hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount); + if (hhash->Status != HAL_OK) { return hhash->Status; } @@ -1879,7 +2362,8 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Write input buffer in Data register */ - if ((hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount)) != HAL_OK) + hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); + if (hhash->Status != HAL_OK) { return hhash->Status; } @@ -1905,6 +2389,9 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim /* Read the message digest */ HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); + + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; } /* Change the HASH state */ @@ -1922,122 +2409,128 @@ static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Tim * @brief Initialize the HASH peripheral, next process pInBuffer then * read the computed digest. * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. - * @param Timeout: Timeout value. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Timeout Timeout value. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm) { uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ - uint32_t Size_tmp = 0x0; /* input data size (in bytes), input parameter of HASH_WriteData() */ + uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + /* Initiate HASH processing in case of start or resumption */ - if((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ((pInBuffer == NULL) /*PDG || (Size == 0)*/ || (pOutBuffer == NULL)) + if ((pInBuffer == NULL) || (pOutBuffer == NULL)) { hhash->State = HAL_HASH_STATE_READY; return HAL_ERROR; } - /* Process Locked */ - __HAL_LOCK(hhash); + /* Process Locked */ + __HAL_LOCK(hhash); - /* Check if initialization phase has not been already performed */ - if(hhash->Phase == HAL_HASH_PHASE_READY) - { - /* Change the HASH state */ - hhash->State = HAL_HASH_STATE_BUSY; - - /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ - MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT); - - /* Configure the number of valid bits in last word of the message */ - __HAL_HASH_SET_NBVALIDBITS(Size); - - /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as - input parameters of HASH_WriteData() */ - pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ - Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ - - /* Set the phase */ - hhash->Phase = HAL_HASH_PHASE_PROCESS; - } - else if (hhash->Phase == HAL_HASH_PHASE_PROCESS) - { - /* if the IP has already been initialized, two cases are possible */ - - /* Process resumption time ... */ - if (hhash->State == HAL_HASH_STATE_SUSPENDED) + /* Check if initialization phase has not been already performed */ + if(hhash->Phase == HAL_HASH_PHASE_READY) { - /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set - to the API input parameters but to those saved beforehand by HASH_WriteData() - when the processing was suspended */ - pInBuffer_tmp = hhash->pHashInBuffPtr; - Size_tmp = hhash->HashInCount; - } - /* ... or multi-buffer HASH processing end */ - else - { - /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as - input parameters of HASH_WriteData() */ - pInBuffer_tmp = pInBuffer; - Size_tmp = Size; + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT); + /* Configure the number of valid bits in last word of the message */ __HAL_HASH_SET_NBVALIDBITS(Size); + + /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as + input parameters of HASH_WriteData() */ + pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ + Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + } + else if (hhash->Phase == HAL_HASH_PHASE_PROCESS) + { + /* if the Peripheral has already been initialized, two cases are possible */ + + /* Process resumption time ... */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set + to the API input parameters but to those saved beforehand by HASH_WriteData() + when the processing was suspended */ + pInBuffer_tmp = hhash->pHashInBuffPtr; + Size_tmp = hhash->HashInCount; + } + /* ... or multi-buffer HASH processing end */ + else + { + /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as + input parameters of HASH_WriteData() */ + pInBuffer_tmp = pInBuffer; + Size_tmp = Size; + /* Configure the number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(Size); + } + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + } + else + { + /* Phase error */ + hhash->State = HAL_HASH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_ERROR; + } + + + /* Write input buffer in Data register */ + hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); + if (hhash->Status != HAL_OK) + { + return hhash->Status; + } + + /* If the process has not been suspended, carry on to digest calculation */ + if (hhash->State != HAL_HASH_STATE_SUSPENDED) + { + /* Start the Digest calculation */ + __HAL_HASH_START_DIGEST(); + + /* Wait for DCIS flag to be set */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Read the message digest */ + HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; + } - /* Change the HASH state */ - hhash->State = HAL_HASH_STATE_BUSY; - } - else - { - /* Phase error */ - hhash->State = HAL_HASH_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hhash); /* Return function status */ - return HAL_ERROR; - } - - - /* Write input buffer in Data register */ - if ((hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp)) != HAL_OK) - { - return hhash->Status; - } - - /* If the process has not been suspended, carry on to digest calculation */ - if (hhash->State != HAL_HASH_STATE_SUSPENDED) - { - /* Start the Digest calculation */ - __HAL_HASH_START_DIGEST(); - - /* Wait for DCIS flag to be set */ - if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) - { - return HAL_TIMEOUT; - } - - /* Read the message digest */ - HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); - - /* Change the HASH state */ - hhash->State = HAL_HASH_STATE_READY; - - } - - /* Process Unlocked */ - __HAL_UNLOCK(hhash); - - /* Return function status */ - return HAL_OK; + return HAL_OK; } else @@ -2051,29 +2544,32 @@ HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint * @brief If not already done, initialize the HASH peripheral then * processes pInBuffer. * @note Field hhash->Phase of HASH handle is tested to check whether or not - * the IP has already been initialized. + * the Peripheral has already been initialized. * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes, must be a multiple of 4. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) { uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ - uint32_t Size_tmp = 0x0; /* input data size (in bytes), input parameter of HASH_WriteData() */ + uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ + HAL_HASH_StateTypeDef State_tmp = hhash->State; /* Make sure the input buffer size (in bytes) is a multiple of 4 */ - assert_param(IS_HASH_POLLING_MULTIBUFFER_SIZE(Size)); - + if ((Size % 4U) != 0U) + { + return HAL_ERROR; + } /* Initiate HASH processing in case of start or resumption */ - if((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ((pInBuffer == NULL) || (Size == 0)) + if ((pInBuffer == NULL) || (Size == 0U)) { hhash->State = HAL_HASH_STATE_READY; return HAL_ERROR; @@ -2118,7 +2614,8 @@ HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, } /* Write input buffer in Data register */ - if ((hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp)) != HAL_OK) + hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); + if (hhash->Status != HAL_OK) { return hhash->Status; } @@ -2146,25 +2643,154 @@ HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, } +/** + * @brief If not already done, initialize the HASH peripheral then + * processes pInBuffer in interruption mode. + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) +{ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + __IO uint32_t inputaddr = (uint32_t) pInBuffer; + uint32_t SizeVar = Size; + + /* Make sure the input buffer size (in bytes) is a multiple of 4 */ + if ((Size % 4U) != 0U) + { + return HAL_ERROR; + } + + /* Initiate HASH processing in case of start or resumption */ + if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* If resuming the HASH processing */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + } + else + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Check if initialization phase has already be performed */ + if(hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT); + hhash->HashITCounter = 1; + } + else + { + hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ + } + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + + /* If DINIS is equal to 0 (for example if an incomplete block has been previously + fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. + Therefore, first words are manually entered until DINIS raises, or until there + is not more data to enter. */ + while((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U)) + { + + /* Write input data 4 bytes at a time */ + HASH->DIN = *(uint32_t*)inputaddr; + inputaddr+=4U; + SizeVar-=4U; + } + + /* If DINIS is still not set or if all the data have been fed, stop here */ + if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U)) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_OK; + } + + /* otherwise, carry on in interrupt-mode */ + hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data + to be fed to the Peripheral */ + hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at + the next interruption */ + /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain + the information describing where the HASH process is stopped. + These variables are used later on to resume the HASH processing at the + correct location. */ + + } + + /* Set multi buffers accumulation flag */ + hhash->Accumulation = 1U; + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Data Input interrupt */ + __HAL_HASH_ENABLE_IT(HASH_IT_DINI); + + /* Return function status */ + return HAL_OK; + + } + else + { + return HAL_BUSY; + } + +} + + + /** * @brief Initialize the HASH peripheral, next process pInBuffer then * read the computed digest in interruption mode. * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm) { + HAL_HASH_StateTypeDef State_tmp = hhash->State; + __IO uint32_t inputaddr = (uint32_t) pInBuffer; + uint32_t polling_step = 0U; + uint32_t initialization_skipped = 0U; + uint32_t SizeVar = Size; /* If State is ready or suspended, start or resume IT-based HASH processing */ - if((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ((pInBuffer == NULL) || (Size == 0) || (pOutBuffer == NULL)) + if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL)) { hhash->State = HAL_HASH_STATE_READY; return HAL_ERROR; @@ -2186,12 +2812,12 @@ HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, u MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT); /* Configure the number of valid bits in last word of the message */ - __HAL_HASH_SET_NBVALIDBITS(Size); + __HAL_HASH_SET_NBVALIDBITS(SizeVar); - hhash->HashInCount = Size; /* Counter used to keep track of number of data - to be fed to the IP */ - hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the IP at + hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data + to be fed to the Peripheral */ + hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at the next interruption */ /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain the information describing where the HASH process is stopped. @@ -2200,10 +2826,82 @@ HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, u hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ } + else + { + initialization_skipped = 1; /* info user later on in case of multi-buffer */ + } /* Set the phase */ hhash->Phase = HAL_HASH_PHASE_PROCESS; + /* If DINIS is equal to 0 (for example if an incomplete block has been previously + fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. + Therefore, first words are manually entered until DINIS raises. */ + while((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U)) + { + polling_step = 1U; /* note that some words are entered before enabling the interrupt */ + + /* Write input data 4 bytes at a time */ + HASH->DIN = *(uint32_t*)inputaddr; + inputaddr+=4U; + SizeVar-=4U; + } + + if (polling_step == 1U) + { + if (SizeVar == 0U) + { + /* If all the data have been entered at this point, it only remains to + read the digest */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + + /* Start the Digest calculation */ + __HAL_HASH_START_DIGEST(); + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Interrupts */ + __HAL_HASH_ENABLE_IT(HASH_IT_DCI); + + /* Return function status */ + return HAL_OK; + } + else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) + { + /* It remains data to enter and the Peripheral is ready to trigger DINIE, + carry on as usual. + Update HashInCount and pHashInBuffPtr accordingly. */ + hhash->HashInCount = SizeVar; + hhash->pHashInBuffPtr = (uint8_t *)inputaddr; + __HAL_HASH_SET_NBVALIDBITS(SizeVar); /* Update the configuration of the number of valid bits in last word of the message */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + if (initialization_skipped == 1U) + { + hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ + } + } + else + { + /* DINIS is not set but it remains a few data to enter (not enough for a full word). + Manually enter the last bytes before enabling DCIE. */ + __HAL_HASH_SET_NBVALIDBITS(SizeVar); + HASH->DIN = *(uint32_t*)inputaddr; + + /* Start the Digest calculation */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + __HAL_HASH_START_DIGEST(); + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Interrupts */ + __HAL_HASH_ENABLE_IT(HASH_IT_DCI); + + /* Return function status */ + return HAL_OK; + } + } /* if (polling_step == 1) */ + + /* Process Unlock */ __HAL_UNLOCK(hhash); @@ -2224,33 +2922,36 @@ HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, u #if 0 /** * @brief Initialize the HASH peripheral then initiate a DMA transfer - * to feed the input buffer to the IP. + * to feed the input buffer to the Peripheral. * @note If MDMAT bit is set before calling this function (multi-buffer * HASH processing case), the input buffer size (in bytes) must be * a multiple of 4 otherwise, the HASH digest computation is corrupted. * For the processing of the last buffer of the thread, MDMAT bit must * be reset and the buffer length (in bytes) doesn't have to be a * multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) { uint32_t inputaddr; - uint32_t inputSize = 0x0; + uint32_t inputSize; + HAL_StatusTypeDef status ; + HAL_HASH_StateTypeDef State_tmp = hhash->State; +#if defined (HASH_CR_MDMAT) /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set (case of multi-buffer HASH processing) */ assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size)); - - /* If State is ready or suspended, start or resume DMA-based HASH processing */ - if ((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) +#endif /* MDMA defined*/ + /* If State is ready or suspended, start or resume polling-based HASH processing */ +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ( (pInBuffer == NULL ) || (Size == 0) || + if ( (pInBuffer == NULL ) || (Size == 0U) || /* Check phase coherency. Phase must be either READY (fresh start) or PROCESS (multi-buffer HASH management) */ @@ -2317,7 +3018,7 @@ HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); /* Enable the DMA In DMA Stream */ - HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (inputSize%4 ? (inputSize+3)/4:inputSize/4)); + status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U))); /* Enable DMA requests */ SET_BIT(HASH->CR, HASH_CR_DMAE); @@ -2326,22 +3027,27 @@ HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, __HAL_UNLOCK(hhash); /* Return function status */ - return HAL_OK; + if (status != HAL_OK) + { + /* Update HASH state machine to error */ + hhash->State = HAL_HASH_STATE_ERROR; + } + + return status; } else { return HAL_BUSY; } - } #endif /** * @brief Return the computed digest. * @note The API waits for DCIS to be set then reads the computed digest. - * @param hhash: HASH handle. - * @param pOutBuffer: pointer to the computed digest. - * @param Timeout: Timeout value. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. + * @param Timeout Timeout value. * @retval HAL status */ HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) @@ -2373,6 +3079,9 @@ HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, ui /* Change the HASH state to ready */ hhash->State = HAL_HASH_STATE_READY; + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; + /* Process UnLock */ __HAL_UNLOCK(hhash); @@ -2394,22 +3103,23 @@ HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, ui * @note Digest is available in pOutBuffer. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. - * @param Timeout: Timeout value. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Timeout Timeout value. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm) { + HAL_HASH_StateTypeDef State_tmp = hhash->State; - /* If State is ready or suspended, start or resume polling-based HASH processing */ - if((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) + /* If State is ready or suspended, start or resume polling-based HASH processing */ +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ((pInBuffer == NULL) || (Size == 0) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0) || (pOutBuffer == NULL)) + if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL)) { hhash->State = HAL_HASH_STATE_READY; return HAL_ERROR; @@ -2425,7 +3135,7 @@ HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint if(hhash->Phase == HAL_HASH_PHASE_READY) { /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ - if(hhash->Init.KeySize > 64) + if(hhash->Init.KeySize > 64U) { MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); } @@ -2435,7 +3145,7 @@ HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint } /* Set the phase to Step 1 */ hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; - /* Resort to hhash internal fields to feed the IP. + /* Resort to hhash internal fields to feed the Peripheral. Parameters will be updated in case of suspension to contain the proper information at resumption time. */ hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ @@ -2464,20 +3174,22 @@ HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint * @note Digest is available in pOutBuffer. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm) { + HAL_HASH_StateTypeDef State_tmp = hhash->State; + /* If State is ready or suspended, start or resume IT-based HASH processing */ - if((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ((pInBuffer == NULL) || (Size == 0) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0) || (pOutBuffer == NULL)) + if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL)) { hhash->State = HAL_HASH_STATE_READY; return HAL_ERROR; @@ -2496,7 +3208,7 @@ HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, u if (hhash->Phase == HAL_HASH_PHASE_READY) { /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ - if(hhash->Init.KeySize > 64) + if(hhash->Init.KeySize > 64U) { MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); } @@ -2506,7 +3218,7 @@ HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, u } /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount - to feed the IP whatever the HMAC step. + to feed the Peripheral whatever the HMAC step. Lines below are set to start HMAC Step 1 processing where key is entered first. */ hhash->HashInCount = hhash->Init.KeySize; /* Key size */ hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */ @@ -2564,33 +3276,33 @@ HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, u #if 0 /** * @brief Initialize the HASH peripheral in HMAC mode then initiate the required - * DMA transfers to feed the key and the input buffer to the IP. + * DMA transfers to feed the key and the input buffer to the Peripheral. * @note Same key is used for the inner and the outer hash functions; pointer to key and * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must * be a multiple of 4 otherwise, the HASH digest computation is corrupted. * Only the length of the last buffer of the thread doesn't have to be a * multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param Algorithm: HASH algorithm. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param Algorithm HASH algorithm. * @retval HAL status */ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) { uint32_t inputaddr; - uint32_t inputSize = 0x0; - + uint32_t inputSize; + HAL_StatusTypeDef status ; + HAL_HASH_StateTypeDef State_tmp = hhash->State; /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */ assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size)); - /* If State is ready or suspended, start or resume DMA-based HASH processing */ - if ((hhash->State == HAL_HASH_STATE_READY) || (hhash->State == HAL_HASH_STATE_SUSPENDED)) +if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) { /* Check input parameters */ - if ((pInBuffer == NULL ) || (Size == 0) || (hhash->Init.pKey == NULL ) || (hhash->Init.KeySize == 0) || + if ((pInBuffer == NULL ) || (Size == 0U) || (hhash->Init.pKey == NULL ) || (hhash->Init.KeySize == 0U) || /* Check phase coherency. Phase must be either READY (fresh start) or one of HMAC PROCESS steps (multi-buffer HASH management) */ @@ -2612,10 +3324,9 @@ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, { /* Change the HASH state */ hhash->State = HAL_HASH_STATE_BUSY; - /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits. At the same time, ensure MDMAT bit is cleared. */ - if(hhash->Init.KeySize > 64) + if(hhash->Init.KeySize > 64U) { MODIFY_REG(HASH->CR, HASH_CR_MDMAT|HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); } @@ -2623,7 +3334,6 @@ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, { MODIFY_REG(HASH->CR, HASH_CR_MDMAT|HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); } - /* Store input aparameters in handle fields to manage steps transition or possible HMAC suspension/resumption */ hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */ @@ -2662,7 +3372,7 @@ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, if (hhash->DigestCalculationDisable == RESET) { /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */ - __HAL_HASH_RESET_MDMAT(); + __HAL_HASH_RESET_MDMAT(); __HAL_HASH_SET_NBVALIDBITS(inputSize); } } @@ -2699,7 +3409,7 @@ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); /* Enable the DMA In DMA Stream */ - HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (inputSize%4 ? (inputSize+3)/4:inputSize/4)); + status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U))); /* Enable DMA requests */ SET_BIT(HASH->CR, HASH_CR_DMAE); @@ -2707,7 +3417,14 @@ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, __HAL_UNLOCK(hhash); /* Return function status */ - return HAL_OK; + if (status != HAL_OK) + { + /* Update HASH state machine to error */ + hhash->State = HAL_HASH_STATE_ERROR; + } + + /* Return function status */ + return status; } else { @@ -2719,16 +3436,16 @@ HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, * @} */ -/** - * @} - */ - -/** - * @} - */ - -#endif /* defined (STM32L4A6xx) */ - #endif /* HAL_HASH_MODULE_ENABLED */ +/** + * @} + */ +#endif /* HASH*/ +/** + * @} + */ + + + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_hash_ex.c b/stm32/mk4-bootloader/stm32l4xx_hal_hash_ex.c deleted file mode 100644 index 5fc1e358..00000000 --- a/stm32/mk4-bootloader/stm32l4xx_hal_hash_ex.c +++ /dev/null @@ -1,939 +0,0 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_hash_ex.c - * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 - * @brief Extended HASH HAL module driver. - * This file provides firmware functions to manage the following - * functionalities of the HASH peripheral for SHA-224 and SHA-256 - * alogrithms: - * + HASH or HMAC processing in polling mode - * + HASH or HMAC processing in interrupt mode - * + HASH or HMAC processing in DMA mode - * Additionally, this file provides functions to manage HMAC - * multi-buffer DMA-based processing for MD-5, SHA-1, SHA-224 - * and SHA-256. - * - * - @verbatim - =============================================================================== - ##### HASH peripheral extended features ##### - =============================================================================== - [..] - The SHA-224 and SHA-256 HASH and HMAC processing can be carried out exactly - the same way as for SHA-1 or MD-5 algorithms. - (#) Three modes are available. - (##) Polling mode: processing APIs are blocking functions - i.e. they process the data and wait till the digest computation is finished, - e.g. HAL_HASHEx_xxx_Start() - (##) Interrupt mode: processing APIs are not blocking functions - i.e. they process the data under interrupt, - e.g. HAL_HASHEx_xxx_Start_IT() - (##) DMA mode: processing APIs are not blocking functions and the CPU is - not used for data transfer i.e. the data transfer is ensured by DMA, - e.g. HAL_HASHEx_xxx_Start_DMA(). Note that in DMA mode, a call to - HAL_HASHEx_xxx_Finish() is then required to retrieve the digest. - - (#)Multi-buffer processing is possible in polling and DMA mode. - (##) In polling mode, only multi-buffer HASH processing is possible. - API HAL_HASHEx_xxx_Accumulate() must be called for each input buffer, except for the last one. - User must resort to HAL_HASHEx_xxx_Start() to enter the last one and retrieve as - well the computed digest. - - (##) In DMA mode, multi-buffer HASH and HMAC processing are possible. - - (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro. - From that point, each buffer can be fed to the IP thru HAL_HASHEx_xxx_Start_DMA() API. - Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT() - macro then wrap-up the HASH processing in feeding the last input buffer thru the - same API HAL_HASHEx_xxx_Start_DMA(). The digest can then be retrieved with a call to - API HAL_HASHEx_xxx_Finish(). - - (+++) HMAC processing (MD-5, SHA-1, SHA-224 and SHA-256 must all resort to - extended functions): after initialization, the key and the first input buffer are entered - in the IP with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and - starts step 2. - The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this - point, the HMAC processing is still carrying out step 2. - Then, step 2 for the last input buffer and step 3 are carried out by a single call - to HAL_HMACEx_xxx_Step2_3_DMA(). - - The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish() for - MD-5 and SHA-1, to HAL_HASHEx_xxx_Finish() for SHA-224 and SHA-256. - - - @endverbatim - ****************************************************************************** - * @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. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32l4xx_hal.h" - -#ifdef HAL_HASH_MODULE_ENABLED - -#if defined (STM32L4A6xx) - -/** @addtogroup STM32L4xx_HAL_Driver - * @{ - */ - -/** @defgroup HASHEx HASHEx - * @brief HASH HAL extended module driver. - * @{ - */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/** @defgroup HASHEx_Exported_Functions HASH Extended Exported Functions - * @{ - */ - - -/** @defgroup HASHEx_Exported_Functions_Group1 HASH extended processing functions in polling mode - * @brief HASH extended processing functions using polling mode. - * -@verbatim - =============================================================================== - ##### Polling mode HASH extended processing functions ##### - =============================================================================== - [..] This section provides functions allowing to calculate in polling mode - the hash value using one of the following algorithms: - (+) SHA224 - (++) HAL_HASHEx_SHA224_Start() - (++) HAL_HASHEx_SHA224_Accumulate() - (+) SHA256 - (++) HAL_HASHEx_SHA256_Start() - (++) HAL_HASHEx_SHA256_Accumulate() - - [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start(). - - [..] In case of multi-buffer HASH processing (a single digest is computed while - several buffers are fed to the IP), the user can resort to successive calls - to HAL_HASHEx_xxx_Accumulate() and wrap-up the digest computation by a call - to HAL_HASHEx_xxx_Start(). - -@endverbatim - * @{ - */ - - -/** - * @brief Initialize the HASH peripheral in SHA224 mode, next process pInBuffer then - * read the computed digest. - * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 28 bytes. - * @param Timeout: Timeout value - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) -{ - return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief If not already done, initialize the HASH peripheral in SHA224 mode then - * processes pInBuffer. - * @note Consecutive calls to HAL_HASHEx_SHA224_Accumulate() can be used to feed - * several input buffers back-to-back to the IP that will yield a single - * HASH signature once all buffers have been entered. Wrap-up of input - * buffers feeding and retrieval of digest is done by a call to - * HAL_HASHEx_SHA224_Start(). - * @note Field hhash->Phase of HASH handle is tested to check whether or not - * the IP has already been initialized. - * @note Digest is not retrieved by this API, user must resort to HAL_HASHEx_SHA224_Start() - * to read it, feeding at the same time the last input buffer to the IP. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. Only HAL_HASHEx_SHA224_Start() is able - * to manage the ending buffer with a length in bytes not a multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes, must be a multiple of 4. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA224_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief Initialize the HASH peripheral in SHA256 mode, next process pInBuffer then - * read the computed digest. - * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 32 bytes. - * @param Timeout: Timeout value - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) -{ - return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256); -} - -/** - * @brief If not already done, initialize the HASH peripheral in SHA256 mode then - * processes pInBuffer. - * @note Consecutive calls to HAL_HASHEx_SHA256_Accumulate() can be used to feed - * several input buffers back-to-back to the IP that will yield a single - * HASH signature once all buffers have been entered. Wrap-up of input - * buffers feeding and retrieval of digest is done by a call to - * HAL_HASHEx_SHA256_Start(). - * @note Field hhash->Phase of HASH handle is tested to check whether or not - * the IP has already been initialized. - * @note Digest is not retrieved by this API, user must resort to HAL_HASHEx_SHA256_Start() - * to read it, feeding at the same time the last input buffer to the IP. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. Only HAL_HASHEx_SHA256_Start() is able - * to manage the ending buffer with a length in bytes not a multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes, must be a multiple of 4. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA256_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA256); -} - - -/** - * @} - */ - -/** @defgroup HASHEx_Exported_Functions_Group2 HASH extended processing functions in interrupt mode - * @brief HASH extended processing functions using interrupt mode. - * -@verbatim - =============================================================================== - ##### Interruption mode HASH extended processing functions ##### - =============================================================================== - [..] This section provides functions allowing to calculate in interrupt mode - the hash value using one of the following algorithms: - (+) SHA224 - (++) HAL_HASHEx_SHA224_Start_IT() - (+) SHA256 - (++) HAL_HASHEx_SHA256_Start_IT() - -@endverbatim - * @{ - */ - - -/** - * @brief Initialize the HASH peripheral in SHA224 mode, next process pInBuffer then - * read the computed digest in interruption mode. - * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 28 bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) -{ - return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief Initialize the HASH peripheral in SHA256 mode, next process pInBuffer then - * read the computed digest in interruption mode. - * @note Digest is available in pOutBuffer. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 32 bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) -{ - return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA256); -} - -/** - * @} - */ - -#if 0 -/** @defgroup HASHEx_Exported_Functions_Group3 HASH extended processing functions in DMA mode - * @brief HASH extended processing functions using DMA mode. - * -@verbatim - =============================================================================== - ##### DMA mode HASH extended processing functionss ##### - =============================================================================== - [..] This section provides functions allowing to calculate in DMA mode - the hash value using one of the following algorithms: - (+) SHA224 - (++) HAL_HASHEx_SHA224_Start_DMA() - (++) HAL_HASHEx_SHA224_Finish() - (+) SHA256 - (++) HAL_HASHEx_SHA256_Start_DMA() - (++) HAL_HASHEx_SHA256_Finish() - - [..] When resorting to DMA mode to enter the data in the IP, user must resort - to HAL_HASHEx_xxx_Start_DMA() then read the resulting digest with - HAL_HASHEx_xxx_Finish(). - - [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before - the successive calls to HAL_HASHEx_xxx_Start_DMA(). Then, MDMAT bit needs to be - reset before the last call to HAL_HASHEx_xxx_Start_DMA(). Digest is finally - retrieved thanks to HAL_HASHEx_xxx_Finish(). - -@endverbatim - * @{ - */ - - - - -/** - * @brief Initialize the HASH peripheral in SHA224 mode then initiate a DMA transfer - * to feed the input buffer to the IP. - * @note Once the DMA transfer is finished, HAL_HASHEx_SHA224_Finish() API must - * be called to retrieve the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); -} -#endif - -/** - * @brief Return the computed digest in SHA224 mode. - * @note The API waits for DCIS to be set then reads the computed digest. - * @note HAL_HASHEx_SHA224_Finish() can be used as well to retrieve the digest in - * HMAC SHA224 mode. - * @param hhash: HASH handle. - * @param pOutBuffer: pointer to the computed digest. Digest size is 28 bytes. - * @param Timeout: Timeout value. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) -{ - return HASH_Finish(hhash, pOutBuffer, Timeout); -} - -#if 0 -/** - * @brief Initialize the HASH peripheral in SHA256 mode then initiate a DMA transfer - * to feed the input buffer to the IP. - * @note Once the DMA transfer is finished, HAL_HASHEx_SHA256_Finish() API must - * be called to retrieve the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); -} -#endif - -/** - * @brief Return the computed digest in SHA256 mode. - * @note The API waits for DCIS to be set then reads the computed digest. - * @note HAL_HASHEx_SHA256_Finish() can be used as well to retrieve the digest in - * HMAC SHA256 mode. - * @param hhash: HASH handle. - * @param pOutBuffer: pointer to the computed digest. Digest size is 32 bytes. - * @param Timeout: Timeout value. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout) -{ - return HASH_Finish(hhash, pOutBuffer, Timeout); -} - -/** - * @} - */ - -/** @defgroup HASHEx_Exported_Functions_Group4 HMAC extended processing functions in polling mode - * @brief HMAC extended processing functions using polling mode. - * -@verbatim - =============================================================================== - ##### Polling mode HMAC extended processing functions ##### - =============================================================================== - [..] This section provides functions allowing to calculate in polling mode - the HMAC value using one of the following algorithms: - (+) SHA224 - (++) HAL_HMACEx_SHA224_Start() - (+) SHA256 - (++) HAL_HMACEx_SHA256_Start() - -@endverbatim - * @{ - */ - - - -/** - * @brief Initialize the HASH peripheral in HMAC SHA224 mode, next process pInBuffer then - * read the computed digest. - * @note Digest is available in pOutBuffer. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 28 bytes. - * @param Timeout: Timeout value. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) -{ - return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief Initialize the HASH peripheral in HMAC SHA256 mode, next process pInBuffer then - * read the computed digest. - * @note Digest is available in pOutBuffer. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 32 bytes. - * @param Timeout: Timeout value. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout) -{ - return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256); -} - -/** - * @} - */ - - -/** @defgroup HASHEx_Exported_Functions_Group5 HMAC extended processing functions in interrupt mode - * @brief HMAC extended processing functions using interruption mode. - * -@verbatim - =============================================================================== - ##### Interrupt mode HMAC extended processing functions ##### - =============================================================================== - [..] This section provides functions allowing to calculate in interrupt mode - the HMAC value using one of the following algorithms: - (+) SHA224 - (++) HAL_HMACEx_SHA224_Start_IT() - (+) SHA256 - (++) HAL_HMACEx_SHA256_Start_IT() - -@endverbatim - * @{ - */ - - - -/** - * @brief Initialize the HASH peripheral in HMAC SHA224 mode, next process pInBuffer then - * read the computed digest in interrupt mode. - * @note Digest is available in pOutBuffer. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 28 bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) -{ - return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief Initialize the HASH peripheral in HMAC SHA256 mode, next process pInBuffer then - * read the computed digest in interrupt mode. - * @note Digest is available in pOutBuffer. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @param pOutBuffer: pointer to the computed digest. Digest size is 32 bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer) -{ - return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA256); -} - - - - -/** - * @} - */ - - -/** @defgroup HASHEx_Exported_Functions_Group6 HMAC extended processing functions in DMA mode - * @brief HMAC extended processing functions using DMA mode. - * -@verbatim - =============================================================================== - ##### DMA mode HMAC extended processing functions ##### - =============================================================================== - [..] This section provides functions allowing to calculate in DMA mode - the HMAC value using one of the following algorithms: - (+) SHA224 - (++) HAL_HMACEx_SHA224_Start_DMA() - (+) SHA256 - (++) HAL_HMACEx_SHA256_Start_DMA() - - [..] When resorting to DMA mode to enter the data in the IP for HMAC processing, - user must resort to HAL_HMACEx_xxx_Start_DMA() then read the resulting digest - with HAL_HASHEx_xxx_Finish(). - - -@endverbatim - * @{ - */ - - -#if 0 -/** - * @brief Initialize the HASH peripheral in HMAC SHA224 mode then initiate the required - * DMA transfers to feed the key and the input buffer to the IP. - * @note Once the DMA transfers are finished (indicated by hhash->State set back - * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA224_Finish() API must be called to retrieve - * the computed digest. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note If MDMAT bit is set before calling this function (multi-buffer - * HASH processing case), the input buffer size (in bytes) must be - * a multiple of 4 otherwise, the HASH digest computation is corrupted. - * For the processing of the last buffer of the thread, MDMAT bit must - * be reset and the buffer length (in bytes) doesn't have to be a - * multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief Initialize the HASH peripheral in HMAC SHA224 mode then initiate the required - * DMA transfers to feed the key and the input buffer to the IP. - * @note Once the DMA transfers are finished (indicated by hhash->State set back - * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve - * the computed digest. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note If MDMAT bit is set before calling this function (multi-buffer - * HASH processing case), the input buffer size (in bytes) must be - * a multiple of 4 otherwise, the HASH digest computation is corrupted. - * For the processing of the last buffer of the thread, MDMAT bit must - * be reset and the buffer length (in bytes) doesn't have to be a - * multiple of 4. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (buffer to be hashed). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); -} - - -/** - * @} - */ - -/** @defgroup HASHEx_Exported_Functions_Group7 Multi-buffer HMAC extended processing functions in DMA mode - * @brief HMAC extended processing functions in multi-buffer DMA mode. - * -@verbatim - =============================================================================== - ##### Multi-buffer DMA mode HMAC extended processing functions ##### - =============================================================================== - [..] This section provides functions to manage HMAC multi-buffer - DMA-based processing for MD5, SHA1, SHA224 and SHA256 algorithms. - (+) MD5 - (++) HAL_HMACEx_MD5_Step1_2_DMA() - (++) HAL_HMACEx_MD5_Step2_DMA() - (++) HAL_HMACEx_MD5_Step2_3_DMA() - (+) SHA1 - (++) HAL_HMACEx_SHA1_Step1_2_DMA() - (++) HAL_HMACEx_SHA1_Step2_DMA() - (++) HAL_HMACEx_SHA1_Step2_3_DMA() - (+) SHA256 - (++) HAL_HMACEx_SHA224_Step1_2_DMA() - (++) HAL_HMACEx_SHA224_Step2_DMA() - (++) HAL_HMACEx_SHA224_Step2_3_DMA() - (+) SHA256 - (++) HAL_HMACEx_SHA256_Step1_2_DMA() - (++) HAL_HMACEx_SHA256_Step2_DMA() - (++) HAL_HMACEx_SHA256_Step2_3_DMA() - - [..] User must first start-up the multi-buffer DMA-based HMAC computation in - calling HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and - intiates step 2 with the first input buffer. - - [..] The following buffers are next fed to the IP with a call to the API - HAL_HMACEx_xxx_Step2_DMA(). There may be several consecutive calls - to this API. - - [..] Multi-buffer DMA-based HMAC computation is wrapped up by a call to - HAL_HMACEx_xxx_Step2_3_DMA(). This finishes step 2 in feeding the last input - buffer to the IP then carries out step 3. - - [..] Digest is retrieved by a call to HAL_HASH_xxx_Finish() for MD-5 or - SHA-1, to HAL_HASHEx_xxx_Finish() for SHA-224 or SHA-256. - - [..] If only two buffers need to be consecutively processed, a call to - HAL_HMACEx_xxx_Step1_2_DMA() followed by a call to HAL_HMACEx_xxx_Step2_3_DMA() - is sufficient. - -@endverbatim - * @{ - */ - -/** - * @brief MD5 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. - * @note Step 1 consists in writing the inner hash function key in the IP, - * step 2 consists in writing the message text. - * @note The API carries out the HMAC step 1 then starts step 2 with - * the first buffer entered to the IP. DCAL bit is not automatically set after - * the message buffer feeding, allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_MD5_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = SET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); -} - -/** - * @brief MD5 HMAC step 2 in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP. - * @note The API carries on the HMAC step 2, applied to the buffer entered as input - * parameter. DCAL bit is not automatically set after the message buffer feeding, - * allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - if (hhash->DigestCalculationDisable != SET) - { - return HAL_ERROR; - } - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); -} - -/** - * @brief MD5 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP, - * step 3 consists in writing the outer hash function key. - * @note The API wraps up the HMAC step 2 in processing the buffer entered as input - * parameter (the input buffer must be the last one of the multi-buffer thread) - * then carries out HMAC step 3. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note Once the DMA transfers are finished (indicated by hhash->State set back - * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve - * the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = RESET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); -} - - -/** - * @brief SHA1 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. - * @note Step 1 consists in writing the inner hash function key in the IP, - * step 2 consists in writing the message text. - * @note The API carries out the HMAC step 1 then starts step 2 with - * the first buffer entered to the IP. DCAL bit is not automatically set after - * the message buffer feeding, allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA1_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = SET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); -} - -/** - * @brief SHA1 HMAC step 2 in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP. - * @note The API carries on the HMAC step 2, applied to the buffer entered as input - * parameter. DCAL bit is not automatically set after the message buffer feeding, - * allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - if (hhash->DigestCalculationDisable != SET) - { - return HAL_ERROR; - } - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); -} - -/** - * @brief SHA1 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP, - * step 3 consists in writing the outer hash function key. - * @note The API wraps up the HMAC step 2 in processing the buffer entered as input - * parameter (the input buffer must be the last one of the multi-buffer thread) - * then carries out HMAC step 3. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note Once the DMA transfers are finished (indicated by hhash->State set back - * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve - * the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = RESET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); -} - -/** - * @brief SHA224 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. - * @note Step 1 consists in writing the inner hash function key in the IP, - * step 2 consists in writing the message text. - * @note The API carries out the HMAC step 1 then starts step 2 with - * the first buffer entered to the IP. DCAL bit is not automatically set after - * the message buffer feeding, allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA224_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = SET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief SHA224 HMAC step 2 in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP. - * @note The API carries on the HMAC step 2, applied to the buffer entered as input - * parameter. DCAL bit is not automatically set after the message buffer feeding, - * allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - if (hhash->DigestCalculationDisable != SET) - { - return HAL_ERROR; - } - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief SHA224 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP, - * step 3 consists in writing the outer hash function key. - * @note The API wraps up the HMAC step 2 in processing the buffer entered as input - * parameter (the input buffer must be the last one of the multi-buffer thread) - * then carries out HMAC step 3. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note Once the DMA transfers are finished (indicated by hhash->State set back - * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve - * the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = RESET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); -} - -/** - * @brief SHA256 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. - * @note Step 1 consists in writing the inner hash function key in the IP, - * step 2 consists in writing the message text. - * @note The API carries out the HMAC step 1 then starts step 2 with - * the first buffer entered to the IP. DCAL bit is not automatically set after - * the message buffer feeding, allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA256_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = SET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); -} - -/** - * @brief SHA256 HMAC step 2 in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP. - * @note The API carries on the HMAC step 2, applied to the buffer entered as input - * parameter. DCAL bit is not automatically set after the message buffer feeding, - * allowing other messages DMA transfers to occur. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the - * HASH digest computation is corrupted. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - if (hhash->DigestCalculationDisable != SET) - { - return HAL_ERROR; - } - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); -} - -/** - * @brief SHA256 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. - * @note Step 2 consists in writing the message text in the IP, - * step 3 consists in writing the outer hash function key. - * @note The API wraps up the HMAC step 2 in processing the buffer entered as input - * parameter (the input buffer must be the last one of the multi-buffer thread) - * then carries out HMAC step 3. - * @note Same key is used for the inner and the outer hash functions; pointer to key and - * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. - * @note Once the DMA transfers are finished (indicated by hhash->State set back - * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve - * the computed digest. - * @param hhash: HASH handle. - * @param pInBuffer: pointer to the input buffer (message buffer). - * @param Size: length of the input buffer in bytes. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) -{ - hhash->DigestCalculationDisable = RESET; - return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); -} -#endif - -/** - * @} - */ - - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#endif /* defined (STM32L4A6xx) */ - -#endif /* HAL_HASH_MODULE_ENABLED */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_ospi.c b/stm32/mk4-bootloader/stm32l4xx_hal_ospi.c new file mode 100644 index 00000000..84677d45 --- /dev/null +++ b/stm32/mk4-bootloader/stm32l4xx_hal_ospi.c @@ -0,0 +1,3213 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_ospi.c + * @author MCD Application Team + * @brief OSPI HAL module driver. + This file provides firmware functions to manage the following + functionalities of the OctoSPI interface (OSPI). + + Initialization and de-initialization functions + + Hyperbus configuration + + Indirect functional mode management + + Memory-mapped functional mode management + + Auto-polling functional mode management + + Interrupts and flags management + + DMA channel configuration for indirect functional mode + + Errors management and abort functionality + + IO manager configuration + + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + *** Initialization *** + ====================== + [..] + As prerequisite, fill in the HAL_OSPI_MspInit() : + (+) Enable OctoSPI and OctoSPIM clocks interface with __HAL_RCC_OSPIx_CLK_ENABLE(). + (+) Reset OctoSPI Peripheral with __HAL_RCC_OSPIx_FORCE_RESET() and __HAL_RCC_OSPIx_RELEASE_RESET(). + (+) Enable the clocks for the OctoSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE(). + (+) Configure these OctoSPI pins in alternate mode using HAL_GPIO_Init(). + (+) If interrupt or DMA mode is used, enable and configure OctoSPI global + interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). + (+) If DMA mode is used, enable the clocks for the OctoSPI DMA channel + with __HAL_RCC_DMAx_CLK_ENABLE(), configure DMA with HAL_DMA_Init(), + link it with OctoSPI handle using __HAL_LINKDMA(), enable and configure + DMA channel global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). + [..] + Configure the fifo threshold, the dual-quad mode, the memory type, the + device size, the CS high time, the free running clock, the clock mode, + the wrap size, the clock prescaler, the sample shifting, the hold delay + and the CS boundary using the HAL_OSPI_Init() function. + [..] + When using Hyperbus, configure the RW recovery time, the access time, + the write latency and the latency mode unsing the HAL_OSPI_HyperbusCfg() + function. + + *** Indirect functional mode *** + ================================ + [..] + In regular mode, configure the command sequence using the HAL_OSPI_Command() + or HAL_OSPI_Command_IT() functions : + (+) Instruction phase : the mode used and if present the size, the instruction + opcode and the DTR mode. + (+) Address phase : the mode used and if present the size, the address + value and the DTR mode. + (+) Alternate-bytes phase : the mode used and if present the size, the + alternate bytes values and the DTR mode. + (+) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). + (+) Data phase : the mode used and if present the number of bytes and the DTR mode. + (+) Data strobe (DQS) mode : the activation (or not) of this mode + (+) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. + (+) Flash identifier : in dual-quad mode, indicates which flash is concerned + (+) Operation type : always common configuration + [..] + In Hyperbus mode, configure the command sequence using the HAL_OSPI_HyperbusCmd() + function : + (+) Address space : indicate if the access will be done in register or memory + (+) Address size + (+) Number of data + (+) Data strobe (DQS) mode : the activation (or not) of this mode + [..] + If no data is required for the command (only for regular mode, not for + Hyperbus mode), it is sent directly to the memory : + (+) In polling mode, the output of the function is done when the transfer is complete. + (+) In interrupt mode, HAL_OSPI_CmdCpltCallback() will be called when the transfer is complete. + [..] + For the indirect write mode, use HAL_OSPI_Transmit(), HAL_OSPI_Transmit_DMA() or + HAL_OSPI_Transmit_IT() after the command configuration : + (+) In polling mode, the output of the function is done when the transfer is complete. + (+) In interrupt mode, HAL_OSPI_FifoThresholdCallback() will be called when the fifo threshold + is reached and HAL_OSPI_TxCpltCallback() will be called when the transfer is complete. + (+) In DMA mode, HAL_OSPI_TxHalfCpltCallback() will be called at the half transfer and + HAL_OSPI_TxCpltCallback() will be called when the transfer is complete. + [..] + For the indirect read mode, use HAL_OSPI_Receive(), HAL_OSPI_Receive_DMA() or + HAL_OSPI_Receive_IT() after the command configuration : + (+) In polling mode, the output of the function is done when the transfer is complete. + (+) In interrupt mode, HAL_OSPI_FifoThresholdCallback() will be called when the fifo threshold + is reached and HAL_OSPI_RxCpltCallback() will be called when the transfer is complete. + (+) In DMA mode, HAL_OSPI_RxHalfCpltCallback() will be called at the half transfer and + HAL_OSPI_RxCpltCallback() will be called when the transfer is complete. + + *** Auto-polling functional mode *** + ==================================== + [..] + Configure the command sequence by the same way than the indirect mode + [..] + Configure the auto-polling functional mode using the HAL_OSPI_AutoPolling() + or HAL_OSPI_AutoPolling_IT() functions : + (+) The size of the status bytes, the match value, the mask used, the match mode (OR/AND), + the polling interval and the automatic stop activation. + [..] + After the configuration : + (+) In polling mode, the output of the function is done when the status match is reached. The + automatic stop is activated to avoid an infinite loop. + (+) In interrupt mode, HAL_OSPI_StatusMatchCallback() will be called each time the status match is reached. + + *** Memory-mapped functional mode *** + ===================================== + [..] + Configure the command sequence by the same way than the indirect mode except + for the operation type in regular mode : + (+) Operation type equals to read configuration : the command configuration + applies to read access in memory-mapped mode + (+) Operation type equals to write configuration : the command configuration + applies to write access in memory-mapped mode + (+) Both read and write configuration should be performed before activating + memory-mapped mode + [..] + Configure the memory-mapped functional mode using the HAL_OSPI_MemoryMapped() + functions : + (+) The timeout activation and the timeout period. + [..] + After the configuration, the OctoSPI will be used as soon as an access on the AHB is done on + the address range. HAL_OSPI_TimeOutCallback() will be called when the timeout expires. + + *** Errors management and abort functionality *** + ================================================= + [..] + HAL_OSPI_GetError() function gives the error raised during the last operation. + [..] + HAL_OSPI_Abort() and HAL_OSPI_AbortIT() functions aborts any on-going operation and + flushes the fifo : + (+) In polling mode, the output of the function is done when the transfer + complete bit is set and the busy bit cleared. + (+) In interrupt mode, HAL_OSPI_AbortCpltCallback() will be called when + the transfer complete bit is set. + + *** Control functions *** + ========================= + [..] + HAL_OSPI_GetState() function gives the current state of the HAL OctoSPI driver. + [..] + HAL_OSPI_SetTimeout() function configures the timeout value used in the driver. + [..] + HAL_OSPI_SetFifoThreshold() function configures the threshold on the Fifo of the OSPI Peripheral. + [..] + HAL_OSPI_GetFifoThreshold() function gives the current of the Fifo's threshold + + *** IO manager configuration functions *** + ========================================== + [..] + HAL_OSPIM_Config() function configures the IO manager for the OctoSPI instance. + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_OSPI_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use function HAL_OSPI_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) FifoThresholdCallback : callback when the fifo threshold is reached. + (+) CmdCpltCallback : callback when a command without data is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxHalfCpltCallback : callback when half of the reception transfer is completed. + (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed. + (+) StatusMatchCallback : callback when a status match occurs. + (+) TimeOutCallback : callback when the timeout perioed expires. + (+) MspInitCallback : OSPI MspInit. + (+) MspDeInitCallback : OSPI MspDeInit. + [..] + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_OSPI_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) FifoThresholdCallback : callback when the fifo threshold is reached. + (+) CmdCpltCallback : callback when a command without data is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxHalfCpltCallback : callback when half of the reception transfer is completed. + (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed. + (+) StatusMatchCallback : callback when a status match occurs. + (+) TimeOutCallback : callback when the timeout perioed expires. + (+) MspInitCallback : OSPI MspInit. + (+) MspDeInitCallback : OSPI MspDeInit. + [..] + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + [..] + By default, after the HAL_OSPI_Init() and if the state is HAL_OSPI_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_OSPI_Init() + and HAL_OSPI_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_OSPI_Init() and HAL_OSPI_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + [..] + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used + during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_OSPI_RegisterCallback() before calling HAL_OSPI_DeInit() + or HAL_OSPI_Init() function. + + [..] + When The compilation define USE_HAL_OSPI_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2018 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +#if defined(OCTOSPI) || defined(OCTOSPI1) || defined(OCTOSPI2) + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup OSPI OSPI + * @brief OSPI HAL module driver + * @{ + */ + +#ifdef HAL_OSPI_MODULE_ENABLED + +/** + @cond 0 + */ +/* Private typedef -----------------------------------------------------------*/ + +/* Private define ------------------------------------------------------------*/ +#define OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE ((uint32_t)0x00000000) /*!< Indirect write mode */ +#define OSPI_FUNCTIONAL_MODE_INDIRECT_READ ((uint32_t)OCTOSPI_CR_FMODE_0) /*!< Indirect read mode */ +#define OSPI_FUNCTIONAL_MODE_AUTO_POLLING ((uint32_t)OCTOSPI_CR_FMODE_1) /*!< Automatic polling mode */ +#define OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED ((uint32_t)OCTOSPI_CR_FMODE) /*!< Memory-mapped mode */ + +#define OSPI_CFG_STATE_MASK 0x00000004U +#define OSPI_BUSY_STATE_MASK 0x00000008U + +#define OSPI_NB_INSTANCE 2U +#define OSPI_IOM_NB_PORTS 2U +#define OSPI_IOM_PORT_MASK 0x1U + +/* Private macro -------------------------------------------------------------*/ +#define IS_OSPI_FUNCTIONAL_MODE(MODE) (((MODE) == OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE) || \ + ((MODE) == OSPI_FUNCTIONAL_MODE_INDIRECT_READ) || \ + ((MODE) == OSPI_FUNCTIONAL_MODE_AUTO_POLLING) || \ + ((MODE) == OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)) + +/* Private variables ---------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +#if 0 +static void OSPI_DMACplt (DMA_HandleTypeDef *hdma); +static void OSPI_DMAHalfCplt (DMA_HandleTypeDef *hdma); +static void OSPI_DMAError (DMA_HandleTypeDef *hdma); +static void OSPI_DMAAbortCplt (DMA_HandleTypeDef *hdma); +#endif +static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag, FlagStatus State, uint32_t Tickstart, uint32_t Timeout); +static HAL_StatusTypeDef OSPI_ConfigCmd (OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd); +static HAL_StatusTypeDef OSPIM_GetConfig (uint8_t instance_nb, OSPIM_CfgTypeDef *cfg); +/** + @endcond + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup OSPI_Exported_Functions OSPI Exported Functions + * @{ + */ + +/** @defgroup OSPI_Exported_Functions_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to : + (+) Initialize the OctoSPI. + (+) De-initialize the OctoSPI. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the OSPI mode according to the specified parameters + * in the OSPI_InitTypeDef and initialize the associated handle. + * @param hospi : OSPI handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Init (OSPI_HandleTypeDef *hospi) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart = HAL_GetTick(); + + /* Check the OSPI handle allocation */ + if (hospi == NULL) + { + status = HAL_ERROR; + /* No error code can be set set as the handler is null */ + } + else + { + /* Check the parameters of the initialization structure */ + assert_param(IS_OSPI_FIFO_THRESHOLD (hospi->Init.FifoThreshold)); + assert_param(IS_OSPI_DUALQUAD_MODE (hospi->Init.DualQuad)); + assert_param(IS_OSPI_MEMORY_TYPE (hospi->Init.MemoryType)); + assert_param(IS_OSPI_DEVICE_SIZE (hospi->Init.DeviceSize)); + assert_param(IS_OSPI_CS_HIGH_TIME (hospi->Init.ChipSelectHighTime)); + assert_param(IS_OSPI_FREE_RUN_CLK (hospi->Init.FreeRunningClock)); + assert_param(IS_OSPI_CLOCK_MODE (hospi->Init.ClockMode)); + assert_param(IS_OSPI_CLK_PRESCALER (hospi->Init.ClockPrescaler)); + assert_param(IS_OSPI_SAMPLE_SHIFTING(hospi->Init.SampleShifting)); + assert_param(IS_OSPI_DHQC (hospi->Init.DelayHoldQuarterCycle)); + assert_param(IS_OSPI_CS_BOUNDARY (hospi->Init.ChipSelectBoundary)); + assert_param(IS_OSPI_DLYBYP (hospi->Init.DelayBlockBypass)); +#if defined (OCTOSPI_DCR3_MAXTRAN) + assert_param(IS_OSPI_MAXTRAN (hospi->Init.MaxTran)); +#endif + + /* Initialize error code */ + hospi->ErrorCode = HAL_OSPI_ERROR_NONE; + + /* Check if the state is the reset state */ + if (hospi->State == HAL_OSPI_STATE_RESET) + { +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + /* Reset Callback pointers in HAL_OSPI_STATE_RESET only */ + hospi->ErrorCallback = HAL_OSPI_ErrorCallback; + hospi->AbortCpltCallback = HAL_OSPI_AbortCpltCallback; + hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback; + hospi->CmdCpltCallback = HAL_OSPI_CmdCpltCallback; + hospi->RxCpltCallback = HAL_OSPI_RxCpltCallback; + hospi->TxCpltCallback = HAL_OSPI_TxCpltCallback; + hospi->RxHalfCpltCallback = HAL_OSPI_RxHalfCpltCallback; + hospi->TxHalfCpltCallback = HAL_OSPI_TxHalfCpltCallback; + hospi->StatusMatchCallback = HAL_OSPI_StatusMatchCallback; + hospi->TimeOutCallback = HAL_OSPI_TimeOutCallback; + + if(hospi->MspInitCallback == NULL) + { + hospi->MspInitCallback = HAL_OSPI_MspInit; + } + + /* Init the low level hardware */ + hospi->MspInitCallback(hospi); +#else + /* Initialization of the low level hardware */ + HAL_OSPI_MspInit(hospi); +#endif + + /* Configure the default timeout for the OSPI memory access */ + (void)HAL_OSPI_SetTimeout(hospi, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); + + /* Configure memory type, device size, chip select high time, delay block bypass, free running clock, clock mode */ + MODIFY_REG(hospi->Instance->DCR1, + (OCTOSPI_DCR1_MTYP | OCTOSPI_DCR1_DEVSIZE | OCTOSPI_DCR1_CSHT | OCTOSPI_DCR1_DLYBYP | + OCTOSPI_DCR1_FRCK | OCTOSPI_DCR1_CKMODE), + (hospi->Init.MemoryType | ((hospi->Init.DeviceSize - 1U) << OCTOSPI_DCR1_DEVSIZE_Pos) | + ((hospi->Init.ChipSelectHighTime - 1U) << OCTOSPI_DCR1_CSHT_Pos) | + hospi->Init.DelayBlockBypass | hospi->Init.ClockMode)); + +#if defined (OCTOSPI_DCR3_MAXTRAN) + /* Configure chip select boundary and maximun transfer */ + hospi->Instance->DCR3 = ((hospi->Init.ChipSelectBoundary << OCTOSPI_DCR3_CSBOUND_Pos) | (hospi->Init.MaxTran << OCTOSPI_DCR3_MAXTRAN_Pos)); +#else + /* Configure chip select boundary */ + hospi->Instance->DCR3 = (hospi->Init.ChipSelectBoundary << OCTOSPI_DCR3_CSBOUND_Pos); +#endif + +#if defined (OCTOSPI_DCR4_REFRESH) + /* Configure refresh */ + hospi->Instance->DCR4 = hospi->Init.Refresh; +#endif + + /* Configure FIFO threshold */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold - 1U) << OCTOSPI_CR_FTHRES_Pos)); + + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout); + + if (status == HAL_OK) + { + /* Configure clock prescaler */ + MODIFY_REG(hospi->Instance->DCR2, OCTOSPI_DCR2_PRESCALER, ((hospi->Init.ClockPrescaler - 1U) << OCTOSPI_DCR2_PRESCALER_Pos)); + + /* Configure Dual Quad mode */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_DQM, hospi->Init.DualQuad); + + /* Configure sample shifting and delay hold quarter cycle */ + MODIFY_REG(hospi->Instance->TCR, (OCTOSPI_TCR_SSHIFT | OCTOSPI_TCR_DHQC), (hospi->Init.SampleShifting | hospi->Init.DelayHoldQuarterCycle)); + + /* Enable OctoSPI */ + __HAL_OSPI_ENABLE(hospi); + + /* Enable free running clock if needed : must be done after OSPI enable */ + if (hospi->Init.FreeRunningClock == HAL_OSPI_FREERUNCLK_ENABLE) + { + SET_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK); + } + + /* Initialize the OSPI state */ + if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS) + { + hospi->State = HAL_OSPI_STATE_HYPERBUS_INIT; + } + else + { + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Initialize the OSPI MSP. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_MspInit(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OSPI_MspInit can be implemented in the user file + */ +} + +/** + * @brief De-Initialize the OSPI peripheral. + * @param hospi : OSPI handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_DeInit(OSPI_HandleTypeDef *hospi) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the OSPI handle allocation */ + if (hospi == NULL) + { + status = HAL_ERROR; + /* No error code can be set set as the handler is null */ + } + else + { + /* Disable OctoSPI */ + __HAL_OSPI_DISABLE(hospi); + + /* Disable free running clock if needed : must be done after OSPI disable */ + CLEAR_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK); + +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + if(hospi->MspDeInitCallback == NULL) + { + hospi->MspDeInitCallback = HAL_OSPI_MspDeInit; + } + + /* DeInit the low level hardware */ + hospi->MspDeInitCallback(hospi); +#else + /* De-initialize the low-level hardware */ + HAL_OSPI_MspDeInit(hospi); +#endif + + /* Reset the driver state */ + hospi->State = HAL_OSPI_STATE_RESET; + } + + return status; +} + +/** + * @brief DeInitialize the OSPI MSP. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_MspDeInit(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OSPI_MspDeInit can be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup OSPI_Exported_Functions_Group2 Input and Output operation functions + * @brief OSPI Transmit/Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to : + (+) Handle the interrupts. + (+) Handle the command sequence (regular and Hyperbus). + (+) Handle the Hyperbus configuration. + (+) Transmit data in blocking, interrupt or DMA mode. + (+) Receive data in blocking, interrupt or DMA mode. + (+) Manage the auto-polling functional mode. + (+) Manage the memory-mapped functional mode. + +@endverbatim + * @{ + */ + +#if 0 +/** + * @brief Handle OSPI interrupt request. + * @param hospi : OSPI handle + * @retval None + */ +void HAL_OSPI_IRQHandler(OSPI_HandleTypeDef *hospi) +{ + __IO uint32_t *data_reg = &hospi->Instance->DR; + uint32_t flag = hospi->Instance->SR; + uint32_t itsource = hospi->Instance->CR; + uint32_t currentstate = hospi->State; + + /* OctoSPI fifo threshold interrupt occurred -------------------------------*/ + if (((flag & HAL_OSPI_FLAG_FT) != 0U) && ((itsource & HAL_OSPI_IT_FT) != 0U)) + { + if (currentstate == HAL_OSPI_STATE_BUSY_TX) + { + /* Write a data in the fifo */ + *((__IO uint8_t *)data_reg) = *hospi->pBuffPtr; + hospi->pBuffPtr++; + hospi->XferCount--; + } + else if (currentstate == HAL_OSPI_STATE_BUSY_RX) + { + /* Read a data from the fifo */ + *hospi->pBuffPtr = *((__IO uint8_t *)data_reg); + hospi->pBuffPtr++; + hospi->XferCount--; + } + else + { + /* Nothing to do */ + } + + if (hospi->XferCount == 0U) + { + /* All data have been received or transmitted for the transfer */ + /* Disable fifo threshold interrupt */ + __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_FT); + } + + /* Fifo threshold callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->FifoThresholdCallback(hospi); +#else + HAL_OSPI_FifoThresholdCallback(hospi); +#endif + } + /* OctoSPI transfer complete interrupt occurred ----------------------------*/ + else if (((flag & HAL_OSPI_FLAG_TC) != 0U) && ((itsource & HAL_OSPI_IT_TC) != 0U)) + { + if (currentstate == HAL_OSPI_STATE_BUSY_RX) + { + if ((hospi->XferCount > 0U) && ((flag & OCTOSPI_SR_FLEVEL) != 0U)) + { + /* Read the last data received in the fifo */ + *hospi->pBuffPtr = *((__IO uint8_t *)data_reg); + hospi->pBuffPtr++; + hospi->XferCount--; + } + else if(hospi->XferCount == 0U) + { + /* Clear flag */ + hospi->Instance->FCR = HAL_OSPI_FLAG_TC; + + /* Disable the interrupts */ + __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* RX complete callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->RxCpltCallback(hospi); +#else + HAL_OSPI_RxCpltCallback(hospi); +#endif + } + else + { + /* Nothing to do */ + } + } + else + { + /* Clear flag */ + hospi->Instance->FCR = HAL_OSPI_FLAG_TC; + + /* Disable the interrupts */ + __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + if (currentstate == HAL_OSPI_STATE_BUSY_TX) + { + /* TX complete callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->TxCpltCallback(hospi); +#else + HAL_OSPI_TxCpltCallback(hospi); +#endif + } + else if (currentstate == HAL_OSPI_STATE_BUSY_CMD) + { + /* Command complete callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->CmdCpltCallback(hospi); +#else + HAL_OSPI_CmdCpltCallback(hospi); +#endif + } + else if (currentstate == HAL_OSPI_STATE_ABORT) + { + if (hospi->ErrorCode == HAL_OSPI_ERROR_NONE) + { + /* Abort called by the user */ + /* Abort complete callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->AbortCpltCallback(hospi); +#else + HAL_OSPI_AbortCpltCallback(hospi); +#endif + } + else + { + /* Abort due to an error (eg : DMA error) */ + /* Error callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->ErrorCallback(hospi); +#else + HAL_OSPI_ErrorCallback(hospi); +#endif + } + } + else + { + /* Nothing to do */ + } + } + } + /* OctoSPI status match interrupt occurred ---------------------------------*/ + else if (((flag & HAL_OSPI_FLAG_SM) != 0U) && ((itsource & HAL_OSPI_IT_SM) != 0U)) + { + /* Clear flag */ + hospi->Instance->FCR = HAL_OSPI_FLAG_SM; + + /* Check if automatic poll mode stop is activated */ + if ((hospi->Instance->CR & OCTOSPI_CR_APMS) != 0U) + { + /* Disable the interrupts */ + __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + } + + /* Status match callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->StatusMatchCallback(hospi); +#else + HAL_OSPI_StatusMatchCallback(hospi); +#endif + } + /* OctoSPI transfer error interrupt occurred -------------------------------*/ + else if (((flag & HAL_OSPI_FLAG_TE) != 0U) && ((itsource & HAL_OSPI_IT_TE) != 0U)) + { + /* Clear flag */ + hospi->Instance->FCR = HAL_OSPI_FLAG_TE; + + /* Disable all interrupts */ + __HAL_OSPI_DISABLE_IT(hospi, (HAL_OSPI_IT_TO | HAL_OSPI_IT_SM | HAL_OSPI_IT_FT | HAL_OSPI_IT_TC | HAL_OSPI_IT_TE)); + + /* Set error code */ + hospi->ErrorCode = HAL_OSPI_ERROR_TRANSFER; + + /* Check if the DMA is enabled */ + if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer on the OctoSPI side */ + CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + + /* Disable the DMA transfer on the DMA side */ + hospi->hdma->XferAbortCallback = OSPI_DMAAbortCplt; + if (HAL_DMA_Abort_IT(hospi->hdma) != HAL_OK) + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Error callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->ErrorCallback(hospi); +#else + HAL_OSPI_ErrorCallback(hospi); +#endif + } + } + else + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Error callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->ErrorCallback(hospi); +#else + HAL_OSPI_ErrorCallback(hospi); +#endif + } + } + /* OctoSPI timeout interrupt occurred --------------------------------------*/ + else if (((flag & HAL_OSPI_FLAG_TO) != 0U) && ((itsource & HAL_OSPI_IT_TO) != 0U)) + { + /* Clear flag */ + hospi->Instance->FCR = HAL_OSPI_FLAG_TO; + + /* Timeout callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->TimeOutCallback(hospi); +#else + HAL_OSPI_TimeOutCallback(hospi); +#endif + } + else + { + /* Nothing to do */ + } +} +#endif + +/** + * @brief Set the command configuration. + * @param hospi : OSPI handle + * @param cmd : structure that contains the command configuration information + * @param Timeout : Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Command(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t state; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters of the command structure */ + assert_param(IS_OSPI_OPERATION_TYPE(cmd->OperationType)); + + if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE) + { + assert_param(IS_OSPI_FLASH_ID(cmd->FlashId)); + } + + assert_param(IS_OSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE) + { + assert_param(IS_OSPI_INSTRUCTION_SIZE (cmd->InstructionSize)); + assert_param(IS_OSPI_INSTRUCTION_DTR_MODE(cmd->InstructionDtrMode)); + } + + assert_param(IS_OSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE) + { + assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize)); + assert_param(IS_OSPI_ADDRESS_DTR_MODE(cmd->AddressDtrMode)); + } + + assert_param(IS_OSPI_ALT_BYTES_MODE(cmd->AlternateBytesMode)); + if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_OSPI_ALT_BYTES_SIZE (cmd->AlternateBytesSize)); + assert_param(IS_OSPI_ALT_BYTES_DTR_MODE(cmd->AlternateBytesDtrMode)); + } + + assert_param(IS_OSPI_DATA_MODE(cmd->DataMode)); + if (cmd->DataMode != HAL_OSPI_DATA_NONE) + { + if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG) + { + assert_param(IS_OSPI_NUMBER_DATA (cmd->NbData)); + } + assert_param(IS_OSPI_DATA_DTR_MODE(cmd->DataDtrMode)); + assert_param(IS_OSPI_DUMMY_CYCLES (cmd->DummyCycles)); + } + + assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode)); + assert_param(IS_OSPI_SIOO_MODE(cmd->SIOOMode)); + + /* Check the state of the driver */ + state = hospi->State; + if (((state == HAL_OSPI_STATE_READY) && (hospi->Init.MemoryType != HAL_OSPI_MEMTYPE_HYPERBUS)) || + ((state == HAL_OSPI_STATE_READ_CMD_CFG) && (cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG)) || + ((state == HAL_OSPI_STATE_WRITE_CMD_CFG) && (cmd->OperationType == HAL_OSPI_OPTYPE_READ_CFG))) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Initialize error code */ + hospi->ErrorCode = HAL_OSPI_ERROR_NONE; + + /* Configure the registers */ + status = OSPI_ConfigCmd(hospi, cmd); + + if (status == HAL_OK) + { + if (cmd->DataMode == HAL_OSPI_DATA_NONE) + { + /* When there is no data phase, the transfer start as soon as the configuration is done + so wait until TC flag is set to go back in idle state */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout); + + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC); + } + else + { + /* Update the state */ + if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG) + { + hospi->State = HAL_OSPI_STATE_CMD_CFG; + } + else if (cmd->OperationType == HAL_OSPI_OPTYPE_READ_CFG) + { + if (hospi->State == HAL_OSPI_STATE_WRITE_CMD_CFG) + { + hospi->State = HAL_OSPI_STATE_CMD_CFG; + } + else + { + hospi->State = HAL_OSPI_STATE_READ_CMD_CFG; + } + } + else + { + if (hospi->State == HAL_OSPI_STATE_READ_CMD_CFG) + { + hospi->State = HAL_OSPI_STATE_CMD_CFG; + } + else + { + hospi->State = HAL_OSPI_STATE_WRITE_CMD_CFG; + } + } + } + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** + * @brief Set the command configuration in interrupt mode. + * @param hospi : OSPI handle + * @param cmd : structure that contains the command configuration information + * @note This function is used only in Indirect Read or Write Modes + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Command_IT(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters of the command structure */ + assert_param(IS_OSPI_OPERATION_TYPE(cmd->OperationType)); + + if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE) + { + assert_param(IS_OSPI_FLASH_ID(cmd->FlashId)); + } + + assert_param(IS_OSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE) + { + assert_param(IS_OSPI_INSTRUCTION_SIZE (cmd->InstructionSize)); + assert_param(IS_OSPI_INSTRUCTION_DTR_MODE(cmd->InstructionDtrMode)); + } + + assert_param(IS_OSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE) + { + assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize)); + assert_param(IS_OSPI_ADDRESS_DTR_MODE(cmd->AddressDtrMode)); + } + + assert_param(IS_OSPI_ALT_BYTES_MODE(cmd->AlternateBytesMode)); + if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_OSPI_ALT_BYTES_SIZE (cmd->AlternateBytesSize)); + assert_param(IS_OSPI_ALT_BYTES_DTR_MODE(cmd->AlternateBytesDtrMode)); + } + + assert_param(IS_OSPI_DATA_MODE(cmd->DataMode)); + if (cmd->DataMode != HAL_OSPI_DATA_NONE) + { + assert_param(IS_OSPI_NUMBER_DATA (cmd->NbData)); + assert_param(IS_OSPI_DATA_DTR_MODE(cmd->DataDtrMode)); + assert_param(IS_OSPI_DUMMY_CYCLES (cmd->DummyCycles)); + } + + assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode)); + assert_param(IS_OSPI_SIOO_MODE(cmd->SIOOMode)); + + /* Check the state of the driver */ + if ((hospi->State == HAL_OSPI_STATE_READY) && (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG) && + (cmd->DataMode == HAL_OSPI_DATA_NONE) && (hospi->Init.MemoryType != HAL_OSPI_MEMTYPE_HYPERBUS)) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout); + + if (status == HAL_OK) + { + /* Initialize error code */ + hospi->ErrorCode = HAL_OSPI_ERROR_NONE; + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC); + + /* Configure the registers */ + status = OSPI_ConfigCmd(hospi, cmd); + + if (status == HAL_OK) + { + /* Update the state */ + hospi->State = HAL_OSPI_STATE_BUSY_CMD; + + /* Enable the transfer complete and transfer error interrupts */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_TE); + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** + * @brief Configure the Hyperbus parameters. + * @param hospi : OSPI handle + * @param cfg : Structure containing the Hyperbus configuration + * @param Timeout : Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_HyperbusCfg(OSPI_HandleTypeDef *hospi, OSPI_HyperbusCfgTypeDef *cfg, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t state; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters of the hyperbus configuration structure */ + assert_param(IS_OSPI_RW_RECOVERY_TIME (cfg->RWRecoveryTime)); + assert_param(IS_OSPI_ACCESS_TIME (cfg->AccessTime)); + assert_param(IS_OSPI_WRITE_ZERO_LATENCY(cfg->WriteZeroLatency)); + assert_param(IS_OSPI_LATENCY_MODE (cfg->LatencyMode)); + + /* Check the state of the driver */ + state = hospi->State; + if ((state == HAL_OSPI_STATE_HYPERBUS_INIT) || (state == HAL_OSPI_STATE_READY)) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Configure Hyperbus configuration Latency register */ + WRITE_REG(hospi->Instance->HLCR, ((cfg->RWRecoveryTime << OCTOSPI_HLCR_TRWR_Pos) | + (cfg->AccessTime << OCTOSPI_HLCR_TACC_Pos) | + cfg->WriteZeroLatency | cfg->LatencyMode)); + + /* Update the state */ + hospi->State = HAL_OSPI_STATE_READY; + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** + * @brief Set the Hyperbus command configuration. + * @param hospi : OSPI handle + * @param cmd : Structure containing the Hyperbus command + * @param Timeout : Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_HyperbusCmd(OSPI_HandleTypeDef *hospi, OSPI_HyperbusCmdTypeDef *cmd, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters of the hyperbus command structure */ + assert_param(IS_OSPI_ADDRESS_SPACE(cmd->AddressSpace)); + assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize)); + assert_param(IS_OSPI_NUMBER_DATA (cmd->NbData)); + assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode)); + + /* Check the state of the driver */ + if ((hospi->State == HAL_OSPI_STATE_READY) && (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Re-initialize the value of the functional mode */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U); + + /* Configure the address space in the DCR1 register */ + MODIFY_REG(hospi->Instance->DCR1, OCTOSPI_DCR1_MTYP_0, cmd->AddressSpace); + + /* Configure the CCR and WCCR registers with the address size and the following configuration : + - DQS signal enabled (used as RWDS) + - DTR mode enabled on address and data + - address and data on 8 lines */ + WRITE_REG(hospi->Instance->CCR, (cmd->DQSMode | OCTOSPI_CCR_DDTR | OCTOSPI_CCR_DMODE_2 | + cmd->AddressSize | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADMODE_2)); + WRITE_REG(hospi->Instance->WCCR, (cmd->DQSMode | OCTOSPI_WCCR_DDTR | OCTOSPI_WCCR_DMODE_2 | + cmd->AddressSize | OCTOSPI_WCCR_ADDTR | OCTOSPI_WCCR_ADMODE_2)); + + /* Configure the DLR register with the number of data */ + WRITE_REG(hospi->Instance->DLR, (cmd->NbData - 1U)); + + /* Configure the AR register with the address value */ + WRITE_REG(hospi->Instance->AR, cmd->Address); + + /* Update the state */ + hospi->State = HAL_OSPI_STATE_CMD_CFG; + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** + * @brief Transmit an amount of data in blocking mode. + * @param hospi : OSPI handle + * @param pData : pointer to data buffer + * @param Timeout : Timeout duration + * @note This function is used only in Indirect Write Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Transmit(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + __IO uint32_t *data_reg = &hospi->Instance->DR; + + /* Check the data pointer allocation */ + if (pData == NULL) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + else + { + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Configure counters and size */ + hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U; + hospi->XferSize = hospi->XferCount; + hospi->pBuffPtr = pData; + + /* Configure CR register with functional mode as indirect write */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + do + { + /* Wait till fifo threshold flag is set to send data */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_FT, SET, tickstart, Timeout); + + if (status != HAL_OK) + { + break; + } + + *((__IO uint8_t *)data_reg) = *hospi->pBuffPtr; + hospi->pBuffPtr++; + hospi->XferCount--; + } while (hospi->XferCount > 0U); + + if (status == HAL_OK) + { + /* Wait till transfer complete flag is set to go back in idle state */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Clear transfer complete flag */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Receive an amount of data in blocking mode. + * @param hospi : OSPI handle + * @param pData : pointer to data buffer + * @param Timeout : Timeout duration + * @note This function is used only in Indirect Read Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Receive(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + __IO uint32_t *data_reg = &hospi->Instance->DR; + uint32_t addr_reg = hospi->Instance->AR; + uint32_t ir_reg = hospi->Instance->IR; + + /* Check the data pointer allocation */ + if (pData == NULL) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + else + { + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Configure counters and size */ + hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U; + hospi->XferSize = hospi->XferCount; + hospi->pBuffPtr = pData; + + /* Configure CR register with functional mode as indirect read */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Trig the transfer by re-writing address or instruction register */ + if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + WRITE_REG(hospi->Instance->IR, ir_reg); + } + } + + do + { + /* Wait till fifo threshold or transfer complete flags are set to read received data */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, (HAL_OSPI_FLAG_FT | HAL_OSPI_FLAG_TC), SET, tickstart, Timeout); + + if (status != HAL_OK) + { + break; + } + + *hospi->pBuffPtr = *((__IO uint8_t *)data_reg); + hospi->pBuffPtr++; + hospi->XferCount--; + } while(hospi->XferCount > 0U); + + if (status == HAL_OK) + { + /* Wait till transfer complete flag is set to go back in idle state */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Clear transfer complete flag */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Send an amount of data in non-blocking mode with interrupt. + * @param hospi : OSPI handle + * @param pData : pointer to data buffer + * @note This function is used only in Indirect Write Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Transmit_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the data pointer allocation */ + if (pData == NULL) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + else + { + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Configure counters and size */ + hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U; + hospi->XferSize = hospi->XferCount; + hospi->pBuffPtr = pData; + + /* Configure CR register with functional mode as indirect write */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC); + + /* Update the state */ + hospi->State = HAL_OSPI_STATE_BUSY_TX; + + /* Enable the transfer complete, fifo threshold and transfer error interrupts */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE); + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Receive an amount of data in non-blocking mode with interrupt. + * @param hospi : OSPI handle + * @param pData : pointer to data buffer + * @note This function is used only in Indirect Read Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Receive_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t addr_reg = hospi->Instance->AR; + uint32_t ir_reg = hospi->Instance->IR; + + /* Check the data pointer allocation */ + if (pData == NULL) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + else + { + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Configure counters and size */ + hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U; + hospi->XferSize = hospi->XferCount; + hospi->pBuffPtr = pData; + + /* Configure CR register with functional mode as indirect read */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC); + + /* Update the state */ + hospi->State = HAL_OSPI_STATE_BUSY_RX; + + /* Enable the transfer complete, fifo threshold and transfer error interrupts */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE); + + /* Trig the transfer by re-writing address or instruction register */ + if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + WRITE_REG(hospi->Instance->IR, ir_reg); + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + } + + /* Return function status */ + return status; +} + +#if 0 +/** + * @brief Send an amount of data in non-blocking mode with DMA. + * @param hospi : OSPI handle + * @param pData : pointer to data buffer + * @note This function is used only in Indirect Write Mode + * @note If DMA peripheral access is configured as halfword, the number + * of data and the fifo threshold should be aligned on halfword + * @note If DMA peripheral access is configured as word, the number + * of data and the fifo threshold should be aligned on word + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Transmit_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t data_size = hospi->Instance->DLR + 1U; + + /* Check the data pointer allocation */ + if (pData == NULL) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + else + { + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Configure counters and size */ + if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE) + { + hospi->XferCount = data_size; + } + else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD) + { + if (((data_size % 2U) != 0U) || ((hospi->Init.FifoThreshold % 2U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on halfword + => no transfer possible with DMA peripheral access configured as halfword */ + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + } + else + { + hospi->XferCount = (data_size >> 1); + } + } + else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD) + { + if (((data_size % 4U) != 0U) || ((hospi->Init.FifoThreshold % 4U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on word + => no transfer possible with DMA peripheral access configured as word */ + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + } + else + { + hospi->XferCount = (data_size >> 2); + } + } + else + { + /* Nothing to do */ + } + + if (status == HAL_OK) + { + hospi->XferSize = hospi->XferCount; + hospi->pBuffPtr = pData; + + /* Configure CR register with functional mode as indirect write */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC); + + /* Update the state */ + hospi->State = HAL_OSPI_STATE_BUSY_TX; + + /* Set the DMA transfer complete callback */ + hospi->hdma->XferCpltCallback = OSPI_DMACplt; + + /* Set the DMA Half transfer complete callback */ + hospi->hdma->XferHalfCpltCallback = OSPI_DMAHalfCplt; + + /* Set the DMA error callback */ + hospi->hdma->XferErrorCallback = OSPI_DMAError; + + /* Clear the DMA abort callback */ + hospi->hdma->XferAbortCallback = NULL; + + /* Configure the direction of the DMA */ + hospi->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; + MODIFY_REG(hospi->hdma->Instance->CCR, DMA_CCR_DIR, hospi->hdma->Init.Direction); + + /* Enable the transmit DMA Channel */ + if (HAL_DMA_Start_IT(hospi->hdma, (uint32_t)pData, (uint32_t)&hospi->Instance->DR, hospi->XferSize) == HAL_OK) + { + /* Enable the transfer error interrupt */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE); + + /* Enable the DMA transfer by setting the DMAEN bit */ + SET_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_DMA; + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Receive an amount of data in non-blocking mode with DMA. + * @param hospi : OSPI handle + * @param pData : pointer to data buffer. + * @note This function is used only in Indirect Read Mode + * @note If DMA peripheral access is configured as halfword, the number + * of data and the fifo threshold should be aligned on halfword + * @note If DMA peripheral access is configured as word, the number + * of data and the fifo threshold should be aligned on word + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_Receive_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t data_size = hospi->Instance->DLR + 1U; + uint32_t addr_reg = hospi->Instance->AR; + uint32_t ir_reg = hospi->Instance->IR; + + /* Check the data pointer allocation */ + if (pData == NULL) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + else + { + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Configure counters and size */ + if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE) + { + hospi->XferCount = data_size; + } + else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD) + { + if (((data_size % 2U) != 0U) || ((hospi->Init.FifoThreshold % 2U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on halfword + => no transfer possible with DMA peripheral access configured as halfword */ + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + } + else + { + hospi->XferCount = (data_size >> 1); + } + } + else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD) + { + if (((data_size % 4U) != 0U) || ((hospi->Init.FifoThreshold % 4U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on word + => no transfer possible with DMA peripheral access configured as word */ + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + } + else + { + hospi->XferCount = (data_size >> 2); + } + } + else + { + /* Nothing to do */ + } + + if (status == HAL_OK) + { + hospi->XferSize = hospi->XferCount; + hospi->pBuffPtr = pData; + + /* Configure CR register with functional mode as indirect read */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC); + + /* Update the state */ + hospi->State = HAL_OSPI_STATE_BUSY_RX; + + /* Set the DMA transfer complete callback */ + hospi->hdma->XferCpltCallback = OSPI_DMACplt; + + /* Set the DMA Half transfer complete callback */ + hospi->hdma->XferHalfCpltCallback = OSPI_DMAHalfCplt; + + /* Set the DMA error callback */ + hospi->hdma->XferErrorCallback = OSPI_DMAError; + + /* Clear the DMA abort callback */ + hospi->hdma->XferAbortCallback = NULL; + + /* Configure the direction of the DMA */ + hospi->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; + MODIFY_REG(hospi->hdma->Instance->CCR, DMA_CCR_DIR, hospi->hdma->Init.Direction); + + /* Enable the transmit DMA Channel */ + if (HAL_DMA_Start_IT(hospi->hdma, (uint32_t)&hospi->Instance->DR, (uint32_t)pData, hospi->XferSize) == HAL_OK) + { + /* Enable the transfer error interrupt */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE); + + /* Trig the transfer by re-writing address or instruction register */ + if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + WRITE_REG(hospi->Instance->IR, ir_reg); + } + } + + /* Enable the DMA transfer by setting the DMAEN bit */ + SET_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_DMA; + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + } + + /* Return function status */ + return status; +} +#endif + +/** + * @brief Configure the OSPI Automatic Polling Mode in blocking mode. + * @param hospi : OSPI handle + * @param cfg : structure that contains the polling configuration information. + * @param Timeout : Timeout duration + * @note This function is used only in Automatic Polling Mode + * @note This function should not be used when the memory is in octal mode (see Errata Sheet) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_AutoPolling(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + uint32_t addr_reg = hospi->Instance->AR; + uint32_t ir_reg = hospi->Instance->IR; +#ifdef USE_FULL_ASSERT + uint32_t dlr_reg = hospi->Instance->DLR; +#endif + + /* Check the parameters of the autopolling configuration structure */ + assert_param(IS_OSPI_MATCH_MODE (cfg->MatchMode)); + assert_param(IS_OSPI_AUTOMATIC_STOP (cfg->AutomaticStop)); + assert_param(IS_OSPI_INTERVAL (cfg->Interval)); + assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg+1U)); + + /* Check the state */ + if ((hospi->State == HAL_OSPI_STATE_CMD_CFG) && (cfg->AutomaticStop == HAL_OSPI_AUTOMATIC_STOP_ENABLE)) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Configure registers */ + WRITE_REG (hospi->Instance->PSMAR, cfg->Match); + WRITE_REG (hospi->Instance->PSMKR, cfg->Mask); + WRITE_REG (hospi->Instance->PIR, cfg->Interval); + MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE), + (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING)); + + /* Trig the transfer by re-writing address or instruction register */ + if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + WRITE_REG(hospi->Instance->IR, ir_reg); + } + } + + /* Wait till status match flag is set to go back in idle state */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_SM, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Clear status match flag */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_SM); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** + * @brief Configure the OSPI Automatic Polling Mode in non-blocking mode. + * @param hospi : OSPI handle + * @param cfg : structure that contains the polling configuration information. + * @note This function is used only in Automatic Polling Mode + * @note This function should not be used when the memory is in octal mode (see Errata Sheet) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_AutoPolling_IT(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + uint32_t addr_reg = hospi->Instance->AR; + uint32_t ir_reg = hospi->Instance->IR; +#ifdef USE_FULL_ASSERT + uint32_t dlr_reg = hospi->Instance->DLR; +#endif + + /* Check the parameters of the autopolling configuration structure */ + assert_param(IS_OSPI_MATCH_MODE (cfg->MatchMode)); + assert_param(IS_OSPI_AUTOMATIC_STOP (cfg->AutomaticStop)); + assert_param(IS_OSPI_INTERVAL (cfg->Interval)); + assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg+1U)); + + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout); + + if (status == HAL_OK) + { + /* Configure registers */ + WRITE_REG (hospi->Instance->PSMAR, cfg->Match); + WRITE_REG (hospi->Instance->PSMKR, cfg->Mask); + WRITE_REG (hospi->Instance->PIR, cfg->Interval); + MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE), + (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING)); + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_SM); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_BUSY_AUTO_POLLING; + + /* Enable the status match and transfer error interrupts */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE); + + /* Trig the transfer by re-writing address or instruction register */ + if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE) + { + WRITE_REG(hospi->Instance->AR, addr_reg); + } + else + { + WRITE_REG(hospi->Instance->IR, ir_reg); + } + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** + * @brief Configure the Memory Mapped mode. + * @param hospi : OSPI handle + * @param cfg : structure that contains the memory mapped configuration information. + * @note This function is used only in Memory mapped Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_MemoryMapped(OSPI_HandleTypeDef *hospi, OSPI_MemoryMappedTypeDef *cfg) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters of the memory-mapped configuration structure */ + assert_param(IS_OSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation)); + + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_CMD_CFG) + { + /* Wait till busy flag is reset */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout); + + if (status == HAL_OK) + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_BUSY_MEM_MAPPED; + + if (cfg->TimeOutActivation == HAL_OSPI_TIMEOUT_COUNTER_ENABLE) + { + assert_param(IS_OSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod)); + + /* Configure register */ + WRITE_REG(hospi->Instance->LPTR, cfg->TimeOutPeriod); + + /* Clear flags related to interrupt */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TO); + + /* Enable the timeout interrupt */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TO); + } + + /* Configure CR register with functional mode as memory-mapped */ + MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_TCEN | OCTOSPI_CR_FMODE), + (cfg->TimeOutActivation | OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)); + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +#if 0 +/** + * @brief Transfer Error callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_ErrorCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OSPI_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Abort completed callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_AbortCpltCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_OSPI_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @brief FIFO Threshold callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_FifoThresholdCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OSPI_FIFOThresholdCallback could be implemented in the user file + */ +} + +/** + * @brief Command completed callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_CmdCpltCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_OSPI_CmdCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_RxCpltCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_OSPI_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Transfer completed callback. + * @param hospi : OSPI handle + * @retval None + */ + __weak void HAL_OSPI_TxCpltCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_OSPI_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_RxHalfCpltCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_OSPI_RxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_OSPI_TxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Status Match callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_StatusMatchCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OSPI_StatusMatchCallback could be implemented in the user file + */ +} + +/** + * @brief Timeout callback. + * @param hospi : OSPI handle + * @retval None + */ +__weak void HAL_OSPI_TimeOutCallback(OSPI_HandleTypeDef *hospi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hospi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_OSPI_TimeOutCallback could be implemented in the user file + */ +} +#endif + +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User OSPI Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hospi : OSPI handle + * @param CallbackID : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_OSPI_ERROR_CB_ID OSPI Error Callback ID + * @arg @ref HAL_OSPI_ABORT_CB_ID OSPI Abort Callback ID + * @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID + * @arg @ref HAL_OSPI_CMD_CPLT_CB_ID OSPI Command Complete Callback ID + * @arg @ref HAL_OSPI_RX_CPLT_CB_ID OSPI Rx Complete Callback ID + * @arg @ref HAL_OSPI_TX_CPLT_CB_ID OSPI Tx Complete Callback ID + * @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID OSPI Rx Half Complete Callback ID + * @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID OSPI Tx Half Complete Callback ID + * @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID OSPI Status Match Callback ID + * @arg @ref HAL_OSPI_TIMEOUT_CB_ID OSPI Timeout Callback ID + * @arg @ref HAL_OSPI_MSP_INIT_CB_ID OSPI MspInit callback ID + * @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID OSPI MspDeInit callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_OSPI_RegisterCallback (OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID, pOSPI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + if(hospi->State == HAL_OSPI_STATE_READY) + { + switch (CallbackID) + { + case HAL_OSPI_ERROR_CB_ID : + hospi->ErrorCallback = pCallback; + break; + case HAL_OSPI_ABORT_CB_ID : + hospi->AbortCpltCallback = pCallback; + break; + case HAL_OSPI_FIFO_THRESHOLD_CB_ID : + hospi->FifoThresholdCallback = pCallback; + break; + case HAL_OSPI_CMD_CPLT_CB_ID : + hospi->CmdCpltCallback = pCallback; + break; + case HAL_OSPI_RX_CPLT_CB_ID : + hospi->RxCpltCallback = pCallback; + break; + case HAL_OSPI_TX_CPLT_CB_ID : + hospi->TxCpltCallback = pCallback; + break; + case HAL_OSPI_RX_HALF_CPLT_CB_ID : + hospi->RxHalfCpltCallback = pCallback; + break; + case HAL_OSPI_TX_HALF_CPLT_CB_ID : + hospi->TxHalfCpltCallback = pCallback; + break; + case HAL_OSPI_STATUS_MATCH_CB_ID : + hospi->StatusMatchCallback = pCallback; + break; + case HAL_OSPI_TIMEOUT_CB_ID : + hospi->TimeOutCallback = pCallback; + break; + case HAL_OSPI_MSP_INIT_CB_ID : + hospi->MspInitCallback = pCallback; + break; + case HAL_OSPI_MSP_DEINIT_CB_ID : + hospi->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hospi->State == HAL_OSPI_STATE_RESET) + { + switch (CallbackID) + { + case HAL_OSPI_MSP_INIT_CB_ID : + hospi->MspInitCallback = pCallback; + break; + case HAL_OSPI_MSP_DEINIT_CB_ID : + hospi->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister a User OSPI Callback + * OSPI Callback is redirected to the weak (surcharged) predefined callback + * @param hospi : OSPI handle + * @param CallbackID : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_OSPI_ERROR_CB_ID OSPI Error Callback ID + * @arg @ref HAL_OSPI_ABORT_CB_ID OSPI Abort Callback ID + * @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID + * @arg @ref HAL_OSPI_CMD_CPLT_CB_ID OSPI Command Complete Callback ID + * @arg @ref HAL_OSPI_RX_CPLT_CB_ID OSPI Rx Complete Callback ID + * @arg @ref HAL_OSPI_TX_CPLT_CB_ID OSPI Tx Complete Callback ID + * @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID OSPI Rx Half Complete Callback ID + * @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID OSPI Tx Half Complete Callback ID + * @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID OSPI Status Match Callback ID + * @arg @ref HAL_OSPI_TIMEOUT_CB_ID OSPI Timeout Callback ID + * @arg @ref HAL_OSPI_MSP_INIT_CB_ID OSPI MspInit callback ID + * @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID OSPI MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_OSPI_UnRegisterCallback (OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(hospi->State == HAL_OSPI_STATE_READY) + { + switch (CallbackID) + { + case HAL_OSPI_ERROR_CB_ID : + hospi->ErrorCallback = HAL_OSPI_ErrorCallback; + break; + case HAL_OSPI_ABORT_CB_ID : + hospi->AbortCpltCallback = HAL_OSPI_AbortCpltCallback; + break; + case HAL_OSPI_FIFO_THRESHOLD_CB_ID : + hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback; + break; + case HAL_OSPI_CMD_CPLT_CB_ID : + hospi->CmdCpltCallback = HAL_OSPI_CmdCpltCallback; + break; + case HAL_OSPI_RX_CPLT_CB_ID : + hospi->RxCpltCallback = HAL_OSPI_RxCpltCallback; + break; + case HAL_OSPI_TX_CPLT_CB_ID : + hospi->TxCpltCallback = HAL_OSPI_TxCpltCallback; + break; + case HAL_OSPI_RX_HALF_CPLT_CB_ID : + hospi->RxHalfCpltCallback = HAL_OSPI_RxHalfCpltCallback; + break; + case HAL_OSPI_TX_HALF_CPLT_CB_ID : + hospi->TxHalfCpltCallback = HAL_OSPI_TxHalfCpltCallback; + break; + case HAL_OSPI_STATUS_MATCH_CB_ID : + hospi->StatusMatchCallback = HAL_OSPI_StatusMatchCallback; + break; + case HAL_OSPI_TIMEOUT_CB_ID : + hospi->TimeOutCallback = HAL_OSPI_TimeOutCallback; + break; + case HAL_OSPI_MSP_INIT_CB_ID : + hospi->MspInitCallback = HAL_OSPI_MspInit; + break; + case HAL_OSPI_MSP_DEINIT_CB_ID : + hospi->MspDeInitCallback = HAL_OSPI_MspDeInit; + break; + default : + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hospi->State == HAL_OSPI_STATE_RESET) + { + switch (CallbackID) + { + case HAL_OSPI_MSP_INIT_CB_ID : + hospi->MspInitCallback = HAL_OSPI_MspInit; + break; + case HAL_OSPI_MSP_DEINIT_CB_ID : + hospi->MspDeInitCallback = HAL_OSPI_MspDeInit; + break; + default : + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + return status; +} +#endif + +/** + * @} + */ + +/** @defgroup OSPI_Exported_Functions_Group3 Peripheral Control and State functions + * @brief OSPI control and State functions + * +@verbatim + =============================================================================== + ##### Peripheral Control and State functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to : + (+) Check in run-time the state of the driver. + (+) Check the error code set during last operation. + (+) Abort any operation. + (+) Manage the Fifo threshold. + (+) Configure the timeout duration used in the driver. + +@endverbatim + * @{ + */ + +#if 0 +/** +* @brief Abort the current transmission. +* @param hospi : OSPI handle +* @retval HAL status +*/ +HAL_StatusTypeDef HAL_OSPI_Abort(OSPI_HandleTypeDef *hospi) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t state; + uint32_t tickstart = HAL_GetTick(); + + /* Check if the state is in one of the busy or configured states */ + state = hospi->State; + if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U)) + { + /* Check if the DMA is enabled */ + if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer on the OctoSPI side */ + CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + + /* Disable the DMA transfer on the DMA side */ + status = HAL_DMA_Abort(hospi->hdma); + if (status != HAL_OK) + { + hospi->ErrorCode = HAL_OSPI_ERROR_DMA; + } + } + + if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET) + { + /* Perform an abort of the OctoSPI */ + SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT); + + /* Wait until the transfer complete flag is set to go back in idle state */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, hospi->Timeout); + + if (status == HAL_OK) + { + /* Clear transfer complete flag */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC); + + /* Wait until the busy flag is reset to go back in idle state */ + status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout); + + if (status == HAL_OK) + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + } + } + } + else + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** +* @brief Abort the current transmission (non-blocking function) +* @param hospi : OSPI handle +* @retval HAL status +*/ +HAL_StatusTypeDef HAL_OSPI_Abort_IT(OSPI_HandleTypeDef *hospi) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t state; + + /* Check if the state is in one of the busy or configured states */ + state = hospi->State; + if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U)) + { + /* Disable all interrupts */ + __HAL_OSPI_DISABLE_IT(hospi, (HAL_OSPI_IT_TO | HAL_OSPI_IT_SM | HAL_OSPI_IT_FT | HAL_OSPI_IT_TC | HAL_OSPI_IT_TE)); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_ABORT; + + /* Check if the DMA is enabled */ + if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer on the OctoSPI side */ + CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + + /* Disable the DMA transfer on the DMA side */ + hospi->hdma->XferAbortCallback = OSPI_DMAAbortCplt; + if (HAL_DMA_Abort_IT(hospi->hdma) != HAL_OK) + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Abort callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->AbortCpltCallback(hospi); +#else + HAL_OSPI_AbortCpltCallback(hospi); +#endif + } + } + else + { + if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET) + { + /* Clear transfer complete flag */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC); + + /* Enable the transfer complete interrupts */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC); + + /* Perform an abort of the OctoSPI */ + SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT); + } + else + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Abort callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->AbortCpltCallback(hospi); +#else + HAL_OSPI_AbortCpltCallback(hospi); +#endif + } + } + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} +#endif + +/** @brief Set OSPI Fifo threshold. + * @param hospi : OSPI handle. + * @param Threshold : Threshold of the Fifo. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPI_SetFifoThreshold(OSPI_HandleTypeDef *hospi, uint32_t Threshold) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the state */ + if ((hospi->State & OSPI_BUSY_STATE_MASK) == 0U) + { + /* Synchronize initialization structure with the new fifo threshold value */ + hospi->Init.FifoThreshold = Threshold; + + /* Configure new fifo threshold */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold-1U) << OCTOSPI_CR_FTHRES_Pos)); + + } + else + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE; + } + + /* Return function status */ + return status; +} + +/** @brief Get OSPI Fifo threshold. + * @param hospi : OSPI handle. + * @retval Fifo threshold + */ +uint32_t HAL_OSPI_GetFifoThreshold(OSPI_HandleTypeDef *hospi) +{ + return ((READ_BIT(hospi->Instance->CR, OCTOSPI_CR_FTHRES) >> OCTOSPI_CR_FTHRES_Pos) + 1U); +} + +/** @brief Set OSPI timeout. + * @param hospi : OSPI handle. + * @param Timeout : Timeout for the memory access. + * @retval None + */ +HAL_StatusTypeDef HAL_OSPI_SetTimeout(OSPI_HandleTypeDef *hospi, uint32_t Timeout) +{ + hospi->Timeout = Timeout; + return HAL_OK; +} + +/** +* @brief Return the OSPI error code. +* @param hospi : OSPI handle +* @retval OSPI Error Code +*/ +uint32_t HAL_OSPI_GetError(OSPI_HandleTypeDef *hospi) +{ + return hospi->ErrorCode; +} + +/** + * @brief Return the OSPI handle state. + * @param hospi : OSPI handle + * @retval HAL state + */ +uint32_t HAL_OSPI_GetState(OSPI_HandleTypeDef *hospi) +{ + /* Return OSPI handle state */ + return hospi->State; +} + +/** + * @} + */ + +/** @defgroup OSPI_Exported_Functions_Group4 IO Manager configuration function + * @brief OSPI IO Manager configuration function + * +@verbatim + =============================================================================== + ##### IO Manager configuration function ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to : + (+) Configure the IO manager. + +@endverbatim + * @{ + */ + +/** + * @brief Configure the OctoSPI IO manager. + * @param hospi : OSPI handle + * @param cfg : Configuration of the IO Manager for the instance + * @param Timeout : Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_OSPIM_Config(OSPI_HandleTypeDef *hospi, OSPIM_CfgTypeDef *cfg, uint32_t Timeout) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t instance; + uint8_t index, ospi_enabled = 0U, other_instance; + OSPIM_CfgTypeDef IOM_cfg[OSPI_NB_INSTANCE]; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(Timeout); + + /* Check the parameters of the OctoSPI IO Manager configuration structure */ + assert_param(IS_OSPIM_PORT(cfg->ClkPort)); + assert_param(IS_OSPIM_DQS_PORT(cfg->DQSPort)); + assert_param(IS_OSPIM_PORT(cfg->NCSPort)); + assert_param(IS_OSPIM_IO_PORT(cfg->IOLowPort)); + assert_param(IS_OSPIM_IO_PORT(cfg->IOHighPort)); +#if defined (OCTOSPIM_CR_MUXEN) + assert_param(IS_OSPIM_REQ2ACKTIME(cfg->Req2AckTime)); +#endif + + if (hospi->Instance == OCTOSPI1) + { + instance = 0U; + other_instance = 1U; + } + else + { + instance = 1U; + other_instance = 0U; + } + + /**************** Get current configuration of the instances ****************/ + for (index = 0U; index < OSPI_NB_INSTANCE; index++) + { + if (OSPIM_GetConfig(index+1U, &(IOM_cfg[index])) != HAL_OK) + { + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + } + + if (status == HAL_OK) + { + /********** Disable both OctoSPI to configure OctoSPI IO Manager **********/ + if ((OCTOSPI1->CR & OCTOSPI_CR_EN) != 0U) + { + CLEAR_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN); + ospi_enabled |= 0x1U; + } + if ((OCTOSPI2->CR & OCTOSPI_CR_EN) != 0U) + { + CLEAR_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN); + ospi_enabled |= 0x2U; + } + + /***************** Deactivation of previous configuration *****************/ + CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].NCSPort-1U)], OCTOSPIM_PCR_NCSEN); +#if defined (OCTOSPIM_CR_MUXEN) + if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) != 0U) + { + /* De-multiplexing should be performed */ + CLEAR_BIT(OCTOSPIM->CR, OCTOSPIM_CR_MUXEN); + + if (other_instance == 1U) + { + SET_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort-1U)], OCTOSPIM_PCR_CLKSRC); + if (IOM_cfg[other_instance].DQSPort != 0U) + { + SET_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort-1U)], OCTOSPIM_PCR_DQSSRC); + } + if (IOM_cfg[other_instance].IOLowPort != HAL_OSPIM_IOPORT_NONE) + { + SET_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLSRC_1); + } + if (IOM_cfg[other_instance].IOHighPort != HAL_OSPIM_IOPORT_NONE) + { + SET_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHSRC_1); + } + } + } + else + { +#endif + if (IOM_cfg[instance].ClkPort != 0U) + { + CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].ClkPort-1U)], OCTOSPIM_PCR_CLKEN); + if (IOM_cfg[instance].DQSPort != 0U) + { + CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].DQSPort-1U)], OCTOSPIM_PCR_DQSEN); + } + if (IOM_cfg[instance].IOLowPort != HAL_OSPIM_IOPORT_NONE) + { + CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLEN); + } + if (IOM_cfg[instance].IOHighPort != HAL_OSPIM_IOPORT_NONE) + { + CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN); + } + } +#if defined (OCTOSPIM_CR_MUXEN) + } +#endif + + /********************* Deactivation of other instance *********************/ + if ((cfg->ClkPort == IOM_cfg[other_instance].ClkPort) || (cfg->DQSPort == IOM_cfg[other_instance].DQSPort) || + (cfg->NCSPort == IOM_cfg[other_instance].NCSPort) || (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) || + (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort)) + { +#if defined (OCTOSPIM_CR_MUXEN) + if ((cfg->ClkPort == IOM_cfg[other_instance].ClkPort) && (cfg->DQSPort == IOM_cfg[other_instance].DQSPort) && + (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) && (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort)) + { + /* Multiplexing should be performed */ + SET_BIT(OCTOSPIM->CR, OCTOSPIM_CR_MUXEN); + } + else + { +#endif + CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort-1U)], OCTOSPIM_PCR_CLKEN); + if (IOM_cfg[other_instance].DQSPort != 0U) + { + CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort-1U)], OCTOSPIM_PCR_DQSEN); + } + CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].NCSPort-1U)], OCTOSPIM_PCR_NCSEN); + if (IOM_cfg[other_instance].IOLowPort != HAL_OSPIM_IOPORT_NONE) + { + CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLEN); + } + if (IOM_cfg[other_instance].IOHighPort != HAL_OSPIM_IOPORT_NONE) + { + CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN); + } +#if defined (OCTOSPIM_CR_MUXEN) + } +#endif + } + + /******************** Activation of new configuration *********************/ + MODIFY_REG(OCTOSPIM->PCR[(cfg->NCSPort-1U)], (OCTOSPIM_PCR_NCSEN | OCTOSPIM_PCR_NCSSRC), (OCTOSPIM_PCR_NCSEN | (instance << OCTOSPIM_PCR_NCSSRC_Pos))); + +#if defined (OCTOSPIM_CR_MUXEN) + if ((cfg->Req2AckTime - 1U) > ((OCTOSPIM->CR & OCTOSPIM_CR_REQ2ACK_TIME) >> OCTOSPIM_CR_REQ2ACK_TIME_Pos)) + { + MODIFY_REG(OCTOSPIM->CR, OCTOSPIM_CR_REQ2ACK_TIME, ((cfg->Req2AckTime - 1U) << OCTOSPIM_CR_REQ2ACK_TIME_Pos)); + } + + if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort-1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC), OCTOSPIM_PCR_CLKEN); + if (cfg->DQSPort != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort-1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC), OCTOSPIM_PCR_DQSEN); + } + + if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), OCTOSPIM_PCR_IOLEN); + } + else if (cfg->IOLowPort != HAL_OSPIM_IOPORT_NONE) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), OCTOSPIM_PCR_IOHEN); + } + else + { + /* Nothing to do */ + } + + if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0)); + } + else if (cfg->IOHighPort != HAL_OSPIM_IOPORT_NONE) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0)); + } + else + { + /* Nothing to do */ + } + } + else + { +#endif + MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort-1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC), (OCTOSPIM_PCR_CLKEN | (instance << OCTOSPIM_PCR_CLKSRC_Pos))); + if (cfg->DQSPort != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort-1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC), (OCTOSPIM_PCR_DQSEN | (instance << OCTOSPIM_PCR_DQSSRC_Pos))); + } + + if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), + (OCTOSPIM_PCR_IOLEN | (instance << (OCTOSPIM_PCR_IOLSRC_Pos+1U)))); + } + else if (cfg->IOLowPort != HAL_OSPIM_IOPORT_NONE) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), + (OCTOSPIM_PCR_IOHEN | (instance << (OCTOSPIM_PCR_IOHSRC_Pos+1U)))); + } + else + { + /* Nothing to do */ + } + + if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), + (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0 | (instance << (OCTOSPIM_PCR_IOLSRC_Pos+1U)))); + } + else if (cfg->IOHighPort != HAL_OSPIM_IOPORT_NONE) + { + MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), + (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0 | (instance << (OCTOSPIM_PCR_IOHSRC_Pos+1U)))); + } + else + { + /* Nothing to do */ + } +#if defined (OCTOSPIM_CR_MUXEN) + } +#endif + + /******* Re-enable both OctoSPI after configure OctoSPI IO Manager ********/ + if ((ospi_enabled & 0x1U) != 0U) + { + SET_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN); + } + if ((ospi_enabled & 0x2U) != 0U) + { + SET_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN); + } + } + + /* Return function status */ + return status; +} + +/** + * @} + */ + +#if 0 +/** + @cond 0 + */ +/** + * @brief DMA OSPI process complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void OSPI_DMACplt(DMA_HandleTypeDef *hdma) +{ + OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent); + hospi->XferCount = 0; + + /* Disable the DMA transfer on the OctoSPI side */ + CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Enable the OSPI transfer complete Interrupt */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC); +} + +/** + * @brief DMA OSPI process half complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void OSPI_DMAHalfCplt(DMA_HandleTypeDef *hdma) +{ + OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent); + hospi->XferCount = (hospi->XferCount >> 1); + + if (hospi->State == HAL_OSPI_STATE_BUSY_RX) + { +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->RxHalfCpltCallback(hospi); +#else + HAL_OSPI_RxHalfCpltCallback(hospi); +#endif + } + else + { +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->TxHalfCpltCallback(hospi); +#else + HAL_OSPI_TxHalfCpltCallback(hospi); +#endif + } +} + +/** + * @brief DMA OSPI communication error callback. + * @param hdma : DMA handle + * @retval None + */ +static void OSPI_DMAError(DMA_HandleTypeDef *hdma) +{ + OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent); + hospi->XferCount = 0; + hospi->ErrorCode = HAL_OSPI_ERROR_DMA; + + /* Disable the DMA transfer on the OctoSPI side */ + CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN); + + /* Abort the OctoSPI */ + if (HAL_OSPI_Abort_IT(hospi) != HAL_OK) + { + /* Disable the interrupts */ + __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE); + + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Error callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->ErrorCallback(hospi); +#else + HAL_OSPI_ErrorCallback(hospi); +#endif + } +} + +/** + * @brief DMA OSPI abort complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void OSPI_DMAAbortCplt(DMA_HandleTypeDef *hdma) +{ + OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent); + hospi->XferCount = 0; + + /* Check the state */ + if (hospi->State == HAL_OSPI_STATE_ABORT) + { + /* DMA abort called by OctoSPI abort */ + if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET) + { + /* Clear transfer complete flag */ + __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC); + + /* Enable the transfer complete interrupts */ + __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC); + + /* Perform an abort of the OctoSPI */ + SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT); + } + else + { + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Abort callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->AbortCpltCallback(hospi); +#else + HAL_OSPI_AbortCpltCallback(hospi); +#endif + } + } + else + { + /* DMA abort called due to a transfer error interrupt */ + /* Update state */ + hospi->State = HAL_OSPI_STATE_READY; + + /* Error callback */ +#if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) + hospi->ErrorCallback(hospi); +#else + HAL_OSPI_ErrorCallback(hospi); +#endif + } +} +#endif + +/** + * @brief Wait for a flag state until timeout. + * @param hospi : OSPI handle + * @param Flag : Flag checked + * @param State : Value of the flag expected + * @param Timeout : Duration of the timeout + * @param Tickstart : Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag, + FlagStatus State, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is in expected state */ + while((__HAL_OSPI_GET_FLAG(hospi, Flag)) != State) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if(((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + hospi->State = HAL_OSPI_STATE_ERROR; + hospi->ErrorCode |= HAL_OSPI_ERROR_TIMEOUT; + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/** + * @brief Configure the registers for the regular command mode. + * @param hospi : OSPI handle + * @param cmd : structure that contains the command configuration information + * @retval HAL status + */ +static HAL_StatusTypeDef OSPI_ConfigCmd(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd) +{ + HAL_StatusTypeDef status = HAL_OK; + __IO uint32_t *ccr_reg, *tcr_reg, *ir_reg, *abr_reg; + + /* Re-initialize the value of the functional mode */ + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U); + + /* Configure the flash ID */ + if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE) + { + MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FSEL, cmd->FlashId); + } + + if (cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG) + { + ccr_reg = &(hospi->Instance->WCCR); + tcr_reg = &(hospi->Instance->WTCR); + ir_reg = &(hospi->Instance->WIR); + abr_reg = &(hospi->Instance->WABR); + } + else + { + ccr_reg = &(hospi->Instance->CCR); + tcr_reg = &(hospi->Instance->TCR); + ir_reg = &(hospi->Instance->IR); + abr_reg = &(hospi->Instance->ABR); + } + + /* Configure the CCR register with DQS and SIOO modes */ + *ccr_reg = (cmd->DQSMode | cmd->SIOOMode); + + if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE) + { + /* Configure the ABR register with alternate bytes value */ + *abr_reg = cmd->AlternateBytes; + + /* Configure the CCR register with alternate bytes communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ABMODE | OCTOSPI_CCR_ABDTR | OCTOSPI_CCR_ABSIZE), + (cmd->AlternateBytesMode | cmd->AlternateBytesDtrMode | cmd->AlternateBytesSize)); + } + + /* Configure the TCR register with the number of dummy cycles */ + MODIFY_REG((*tcr_reg), OCTOSPI_TCR_DCYC, cmd->DummyCycles); + + if (cmd->DataMode != HAL_OSPI_DATA_NONE) + { + if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG) + { + /* Configure the DLR register with the number of data */ + hospi->Instance->DLR = (cmd->NbData - 1U); + } + } + + if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE) + { + if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE) + { + if (cmd->DataMode != HAL_OSPI_DATA_NONE) + { + /* ---- Command with instruction, address and data ---- */ + + /* Configure the CCR register with all communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE | + OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE | + OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR), + (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize | + cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize | + cmd->DataMode | cmd->DataDtrMode)); + } + else + { + /* ---- Command with instruction and address ---- */ + + /* Configure the CCR register with all communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE | + OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE), + (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize | + cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize)); + + /* The DHQC bit is linked with DDTR bit which should be activated */ + if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) && + (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE)) + { + MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE); + } + } + + /* Configure the IR register with the instruction value */ + *ir_reg = cmd->Instruction; + + /* Configure the AR register with the address value */ + hospi->Instance->AR = cmd->Address; + } + else + { + if (cmd->DataMode != HAL_OSPI_DATA_NONE) + { + /* ---- Command with instruction and data ---- */ + + /* Configure the CCR register with all communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE | + OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR), + (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize | + cmd->DataMode | cmd->DataDtrMode)); + } + else + { + /* ---- Command with only instruction ---- */ + + /* Configure the CCR register with all communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE), + (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize)); + + /* The DHQC bit is linked with DDTR bit which should be activated */ + if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) && + (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE)) + { + MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE); + } + } + + /* Configure the IR register with the instruction value */ + *ir_reg = cmd->Instruction; + + } + } + else + { + if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE) + { + if (cmd->DataMode != HAL_OSPI_DATA_NONE) + { + /* ---- Command with address and data ---- */ + + /* Configure the CCR register with all communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE | + OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR), + (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize | + cmd->DataMode | cmd->DataDtrMode)); + } + else + { + /* ---- Command with only address ---- */ + + /* Configure the CCR register with all communication parameters */ + MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE), + (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize)); + } + + /* Configure the AR register with the instruction value */ + hospi->Instance->AR = cmd->Address; + } + else + { + /* ---- Invalid command configuration (no instruction, no address) ---- */ + status = HAL_ERROR; + hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM; + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Get the current IOM configuration for an OctoSPI instance. + * @param instance_nb : number of the instance + * @param cfg : configuration of the IO Manager for the instance + * @retval HAL status + */ +static HAL_StatusTypeDef OSPIM_GetConfig(uint8_t instance_nb, OSPIM_CfgTypeDef *cfg) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t reg, value = 0U; + uint32_t index; + + if ((instance_nb == 0U) || (instance_nb > OSPI_NB_INSTANCE) || (cfg == NULL)) + { + /* Invalid parameter -> error returned */ + status = HAL_ERROR; + } + else + { + /* Initialize the structure */ + cfg->ClkPort = 0U; + cfg->DQSPort = 0U; + cfg->NCSPort = 0U; + cfg->IOLowPort = 0U; + cfg->IOHighPort = 0U; + + if (instance_nb == 2U) + { +#if defined (OCTOSPIM_CR_MUXEN) + if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) == 0U) + { +#endif + value = (OCTOSPIM_PCR_CLKSRC | OCTOSPIM_PCR_DQSSRC | OCTOSPIM_PCR_NCSSRC | OCTOSPIM_PCR_IOLSRC_1 | OCTOSPIM_PCR_IOHSRC_1); +#if defined (OCTOSPIM_CR_MUXEN) + } + else + { + value = OCTOSPIM_PCR_NCSSRC; + } +#endif + } + + /* Get the information about the instance */ + for (index = 0U; index < OSPI_IOM_NB_PORTS; index ++) + { + reg = OCTOSPIM->PCR[index]; + + if ((reg & OCTOSPIM_PCR_CLKEN) != 0U) + { + /* The clock is enabled on this port */ + if ((reg & OCTOSPIM_PCR_CLKSRC) == (value & OCTOSPIM_PCR_CLKSRC)) + { + /* The clock correspond to the instance passed as parameter */ + cfg->ClkPort = index+1U; + } + } + + if ((reg & OCTOSPIM_PCR_DQSEN) != 0U) + { + /* The DQS is enabled on this port */ + if ((reg & OCTOSPIM_PCR_DQSSRC) == (value & OCTOSPIM_PCR_DQSSRC)) + { + /* The DQS correspond to the instance passed as parameter */ + cfg->DQSPort = index+1U; + } + } + + if ((reg & OCTOSPIM_PCR_NCSEN) != 0U) + { + /* The nCS is enabled on this port */ + if ((reg & OCTOSPIM_PCR_NCSSRC) == (value & OCTOSPIM_PCR_NCSSRC)) + { + /* The nCS correspond to the instance passed as parameter */ + cfg->NCSPort = index+1U; + } + } + + if ((reg & OCTOSPIM_PCR_IOLEN) != 0U) + { + /* The IO Low is enabled on this port */ + if ((reg & OCTOSPIM_PCR_IOLSRC_1) == (value & OCTOSPIM_PCR_IOLSRC_1)) + { + /* The IO Low correspond to the instance passed as parameter */ + if ((reg & OCTOSPIM_PCR_IOLSRC_0) == 0U) + { + cfg->IOLowPort = (OCTOSPIM_PCR_IOLEN | (index+1U)); + } + else + { + cfg->IOLowPort = (OCTOSPIM_PCR_IOHEN | (index+1U)); + } + } + } + + if ((reg & OCTOSPIM_PCR_IOHEN) != 0U) + { + /* The IO High is enabled on this port */ + if ((reg & OCTOSPIM_PCR_IOHSRC_1) == (value & OCTOSPIM_PCR_IOHSRC_1)) + { + /* The IO High correspond to the instance passed as parameter */ + if ((reg & OCTOSPIM_PCR_IOHSRC_0) == 0U) + { + cfg->IOHighPort = (OCTOSPIM_PCR_IOLEN | (index+1U)); + } + else + { + cfg->IOHighPort = (OCTOSPIM_PCR_IOHEN | (index+1U)); + } + } + } + } + } + + /* Return function status */ + return status; +} + +/** + @endcond + */ + +/** + * @} + */ + +#endif /* HAL_OSPI_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* OCTOSPI || OCTOSPI1 || OCTOSPI2 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_qspi.c b/stm32/mk4-bootloader/stm32l4xx_hal_qspi.c deleted file mode 100644 index b8b3b8d9..00000000 --- a/stm32/mk4-bootloader/stm32l4xx_hal_qspi.c +++ /dev/null @@ -1,2356 +0,0 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_qspi.c - * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 - * @brief QSPI HAL module driver. - * This file provides firmware functions to manage the following - * functionalities of the QuadSPI interface (QSPI). - * + Initialization and de-initialization functions - * + Indirect functional mode management - * + Memory-mapped functional mode management - * + Auto-polling functional mode management - * + Interrupts and flags management - * + DMA channel configuration for indirect functional mode - * + Errors management and abort functionality - * - * - @verbatim - =============================================================================== - ##### How to use this driver ##### - =============================================================================== - [..] - *** Initialization *** - ====================== - [..] - (#) As prerequisite, fill in the HAL_QSPI_MspInit() : - (++) Enable QuadSPI clock interface with __HAL_RCC_QSPI_CLK_ENABLE(). - (++) Reset QuadSPI IP with __HAL_RCC_QSPI_FORCE_RESET() and __HAL_RCC_QSPI_RELEASE_RESET(). - (++) Enable the clocks for the QuadSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE(). - (++) Configure these QuadSPI pins in alternate mode using HAL_GPIO_Init(). - (++) If interrupt mode is used, enable and configure QuadSPI global - interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). - (++) If DMA mode is used, enable the clocks for the QuadSPI DMA channel - with __HAL_RCC_DMAx_CLK_ENABLE(), configure DMA with HAL_DMA_Init(), - link it with QuadSPI handle using __HAL_LINKDMA(), enable and configure - DMA channel global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). - (#) Configure the flash size, the clock prescaler, the fifo threshold, the - clock mode, the sample shifting and the CS high time using the HAL_QSPI_Init() function. - - *** Indirect functional mode *** - ================================ - [..] - (#) Configure the command sequence using the HAL_QSPI_Command() or HAL_QSPI_Command_IT() - functions : - (++) Instruction phase : the mode used and if present the instruction opcode. - (++) Address phase : the mode used and if present the size and the address value. - (++) Alternate-bytes phase : the mode used and if present the size and the alternate - bytes values. - (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). - (++) Data phase : the mode used and if present the number of bytes. - (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay - if activated. - (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. - (#) If no data is required for the command, it is sent directly to the memory : - (++) In polling mode, the output of the function is done when the transfer is complete. - (++) In interrupt mode, HAL_QSPI_CmdCpltCallback() will be called when the transfer is complete. - (#) For the indirect write mode, use HAL_QSPI_Transmit(), HAL_QSPI_Transmit_DMA() or - HAL_QSPI_Transmit_IT() after the command configuration : - (++) In polling mode, the output of the function is done when the transfer is complete. - (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold - is reached and HAL_QSPI_TxCpltCallback() will be called when the transfer is complete. - (++) In DMA mode, HAL_QSPI_TxHalfCpltCallback() will be called at the half transfer and - HAL_QSPI_TxCpltCallback() will be called when the transfer is complete. - (#) For the indirect read mode, use HAL_QSPI_Receive(), HAL_QSPI_Receive_DMA() or - HAL_QSPI_Receive_IT() after the command configuration : - (++) In polling mode, the output of the function is done when the transfer is complete. - (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold - is reached and HAL_QSPI_RxCpltCallback() will be called when the transfer is complete. - (++) In DMA mode, HAL_QSPI_RxHalfCpltCallback() will be called at the half transfer and - HAL_QSPI_RxCpltCallback() will be called when the transfer is complete. - - *** Auto-polling functional mode *** - ==================================== - [..] - (#) Configure the command sequence and the auto-polling functional mode using the - HAL_QSPI_AutoPolling() or HAL_QSPI_AutoPolling_IT() functions : - (++) Instruction phase : the mode used and if present the instruction opcode. - (++) Address phase : the mode used and if present the size and the address value. - (++) Alternate-bytes phase : the mode used and if present the size and the alternate - bytes values. - (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). - (++) Data phase : the mode used. - (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay - if activated. - (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. - (++) The size of the status bytes, the match value, the mask used, the match mode (OR/AND), - the polling interval and the automatic stop activation. - (#) After the configuration : - (++) In polling mode, the output of the function is done when the status match is reached. The - automatic stop is activated to avoid an infinite loop. - (++) In interrupt mode, HAL_QSPI_StatusMatchCallback() will be called each time the status match is reached. - - *** Memory-mapped functional mode *** - ===================================== - [..] - (#) Configure the command sequence and the memory-mapped functional mode using the - HAL_QSPI_MemoryMapped() functions : - (++) Instruction phase : the mode used and if present the instruction opcode. - (++) Address phase : the mode used and the size. - (++) Alternate-bytes phase : the mode used and if present the size and the alternate - bytes values. - (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). - (++) Data phase : the mode used. - (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay - if activated. - (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. - (++) The timeout activation and the timeout period. - (#) After the configuration, the QuadSPI will be used as soon as an access on the AHB is done on - the address range. HAL_QSPI_TimeOutCallback() will be called when the timeout expires. - - *** Errors management and abort functionality *** - ================================================= - [..] - (#) HAL_QSPI_GetError() function gives the error raised during the last operation. - (#) HAL_QSPI_Abort() and HAL_QSPI_AbortIT() functions aborts any on-going operation and - flushes the fifo : - (++) In polling mode, the output of the function is done when the transfer - complete bit is set and the busy bit cleared. - (++) In interrupt mode, HAL_QSPI_AbortCpltCallback() will be called when - the transfer complete bi is set. - - *** Control functions *** - ========================= - [..] - (#) HAL_QSPI_GetState() function gives the current state of the HAL QuadSPI driver. - (#) HAL_QSPI_SetTimeout() function configures the timeout value used in the driver. - (#) HAL_QSPI_SetFifoThreshold() function configures the threshold on the Fifo of the QSPI IP. - (#) HAL_QSPI_GetFifoThreshold() function gives the current of the Fifo's threshold - - *** Workarounds linked to Silicon Limitation *** - ==================================================== - [..] - (#) Workarounds Implemented inside HAL Driver - (++) Extra data written in the FIFO at the end of a read transfer - - @endverbatim - ****************************************************************************** - * @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. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32l4xx_hal.h" - -/** @addtogroup STM32L4xx_HAL_Driver - * @{ - */ - -/** @defgroup QSPI QSPI - * @brief QSPI HAL module driver - * @{ - */ -#ifdef HAL_QSPI_MODULE_ENABLED - -/* Private typedef -----------------------------------------------------------*/ - -/* Private define ------------------------------------------------------------*/ -/** @defgroup QSPI_Private_Constants QSPI Private Constants - * @{ - */ -#define QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE ((uint32_t)0x00000000) /*!Instance)); - assert_param(IS_QSPI_CLOCK_PRESCALER(hqspi->Init.ClockPrescaler)); - assert_param(IS_QSPI_FIFO_THRESHOLD(hqspi->Init.FifoThreshold)); - assert_param(IS_QSPI_SSHIFT(hqspi->Init.SampleShifting)); - assert_param(IS_QSPI_FLASH_SIZE(hqspi->Init.FlashSize)); - assert_param(IS_QSPI_CS_HIGH_TIME(hqspi->Init.ChipSelectHighTime)); - assert_param(IS_QSPI_CLOCK_MODE(hqspi->Init.ClockMode)); -#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || \ - defined(STM32L443xx) || defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \ - defined(STM32L496xx) || defined(STM32L4A6xx) - assert_param(IS_QSPI_DUAL_FLASH_MODE(hqspi->Init.DualFlash)); - - if (hqspi->Init.DualFlash != QSPI_DUALFLASH_ENABLE ) - { - assert_param(IS_QSPI_FLASH_ID(hqspi->Init.FlashID)); - } -#endif - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_RESET) - { - /* Allocate lock resource and initialize it */ - hqspi->Lock = HAL_UNLOCKED; - - /* Init the low level hardware : GPIO, CLOCK */ - HAL_QSPI_MspInit(hqspi); - - /* Configure the default timeout for the QSPI memory access */ - HAL_QSPI_SetTimeout(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE); - } - - /* Configure QSPI FIFO Threshold */ - MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES, - ((hqspi->Init.FifoThreshold - 1) << POSITION_VAL(QUADSPI_CR_FTHRES))); - - /* Wait till BUSY flag reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); - - if(status == HAL_OK) - { - /* Configure QSPI Clock Prescaler and Sample Shift */ -#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || \ - defined(STM32L443xx) || defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \ - defined(STM32L496xx) || defined(STM32L4A6xx) - MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PRESCALER | QUADSPI_CR_SSHIFT | QUADSPI_CR_FSEL | QUADSPI_CR_DFM), - ((hqspi->Init.ClockPrescaler << POSITION_VAL(QUADSPI_CR_PRESCALER)) | - hqspi->Init.SampleShifting | hqspi->Init.FlashID | hqspi->Init.DualFlash)); -#else - MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PRESCALER | QUADSPI_CR_SSHIFT), - ((hqspi->Init.ClockPrescaler << POSITION_VAL(QUADSPI_CR_PRESCALER)) | - hqspi->Init.SampleShifting)); -#endif - - /* Configure QSPI Flash Size, CS High Time and Clock Mode */ - MODIFY_REG(hqspi->Instance->DCR, (QUADSPI_DCR_FSIZE | QUADSPI_DCR_CSHT | QUADSPI_DCR_CKMODE), - ((hqspi->Init.FlashSize << POSITION_VAL(QUADSPI_DCR_FSIZE)) | - hqspi->Init.ChipSelectHighTime | hqspi->Init.ClockMode)); - - /* Enable the QSPI peripheral */ - __HAL_QSPI_ENABLE(hqspi); - - /* Set QSPI error code to none */ - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Initialize the QSPI state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - - /* Release Lock */ - __HAL_UNLOCK(hqspi); - - /* Return function status */ - return status; -} - -/** - * @brief De-Initialize the QSPI peripheral. - * @param hqspi: QSPI handle - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_DeInit(QSPI_HandleTypeDef *hqspi) -{ - /* Check the QSPI handle allocation */ - if(hqspi == NULL) - { - return HAL_ERROR; - } - - /* Process locked */ - __HAL_LOCK(hqspi); - - /* Disable the QSPI Peripheral Clock */ - __HAL_QSPI_DISABLE(hqspi); - - /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ - HAL_QSPI_MspDeInit(hqspi); - - /* Set QSPI error code to none */ - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Initialize the QSPI state */ - hqspi->State = HAL_QSPI_STATE_RESET; - - /* Release Lock */ - __HAL_UNLOCK(hqspi); - - return HAL_OK; -} - -/** - * @brief Initialize the QSPI MSP. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_QSPI_MspInit can be implemented in the user file - */ -} - -/** - * @brief DeInitialize the QSPI MSP. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_QSPI_MspDeInit can be implemented in the user file - */ -} - -/** - * @} - */ - -/** @defgroup QSPI_Exported_Functions_Group2 Input and Output operation functions - * @brief QSPI Transmit/Receive functions - * -@verbatim - =============================================================================== - ##### IO operation functions ##### - =============================================================================== - [..] - This subsection provides a set of functions allowing to : - (+) Handle the interrupts. - (+) Handle the command sequence. - (+) Transmit data in blocking, interrupt or DMA mode. - (+) Receive data in blocking, interrupt or DMA mode. - (+) Manage the auto-polling functional mode. - (+) Manage the memory-mapped functional mode. - -@endverbatim - * @{ - */ - -#if 0 -/** - * @brief Handle QSPI interrupt request. - * @param hqspi: QSPI handle - * @retval None - */ -void HAL_QSPI_IRQHandler(QSPI_HandleTypeDef *hqspi) -{ - __IO uint32_t *data_reg; - uint32_t flag = READ_REG(hqspi->Instance->SR); - uint32_t itsource = READ_REG(hqspi->Instance->CR); - - /* QSPI Fifo Threshold interrupt occurred ----------------------------------*/ - if((flag & QSPI_FLAG_FT) && (itsource & QSPI_IT_FT)) - { - data_reg = &hqspi->Instance->DR; - - if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX) - { - /* Transmission process */ - while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != 0) - { - if (hqspi->TxXferCount > 0) - { - /* Fill the FIFO until the threshold is reached */ - *(__IO uint8_t *)data_reg = *hqspi->pTxBuffPtr++; - hqspi->TxXferCount--; - } - else - { - /* No more data available for the transfer */ - /* Disable the QSPI FIFO Threshold Interrupt */ - __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT); - break; - } - } - } - else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX) - { - /* Receiving Process */ - while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != 0) - { - if (hqspi->RxXferCount > 0) - { - /* Read the FIFO until the threshold is reached */ - *hqspi->pRxBuffPtr++ = *(__IO uint8_t *)data_reg; - hqspi->RxXferCount--; - } - else - { - /* All data have been received for the transfer */ - /* Disable the QSPI FIFO Threshold Interrupt */ - __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT); - break; - } - } - } - - /* FIFO Threshold callback */ - HAL_QSPI_FifoThresholdCallback(hqspi); - } - - /* QSPI Transfer Complete interrupt occurred -------------------------------*/ - else if((flag & QSPI_FLAG_TC) && (itsource & QSPI_IT_TC)) - { - /* Clear interrupt */ - WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TC); - - /* Disable the QSPI FIFO Threshold, Transfer Error and Transfer complete Interrupts */ - __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT); - - /* Transfer complete callback */ - if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX) - { - if (hqspi->Instance->CR & QUADSPI_CR_DMAEN) - { - /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ - CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - - /* Disable the DMA channel */ - __HAL_DMA_DISABLE(hqspi->hdma); - } - -#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) - /* Clear Busy bit */ - HAL_QSPI_Abort_IT(hqspi); -#endif - - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - - /* TX Complete callback */ - HAL_QSPI_TxCpltCallback(hqspi); - } - else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX) - { - if (hqspi->Instance->CR & QUADSPI_CR_DMAEN) - { - /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ - CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - - /* Disable the DMA channel */ - __HAL_DMA_DISABLE(hqspi->hdma); - } - else - { - data_reg = &hqspi->Instance->DR; - while(READ_BIT(hqspi->Instance->SR, QUADSPI_SR_FLEVEL) != 0) - { - if (hqspi->RxXferCount > 0) - { - /* Read the last data received in the FIFO until it is empty */ - *hqspi->pRxBuffPtr++ = *(__IO uint8_t *)data_reg; - hqspi->RxXferCount--; - } - else - { - /* All data have been received for the transfer */ - break; - } - } - } - -#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) - /* Workaround - Extra data written in the FIFO at the end of a read transfer */ - HAL_QSPI_Abort_IT(hqspi); -#endif - - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - - /* RX Complete callback */ - HAL_QSPI_RxCpltCallback(hqspi); - } - else if(hqspi->State == HAL_QSPI_STATE_BUSY) - { - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - - /* Command Complete callback */ - HAL_QSPI_CmdCpltCallback(hqspi); - } - else if(hqspi->State == HAL_QSPI_STATE_ABORT) - { - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - - if (hqspi->ErrorCode == HAL_QSPI_ERROR_NONE) - { - /* Abort called by the user */ - - /* Abort Complete callback */ - HAL_QSPI_AbortCpltCallback(hqspi); - } - else - { - /* Abort due to an error (eg : DMA error) */ - - /* Error callback */ - HAL_QSPI_ErrorCallback(hqspi); - } - } - } - - /* QSPI Status Match interrupt occurred ------------------------------------*/ - else if((flag & QSPI_FLAG_SM) && (itsource & QSPI_IT_SM)) - { - /* Clear interrupt */ - WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_SM); - - /* Check if the automatic poll mode stop is activated */ - if(READ_BIT(hqspi->Instance->CR, QUADSPI_CR_APMS) != 0) - { - /* Disable the QSPI Transfer Error and Status Match Interrupts */ - __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE)); - - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - } - - /* Status match callback */ - HAL_QSPI_StatusMatchCallback(hqspi); - } - - /* QSPI Transfer Error interrupt occurred ----------------------------------*/ - else if((flag & QSPI_FLAG_TE) && (itsource & QSPI_IT_TE)) - { - /* Clear interrupt */ - WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TE); - - /* Disable all the QSPI Interrupts */ - __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_SM | QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT); - - /* Set error code */ - hqspi->ErrorCode |= HAL_QSPI_ERROR_TRANSFER; - - if (hqspi->Instance->CR & QUADSPI_CR_DMAEN) - { - /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ - CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - - /* Disable the DMA channel */ - hqspi->hdma->XferAbortCallback = QSPI_DMAAbortCplt; - HAL_DMA_Abort_IT(hqspi->hdma); - } - else - { - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - - /* Error callback */ - HAL_QSPI_ErrorCallback(hqspi); - } - } - - /* QSPI Timeout interrupt occurred -----------------------------------------*/ - else if((flag & QSPI_FLAG_TO) && (itsource & QSPI_IT_TO)) - { - /* Clear interrupt */ - WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TO); - - /* Timeout callback */ - HAL_QSPI_TimeOutCallback(hqspi); - } -} -#endif - -/** - * @brief Set the command configuration. - * @param hqspi: QSPI handle - * @param cmd : structure that contains the command configuration information - * @param Timeout : Timeout duration - * @note This function is used only in Indirect Read or Write Modes - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Command(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout) -{ - HAL_StatusTypeDef status = HAL_ERROR; - uint32_t tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); - if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) - { - assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); - } - - assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); - } - - assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); - } - - assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); - assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); - - assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); - assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); - assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_BUSY; - - /* Wait till BUSY flag reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, Timeout); - - if (status == HAL_OK) - { - /* Call the configuration function */ - QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); - - if (cmd->DataMode == QSPI_DATA_NONE) - { - /* When there is no data phase, the transfer start as soon as the configuration is done - so wait until TC flag is set to go back in idle state */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout); - - if (status == HAL_OK) - { - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); - - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - } - else - { - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - } - } - else - { - status = HAL_BUSY; - } - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Return function status */ - return status; -} - -/** - * @brief Set the command configuration in interrupt mode. - * @param hqspi: QSPI handle - * @param cmd : structure that contains the command configuration information - * @note This function is used only in Indirect Read or Write Modes - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Command_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd) -{ - HAL_StatusTypeDef status = HAL_ERROR; - uint32_t tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); - if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) - { - assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); - } - - assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); - } - - assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); - } - - assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); - assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); - - assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); - assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); - assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_BUSY; - - /* Wait till BUSY flag reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); - - if (status == HAL_OK) - { - if (cmd->DataMode == QSPI_DATA_NONE) - { - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC); - } - - /* Call the configuration function */ - QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); - - if (cmd->DataMode == QSPI_DATA_NONE) - { - /* When there is no data phase, the transfer start as soon as the configuration is done - so activate TC and TE interrupts */ - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Enable the QSPI Transfer Error Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_TC); - } - else - { - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_READY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - status = HAL_BUSY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - - /* Return function status */ - return status; -} - -/** - * @brief Transmit an amount of data in blocking mode. - * @param hqspi: QSPI handle - * @param pData: pointer to data buffer - * @param Timeout : Timeout duration - * @note This function is used only in Indirect Write Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Transmit(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout) -{ - HAL_StatusTypeDef status = HAL_OK; - uint32_t tickstart = HAL_GetTick(); - __IO uint32_t *data_reg = &hqspi->Instance->DR; - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - if(pData != NULL ) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX; - - /* Configure counters and size of the handle */ - hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->pTxBuffPtr = pData; - - /* Configure QSPI: CCR register with functional as indirect write */ - MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); - - while(hqspi->TxXferCount > 0) - { - /* Wait until FT flag is set to send data */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_FT, SET, tickstart, Timeout); - - if (status != HAL_OK) - { - break; - } - - *(__IO uint8_t *)data_reg = *hqspi->pTxBuffPtr++; - hqspi->TxXferCount--; - } - - if (status == HAL_OK) - { - /* Wait until TC flag is set to go back in idle state */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout); - - if (status == HAL_OK) - { - /* Clear Transfer Complete bit */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); - -#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) - /* Clear Busy bit */ - status = HAL_QSPI_Abort(hqspi); -#endif - } - } - - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - else - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - } - } - else - { - status = HAL_BUSY; - } - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - return status; -} - - -/** - * @brief Receive an amount of data in blocking mode. - * @param hqspi: QSPI handle - * @param pData: pointer to data buffer - * @param Timeout : Timeout duration - * @note This function is used only in Indirect Read Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Receive(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout) -{ - HAL_StatusTypeDef status = HAL_OK; - uint32_t tickstart = HAL_GetTick(); - uint32_t addr_reg = READ_REG(hqspi->Instance->AR); - __IO uint32_t *data_reg = &hqspi->Instance->DR; - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - if(pData != NULL ) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX; - - /* Configure counters and size of the handle */ - hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->pRxBuffPtr = pData; - - /* Configure QSPI: CCR register with functional as indirect read */ - MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); - - /* Start the transfer by re-writing the address in AR register */ - WRITE_REG(hqspi->Instance->AR, addr_reg); - - while(hqspi->RxXferCount > 0) - { - /* Wait until FT or TC flag is set to read received data */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, (QSPI_FLAG_FT | QSPI_FLAG_TC), SET, tickstart, Timeout); - - if (status != HAL_OK) - { - break; - } - - *hqspi->pRxBuffPtr++ = *(__IO uint8_t *)data_reg; - hqspi->RxXferCount--; - } - - if (status == HAL_OK) - { - /* Wait until TC flag is set to go back in idle state */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout); - - if (status == HAL_OK) - { - /* Clear Transfer Complete bit */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); - -#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) - /* Workaround - Extra data written in the FIFO at the end of a read transfer */ - status = HAL_QSPI_Abort(hqspi); -#endif - } - } - - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - else - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - } - } - else - { - status = HAL_BUSY; - } - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - return status; -} - -/** - * @brief Send an amount of data in non-blocking mode with interrupt. - * @param hqspi: QSPI handle - * @param pData: pointer to data buffer - * @note This function is used only in Indirect Write Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Transmit_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - if(pData != NULL ) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX; - - /* Configure counters and size of the handle */ - hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->pTxBuffPtr = pData; - - /* Configure QSPI: CCR register with functional as indirect write */ - MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); - - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC); - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC); - } - else - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - status = HAL_BUSY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - - return status; -} - -/** - * @brief Receive an amount of data in non-blocking mode with interrupt. - * @param hqspi: QSPI handle - * @param pData: pointer to data buffer - * @note This function is used only in Indirect Read Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Receive_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData) -{ - HAL_StatusTypeDef status = HAL_OK; - uint32_t addr_reg = READ_REG(hqspi->Instance->AR); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - if(pData != NULL ) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX; - - /* Configure counters and size of the handle */ - hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1; - hqspi->pRxBuffPtr = pData; - - /* Configure QSPI: CCR register with functional as indirect read */ - MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); - - /* Start the transfer by re-writing the address in AR register */ - WRITE_REG(hqspi->Instance->AR, addr_reg); - - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC); - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC); - } - else - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - status = HAL_BUSY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - - return status; -} - -#if 0 -/** - * @brief Send an amount of data in non-blocking mode with DMA. - * @param hqspi: QSPI handle - * @param pData: pointer to data buffer - * @note This function is used only in Indirect Write Mode - * @note If DMA peripheral access is configured as halfword, the number - * of data and the fifo threshold should be aligned on halfword - * @note If DMA peripheral access is configured as word, the number - * of data and the fifo threshold should be aligned on word - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Transmit_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData) -{ - HAL_StatusTypeDef status = HAL_OK; - uint32_t *tmp; - uint32_t data_size = (READ_REG(hqspi->Instance->DLR) + 1); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - /* Clear the error code */ - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - if(pData != NULL ) - { - /* Configure counters of the handle */ - if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE) - { - hqspi->TxXferCount = data_size; - } - else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD) - { - if (((data_size % 2) != 0) || ((hqspi->Init.FifoThreshold % 2) != 0)) - { - /* The number of data or the fifo threshold is not aligned on halfword - => no transfer possible with DMA peripheral access configured as halfword */ - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - else - { - hqspi->TxXferCount = (data_size >> 1); - } - } - else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD) - { - if (((data_size % 4) != 0) || ((hqspi->Init.FifoThreshold % 4) != 0)) - { - /* The number of data or the fifo threshold is not aligned on word - => no transfer possible with DMA peripheral access configured as word */ - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - else - { - hqspi->TxXferCount = (data_size >> 2); - } - } - - if (status == HAL_OK) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX; - - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, (QSPI_FLAG_TE | QSPI_FLAG_TC)); - - /* Configure size and pointer of the handle */ - hqspi->TxXferSize = hqspi->TxXferCount; - hqspi->pTxBuffPtr = pData; - - /* Configure QSPI: CCR register with functional mode as indirect write */ - MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); - - /* Set the QSPI DMA transfer complete callback */ - hqspi->hdma->XferCpltCallback = QSPI_DMATxCplt; - - /* Set the QSPI DMA Half transfer complete callback */ - hqspi->hdma->XferHalfCpltCallback = QSPI_DMATxHalfCplt; - - /* Set the DMA error callback */ - hqspi->hdma->XferErrorCallback = QSPI_DMAError; - - /* Clear the DMA abort callback */ - hqspi->hdma->XferAbortCallback = NULL; - - /* Configure the direction of the DMA */ - hqspi->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; - MODIFY_REG(hqspi->hdma->Instance->CCR, DMA_CCR_DIR, hqspi->hdma->Init.Direction); - - /* Enable the QSPI transmit DMA Channel */ - tmp = (uint32_t*)&pData; - HAL_DMA_Start_IT(hqspi->hdma, *(uint32_t*)tmp, (uint32_t)&hqspi->Instance->DR, hqspi->TxXferSize); - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Enable the QSPI transfer error Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE); - - /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */ - SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - } - } - else - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - status = HAL_BUSY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - - return status; -} - -/** - * @brief Receive an amount of data in non-blocking mode with DMA. - * @param hqspi: QSPI handle - * @param pData: pointer to data buffer. - * @note This function is used only in Indirect Read Mode - * @note If DMA peripheral access is configured as halfword, the number - * of data and the fifo threshold should be aligned on halfword - * @note If DMA peripheral access is configured as word, the number - * of data and the fifo threshold should be aligned on word - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_Receive_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData) -{ - HAL_StatusTypeDef status = HAL_OK; - uint32_t *tmp; - uint32_t addr_reg = READ_REG(hqspi->Instance->AR); - uint32_t data_size = (READ_REG(hqspi->Instance->DLR) + 1); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - /* Clear the error code */ - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - if(pData != NULL) - { - /* Configure counters of the handle */ - if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE) - { - hqspi->RxXferCount = data_size; - } - else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD) - { - if (((data_size % 2) != 0) || ((hqspi->Init.FifoThreshold % 2) != 0)) - { - /* The number of data or the fifo threshold is not aligned on halfword - => no transfer possible with DMA peripheral access configured as halfword */ - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - else - { - hqspi->RxXferCount = (data_size >> 1); - } - } - else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD) - { - if (((data_size % 4) != 0) || ((hqspi->Init.FifoThreshold % 4) != 0)) - { - /* The number of data or the fifo threshold is not aligned on word - => no transfer possible with DMA peripheral access configured as word */ - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - else - { - hqspi->RxXferCount = (data_size >> 2); - } - } - - if (status == HAL_OK) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX; - - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, (QSPI_FLAG_TE | QSPI_FLAG_TC)); - - /* Configure size and pointer of the handle */ - hqspi->RxXferSize = hqspi->RxXferCount; - hqspi->pRxBuffPtr = pData; - - /* Set the QSPI DMA transfer complete callback */ - hqspi->hdma->XferCpltCallback = QSPI_DMARxCplt; - - /* Set the QSPI DMA Half transfer complete callback */ - hqspi->hdma->XferHalfCpltCallback = QSPI_DMARxHalfCplt; - - /* Set the DMA error callback */ - hqspi->hdma->XferErrorCallback = QSPI_DMAError; - - /* Clear the DMA abort callback */ - hqspi->hdma->XferAbortCallback = NULL; - - /* Configure the direction of the DMA */ - hqspi->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; - MODIFY_REG(hqspi->hdma->Instance->CCR, DMA_CCR_DIR, hqspi->hdma->Init.Direction); - - /* Enable the DMA Channel */ - tmp = (uint32_t*)&pData; - HAL_DMA_Start_IT(hqspi->hdma, (uint32_t)&hqspi->Instance->DR, *(uint32_t*)tmp, hqspi->RxXferSize); - - /* Configure QSPI: CCR register with functional as indirect read */ - MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); - - /* Start the transfer by re-writing the address in AR register */ - WRITE_REG(hqspi->Instance->AR, addr_reg); - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Enable the QSPI transfer error Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE); - - /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */ - SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - } - } - else - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; - status = HAL_ERROR; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - status = HAL_BUSY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - - return status; -} -#endif - -/** - * @brief Configure the QSPI Automatic Polling Mode in blocking mode. - * @param hqspi: QSPI handle - * @param cmd: structure that contains the command configuration information. - * @param cfg: structure that contains the polling configuration information. - * @param Timeout : Timeout duration - * @note This function is used only in Automatic Polling Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_AutoPolling(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg, uint32_t Timeout) -{ - HAL_StatusTypeDef status = HAL_ERROR; - uint32_t tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); - if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) - { - assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); - } - - assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); - } - - assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); - } - - assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); - assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); - - assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); - assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); - assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); - - assert_param(IS_QSPI_INTERVAL(cfg->Interval)); - assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize)); - assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode)); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING; - - /* Wait till BUSY flag reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, Timeout); - - if (status == HAL_OK) - { - /* Configure QSPI: PSMAR register with the status match value */ - WRITE_REG(hqspi->Instance->PSMAR, cfg->Match); - - /* Configure QSPI: PSMKR register with the status mask value */ - WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask); - - /* Configure QSPI: PIR register with the interval value */ - WRITE_REG(hqspi->Instance->PIR, cfg->Interval); - - /* Configure QSPI: CR register with Match mode and Automatic stop enabled - (otherwise there will be an infinite loop in blocking mode) */ - MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS), - (cfg->MatchMode | QSPI_AUTOMATIC_STOP_ENABLE)); - - /* Call the configuration function */ - cmd->NbData = cfg->StatusBytesSize; - QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING); - - /* Wait until SM flag is set to go back in idle state */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_SM, SET, tickstart, Timeout); - - if (status == HAL_OK) - { - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_SM); - - /* Update state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - } - } - else - { - status = HAL_BUSY; - } - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Return function status */ - return status; -} - -/** - * @brief Configure the QSPI Automatic Polling Mode in non-blocking mode. - * @param hqspi: QSPI handle - * @param cmd: structure that contains the command configuration information. - * @param cfg: structure that contains the polling configuration information. - * @note This function is used only in Automatic Polling Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_AutoPolling_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg) -{ - HAL_StatusTypeDef status = HAL_ERROR; - uint32_t tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); - if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) - { - assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); - } - - assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); - } - - assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); - } - - assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); - assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); - - assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); - assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); - assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); - - assert_param(IS_QSPI_INTERVAL(cfg->Interval)); - assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize)); - assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode)); - assert_param(IS_QSPI_AUTOMATIC_STOP(cfg->AutomaticStop)); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING; - - /* Wait till BUSY flag reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); - - if (status == HAL_OK) - { - /* Configure QSPI: PSMAR register with the status match value */ - WRITE_REG(hqspi->Instance->PSMAR, cfg->Match); - - /* Configure QSPI: PSMKR register with the status mask value */ - WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask); - - /* Configure QSPI: PIR register with the interval value */ - WRITE_REG(hqspi->Instance->PIR, cfg->Interval); - - /* Configure QSPI: CR register with Match mode and Automatic stop mode */ - MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS), - (cfg->MatchMode | cfg->AutomaticStop)); - - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_SM); - - /* Call the configuration function */ - cmd->NbData = cfg->StatusBytesSize; - QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING); - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Enable the QSPI Transfer Error and status match Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE)); - - } - else - { - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - } - else - { - status = HAL_BUSY; - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - } - - /* Return function status */ - return status; -} - -/** - * @brief Configure the Memory Mapped mode. - * @param hqspi: QSPI handle - * @param cmd: structure that contains the command configuration information. - * @param cfg: structure that contains the memory mapped configuration information. - * @note This function is used only in Memory mapped Mode - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_MemoryMapped(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_MemoryMappedTypeDef *cfg) -{ - HAL_StatusTypeDef status = HAL_ERROR; - uint32_t tickstart = HAL_GetTick(); - - /* Check the parameters */ - assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); - if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) - { - assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); - } - - assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); - } - - assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); - } - - assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); - assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); - - assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); - assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); - assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); - - assert_param(IS_QSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation)); - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; - - /* Update state */ - hqspi->State = HAL_QSPI_STATE_BUSY_MEM_MAPPED; - - /* Wait till BUSY flag reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); - - if (status == HAL_OK) - { - /* Configure QSPI: CR register with timeout counter enable */ - MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_TCEN, cfg->TimeOutActivation); - - if (cfg->TimeOutActivation == QSPI_TIMEOUT_COUNTER_ENABLE) - { - assert_param(IS_QSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod)); - - /* Configure QSPI: LPTR register with the low-power timeout value */ - WRITE_REG(hqspi->Instance->LPTR, cfg->TimeOutPeriod); - - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TO); - - /* Enable the QSPI TimeOut Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TO); - } - - /* Call the configuration function */ - QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED); - } - } - else - { - status = HAL_BUSY; - } - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Return function status */ - return status; -} - -/** - * @brief Transfer Error callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_ErrorCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_QSPI_ErrorCallback could be implemented in the user file - */ -} - -/** - * @brief Abort completed callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_AbortCpltCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE: This function should not be modified, when the callback is needed, - the HAL_QSPI_AbortCpltCallback could be implemented in the user file - */ -} - -/** - * @brief Command completed callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE: This function should not be modified, when the callback is needed, - the HAL_QSPI_CmdCpltCallback could be implemented in the user file - */ -} - -/** - * @brief Rx Transfer completed callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE: This function should not be modified, when the callback is needed, - the HAL_QSPI_RxCpltCallback could be implemented in the user file - */ -} - -/** - * @brief Tx Transfer completed callback. - * @param hqspi: QSPI handle - * @retval None - */ - __weak void HAL_QSPI_TxCpltCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE: This function should not be modified, when the callback is needed, - the HAL_QSPI_TxCpltCallback could be implemented in the user file - */ -} - -/** - * @brief Rx Half Transfer completed callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_RxHalfCpltCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE: This function should not be modified, when the callback is needed, - the HAL_QSPI_RxHalfCpltCallback could be implemented in the user file - */ -} - -/** - * @brief Tx Half Transfer completed callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_TxHalfCpltCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE: This function should not be modified, when the callback is needed, - the HAL_QSPI_TxHalfCpltCallback could be implemented in the user file - */ -} - -/** - * @brief FIFO Threshold callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_FifoThresholdCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_QSPI_FIFOThresholdCallback could be implemented in the user file - */ -} - -/** - * @brief Status Match callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_QSPI_StatusMatchCallback could be implemented in the user file - */ -} - -/** - * @brief Timeout callback. - * @param hqspi: QSPI handle - * @retval None - */ -__weak void HAL_QSPI_TimeOutCallback(QSPI_HandleTypeDef *hqspi) -{ - /* Prevent unused argument(s) compilation warning */ - UNUSED(hqspi); - - /* NOTE : This function should not be modified, when the callback is needed, - the HAL_QSPI_TimeOutCallback could be implemented in the user file - */ -} - -/** - * @} - */ - -/** @defgroup QSPI_Exported_Functions_Group3 Peripheral Control and State functions - * @brief QSPI control and State functions - * -@verbatim - =============================================================================== - ##### Peripheral Control and State functions ##### - =============================================================================== - [..] - This subsection provides a set of functions allowing to : - (+) Check in run-time the state of the driver. - (+) Check the error code set during last operation. - (+) Abort any operation. - - -@endverbatim - * @{ - */ - -/** - * @brief Return the QSPI handle state. - * @param hqspi: QSPI handle - * @retval HAL state - */ -HAL_QSPI_StateTypeDef HAL_QSPI_GetState(QSPI_HandleTypeDef *hqspi) -{ - /* Return QSPI handle state */ - return hqspi->State; -} - -/** -* @brief Return the QSPI error code. -* @param hqspi: QSPI handle -* @retval QSPI Error Code -*/ -uint32_t HAL_QSPI_GetError(QSPI_HandleTypeDef *hqspi) -{ - return hqspi->ErrorCode; -} - -#if 0 -/** -* @brief Abort the current transmission. -* @param hqspi: QSPI handle -* @retval HAL status -*/ -HAL_StatusTypeDef HAL_QSPI_Abort(QSPI_HandleTypeDef *hqspi) -{ - HAL_StatusTypeDef status = HAL_OK; - uint32_t tickstart = HAL_GetTick(); - - /* Check if the state is in one of the busy states */ - if ((hqspi->State & 0x2) != 0) - { - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - if (hqspi->Instance->CR & QUADSPI_CR_DMAEN) - { - /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ - CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - - /* Abort DMA channel */ - status = HAL_DMA_Abort(hqspi->hdma); - if(status != HAL_OK) - { - hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; - } - } - - /* Configure QSPI: CR register with Abort request */ - SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT); - - /* Wait until TC flag is set to go back in idle state */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, hqspi->Timeout); - - if(status == HAL_OK) - { - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); - - /* Wait until BUSY flag is reset */ - status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); - } - - if (status == HAL_OK) - { - /* Update state */ - hqspi->State = HAL_QSPI_STATE_READY; - } - } - - return status; -} - -/** -* @brief Abort the current transmission (non-blocking function) -* @param hqspi: QSPI handle -* @retval HAL status -*/ -HAL_StatusTypeDef HAL_QSPI_Abort_IT(QSPI_HandleTypeDef *hqspi) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check if the state is in one of the busy states */ - if ((hqspi->State & 0x2) != 0) - { - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Update QSPI state */ - hqspi->State = HAL_QSPI_STATE_ABORT; - - /* Disable all interrupts */ - __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_TO | QSPI_IT_SM | QSPI_IT_FT | QSPI_IT_TC | QSPI_IT_TE)); - - if (hqspi->Instance->CR & QUADSPI_CR_DMAEN) - { - /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ - CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - - /* Abort DMA channel */ - hqspi->hdma->XferAbortCallback = QSPI_DMAAbortCplt; - HAL_DMA_Abort_IT(hqspi->hdma); - } - else - { - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); - - /* Enable the QSPI Transfer Complete Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); - - /* Configure QSPI: CR register with Abort request */ - SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT); - } - } - return status; -} -#endif - -/** @brief Set QSPI timeout. - * @param hqspi: QSPI handle. - * @param Timeout: Timeout for the QSPI memory access. - * @retval None - */ -void HAL_QSPI_SetTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) -{ - hqspi->Timeout = Timeout; -} - -/** @brief Set QSPI Fifo threshold. - * @param hqspi: QSPI handle. - * @param Threshold: Threshold of the Fifo (value between 1 and 16). - * @retval HAL status - */ -HAL_StatusTypeDef HAL_QSPI_SetFifoThreshold(QSPI_HandleTypeDef *hqspi, uint32_t Threshold) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Process locked */ - __HAL_LOCK(hqspi); - - if(hqspi->State == HAL_QSPI_STATE_READY) - { - /* Synchronize init structure with new FIFO threshold value */ - hqspi->Init.FifoThreshold = Threshold; - - /* Configure QSPI FIFO Threshold */ - MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES, - ((hqspi->Init.FifoThreshold - 1) << POSITION_VAL(QUADSPI_CR_FTHRES))); - } - else - { - status = HAL_BUSY; - } - - /* Process unlocked */ - __HAL_UNLOCK(hqspi); - - /* Return function status */ - return status; -} - -/** @brief Get QSPI Fifo threshold. - * @param hqspi: QSPI handle. - * @retval Fifo threshold (value between 1 and 16) - */ -uint32_t HAL_QSPI_GetFifoThreshold(QSPI_HandleTypeDef *hqspi) -{ - return ((READ_BIT(hqspi->Instance->CR, QUADSPI_CR_FTHRES) >> POSITION_VAL(QUADSPI_CR_FTHRES)) + 1); -} - -/** - * @} - */ - -#if 0 -/** - * @brief DMA QSPI receive process complete callback. - * @param hdma: DMA handle - * @retval None - */ -static void QSPI_DMARxCplt(DMA_HandleTypeDef *hdma) -{ - QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - hqspi->RxXferCount = 0; - - /* Enable the QSPI transfer complete Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); -} - -/** - * @brief DMA QSPI transmit process complete callback. - * @param hdma: DMA handle - * @retval None - */ -static void QSPI_DMATxCplt(DMA_HandleTypeDef *hdma) -{ - QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - hqspi->TxXferCount = 0; - - /* Enable the QSPI transfer complete Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); -} - -/** - * @brief DMA QSPI receive process half complete callback. - * @param hdma : DMA handle - * @retval None - */ -static void QSPI_DMARxHalfCplt(DMA_HandleTypeDef *hdma) -{ - QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; - - HAL_QSPI_RxHalfCpltCallback(hqspi); -} - -/** - * @brief DMA QSPI transmit process half complete callback. - * @param hdma : DMA handle - * @retval None - */ -static void QSPI_DMATxHalfCplt(DMA_HandleTypeDef *hdma) -{ - QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; - - HAL_QSPI_TxHalfCpltCallback(hqspi); -} - -/** - * @brief DMA QSPI communication error callback. - * @param hdma: DMA handle - * @retval None - */ -static void QSPI_DMAError(DMA_HandleTypeDef *hdma) -{ - QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - - hqspi->RxXferCount = 0; - hqspi->TxXferCount = 0; - hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; - - /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ - CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); - - /* Abort the QSPI */ - HAL_QSPI_Abort_IT(hqspi); -} - -/** - * @brief DMA QSPI abort complete callback. - * @param hdma: DMA handle - * @retval None - */ -static void QSPI_DMAAbortCplt(DMA_HandleTypeDef *hdma) -{ - QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - - hqspi->RxXferCount = 0; - hqspi->TxXferCount = 0; - - if(hqspi->State == HAL_QSPI_STATE_ABORT) - { - /* DMA Abort called by QSPI abort */ - /* Clear interrupt */ - __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); - - /* Enable the QSPI Transfer Complete Interrupt */ - __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); - - /* Configure QSPI: CR register with Abort request */ - SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT); - } - else - { - /* DMA Abort called due to a transfer error interrupt */ - /* Change state of QSPI */ - hqspi->State = HAL_QSPI_STATE_READY; - - /* Error callback */ - HAL_QSPI_ErrorCallback(hqspi); - } -} -#endif - -/** - * @brief Wait for a flag state until timeout. - * @param hqspi: QSPI handle - * @param Flag: Flag checked - * @param State: Value of the flag expected - * @param Timeout: Duration of the timeout - * @param Tickstart Tick start value - * @retval HAL status - */ -static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Flag, - FlagStatus State, uint32_t Tickstart, uint32_t Timeout) -{ - /* Wait until flag is in expected state */ - while((FlagStatus)(__HAL_QSPI_GET_FLAG(hqspi, Flag)) != State) - { - /* Check for the Timeout */ - if (Timeout != HAL_MAX_DELAY) - { - if((Timeout == 0) || ((HAL_GetTick() - Tickstart) > Timeout)) - { - hqspi->State = HAL_QSPI_STATE_ERROR; - hqspi->ErrorCode |= HAL_QSPI_ERROR_TIMEOUT; - - return HAL_ERROR; - } - } - } - return HAL_OK; -} - -/** - * @brief Configure the communication registers. - * @param hqspi: QSPI handle - * @param cmd: structure that contains the command configuration information - * @param FunctionalMode: functional mode to configured - * This parameter can be one of the following values: - * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE: Indirect write mode - * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_READ: Indirect read mode - * @arg QSPI_FUNCTIONAL_MODE_AUTO_POLLING: Automatic polling mode - * @arg QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED: Memory-mapped mode - * @retval None - */ -static void QSPI_Config(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t FunctionalMode) -{ - assert_param(IS_QSPI_FUNCTIONAL_MODE(FunctionalMode)); - - if ((cmd->DataMode != QSPI_DATA_NONE) && (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)) - { - /* Configure QSPI: DLR register with the number of data to read or write */ - WRITE_REG(hqspi->Instance->DLR, (cmd->NbData - 1)); - } - - if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) - { - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - /* Configure QSPI: ABR register with alternate bytes value */ - WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes); - - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - /*---- Command with instruction, address and alternate bytes ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateBytesSize | cmd->AlternateByteMode | - cmd->AddressSize | cmd->AddressMode | cmd->InstructionMode | - cmd->Instruction | FunctionalMode)); - - if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) - { - /* Configure QSPI: AR register with address value */ - WRITE_REG(hqspi->Instance->AR, cmd->Address); - } - } - else - { - /*---- Command with instruction and alternate bytes ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateBytesSize | cmd->AlternateByteMode | - cmd->AddressMode | cmd->InstructionMode | - cmd->Instruction | FunctionalMode)); - } - } - else - { - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - /*---- Command with instruction and address ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateByteMode | cmd->AddressSize | cmd->AddressMode | - cmd->InstructionMode | cmd->Instruction | FunctionalMode)); - - if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) - { - /* Configure QSPI: AR register with address value */ - WRITE_REG(hqspi->Instance->AR, cmd->Address); - } - } - else - { - /*---- Command with only instruction ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateByteMode | cmd->AddressMode | - cmd->InstructionMode | cmd->Instruction | FunctionalMode)); - } - } - } - else - { - if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) - { - /* Configure QSPI: ABR register with alternate bytes value */ - WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes); - - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - /*---- Command with address and alternate bytes ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateBytesSize | cmd->AlternateByteMode | - cmd->AddressSize | cmd->AddressMode | - cmd->InstructionMode | FunctionalMode)); - - if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) - { - /* Configure QSPI: AR register with address value */ - WRITE_REG(hqspi->Instance->AR, cmd->Address); - } - } - else - { - /*---- Command with only alternate bytes ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateBytesSize | cmd->AlternateByteMode | - cmd->AddressMode | cmd->InstructionMode | FunctionalMode)); - } - } - else - { - if (cmd->AddressMode != QSPI_ADDRESS_NONE) - { - /*---- Command with only address ----*/ - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateByteMode | cmd->AddressSize | - cmd->AddressMode | cmd->InstructionMode | FunctionalMode)); - - if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) - { - /* Configure QSPI: AR register with address value */ - WRITE_REG(hqspi->Instance->AR, cmd->Address); - } - } - else - { - /*---- Command with only data phase ----*/ - if (cmd->DataMode != QSPI_DATA_NONE) - { - /* Configure QSPI: CCR register with all communications parameters */ - WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | - cmd->DataMode | (cmd->DummyCycles << POSITION_VAL(QUADSPI_CCR_DCYC)) | - cmd->AlternateByteMode | cmd->AddressMode | - cmd->InstructionMode | FunctionalMode)); - } - } - } - } -} - -/** - * @} - */ - -#endif /* HAL_QSPI_MODULE_ENABLED */ -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_rcc.c b/stm32/mk4-bootloader/stm32l4xx_hal_rcc.c index 05a371e2..552a4713 100644 --- a/stm32/mk4-bootloader/stm32l4xx_hal_rcc.c +++ b/stm32/mk4-bootloader/stm32l4xx_hal_rcc.c @@ -1,10 +1,7 @@ - /** ****************************************************************************** * @file stm32l4xx_hal_rcc.c * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 * @brief RCC HAL module driver. * This file provides firmware functions to manage the following * functionalities of the Reset and Clock Control (RCC) peripheral: @@ -41,29 +38,13 @@ ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * 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. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -71,10 +52,6 @@ /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal.h" -// unwanted junk -HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) { return 0; } -static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) { return 0; } - /** @addtogroup STM32L4xx_HAL_Driver * @{ */ @@ -92,12 +69,16 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) { re * @{ */ #define HSE_TIMEOUT_VALUE HSE_STARTUP_TIMEOUT -#define HSI_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define MSI_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define LSI_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define HSI48_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define PLL_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define CLOCKSWITCH_TIMEOUT_VALUE ((uint32_t)5000U) /* 5 s */ +#define HSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define MSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#if defined(RCC_CSR_LSIPREDIV) +#define LSI_TIMEOUT_VALUE 17U /* 17 ms (16 ms starting time + 1) */ +#else +#define LSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#endif /* RCC_CSR_LSIPREDIV */ +#define HSI48_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define CLOCKSWITCH_TIMEOUT_VALUE 5000U /* 5 s */ /** * @} */ @@ -111,25 +92,22 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) { re #define MCO1_PIN GPIO_PIN_8 #define RCC_PLL_OSCSOURCE_CONFIG(__HAL_RCC_PLLSOURCE__) \ - (MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (uint32_t)(__HAL_RCC_PLLSOURCE__))) + (MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (__HAL_RCC_PLLSOURCE__))) /** * @} */ /* Private variables ---------------------------------------------------------*/ -/** @defgroup RCC_Private_Variables RCC Private Variables - * @{ - */ - -/** - * @} - */ /* Private function prototypes -----------------------------------------------*/ /** @defgroup RCC_Private_Functions RCC Private Functions * @{ */ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +static uint32_t RCC_GetSysClockFreqFromPLLSource(void); +#endif /** * @} */ @@ -180,13 +158,15 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); (++) The first output is used to generate SAR ADC1 clock. (++) The second output is used to generate the clock for the USB OTG FS (48 MHz), the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). - (++) The Third output is used to generate an accurate clock to achieve + (++) The third output is used to generate an accurate clock to achieve high-quality audio performance on SAI interface. - (+) PLLSAI2 (clocked by HSI , HSE or MSI) providing up to two independent output clocks: - (++) The first output is used to generate SAR ADC2 clock. - (++) The second output is used to generate an accurate clock to achieve + (+) PLLSAI2 (clocked by HSI, HSE or MSI) providing up to three independent output clocks: + (++) The first output is used to generate an accurate clock to achieve high-quality audio performance on SAI interface. + (++) The second output is used to generate either SAR ADC2 clock if ADC2 is present + or LCD clock if LTDC is present. + (++) The third output is used to generate DSI clock if DSI is present. (+) CSS (Clock security system): once enabled, if a HSE clock failure occurs (HSE used directly or through PLL as System clock source), the System clock @@ -230,7 +210,7 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); @endverbatim - Table 1. HCLK clock frequency. + Table 1. HCLK clock frequency for other STM32L4 devices +-------------------------------------------------------+ | Latency | HCLK clock frequency (MHz) | | |-------------------------------------| @@ -247,6 +227,26 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); |-----------------|------------------|------------------| |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 | +-------------------------------------------------------+ + + Table 2. HCLK clock frequency for STM32L4+ devices + +--------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |--------------------------------------| + | | voltage range 1 | voltage range 2 | + | | 1.2 V | 1.0 V | + |-----------------|-------------------|------------------| + |0WS(1 CPU cycles)| 0 < HCLK <= 20 | 0 < HCLK <= 8 | + |-----------------|-------------------|------------------| + |1WS(2 CPU cycles)| 20 < HCLK <= 40 | 8 < HCLK <= 16 | + |-----------------|-------------------|------------------| + |2WS(3 CPU cycles)| 40 < HCLK <= 60 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |3WS(4 CPU cycles)| 60 < HCLK <= 80 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |4WS(5 CPU cycles)| 80 < HCLK <= 100 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |5WS(6 CPU cycles)| 100 < HCLK <= 120 | 16 < HCLK <= 26 | + +--------------------------------------------------------+ * @{ */ @@ -254,22 +254,36 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); * @brief Reset the RCC clock configuration to the default reset state. * @note The default reset state of the clock configuration is given below: * - MSI ON and used as system clock source - * - HSE, HSI, PLL, PLLSAI1 and PLLISAI2 OFF - * - AHB, APB1 and APB2 prescaler set to 1. + * - HSE, HSI, PLL, PLLSAI1 and PLLSAI2 OFF + * - AHB, APB1 and APB2 prescalers set to 1. * - CSS, MCO1 OFF * - All interrupts disabled - * @note This function doesn't modify the configuration of the - * - Peripheral clocks - * - LSI, LSE and RTC clocks - * @retval None + * - All interrupt and reset flags cleared + * @note This function does not modify the configuration of the + * - Peripheral clock sources + * - LSI, LSE and RTC clocks (Backup domain) + * @retval HAL status */ -void HAL_RCC_DeInit(void) +HAL_StatusTypeDef HAL_RCC_DeInit(void) { + uint32_t tickstart; + + /* Reset to default System clock */ /* Set MSION bit */ SET_BIT(RCC->CR, RCC_CR_MSION); /* Insure MSIRDY bit is set before writing default MSIRANGE value */ - while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) { __NOP(); } + /* Get start tick */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } /* Set MSIRANGE default value */ MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6); @@ -277,25 +291,79 @@ void HAL_RCC_DeInit(void) /* Reset CFGR register (MSI is selected as system clock source) */ CLEAR_REG(RCC->CFGR); + /* Update the SystemCoreClock global variable for MSI as system clock source */ + SystemCoreClock = MSI_VALUE; + + /* Configure the source of time base considering new system clock settings */ + if(HAL_InitTick(uwTickPrio) != HAL_OK) + { + return HAL_ERROR; + } + + /* Insure MSI selected as system clock source */ + /* Get start tick */ + tickstart = HAL_GetTick(); + + /* Wait till system clock source is ready */ + while(READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */ #if defined(RCC_PLLSAI2_SUPPORT) CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON); -#else +#elif defined(RCC_PLLSAI1_SUPPORT) CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON); +#else + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON); + #endif /* RCC_PLLSAI2_SUPPORT */ + /* Insure PLLRDY, PLLSAI1RDY and PLLSAI2RDY (if present) are reset */ + /* Get start tick */ + tickstart = HAL_GetTick(); + +#if defined(RCC_PLLSAI2_SUPPORT) + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U) + +#elif defined(RCC_PLLSAI1_SUPPORT) + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U) + +#else + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U) + +#endif + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + /* Reset PLLCFGR register */ CLEAR_REG(RCC->PLLCFGR); SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 ); +#if defined(RCC_PLLSAI1_SUPPORT) + /* Reset PLLSAI1CFGR register */ CLEAR_REG(RCC->PLLSAI1CFGR); SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N_4 ); +#endif /* RCC_PLLSAI1_SUPPORT */ + #if defined(RCC_PLLSAI2_SUPPORT) /* Reset PLLSAI2CFGR register */ @@ -310,8 +378,13 @@ void HAL_RCC_DeInit(void) /* Disable all interrupts */ CLEAR_REG(RCC->CIER); - /* Update the SystemCoreClock global variable */ - SystemCoreClock = MSI_VALUE; + /* Clear all interrupt flags */ + WRITE_REG(RCC->CICR, 0xFFFFFFFFU); + + /* Clear all reset flags */ + SET_BIT(RCC->CSR, RCC_CSR_RMVF); + + return HAL_OK; } /** @@ -320,6 +393,7 @@ void HAL_RCC_DeInit(void) * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that * contains the configuration information for the RCC Oscillators. * @note The PLL is not disabled when used as system clock. + * @note The PLL source is not updated when used as PLLSAI(s) clock source. * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not * supported by this macro. User should request a transition to LSE Off * first and then LSE On or LSE Bypass. @@ -330,12 +404,22 @@ void HAL_RCC_DeInit(void) */ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { - uint32_t tickstart = 0; + uint32_t tickstart; + HAL_StatusTypeDef status; + uint32_t sysclk_source, pll_config; + + /* Check Null pointer */ + if(RCC_OscInitStruct == NULL) + { + return HAL_ERROR; + } /* Check the parameters */ - assert_param(RCC_OscInitStruct != NULL); assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); + sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE(); + pll_config = __HAL_RCC_GET_PLL_OSCSOURCE(); + /*----------------------------- MSI Configuration --------------------------*/ if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) { @@ -344,10 +428,11 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue)); assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange)); - /* When the MSI is used as system clock it will not be disabled */ - if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ) + /* Check if MSI is used as system clock or as PLL source when PLL is selected as system clock */ + if((sysclk_source == RCC_CFGR_SWS_MSI) || + ((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_config == RCC_PLLSOURCE_MSI))) { - if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF)) + if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF)) { return HAL_ERROR; } @@ -380,17 +465,25 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); /* Decrease number of wait states update if necessary */ - if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK) + /* Only possible when MSI is the System clock source */ + if(sysclk_source == RCC_CFGR_SWS_MSI) { - return HAL_ERROR; + if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK) + { + return HAL_ERROR; + } } } /* Update the SystemCoreClock global variable */ - SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU); /* Configure the source of time base considering new system clocks settings*/ - HAL_InitTick (TICK_INT_PRIORITY); + status = HAL_InitTick(uwTickPrio); + if(status != HAL_OK) + { + return status; + } } } else @@ -405,7 +498,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till MSI is ready */ - while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U) { if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) { @@ -427,7 +520,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till MSI is ready */ - while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U) { if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) { @@ -444,10 +537,10 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ - if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) || - ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE))) + if((sysclk_source == RCC_CFGR_SWS_HSE) || + ((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_config == RCC_PLLSOURCE_HSE))) { - if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) + if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) { return HAL_ERROR; } @@ -464,7 +557,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till HSE is ready */ - while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) { if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) { @@ -478,7 +571,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till HSE is disabled */ - while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) { if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) { @@ -496,11 +589,11 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue)); /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ - if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) || - ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI))) + if((sysclk_source == RCC_CFGR_SWS_HSI) || + ((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_config == RCC_PLLSOURCE_HSI))) { /* When HSI is used as system clock it will not be disabled */ - if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)) + if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)) { return HAL_ERROR; } @@ -523,7 +616,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till HSI is ready */ - while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U) { if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) { @@ -543,7 +636,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till HSI is disabled */ - while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) { if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) { @@ -562,6 +655,45 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) /* Check the LSI State */ if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF) { +#if defined(RCC_CSR_LSIPREDIV) + uint32_t csr_temp = RCC->CSR; + + /* Check LSI division factor */ + assert_param(IS_RCC_LSIDIV(RCC_OscInitStruct->LSIDiv)); + + if (RCC_OscInitStruct->LSIDiv != (csr_temp & RCC_CSR_LSIPREDIV)) + { + if (((csr_temp & RCC_CSR_LSIRDY) == RCC_CSR_LSIRDY) && \ + ((csr_temp & RCC_CSR_LSION) != RCC_CSR_LSION)) + { + /* If LSIRDY is set while LSION is not enabled, + LSIPREDIV can't be updated */ + return HAL_ERROR; + } + + /* Turn off LSI before changing RCC_CSR_LSIPREDIV */ + if ((csr_temp & RCC_CSR_LSION) == RCC_CSR_LSION) + { + __HAL_RCC_LSI_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSI is disabled */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U) + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + /* Set LSI division factor */ + MODIFY_REG(RCC->CSR, RCC_CSR_LSIPREDIV, RCC_OscInitStruct->LSIDiv); + } +#endif /* RCC_CSR_LSIPREDIV */ + /* Enable the Internal Low Speed oscillator (LSI). */ __HAL_RCC_LSI_ENABLE(); @@ -569,7 +701,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till LSI is ready */ - while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RESET) + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == 0U) { if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) { @@ -586,7 +718,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till LSI is disabled */ - while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != RESET) + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U) { if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) { @@ -629,7 +761,32 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) } /* Set the new LSE configuration -----------------------------------------*/ +#if defined(RCC_BDCR_LSESYSDIS) + if((RCC_OscInitStruct->LSEState & RCC_BDCR_LSEON) != 0U) + { + /* Set LSESYSDIS bit according to LSE propagation option (enabled or disabled) */ + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSESYSDIS, (RCC_OscInitStruct->LSEState & RCC_BDCR_LSESYSDIS)); + + if((RCC_OscInitStruct->LSEState & RCC_BDCR_LSEBYP) != 0U) + { + /* LSE oscillator bypass enable */ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); + } + else + { + /* LSE oscillator enable */ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); + } + } + else + { + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); + } +#else __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); +#endif /* RCC_BDCR_LSESYSDIS */ /* Check the LSE State */ if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF) @@ -638,7 +795,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till LSE is ready */ - while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U) { if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) { @@ -652,13 +809,18 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till LSE is disabled */ - while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET) + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != 0U) { if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) { return HAL_TIMEOUT; } } + +#if defined(RCC_BDCR_LSESYSDIS) + /* By default, stop disabling LSE propagation */ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSESYSDIS); +#endif /* RCC_BDCR_LSESYSDIS */ } /* Restore clock configuration if changed */ @@ -684,7 +846,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till HSI48 is ready */ - while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == RESET) + while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == 0U) { if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE) { @@ -701,7 +863,7 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) tickstart = HAL_GetTick(); /* Wait till HSI48 is disabled */ - while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != RESET) + while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != 0U) { if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE) { @@ -717,53 +879,163 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) { - /* Check if the PLL is used as system clock or not */ - if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + /* PLL On ? */ + if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON) { - if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON) - { - /* Check the parameters */ - assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource)); - assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM)); - assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN)); - assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); - assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); - assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); + /* Check the parameters */ + assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource)); + assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM)); + assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN)); +#if defined(RCC_PLLP_SUPPORT) + assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); +#endif /* RCC_PLLP_SUPPORT */ + assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); + assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); + /* Do nothing if PLL configuration is the unchanged */ + pll_config = RCC->PLLCFGR; + if((READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) || + (READ_BIT(pll_config, RCC_PLLCFGR_PLLM) != ((RCC_OscInitStruct->PLL.PLLM - 1U) << RCC_PLLCFGR_PLLM_Pos)) || + (READ_BIT(pll_config, RCC_PLLCFGR_PLLN) != (RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos)) || +#if defined(RCC_PLLP_SUPPORT) +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + (READ_BIT(pll_config, RCC_PLLCFGR_PLLPDIV) != (RCC_OscInitStruct->PLL.PLLP << RCC_PLLCFGR_PLLPDIV_Pos)) || +#else + (READ_BIT(pll_config, RCC_PLLCFGR_PLLP) != ((RCC_OscInitStruct->PLL.PLLP == RCC_PLLP_DIV7) ? 0U : 1U)) || +#endif +#endif + (READ_BIT(pll_config, RCC_PLLCFGR_PLLQ) != ((((RCC_OscInitStruct->PLL.PLLQ) >> 1U) - 1U) << RCC_PLLCFGR_PLLQ_Pos)) || + (READ_BIT(pll_config, RCC_PLLCFGR_PLLR) != ((((RCC_OscInitStruct->PLL.PLLR) >> 1U) - 1U) << RCC_PLLCFGR_PLLR_Pos))) + { + /* Check if the PLL is used as system clock or not */ + if(sysclk_source != RCC_CFGR_SWS_PLL) + { +#if defined(RCC_PLLSAI1_SUPPORT) || defined(RCC_PLLSAI2_SUPPORT) + /* Check if main PLL can be updated */ + /* Not possible if the source is shared by other enabled PLLSAIx */ + if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1ON) != 0U) +#if defined(RCC_PLLSAI2_SUPPORT) + || (READ_BIT(RCC->CR, RCC_CR_PLLSAI2ON) != 0U) +#endif + ) + { + return HAL_ERROR; + } + else +#endif /* RCC_PLLSAI1_SUPPORT || RCC_PLLSAI2_SUPPORT */ + { + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Configure the main PLL clock source, multiplication and division factors. */ + __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource, + RCC_OscInitStruct->PLL.PLLM, + RCC_OscInitStruct->PLL.PLLN, +#if defined(RCC_PLLP_SUPPORT) + RCC_OscInitStruct->PLL.PLLP, +#endif + RCC_OscInitStruct->PLL.PLLQ, + RCC_OscInitStruct->PLL.PLLR); + + /* Enable the main PLL. */ + __HAL_RCC_PLL_ENABLE(); + + /* Enable PLL System Clock output. */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + else + { + /* PLL is already used as System core clock */ + return HAL_ERROR; + } + } + else + { + /* PLL configuration is unchanged */ + /* Re-enable PLL if it was disabled (ie. low power mode) */ + if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) + { + /* Enable the main PLL. */ + __HAL_RCC_PLL_ENABLE(); + + /* Enable PLL System Clock output. */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + else + { + /* Check that PLL is not used as system clock or not */ + if(sysclk_source != RCC_CFGR_SWS_PLL) + { /* Disable the main PLL. */ __HAL_RCC_PLL_DISABLE(); - /* Get Start Tick*/ - tickstart = HAL_GetTick(); - - /* Wait till PLL is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + /* Disable all PLL outputs to save power if no PLLs on */ +#if defined(RCC_PLLSAI1_SUPPORT) && defined(RCC_CR_PLLSAI2RDY) + if(READ_BIT(RCC->CR, (RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY)) == 0U) { - if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); } +#elif defined(RCC_PLLSAI1_SUPPORT) + if(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == 0U) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } +#else + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); +#endif /* RCC_PLLSAI1_SUPPORT && RCC_CR_PLLSAI2RDY */ - /* Configure the main PLL clock source, multiplication and division factors. */ - __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource, - RCC_OscInitStruct->PLL.PLLM, - RCC_OscInitStruct->PLL.PLLN, - RCC_OscInitStruct->PLL.PLLP, - RCC_OscInitStruct->PLL.PLLQ, - RCC_OscInitStruct->PLL.PLLR); - - /* Enable the main PLL. */ - __HAL_RCC_PLL_ENABLE(); - - /* Enable PLL System Clock output. */ - __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK); +#if defined(RCC_PLLSAI2_SUPPORT) + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK); +#elif defined(RCC_PLLSAI1_SUPPORT) + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK); +#else + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK); +#endif /* RCC_PLLSAI2_SUPPORT */ /* Get Start Tick*/ tickstart = HAL_GetTick(); - /* Wait till PLL is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + /* Wait till PLL is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U) { if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) { @@ -773,43 +1045,10 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) } else { - /* Disable the main PLL. */ - __HAL_RCC_PLL_DISABLE(); - - /* Disable all PLL outputs to save power if no PLLs on */ - if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) -#if defined(RCC_PLLSAI2_SUPPORT) - && - (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) -#endif /* RCC_PLLSAI2_SUPPORT */ - ) - { - MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); - } - -#if defined(RCC_PLLSAI2_SUPPORT) - __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK); -#else - __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK); -#endif /* RCC_PLLSAI2_SUPPORT */ - - /* Get Start Tick*/ - tickstart = HAL_GetTick(); - - /* Wait till PLL is disabled */ - while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) - { - if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } + /* PLL is already used as System core clock */ + return HAL_ERROR; } } - else - { - return HAL_ERROR; - } } return HAL_OK; } @@ -826,6 +1065,19 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) * @arg FLASH_LATENCY_2 FLASH 2 Latency cycles * @arg FLASH_LATENCY_3 FLASH 3 Latency cycles * @arg FLASH_LATENCY_4 FLASH 4 Latency cycles + @if STM32L4S9xx + * @arg FLASH_LATENCY_5 FLASH 5 Latency cycles + * @arg FLASH_LATENCY_6 FLASH 6 Latency cycles + * @arg FLASH_LATENCY_7 FLASH 7 Latency cycles + * @arg FLASH_LATENCY_8 FLASH 8 Latency cycles + * @arg FLASH_LATENCY_9 FLASH 9 Latency cycles + * @arg FLASH_LATENCY_10 FLASH 10 Latency cycles + * @arg FLASH_LATENCY_11 FLASH 11 Latency cycles + * @arg FLASH_LATENCY_12 FLASH 12 Latency cycles + * @arg FLASH_LATENCY_13 FLASH 13 Latency cycles + * @arg FLASH_LATENCY_14 FLASH 14 Latency cycles + * @arg FLASH_LATENCY_15 FLASH 15 Latency cycles + @endif * * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency * and updated by HAL_RCC_GetHCLKFreq() function called within this function @@ -853,10 +1105,20 @@ HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) */ HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency) { - uint32_t tickstart = 0; + uint32_t tickstart; +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t hpre = RCC_SYSCLK_DIV1; +#endif + HAL_StatusTypeDef status; + + /* Check Null pointer */ + if(RCC_ClkInitStruct == NULL) + { + return HAL_ERROR; + } /* Check the parameters */ - assert_param(RCC_ClkInitStruct != NULL); assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType)); assert_param(IS_FLASH_LATENCY(FLatency)); @@ -865,123 +1127,140 @@ HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, ui (HCLK) and the supply voltage of the device. */ /* Increasing the number of wait states because of higher CPU frequency */ - if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY)) + if(FLatency > __HAL_FLASH_GET_LATENCY()) { /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ __HAL_FLASH_SET_LATENCY(FLatency); /* Check that the new number of wait states is taken into account to access the Flash memory by reading the FLASH_ACR register */ - if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency) + if(__HAL_FLASH_GET_LATENCY() != FLatency) { return HAL_ERROR; } } + /*------------------------- SYSCLK Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) + { + assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource)); + + /* PLL is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + { + /* Check the PLL ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) + { + return HAL_ERROR; + } +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Undershoot management when selection PLL as SYSCLK source and frequency above 80Mhz */ + /* Compute target PLL output frequency */ + if(RCC_GetSysClockFreqFromPLLSource() > 80000000U) + { + if(READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1) + { + /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */ + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } + else if((((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) && (RCC_ClkInitStruct->AHBCLKDivider == RCC_SYSCLK_DIV1)) + { + /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */ + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } + else + { + /* nothing to do */ + } + } +#endif + } + else + { + /* HSE is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + { + /* Check the HSE ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) + { + return HAL_ERROR; + } + } + /* MSI is selected as System Clock Source */ + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + { + /* Check the MSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U) + { + return HAL_ERROR; + } + } + /* HSI is selected as System Clock Source */ + else + { + /* Check the HSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U) + { + return HAL_ERROR; + } + } +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Overshoot management when going down from PLL as SYSCLK source and frequency above 80Mhz */ + if(HAL_RCC_GetSysClockFreq() > 80000000U) + { + /* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */ + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } +#endif + + } + + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + while(__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos)) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + /*-------------------------- HCLK Configuration --------------------------*/ if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) { assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider)); MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); } - - /*------------------------- SYSCLK Configuration ---------------------------*/ - if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + else { - assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource)); - - /* HSE is selected as System Clock Source */ - if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + /* Is intermediate HCLK prescaler 2 applied internally, complete with HCLK prescaler 1 */ + if(hpre == RCC_SYSCLK_DIV2) { - /* Check the HSE ready flag */ - if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) - { - return HAL_ERROR; - } - } - /* PLL is selected as System Clock Source */ - else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) - { - /* Check the PLL ready flag */ - if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) - { - return HAL_ERROR; - } - } - /* MSI is selected as System Clock Source */ - else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) - { - /* Check the MSI ready flag */ - if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) - { - return HAL_ERROR; - } - } - /* HSI is selected as System Clock Source */ - else - { - /* Check the HSI ready flag */ - if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) - { - return HAL_ERROR; - } - } - MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); - - /* Get Start Tick*/ - tickstart = HAL_GetTick(); - - if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) - { - while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE) - { - if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) - { - while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) - { - if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) - { - while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_MSI) - { - if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } - } - else - { - while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI) - { - if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) - { - return HAL_TIMEOUT; - } - } + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1); } } +#endif /* Decreasing the number of wait states because of lower CPU frequency */ - if(FLatency < (FLASH->ACR & FLASH_ACR_LATENCY)) + if(FLatency < __HAL_FLASH_GET_LATENCY()) { /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ __HAL_FLASH_SET_LATENCY(FLatency); /* Check that the new number of wait states is taken into account to access the Flash memory by reading the FLASH_ACR register */ - if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency) + if(__HAL_FLASH_GET_LATENCY() != FLatency) { return HAL_ERROR; } @@ -1002,12 +1281,12 @@ HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, ui } /* Update the SystemCoreClock global variable */ - SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU); /* Configure the source of time base considering new system clocks settings*/ - HAL_InitTick (TICK_INT_PRIORITY); + status = HAL_InitTick(uwTickPrio); - return HAL_OK; + return status; } /** @@ -1063,11 +1342,15 @@ HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, ui void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) { GPIO_InitTypeDef GPIO_InitStruct; + /* Check the parameters */ assert_param(IS_RCC_MCO(RCC_MCOx)); assert_param(IS_RCC_MCODIV(RCC_MCODiv)); assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource)); + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(RCC_MCOx); + /* MCO Clock Enable */ __MCO1_CLK_ENABLE(); @@ -1117,70 +1400,79 @@ void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_ */ uint32_t HAL_RCC_GetSysClockFreq(void) { - uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; - uint32_t sysclockfreq = 0U; + uint32_t msirange = 0U, sysclockfreq = 0U; + uint32_t pllvco, pllsource, pllr, pllm; /* no init needed */ + uint32_t sysclk_source, pll_oscsource; - if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) || - ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI))) + sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE(); + pll_oscsource = __HAL_RCC_GET_PLL_OSCSOURCE(); + + if((sysclk_source == RCC_CFGR_SWS_MSI) || + ((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_oscsource == RCC_PLLSOURCE_MSI))) { /* MSI or PLL with MSI source used as system clock source */ /* Get SYSCLK source */ - if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == 0U) { /* MSISRANGE from RCC_CSR applies */ - msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; } else { /* MSIRANGE from RCC_CR applies */ - msirange = (RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; } /*MSI frequency range in HZ*/ msirange = MSIRangeTable[msirange]; - if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) + if(sysclk_source == RCC_CFGR_SWS_MSI) { /* MSI used as system clock source */ sysclockfreq = msirange; } } - else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) + else if(sysclk_source == RCC_CFGR_SWS_HSI) { /* HSI used as system clock source */ sysclockfreq = HSI_VALUE; } - else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) + else if(sysclk_source == RCC_CFGR_SWS_HSE) { /* HSE used as system clock source */ sysclockfreq = HSE_VALUE; } + else + { + /* unexpected case: sysclockfreq at 0 */ + } - if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) + if(sysclk_source == RCC_CFGR_SWS_PLL) { /* PLL used as system clock source */ - /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE) * PLLN / PLLM SYSCLK = PLL_VCO / PLLR */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); - pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); switch (pllsource) { case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + pllvco = HSI_VALUE; break; case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + pllvco = HSE_VALUE; break; case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ default: - pllvco = (msirange / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + pllvco = msirange; break; } - pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; - sysclockfreq = pllvco/pllr; + pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + pllvco = (pllvco * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)) / pllm; + pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + sysclockfreq = pllvco / pllr; } return sysclockfreq; @@ -1208,7 +1500,7 @@ uint32_t HAL_RCC_GetHCLKFreq(void) uint32_t HAL_RCC_GetPCLK1Freq(void) { /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/ - return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]); + return (HAL_RCC_GetHCLKFreq() >> (APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos] & 0x1FU)); } /** @@ -1220,7 +1512,7 @@ uint32_t HAL_RCC_GetPCLK1Freq(void) uint32_t HAL_RCC_GetPCLK2Freq(void) { /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/ - return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]); + return (HAL_RCC_GetHCLKFreq()>> (APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos] & 0x1FU)); } /** @@ -1233,7 +1525,7 @@ uint32_t HAL_RCC_GetPCLK2Freq(void) void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { /* Check the parameters */ - assert_param(RCC_OscInitStruct != NULL); + assert_param(RCC_OscInitStruct != (void *)NULL); /* Set all possible values for the Oscillator type parameter ---------------*/ #if defined(RCC_HSI48_SUPPORT) @@ -1245,11 +1537,11 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) #endif /* RCC_HSI48_SUPPORT */ /* Get the HSE configuration -----------------------------------------------*/ - if((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP) + if(READ_BIT(RCC->CR, RCC_CR_HSEBYP) == RCC_CR_HSEBYP) { RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS; } - else if((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON) + else if(READ_BIT(RCC->CR, RCC_CR_HSEON) == RCC_CR_HSEON) { RCC_OscInitStruct->HSEState = RCC_HSE_ON; } @@ -1259,7 +1551,7 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) } /* Get the MSI configuration -----------------------------------------------*/ - if((RCC->CR & RCC_CR_MSION) == RCC_CR_MSION) + if(READ_BIT(RCC->CR, RCC_CR_MSION) == RCC_CR_MSION) { RCC_OscInitStruct->MSIState = RCC_MSI_ON; } @@ -1268,11 +1560,11 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) RCC_OscInitStruct->MSIState = RCC_MSI_OFF; } - RCC_OscInitStruct->MSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos); - RCC_OscInitStruct->MSIClockRange = (uint32_t)((RCC->CR & RCC_CR_MSIRANGE) ); + RCC_OscInitStruct->MSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos; + RCC_OscInitStruct->MSIClockRange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE); /* Get the HSI configuration -----------------------------------------------*/ - if((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION) + if(READ_BIT(RCC->CR, RCC_CR_HSION) == RCC_CR_HSION) { RCC_OscInitStruct->HSIState = RCC_HSI_ON; } @@ -1281,16 +1573,34 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) RCC_OscInitStruct->HSIState = RCC_HSI_OFF; } - RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos); + RCC_OscInitStruct->HSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos; /* Get the LSE configuration -----------------------------------------------*/ - if((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP) + if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP) { - RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS; +#if defined(RCC_BDCR_LSESYSDIS) + if((RCC->BDCR & RCC_BDCR_LSESYSDIS) == RCC_BDCR_LSESYSDIS) + { + RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS_RTC_ONLY; + } + else +#endif /* RCC_BDCR_LSESYSDIS */ + { + RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS; + } } - else if((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON) + else if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEON) == RCC_BDCR_LSEON) { - RCC_OscInitStruct->LSEState = RCC_LSE_ON; +#if defined(RCC_BDCR_LSESYSDIS) + if((RCC->BDCR & RCC_BDCR_LSESYSDIS) == RCC_BDCR_LSESYSDIS) + { + RCC_OscInitStruct->LSEState = RCC_LSE_ON_RTC_ONLY; + } + else +#endif /* RCC_BDCR_LSESYSDIS */ + { + RCC_OscInitStruct->LSEState = RCC_LSE_ON; + } } else { @@ -1298,7 +1608,7 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) } /* Get the LSI configuration -----------------------------------------------*/ - if((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION) + if(READ_BIT(RCC->CSR, RCC_CSR_LSION) == RCC_CSR_LSION) { RCC_OscInitStruct->LSIState = RCC_LSI_ON; } @@ -1306,10 +1616,22 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { RCC_OscInitStruct->LSIState = RCC_LSI_OFF; } +#if defined(RCC_CSR_LSIPREDIV) + + /* Get the LSI configuration -----------------------------------------------*/ + if((RCC->CSR & RCC_CSR_LSIPREDIV) == RCC_CSR_LSIPREDIV) + { + RCC_OscInitStruct->LSIDiv = RCC_LSI_DIV128; + } + else + { + RCC_OscInitStruct->LSIDiv = RCC_LSI_DIV1; + } +#endif /* RCC_CSR_LSIPREDIV */ #if defined(RCC_HSI48_SUPPORT) /* Get the HSI48 configuration ---------------------------------------------*/ - if((RCC->CRRCR & RCC_CRRCR_HSI48ON) == RCC_CRRCR_HSI48ON) + if(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) == RCC_CRRCR_HSI48ON) { RCC_OscInitStruct->HSI48State = RCC_HSI48_ON; } @@ -1322,7 +1644,7 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) #endif /* RCC_HSI48_SUPPORT */ /* Get the PLL configuration -----------------------------------------------*/ - if((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON) + if(READ_BIT(RCC->CR, RCC_CR_PLLON) == RCC_CR_PLLON) { RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON; } @@ -1330,15 +1652,16 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) { RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF; } - RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); - RCC_OscInitStruct->PLL.PLLM = (uint32_t)(((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U); - RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); - RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); - RCC_OscInitStruct->PLL.PLLR = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U); + RCC_OscInitStruct->PLL.PLLSource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + RCC_OscInitStruct->PLL.PLLM = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; + RCC_OscInitStruct->PLL.PLLN = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + RCC_OscInitStruct->PLL.PLLQ = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + RCC_OscInitStruct->PLL.PLLR = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U); +#if defined(RCC_PLLP_SUPPORT) #if defined(RCC_PLLP_DIV_2_31_SUPPORT) - RCC_OscInitStruct->PLL.PLLP = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos); + RCC_OscInitStruct->PLL.PLLP = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; #else - if((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) != RESET) + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U) { RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17; } @@ -1347,6 +1670,7 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7; } #endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +#endif /* RCC_PLLP_SUPPORT */ } /** @@ -1360,26 +1684,26 @@ void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency) { /* Check the parameters */ - assert_param(RCC_ClkInitStruct != NULL); - assert_param(pFLatency != NULL); + assert_param(RCC_ClkInitStruct != (void *)NULL); + assert_param(pFLatency != (void *)NULL); /* Set all possible values for the Clock type parameter --------------------*/ RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; /* Get the SYSCLK configuration --------------------------------------------*/ - RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW); + RCC_ClkInitStruct->SYSCLKSource = READ_BIT(RCC->CFGR, RCC_CFGR_SW); /* Get the HCLK configuration ----------------------------------------------*/ - RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE); + RCC_ClkInitStruct->AHBCLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_HPRE); /* Get the APB1 configuration ----------------------------------------------*/ - RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1); + RCC_ClkInitStruct->APB1CLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1); /* Get the APB2 configuration ----------------------------------------------*/ - RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3U); + RCC_ClkInitStruct->APB2CLKDivider = (READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> 3U); /* Get the Flash Wait State (Latency) configuration ------------------------*/ - *pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_LATENCY); + *pFLatency = __HAL_FLASH_GET_LATENCY(); } /** @@ -1434,7 +1758,6 @@ __weak void HAL_RCC_CSSCallback(void) * @} */ -#if 0 /* Private function prototypes -----------------------------------------------*/ /** @addtogroup RCC_Private_Functions * @{ @@ -1447,7 +1770,7 @@ __weak void HAL_RCC_CSSCallback(void) */ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) { - uint32_t vos = 0; + uint32_t vos; uint32_t latency = FLASH_LATENCY_0; /* default value 0WS */ if(__HAL_RCC_PWR_IS_CLK_ENABLED()) @@ -1481,6 +1804,23 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) } else { +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + if(msirange >= RCC_MSIRANGE_8) + { + /* MSI >= 16Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else + { + if(msirange == RCC_MSIRANGE_7) + { + /* MSI 8Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */ + } +#else if(msirange > RCC_MSIRANGE_8) { /* MSI > 16Mhz */ @@ -1500,19 +1840,74 @@ static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) } /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */ } +#endif } __HAL_FLASH_SET_LATENCY(latency); /* Check that the new number of wait states is taken into account to access the Flash memory by reading the FLASH_ACR register */ - if((FLASH->ACR & FLASH_ACR_LATENCY) != latency) + if(__HAL_FLASH_GET_LATENCY() != latency) { return HAL_ERROR; } return HAL_OK; } + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +/** + * @brief Compute SYSCLK frequency based on PLL SYSCLK source. + * @retval SYSCLK frequency + */ +static uint32_t RCC_GetSysClockFreqFromPLLSource(void) +{ + uint32_t msirange = 0U; + uint32_t pllvco, pllsource, pllr, pllm, sysclockfreq; /* no init needed */ + + if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) + { + /* Get MSI range source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == 0U) + { /* MSISRANGE from RCC_CSR applies */ + msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + } + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE) * PLLN / PLLM + SYSCLK = PLL_VCO / PLLR + */ + pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + + switch (pllsource) + { + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = HSI_VALUE; + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = HSE_VALUE; + break; + + case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + default: + pllvco = msirange; + break; + } + pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + pllvco = (pllvco * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)) / pllm; + pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + sysclockfreq = pllvco / pllr; + + return sysclockfreq; +} #endif /** diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_rcc_ex.c b/stm32/mk4-bootloader/stm32l4xx_hal_rcc_ex.c index fb95fb2d..652cc687 100644 --- a/stm32/mk4-bootloader/stm32l4xx_hal_rcc_ex.c +++ b/stm32/mk4-bootloader/stm32l4xx_hal_rcc_ex.c @@ -2,8 +2,6 @@ ****************************************************************************** * @file stm32l4xx_hal_rcc_ex.c * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 * @brief Extended RCC HAL module driver. * This file provides firmware functions to manage the following * functionalities RCC extended peripheral: @@ -14,29 +12,13 @@ ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * 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. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -44,11 +26,6 @@ /* Includes ------------------------------------------------------------------*/ #include "stm32l4xx_hal.h" -// XXX: kill some dead code -#define HACK_N_SLASH -#undef RCC_PLLSAI2_SUPPORT - - /** @addtogroup STM32L4xx_HAL_Driver * @{ */ @@ -65,9 +42,9 @@ /** @defgroup RCCEx_Private_Constants RCCEx Private Constants * @{ */ -#define PLLSAI1_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define PLLSAI2_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ -#define PLL_TIMEOUT_VALUE ((uint32_t)2U) /* 2 ms (minimum Tick + 1) */ +#define PLLSAI1_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLLSAI2_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ #define DIVIDER_P_UPDATE 0U #define DIVIDER_Q_UPDATE 1U @@ -86,14 +63,23 @@ /** @defgroup RCCEx_Private_Functions RCCEx Private Functions * @{ */ +#if defined(RCC_PLLSAI1_SUPPORT) + static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider); +#endif /* RCC_PLLSAI1_SUPPORT */ + #if defined(RCC_PLLSAI2_SUPPORT) static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider); #endif /* RCC_PLLSAI2_SUPPORT */ +#if defined(SAI1) + +static uint32_t RCCEx_GetSAIxPeriphCLKFreq(uint32_t PeriphClk, uint32_t InputFrequency); + +#endif /* SAI1 */ /** * @} */ @@ -148,17 +134,23 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u @if STM32L4A6xx * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock - * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock + * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock (only for devices with SAI1) @if STM32L486xx * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) @endif @if STM32L4A6xx * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock @if STM32L443xx * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) @@ -178,12 +170,23 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u @if STM32L486xx * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) @endif @if STM32L4A6xx * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) - @endif * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC) + * @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI) + * @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI) + @endif * * @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select * the RTC clock source: in this case the access to Backup domain is enabled. @@ -192,14 +195,15 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u */ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) { - uint32_t tmpregister = 0; - uint32_t tickstart = 0U; + uint32_t tmpregister, tickstart; /* no init needed */ HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */ HAL_StatusTypeDef status = HAL_OK; /* Final status */ /* Check the parameters */ assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); +#if defined(SAI1) + /*-------------------------- SAI1 clock source configuration ---------------------*/ if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)) { @@ -209,14 +213,12 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk switch(PeriphClkInit->Sai1ClockSelection) { case RCC_SAI1CLKSOURCE_PLL: /* PLL is used as clock source for SAI1*/ - /* Enable SAI Clock output generated form System PLL . */ -#ifndef HACK_N_SLASH + /* Enable SAI Clock output generated from System PLL . */ #if defined(RCC_PLLSAI2_SUPPORT) __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); #else __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI2CLK); #endif /* RCC_PLLSAI2_SUPPORT */ -#endif /* SAI1 clock source config set later after clock selection check */ break; @@ -237,6 +239,9 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk #endif /* RCC_PLLSAI2_SUPPORT */ case RCC_SAI1CLKSOURCE_PIN: /* External clock is used as source of SAI1 clock*/ +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + case RCC_SAI1CLKSOURCE_HSI: /* HSI is used as source of SAI1 clock*/ +#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ /* SAI1 clock source config set later after clock selection check */ break; @@ -257,6 +262,8 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk } } +#endif /* SAI1 */ + #if defined(SAI2) /*-------------------------- SAI2 clock source configuration ---------------------*/ @@ -268,7 +275,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk switch(PeriphClkInit->Sai2ClockSelection) { case RCC_SAI2CLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/ - /* Enable SAI Clock output generated form System PLL . */ + /* Enable SAI Clock output generated from System PLL . */ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); /* SAI2 clock source config set later after clock selection check */ break; @@ -281,13 +288,14 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk case RCC_SAI2CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI2*/ /* PLLSAI2 input clock, parameters M, N & P configuration and clock output (PLLSAI2ClockOut) */ -#if defined(RCC_PLLSAI2_SUPPORT) ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE); -#endif /* SAI2 clock source config set later after clock selection check */ break; case RCC_SAI2CLKSOURCE_PIN: /* External clock is used as source of SAI2 clock*/ +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + case RCC_SAI2CLKSOURCE_HSI: /* HSI is used as source of SAI2 clock*/ +#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ /* SAI2 clock source config set later after clock selection check */ break; @@ -318,7 +326,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); /* Enable Power Clock */ - if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + if(__HAL_RCC_PWR_IS_CLK_DISABLED() != 0U) { __HAL_RCC_PWR_CLK_ENABLE(); pwrclkchanged = SET; @@ -330,7 +338,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk /* Wait for Backup domain Write protection disable */ tickstart = HAL_GetTick(); - while((PWR->CR1 & PWR_CR1_DBP) == RESET) + while(READ_BIT(PWR->CR1, PWR_CR1_DBP) == 0U) { if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) { @@ -344,7 +352,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk /* Reset the Backup domain only if the RTC Clock source selection is modified from default */ tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL); - if((tmpregister != RCC_RTCCLKSOURCE_NO_CLK) && (tmpregister != PeriphClkInit->RTCClockSelection)) + if((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection)) { /* Store the content of BDCR register before the reset of Backup Domain */ tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL)); @@ -362,7 +370,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk tickstart = HAL_GetTick(); /* Wait till LSE is ready */ - while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U) { if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) { @@ -464,7 +472,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk /* Check the parameters */ assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection)); - /* Configure the LPUAR1 clock source */ + /* Configure the LPUART1 clock source */ __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection); } @@ -540,11 +548,12 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL) { - /* Enable PLL48M1CLK output */ + /* Enable PLL48M1CLK output clock */ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); } else { +#if defined(RCC_PLLSAI1_SUPPORT) if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1) { /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ @@ -556,6 +565,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk status = ret; } } +#endif /* RCC_PLLSAI1_SUPPORT */ } } @@ -569,11 +579,18 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection)); __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection); - if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) + if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) /* PLL "Q" ? */ { - /* Enable PLL48M1CLK output */ + /* Enable PLL48M1CLK output clock */ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); } +#if defined(RCC_CCIPR2_SDMMCSEL) + else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLP) /* PLL "P" ? */ + { + /* Enable PLLSAI3CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); + } +#endif else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLSAI1) { /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ @@ -585,6 +602,10 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk status = ret; } } + else + { + /* nothing to do */ + } } #endif /* SDMMC1 */ @@ -597,9 +618,10 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL) { - /* Enable PLL48M1CLK output */ + /* Enable PLL48M1CLK output clock */ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); } +#if defined(RCC_PLLSAI1_SUPPORT) else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLLSAI1) { /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ @@ -611,9 +633,15 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk status = ret; } } +#endif /* RCC_PLLSAI1_SUPPORT */ + else + { + /* nothing to do */ + } } /*-------------------------- ADC clock source configuration ----------------------*/ +#if !defined(STM32L412xx) && !defined(STM32L422xx) if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) { /* Check the parameters */ @@ -622,6 +650,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk /* Configure the ADC interface clock source */ __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection); +#if defined(RCC_PLLSAI1_SUPPORT) if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1) { /* PLLSAI1 input clock, parameters M, N & R configuration and clock output (PLLSAI1ClockOut) */ @@ -633,15 +662,14 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk status = ret; } } +#endif /* RCC_PLLSAI1_SUPPORT */ #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2) { /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ -#if defined(RCC_PLLSAI2_SUPPORT) ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); -#endif if(ret != HAL_OK) { @@ -653,6 +681,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ } +#endif /* !STM32L412xx && !STM32L422xx */ #if defined(SWPMI1) @@ -680,8 +709,109 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection); } +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /*-------------------------- DFSDM1 audio clock source configuration -------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) + { + /* Check the parameters */ + assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection)); + + /* Configure the DFSDM1 interface audio clock source */ + __HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection); + } + +#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + #endif /* DFSDM1_Filter0 */ +#if defined(LTDC) + + /*-------------------------- LTDC clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC) + { + /* Check the parameters */ + assert_param(IS_RCC_LTDCCLKSOURCE(PeriphClkInit->LtdcClockSelection)); + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + + if(ret == HAL_OK) + { + /* Configure the LTDC clock source */ + __HAL_RCC_LTDC_CONFIG(PeriphClkInit->LtdcClockSelection); + + /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); + } + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#endif /* LTDC */ + +#if defined(DSI) + + /*-------------------------- DSI clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI) + { + /* Check the parameters */ + assert_param(IS_RCC_DSICLKSOURCE(PeriphClkInit->DsiClockSelection)); + + /* Configure the DSI clock source */ + __HAL_RCC_DSI_CONFIG(PeriphClkInit->DsiClockSelection); + + if(PeriphClkInit->DsiClockSelection == RCC_DSICLKSOURCE_PLLSAI2) + { + /* PLLSAI2 input clock, parameters M, N & Q configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + /*-------------------------- OctoSPIx clock source configuration ----------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) + { + /* Check the parameters */ + assert_param(IS_RCC_OSPICLKSOURCE(PeriphClkInit->OspiClockSelection)); + + /* Configure the OctoSPI clock source */ + __HAL_RCC_OSPI_CONFIG(PeriphClkInit->OspiClockSelection); + + if(PeriphClkInit->OspiClockSelection == RCC_OSPICLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + } + +#endif /* OCTOSPI1 || OCTOSPI2 */ + return status; } @@ -689,7 +819,7 @@ HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClk * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers. * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that * returns the configuration information for the Extended Peripherals - * clocks(SAI1, SAI2, LPTIM1, LPTIM2, I2C1, I2C2, I2C3, I2C4, LPUART, + * clocks(SAI1, SAI2, LPTIM1, LPTIM2, I2C1, I2C2, I2C3, I2C4, LPUART1, * USART1, USART2, USART3, UART4, UART5, RTC, ADCx, DFSDMx, SWPMI1, USB, SDMMC1 and RNG). * @retval None */ @@ -697,7 +827,15 @@ void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) { /* Set all possible values for the extended clock type parameter------------*/ -#if defined(STM32L431xx) +#if defined(STM32L412xx) || defined(STM32L422xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_RNG | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L431xx) PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \ RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ @@ -761,26 +899,65 @@ void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ RCC_PERIPHCLK_RTC ; +#elif defined(STM32L4R5xx) || defined(STM32L4S5xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI; + +#elif defined(STM32L4R7xx) || defined(STM32L4S7xx) || defined(STM32L4Q5xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC; + +#elif defined(STM32L4R9xx) || defined(STM32L4S9xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; + #endif /* STM32L431xx */ +#if defined(RCC_PLLSAI1_SUPPORT) + /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/ - PeriphClkInit->PLLSAI1.PLLSAI1Source = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos); - PeriphClkInit->PLLSAI1.PLLSAI1M = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; - PeriphClkInit->PLLSAI1.PLLSAI1N = (uint32_t)((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos); - PeriphClkInit->PLLSAI1.PLLSAI1P = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U; - PeriphClkInit->PLLSAI1.PLLSAI1Q = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos)+1U) * 2U; - PeriphClkInit->PLLSAI1.PLLSAI1R = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos)+1U) * 2U; + PeriphClkInit->PLLSAI1.PLLSAI1Source = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos; +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U; +#else + PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + PeriphClkInit->PLLSAI1.PLLSAI1N = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + PeriphClkInit->PLLSAI1.PLLSAI1P = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U; + PeriphClkInit->PLLSAI1.PLLSAI1Q = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) * 2U; + PeriphClkInit->PLLSAI1.PLLSAI1R = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) * 2U; + +#endif /* RCC_PLLSAI1_SUPPORT */ #if defined(RCC_PLLSAI2_SUPPORT) /* Get the PLLSAI2 Clock configuration -----------------------------------------------*/ PeriphClkInit->PLLSAI2.PLLSAI2Source = PeriphClkInit->PLLSAI1.PLLSAI1Source; +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + PeriphClkInit->PLLSAI2.PLLSAI2M = (READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U; +#else PeriphClkInit->PLLSAI2.PLLSAI2M = PeriphClkInit->PLLSAI1.PLLSAI1M; -PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos); - PeriphClkInit->PLLSAI2.PLLSAI2P = (uint32_t)(((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2P) >> RCC_PLLSAI2CFGR_PLLSAI2P_Pos) << 4U) + 7U; - PeriphClkInit->PLLSAI2.PLLSAI2R = (uint32_t)(((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos)+1U) * 2U; +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + PeriphClkInit->PLLSAI2.PLLSAI2N = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; + PeriphClkInit->PLLSAI2.PLLSAI2P = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) >> RCC_PLLSAI2CFGR_PLLSAI2P_Pos) << 4U) + 7U; +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + PeriphClkInit->PLLSAI2.PLLSAI2Q = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q) >> RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + 1U) * 2U; +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + PeriphClkInit->PLLSAI2.PLLSAI2R = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) * 2U; #endif /* RCC_PLLSAI2_SUPPORT */ @@ -829,8 +1006,10 @@ PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR /* Get the LPTIM2 clock source ---------------------------------------------*/ PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE(); +#if defined(SAI1) /* Get the SAI1 clock source -----------------------------------------------*/ PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE(); +#endif /* SAI1 */ #if defined(SAI2) /* Get the SAI2 clock source -----------------------------------------------*/ @@ -853,8 +1032,10 @@ PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR /* Get the RNG clock source ------------------------------------------------*/ PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE(); +#if !defined(STM32L412xx) && !defined(STM32L422xx) /* Get the ADC clock source ------------------------------------------------*/ PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE(); +#endif /* !STM32L412xx && !STM32L422xx */ #if defined(SWPMI1) /* Get the SWPMI1 clock source ---------------------------------------------*/ @@ -864,7 +1045,27 @@ PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR #if defined(DFSDM1_Filter0) /* Get the DFSDM1 clock source ---------------------------------------------*/ PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE(); + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Get the DFSDM1 audio clock source ---------------------------------------*/ + PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ #endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + /* Get the LTDC clock source -----------------------------------------------*/ + PeriphClkInit->LtdcClockSelection = __HAL_RCC_GET_LTDC_SOURCE(); +#endif /* LTDC */ + +#if defined(DSI) + /* Get the DSI clock source ------------------------------------------------*/ + PeriphClkInit->DsiClockSelection = __HAL_RCC_GET_DSI_SOURCE(); +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + /* Get the OctoSPIclock source --------------------------------------------*/ + PeriphClkInit->OspiClockSelection = __HAL_RCC_GET_OSPI_SOURCE(); +#endif /* OCTOSPI1 || OCTOSPI2 */ } /** @@ -892,17 +1093,23 @@ PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR @if STM32L4A6xx * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock - * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock + * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock (only for devices with SAI1) @if STM32L486xx * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) @endif @if STM32L4A6xx * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock @if STM32L443xx * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) @@ -918,23 +1125,37 @@ PeriphClkInit->PLLSAI2.PLLSAI2N = (uint32_t)((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock @if STM32L462xx * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) - @endif + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif @if STM32L486xx * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) * @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) @endif @if STM32L4A6xx * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) * @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5) - @endif * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC) + * @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI) + * @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI) + @endif * @retval Frequency in Hz */ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) { uint32_t frequency = 0U; - uint32_t srcclk = 0U; - uint32_t pllvco = 0U, plln = 0U, pllp = 0U; + uint32_t srcclk, pll_oscsource, pllvco, plln; /* no init needed */ +#if defined(SDMMC1) && defined(RCC_CCIPR2_SDMMCSEL) + uint32_t pllp; /* no init needed */ +#endif /* Check the parameters */ assert_param(IS_RCC_PERIPHCLOCK(PeriphClk)); @@ -944,34 +1165,52 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) /* Get the current RTC source */ srcclk = __HAL_RCC_GET_RTC_SOURCE(); - /* Check if LSE is ready and if RTC clock selection is LSE */ - if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + switch(srcclk) { - frequency = LSE_VALUE; - } - /* Check if LSI is ready and if RTC clock selection is LSI */ - else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) - { - frequency = LSI_VALUE; - } - /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/ - else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))) - { - frequency = HSE_VALUE / 32; - } - /* Clock not enabled for RTC*/ - else - { - frequency = 0U; + case RCC_RTCCLKSOURCE_LSE: + /* Check if LSE is ready */ + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + case RCC_RTCCLKSOURCE_LSI: + /* Check if LSI is ready */ + if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)) + { +#if defined(RCC_CSR_LSIPREDIV) + if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIPREDIV)) + { + frequency = LSI_VALUE/128U; + } + else +#endif /* RCC_CSR_LSIPREDIV */ + { + frequency = LSI_VALUE; + } + } + break; + case RCC_RTCCLKSOURCE_HSE_DIV32: + /* Check if HSE is ready */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) + { + frequency = HSE_VALUE / 32U; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; } } else { /* Other external peripheral clock source than RTC */ + pll_oscsource = __HAL_RCC_GET_PLL_OSCSOURCE(); /* Compute PLL clock input */ - if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) /* MSI ? */ + switch(pll_oscsource) { + case RCC_PLLSOURCE_MSI: /* MSI ? */ if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) { /*MSI frequency range in HZ*/ @@ -981,9 +1220,8 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) { pllvco = 0U; } - } - else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI) /* HSI ? */ - { + break; + case RCC_PLLSOURCE_HSI: /* HSI ? */ if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) { pllvco = HSI_VALUE; @@ -992,9 +1230,8 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) { pllvco = 0U; } - } - else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) /* HSE ? */ - { + break; + case RCC_PLLSOURCE_HSE: /* HSE ? */ if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) { pllvco = HSE_VALUE; @@ -1003,213 +1240,31 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) { pllvco = 0U; } - } - else /* No source */ - { + break; + default: + /* No source */ pllvco = 0U; + break; } - /* f(PLL Source) / PLLM */ - pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); - switch(PeriphClk) { -#if defined(SAI2) +#if defined(SAI1) case RCC_PERIPHCLK_SAI1: - case RCC_PERIPHCLK_SAI2: - - if(PeriphClk == RCC_PERIPHCLK_SAI1) - { - srcclk = __HAL_RCC_GET_SAI1_SOURCE(); - - if(srcclk == RCC_SAI1CLKSOURCE_PIN) - { - frequency = EXTERNAL_SAI1_CLOCK_VALUE; - } - /* Else, PLL clock output to check below */ - } - else /* RCC_PERIPHCLK_SAI2 */ - { - srcclk = __HAL_RCC_GET_SAI2_SOURCE(); - - if(srcclk == RCC_SAI2CLKSOURCE_PIN) - { - frequency = EXTERNAL_SAI2_CLOCK_VALUE; - } - /* Else, PLL clock output to check below */ - } - -#else - - case RCC_PERIPHCLK_SAI1: - - if(PeriphClk == RCC_PERIPHCLK_SAI1) - { - srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI1SEL); - - if(srcclk == RCC_SAI1CLKSOURCE_PIN) - { - frequency = EXTERNAL_SAI1_CLOCK_VALUE; - } - /* Else, PLL clock output to check below */ - } - -#endif /* SAI2 */ - - if(frequency == 0U) - { -#if defined(SAI2) - if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) - { - if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET) - { - /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ - plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; -#if defined(RCC_PLLP_DIV_2_31_SUPPORT) - pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; -#endif - if(pllp == 0U) - { - if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) - { - pllp = 17U; - } - else - { - pllp = 7U; - } - } - frequency = (pllvco * plln) / pllp; - } - } - else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */ - { - if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) - { - /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ - plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; -#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) - pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; -#endif - if(pllp == 0U) - { - if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) - { - pllp = 17U; - } - else - { - pllp = 7U; - } - } - frequency = (pllvco * plln) / pllp; - } - } -#else - if(srcclk == RCC_SAI1CLKSOURCE_PLL) - { - if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI2CLK) != RESET) - { - /* f(PLLSAI2CLK) = f(VCO input) * PLLN / PLLP */ - plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; -#if defined(RCC_PLLP_DIV_2_31_SUPPORT) - pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; -#endif - if(pllp == 0U) - { - if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) - { - pllp = 17U; - } - else - { - pllp = 7U; - } - } - - frequency = (pllvco * plln) / pllp; - } - else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) - { - /* HSI automatically selected as clock source if PLLs not enabled */ - frequency = HSI_VALUE; - } - else - { - /* No clock source */ - frequency = 0U; - } - } - else if(srcclk == RCC_SAI1CLKSOURCE_PLLSAI1) - { - if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) - { - /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ - plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; -#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) - pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; -#endif - if(pllp == 0U) - { - if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) - { - pllp = 17U; - } - else - { - pllp = 7U; - } - } - - frequency = (pllvco * plln) / pllp; - } - else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) - { - /* HSI automatically selected as clock source if PLLs not enabled */ - frequency = HSI_VALUE; - } - else - { - /* No clock source */ - frequency = 0U; - } - } -#endif /* SAI2 */ - -#if defined(RCC_PLLSAI2_SUPPORT) - - else if((srcclk == RCC_SAI1CLKSOURCE_PLLSAI2) || (srcclk == RCC_SAI2CLKSOURCE_PLLSAI2)) - { - if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_SAI2CLK) != RESET) - { - /* f(PLLSAI2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2P */ - plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; - if(pllp == 0U) - { - if(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) != RESET) - { - pllp = 17U; - } - else - { - pllp = 7U; - } - } - frequency = (pllvco * plln) / pllp; - } - } - -#endif /* RCC_PLLSAI2_SUPPORT */ - - else - { - /* No clock source */ - frequency = 0U; - } - } + frequency = RCCEx_GetSAIxPeriphCLKFreq(RCC_PERIPHCLK_SAI1, pllvco); break; +#endif + +#if defined(SAI2) + + case RCC_PERIPHCLK_SAI2: + frequency = RCCEx_GetSAIxPeriphCLKFreq(RCC_PERIPHCLK_SAI2, pllvco); + break; + +#endif + #if defined(USB_OTG_FS) || defined(USB) case RCC_PERIPHCLK_USB: @@ -1218,474 +1273,751 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) case RCC_PERIPHCLK_RNG: -#if defined(SDMMC1) +#if defined(SDMMC1) && !defined(RCC_CCIPR2_SDMMCSEL) case RCC_PERIPHCLK_SDMMC1: -#endif /* SDMMC1 */ +#endif /* SDMMC1 && !RCC_CCIPR2_SDMMCSEL */ + { + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); - srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); - - if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */ - { - if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + switch(srcclk) { - /*MSI frequency range in HZ*/ - frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; - } - else - { - frequency = 0U; - } - } - else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL ? */ - { - if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) - { - /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ - plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; - frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); - } - else - { - frequency = 0U; - } - } - else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */ - { - if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) - { - /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */ - plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; - frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U); - } - else - { - frequency = 0U; - } - } -#if defined(RCC_HSI48_SUPPORT) - else if((srcclk == 0U) && (HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY))) /* HSI48 ? */ - { - //PDG//frequency = HSI48_VALUE; - frequency = 0; - } - else /* No clock source */ - { - frequency = 0U; - } + case RCC_CCIPR_CLK48SEL: /* MSI ? */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + break; + case RCC_CCIPR_CLK48SEL_1: /* PLL ? */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY)) + { + if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { + /* f(PLL Source) * PLLN / PLLM */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLL48M1CLK) = f(VCO input) / PLLQ */ + frequency = (pllvco / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U)); + } + } + break; +#if defined(RCC_PLLSAI1_SUPPORT) + case RCC_CCIPR_CLK48SEL_0: /* PLLSAI1 ? */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY)) + { + if(HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + { + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */ + /* f(PLLSAI1 Source) * PLLSAI1N / PLLSAI1M */ + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); #else - else /* No clock source */ - { - frequency = 0U; - } + /* f(PLL Source) * PLLSAI1N / PLLM */ + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLL48M2CLK) = f(VCOSAI1 input) / PLLSAI1Q */ + frequency = (pllvco / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U)); + } + } + break; +#endif /* RCC_PLLSAI1_SUPPORT */ +#if defined(RCC_HSI48_SUPPORT) + case 0U: + if(HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY)) /* HSI48 ? */ + { + frequency = HSI48_VALUE; + } + break; #endif /* RCC_HSI48_SUPPORT */ + default: + /* No clock source, frequency default init at 0 */ + break; + } /* switch(srcclk) */ + break; + } + +#if defined(SDMMC1) && defined(RCC_CCIPR2_SDMMCSEL) + + case RCC_PERIPHCLK_SDMMC1: + + if(HAL_IS_BIT_SET(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL)) /* PLL "P" ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY)) + { + if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN)) + { + /* f(PLL Source) * PLLN / PLLM */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLLSAI3CLK) = f(VCO input) / PLLP */ + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco / pllp); + } + } + } + else /* 48MHz from PLL "Q" or MSI or PLLSAI1Q or HSI48 */ + { + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); + + switch(srcclk) + { + case RCC_CCIPR_CLK48SEL: /* MSI ? */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + break; + case RCC_CCIPR_CLK48SEL_1: /* PLL "Q" ? */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY)) + { + if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { + /* f(PLL Source) * PLLN / PLLM */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLL48M1CLK) = f(VCO input) / PLLQ */ + frequency = (pllvco / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U)); + } + } + break; + case RCC_CCIPR_CLK48SEL_0: /* PLLSAI1 ? */ + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY)) + { + if(HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + { + /* f(PLLSAI1 Source) * PLLSAI1N / PLLSAI1M */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); + /* f(PLL48M2CLK) = f(VCOSAI1 input) / PLLSAI1Q */ + frequency = (pllvco / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U)); + } + } + break; + case 0U: + if(HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY)) /* HSI48 ? */ + { + frequency = HSI48_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } /* switch(srcclk) */ + } break; +#endif /* SDMMC1 && RCC_CCIPR2_SDMMCSEL */ + case RCC_PERIPHCLK_USART1: - /* Get the current USART1 source */ - srcclk = __HAL_RCC_GET_USART1_SOURCE(); + { + /* Get the current USART1 source */ + srcclk = __HAL_RCC_GET_USART1_SOURCE(); - if(srcclk == RCC_USART1CLKSOURCE_PCLK2) - { - frequency = HAL_RCC_GetPCLK2Freq(); + switch(srcclk) + { + case RCC_USART1CLKSOURCE_PCLK2: + frequency = HAL_RCC_GetPCLK2Freq(); + break; + case RCC_USART1CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_USART1CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_USART1CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for USART1 */ - else - { - frequency = 0U; - } - break; case RCC_PERIPHCLK_USART2: - /* Get the current USART2 source */ - srcclk = __HAL_RCC_GET_USART2_SOURCE(); + { + /* Get the current USART2 source */ + srcclk = __HAL_RCC_GET_USART2_SOURCE(); - if(srcclk == RCC_USART2CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_USART2CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_USART2CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_USART2CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_USART2CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_USART2CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for USART2 */ - else - { - frequency = 0U; - } - break; #if defined(USART3) case RCC_PERIPHCLK_USART3: - /* Get the current USART3 source */ - srcclk = __HAL_RCC_GET_USART3_SOURCE(); + { + /* Get the current USART3 source */ + srcclk = __HAL_RCC_GET_USART3_SOURCE(); - if(srcclk == RCC_USART3CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_USART3CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_USART3CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_USART3CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_USART3CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_USART3CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for USART3 */ - else - { - frequency = 0U; - } - break; #endif /* USART3 */ #if defined(UART4) case RCC_PERIPHCLK_UART4: - /* Get the current UART4 source */ - srcclk = __HAL_RCC_GET_UART4_SOURCE(); + { + /* Get the current UART4 source */ + srcclk = __HAL_RCC_GET_UART4_SOURCE(); - if(srcclk == RCC_UART4CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_UART4CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_UART4CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_UART4CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_UART4CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_UART4CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_UART4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if((srcclk == RCC_UART4CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for UART4 */ - else - { - frequency = 0U; - } - break; #endif /* UART4 */ #if defined(UART5) case RCC_PERIPHCLK_UART5: - /* Get the current UART5 source */ - srcclk = __HAL_RCC_GET_UART5_SOURCE(); + { + /* Get the current UART5 source */ + srcclk = __HAL_RCC_GET_UART5_SOURCE(); - if(srcclk == RCC_UART5CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_UART5CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_UART5CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_UART5CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_UART5CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_UART5CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_UART5CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if((srcclk == RCC_UART5CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for UART5 */ - else - { - frequency = 0U; - } - break; #endif /* UART5 */ case RCC_PERIPHCLK_LPUART1: - /* Get the current LPUART1 source */ - srcclk = __HAL_RCC_GET_LPUART1_SOURCE(); + { + /* Get the current LPUART1 source */ + srcclk = __HAL_RCC_GET_LPUART1_SOURCE(); - if(srcclk == RCC_LPUART1CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_LPUART1CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_LPUART1CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_LPUART1CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_LPUART1CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_LPUART1CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_LPUART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if((srcclk == RCC_LPUART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for LPUART1 */ - else - { - frequency = 0U; - } - break; case RCC_PERIPHCLK_ADC: - - srcclk = __HAL_RCC_GET_ADC_SOURCE(); - - if(srcclk == RCC_ADCCLKSOURCE_SYSCLK) { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI1) - { - if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != RESET) + srcclk = __HAL_RCC_GET_ADC_SOURCE(); + + switch(srcclk) { - /* f(PLLADC1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1R */ - plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; - frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U); - } - } + case RCC_ADCCLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; +#if defined(RCC_PLLSAI1_SUPPORT) + case RCC_ADCCLKSOURCE_PLLSAI1: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && (__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != 0U)) + { + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */ + /* f(PLLSAI1 Source) * PLLSAI1N / PLLSAI1M */ + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#else + /* f(PLL Source) * PLLSAI1N / PLLM */ + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLADC1CLK) = f(VCOSAI1 input) / PLLSAI1R */ + frequency = (pllvco / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U)); + } + break; +#endif /* RCC_PLLSAI1_SUPPORT */ #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) - else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI2) - { - if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != RESET) - { - /* f(PLLADC2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2R */ - plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; - frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U); - } - } + case RCC_ADCCLKSOURCE_PLLSAI2: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI2RDY) && (__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != 0U)) + { + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* PLLSAI2M exists: apply PLLSAI2M divider for PLLSAI2 output computation */ + /* f(PLLSAI2 Source) * PLLSAI2N / PLLSAI2M */ + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)); +#else + /* f(PLL Source) * PLLSAI2N / PLLM */ + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLADC2CLK) = f(VCOSAI2 input) / PLLSAI2R */ + frequency = (pllvco / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U)); + } + break; #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ - /* Clock not enabled for ADC */ - else - { - frequency = 0U; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - break; #if defined(DFSDM1_Filter0) case RCC_PERIPHCLK_DFSDM1: - /* Get the current DFSDM1 source */ - srcclk = __HAL_RCC_GET_DFSDM1_SOURCE(); + { + /* Get the current DFSDM1 source */ + srcclk = __HAL_RCC_GET_DFSDM1_SOURCE(); - if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2) - { - frequency = HAL_RCC_GetPCLK2Freq(); + if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2) + { + frequency = HAL_RCC_GetPCLK2Freq(); + } + else + { + frequency = HAL_RCC_GetSysClockFreq(); + } + + break; } - else + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + + case RCC_PERIPHCLK_DFSDM1AUDIO: { - frequency = HAL_RCC_GetSysClockFreq(); + /* Get the current DFSDM1 audio source */ + srcclk = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); + + switch(srcclk) + { + case RCC_DFSDM1AUDIOCLKSOURCE_SAI1: + frequency = RCCEx_GetSAIxPeriphCLKFreq(RCC_PERIPHCLK_SAI1, pllvco); + break; + case RCC_DFSDM1AUDIOCLKSOURCE_MSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + break; + case RCC_DFSDM1AUDIOCLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - break; + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ #endif /* DFSDM1_Filter0 */ case RCC_PERIPHCLK_I2C1: - /* Get the current I2C1 source */ - srcclk = __HAL_RCC_GET_I2C1_SOURCE(); + { + /* Get the current I2C1 source */ + srcclk = __HAL_RCC_GET_I2C1_SOURCE(); - if(srcclk == RCC_I2C1CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_I2C1CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_I2C1CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_I2C1CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_I2C1CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - /* Clock not enabled for I2C1 */ - else - { - frequency = 0U; - } - break; #if defined(I2C2) case RCC_PERIPHCLK_I2C2: - /* Get the current I2C2 source */ - srcclk = __HAL_RCC_GET_I2C2_SOURCE(); + { + /* Get the current I2C2 source */ + srcclk = __HAL_RCC_GET_I2C2_SOURCE(); - if(srcclk == RCC_I2C2CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_I2C2CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_I2C2CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_I2C2CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_I2C2CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_I2C2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - /* Clock not enabled for I2C2 */ - else - { - frequency = 0U; - } - break; #endif /* I2C2 */ case RCC_PERIPHCLK_I2C3: - /* Get the current I2C3 source */ - srcclk = __HAL_RCC_GET_I2C3_SOURCE(); + { + /* Get the current I2C3 source */ + srcclk = __HAL_RCC_GET_I2C3_SOURCE(); - if(srcclk == RCC_I2C3CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_I2C3CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_I2C3CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_I2C3CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_I2C3CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_I2C3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - /* Clock not enabled for I2C3 */ - else - { - frequency = 0U; - } - break; #if defined(I2C4) case RCC_PERIPHCLK_I2C4: - /* Get the current I2C4 source */ - srcclk = __HAL_RCC_GET_I2C4_SOURCE(); + { + /* Get the current I2C4 source */ + srcclk = __HAL_RCC_GET_I2C4_SOURCE(); - if(srcclk == RCC_I2C4CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_I2C4CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_I2C4CLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_I2C4CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if(srcclk == RCC_I2C4CLKSOURCE_SYSCLK) - { - frequency = HAL_RCC_GetSysClockFreq(); - } - else if((srcclk == RCC_I2C4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - /* Clock not enabled for I2C4 */ - else - { - frequency = 0U; - } - break; #endif /* I2C4 */ case RCC_PERIPHCLK_LPTIM1: - /* Get the current LPTIM1 source */ - srcclk = __HAL_RCC_GET_LPTIM1_SOURCE(); + { + /* Get the current LPTIM1 source */ + srcclk = __HAL_RCC_GET_LPTIM1_SOURCE(); - if(srcclk == RCC_LPTIM1CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_LPTIM1CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_LPTIM1CLKSOURCE_LSI: + if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)) + { +#if defined(RCC_CSR_LSIPREDIV) + if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIPREDIV)) + { + frequency = LSI_VALUE/128U; + } + else +#endif /* RCC_CSR_LSIPREDIV */ + { + frequency = LSI_VALUE; + } + } + break; + case RCC_LPTIM1CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_LPTIM1CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) - { - frequency = LSI_VALUE; - } - else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if ((srcclk == RCC_LPTIM1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for LPTIM1 */ - else - { - frequency = 0U; - } - break; case RCC_PERIPHCLK_LPTIM2: - /* Get the current LPTIM2 source */ - srcclk = __HAL_RCC_GET_LPTIM2_SOURCE(); + { + /* Get the current LPTIM2 source */ + srcclk = __HAL_RCC_GET_LPTIM2_SOURCE(); - if(srcclk == RCC_LPTIM2CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_LPTIM2CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_LPTIM2CLKSOURCE_LSI: + if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)) + { +#if defined(RCC_CSR_LSIPREDIV) + if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIPREDIV)) + { + frequency = LSI_VALUE/128U; + } + else +#endif /* RCC_CSR_LSIPREDIV */ + { + frequency = LSI_VALUE; + } + } + break; + case RCC_LPTIM2CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + case RCC_LPTIM2CLKSOURCE_LSE: + if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)) + { + frequency = LSE_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) - { - frequency = LSI_VALUE; - } - else if((srcclk == RCC_LPTIM2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - else if ((srcclk == RCC_LPTIM2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) - { - frequency = LSE_VALUE; - } - /* Clock not enabled for LPTIM2 */ - else - { - frequency = 0U; - } - break; #if defined(SWPMI1) case RCC_PERIPHCLK_SWPMI1: - /* Get the current SWPMI1 source */ - srcclk = __HAL_RCC_GET_SWPMI1_SOURCE(); + { + /* Get the current SWPMI1 source */ + srcclk = __HAL_RCC_GET_SWPMI1_SOURCE(); - if(srcclk == RCC_SWPMI1CLKSOURCE_PCLK1) - { - frequency = HAL_RCC_GetPCLK1Freq(); + switch(srcclk) + { + case RCC_SWPMI1CLKSOURCE_PCLK1: + frequency = HAL_RCC_GetPCLK1Freq(); + break; + case RCC_SWPMI1CLKSOURCE_HSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; } - else if((srcclk == RCC_SWPMI1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) - { - frequency = HSI_VALUE; - } - /* Clock not enabled for SWPMI1 */ - else - { - frequency = 0U; - } - break; #endif /* SWPMI1 */ +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + case RCC_PERIPHCLK_OSPI: + { + /* Get the current OctoSPI clock source */ + srcclk = __HAL_RCC_GET_OSPI_SOURCE(); + + switch(srcclk) + { + case RCC_OSPICLKSOURCE_SYSCLK: + frequency = HAL_RCC_GetSysClockFreq(); + break; + case RCC_OSPICLKSOURCE_MSI: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + break; + case RCC_OSPICLKSOURCE_PLL: + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY)) + { + if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { + /* f(PLL Source) * PLLN / PLLM */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLL48M1CLK) = f(VCO input) / PLLQ */ + frequency = (pllvco / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U)); + } + } + break; + default: + /* No clock source, frequency default init at 0 */ + break; + } + + break; + } + +#endif /* OCTOSPI1 || OCTOSPI2 */ + default: break; } @@ -1713,6 +2045,8 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) * @{ */ +#if defined(RCC_PLLSAI1_SUPPORT) + /** * @brief Enable PLLSAI1. * @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that @@ -1721,7 +2055,7 @@ uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) */ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) { - uint32_t tickstart = 0U; + uint32_t tickstart; HAL_StatusTypeDef status = HAL_OK; /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */ @@ -1740,7 +2074,7 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) tickstart = HAL_GetTick(); /* Wait till PLLSAI1 is ready to be updated */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != 0U) { if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) { @@ -1751,9 +2085,15 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) if(status == HAL_OK) { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Multiplication factor N */ + /* Configure the PLLSAI1 Division factors M, P, Q and R */ + __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1M, PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); +#else /* Configure the PLLSAI1 Multiplication factor N */ /* Configure the PLLSAI1 Division factors P, Q and R */ __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ /* Configure the PLLSAI1 Clock output(s) */ __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut); @@ -1764,7 +2104,7 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) tickstart = HAL_GetTick(); /* Wait till PLLSAI1 is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == 0U) { if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) { @@ -1783,7 +2123,7 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) */ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) { - uint32_t tickstart = 0U; + uint32_t tickstart; HAL_StatusTypeDef status = HAL_OK; /* Disable the PLLSAI1 */ @@ -1793,7 +2133,7 @@ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) tickstart = HAL_GetTick(); /* Wait till PLLSAI1 is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != 0U) { if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) { @@ -1806,19 +2146,23 @@ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) __HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1CFGR_PLLSAI1PEN|RCC_PLLSAI1CFGR_PLLSAI1QEN|RCC_PLLSAI1CFGR_PLLSAI1REN); /* Reset PLL source to save power if no PLLs on */ - if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) #if defined(RCC_PLLSAI2_SUPPORT) - && - (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) -#endif /* RCC_PLLSAI2_SUPPORT */ - ) + if(READ_BIT(RCC->CR, (RCC_CR_PLLRDY | RCC_CR_PLLSAI2RDY)) == 0U) { MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); } +#else + if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } +#endif /* RCC_PLLSAI2_SUPPORT */ return status; } +#endif /* RCC_PLLSAI1_SUPPORT */ + #if defined(RCC_PLLSAI2_SUPPORT) /** @@ -1829,7 +2173,7 @@ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) */ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) { - uint32_t tickstart = 0U; + uint32_t tickstart; HAL_StatusTypeDef status = HAL_OK; /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */ @@ -1837,6 +2181,9 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) assert_param(IS_RCC_PLLSAI2M_VALUE(PLLSAI2Init->PLLSAI2M)); assert_param(IS_RCC_PLLSAI2N_VALUE(PLLSAI2Init->PLLSAI2N)); assert_param(IS_RCC_PLLSAI2P_VALUE(PLLSAI2Init->PLLSAI2P)); +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + assert_param(IS_RCC_PLLSAI2Q_VALUE(PLLSAI2Init->PLLSAI2Q)); +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ assert_param(IS_RCC_PLLSAI2R_VALUE(PLLSAI2Init->PLLSAI2R)); assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PLLSAI2Init->PLLSAI2ClockOut)); @@ -1847,7 +2194,7 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) tickstart = HAL_GetTick(); /* Wait till PLLSAI2 is ready to be updated */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U) { if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) { @@ -1858,9 +2205,23 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) if(status == HAL_OK) { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors M, P, Q and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R); +#elif defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors M, P and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R); +#elif defined(RCC_PLLSAI2Q_DIV_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors P, Q and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R); +#else /* Configure the PLLSAI2 Multiplication factor N */ /* Configure the PLLSAI2 Division factors P and R */ __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ /* Configure the PLLSAI2 Clock output(s) */ __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PLLSAI2Init->PLLSAI2ClockOut); @@ -1871,7 +2232,7 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) tickstart = HAL_GetTick(); /* Wait till PLLSAI2 is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == 0U) { if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) { @@ -1890,7 +2251,7 @@ HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) */ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void) { - uint32_t tickstart = 0U; + uint32_t tickstart; HAL_StatusTypeDef status = HAL_OK; /* Disable the PLLSAI2 */ @@ -1900,7 +2261,7 @@ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void) tickstart = HAL_GetTick(); /* Wait till PLLSAI2 is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U) { if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) { @@ -1910,13 +2271,14 @@ HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void) } /* Disable the PLLSAI2 Clock outputs */ +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2QEN|RCC_PLLSAI2CFGR_PLLSAI2REN); +#else __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2REN); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ /* Reset PLL source to save power if no PLLs on */ - if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) - && - (READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) - ) + if(READ_BIT(RCC->CR, (RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY)) == 0U) { MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); } @@ -1970,7 +2332,7 @@ void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange) */ void HAL_RCCEx_EnableLSECSS(void) { - SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON); } /** @@ -2144,6 +2506,23 @@ void HAL_RCCEx_DisableMSIPLLMode(void) CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; } +#if defined (OCTOSPI1) && defined (OCTOSPI2) +/** + * @brief Configure OCTOSPI instances DQS delays. + * @param Delay1 OCTOSPI1 DQS delay + * @param Delay2 OCTOSPI2 DQS delay + * @note Delay parameters stand for unitary delays from 0 to 15. Actual delay is Delay1 or Delay2 + 1. + * @retval None + */ +void HAL_RCCEx_OCTOSPIDelayConfig(uint32_t Delay1, uint32_t Delay2) +{ + assert_param(IS_RCC_OCTOSPIDELAY(Delay1)); + assert_param(IS_RCC_OCTOSPIDELAY(Delay2)); + + MODIFY_REG(RCC->DLYCFGR, RCC_DLYCFGR_OCTOSPI1_DLY|RCC_DLYCFGR_OCTOSPI2_DLY, (Delay1 | (Delay2 << RCC_DLYCFGR_OCTOSPI2_DLY_Pos))) ; +} +#endif /* OCTOSPI1 && OCTOSPI2 */ + /** * @} */ @@ -2221,7 +2600,7 @@ void HAL_RCCEx_DisableMSIPLLMode(void) */ void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit) { - uint32_t value = 0; + uint32_t value; /* no init needed */ /* Check the parameters */ assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler)); @@ -2248,7 +2627,8 @@ void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit) WRITE_REG(CRS->CFGR, value); /* Adjust HSI48 oscillator smooth trimming */ - /* Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value */ + /* Set the TRIM[6:0] bits for STM32L412xx/L422xx or TRIM[5:0] bits otherwise + according to RCC_CRS_HSI48CalibrationValue value */ MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos)); /* START AUTOMATIC SYNCHRONIZATION*/ @@ -2274,19 +2654,19 @@ void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void) void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo) { /* Check the parameter */ - assert_param(pSynchroInfo != NULL); + assert_param(pSynchroInfo != (void *)NULL); /* Get the reload value */ - pSynchroInfo->ReloadValue = (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD)); + pSynchroInfo->ReloadValue = (READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD)); /* Get HSI48 oscillator smooth trimming */ - pSynchroInfo->HSI48CalibrationValue = (uint32_t)(READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos); + pSynchroInfo->HSI48CalibrationValue = (READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos); /* Get Frequency error capture */ - pSynchroInfo->FreqErrorCapture = (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos); + pSynchroInfo->FreqErrorCapture = (READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos); /* Get Frequency error direction */ - pSynchroInfo->FreqErrorDirection = (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FEDIR)); + pSynchroInfo->FreqErrorDirection = (READ_BIT(CRS->ISR, CRS_ISR_FEDIR)); } /** @@ -2307,7 +2687,7 @@ void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout) { uint32_t crsstatus = RCC_CRS_NONE; - uint32_t tickstart = 0U; + uint32_t tickstart; /* Get timeout */ tickstart = HAL_GetTick(); @@ -2317,7 +2697,7 @@ uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout) { if(Timeout != HAL_MAX_DELAY) { - if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) { crsstatus = RCC_CRS_TIMEOUT; } @@ -2395,7 +2775,7 @@ void HAL_RCCEx_CRS_IRQHandler(void) uint32_t itsources = READ_REG(CRS->CR); /* Check CRS SYNCOK flag */ - if(((itflags & RCC_CRS_FLAG_SYNCOK) != RESET) && ((itsources & RCC_CRS_IT_SYNCOK) != RESET)) + if(((itflags & RCC_CRS_FLAG_SYNCOK) != 0U) && ((itsources & RCC_CRS_IT_SYNCOK) != 0U)) { /* Clear CRS SYNC event OK flag */ WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC); @@ -2404,7 +2784,7 @@ void HAL_RCCEx_CRS_IRQHandler(void) HAL_RCCEx_CRS_SyncOkCallback(); } /* Check CRS SYNCWARN flag */ - else if(((itflags & RCC_CRS_FLAG_SYNCWARN) != RESET) && ((itsources & RCC_CRS_IT_SYNCWARN) != RESET)) + else if(((itflags & RCC_CRS_FLAG_SYNCWARN) != 0U) && ((itsources & RCC_CRS_IT_SYNCWARN) != 0U)) { /* Clear CRS SYNCWARN flag */ WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC); @@ -2413,7 +2793,7 @@ void HAL_RCCEx_CRS_IRQHandler(void) HAL_RCCEx_CRS_SyncWarnCallback(); } /* Check CRS Expected SYNC flag */ - else if(((itflags & RCC_CRS_FLAG_ESYNC) != RESET) && ((itsources & RCC_CRS_IT_ESYNC) != RESET)) + else if(((itflags & RCC_CRS_FLAG_ESYNC) != 0U) && ((itsources & RCC_CRS_IT_ESYNC) != 0U)) { /* frequency error counter reached a zero value */ WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC); @@ -2424,17 +2804,17 @@ void HAL_RCCEx_CRS_IRQHandler(void) /* Check CRS Error flags */ else { - if(((itflags & RCC_CRS_FLAG_ERR) != RESET) && ((itsources & RCC_CRS_IT_ERR) != RESET)) + if(((itflags & RCC_CRS_FLAG_ERR) != 0U) && ((itsources & RCC_CRS_IT_ERR) != 0U)) { - if((itflags & RCC_CRS_FLAG_SYNCERR) != RESET) + if((itflags & RCC_CRS_FLAG_SYNCERR) != 0U) { crserror |= RCC_CRS_SYNCERR; } - if((itflags & RCC_CRS_FLAG_SYNCMISS) != RESET) + if((itflags & RCC_CRS_FLAG_SYNCMISS) != 0U) { crserror |= RCC_CRS_SYNCMISS; } - if((itflags & RCC_CRS_FLAG_TRIMOVF) != RESET) + if((itflags & RCC_CRS_FLAG_TRIMOVF) != 0U) { crserror |= RCC_CRS_TRIMOVF; } @@ -2514,6 +2894,8 @@ __weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error) * @{ */ +#if defined(RCC_PLLSAI1_SUPPORT) + /** * @brief Configure the parameters N & P & optionally M of PLLSAI1 and enable PLLSAI1 output clock(s). * @param PllSai1 pointer to an RCC_PLLSAI1InitTypeDef structure that @@ -2526,12 +2908,7 @@ __weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error) */ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider) { -#ifndef HACK_N_SLASH - asm("BKPT #0") - return 0; -#else - - uint32_t tickstart = 0U; + uint32_t tickstart; HAL_StatusTypeDef status = HAL_OK; /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */ @@ -2548,8 +2925,10 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source) || (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE) +#if !defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai1->PLLSAI1M) +#endif ) { status = HAL_ERROR; @@ -2573,9 +2952,12 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u } break; case RCC_PLLSOURCE_HSE: - if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY)) { - status = HAL_ERROR; + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + { + status = HAL_ERROR; + } } break; default: @@ -2585,8 +2967,13 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u if(status == HAL_OK) { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Set PLLSAI1 clock source */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai1->PLLSAI1Source); +#else /* Set PLLSAI1 clock source and divider M */ - MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos); + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos); +#endif } } @@ -2599,7 +2986,7 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u tickstart = HAL_GetTick(); /* Wait till PLLSAI1 is ready to be updated */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != 0U) { if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) { @@ -2613,6 +3000,24 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u if(Divider == DIVIDER_P_UPDATE) { assert_param(IS_RCC_PLLSAI1P_VALUE(PllSai1->PLLSAI1P)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + + /* Configure the PLLSAI1 Division factor M, P and Multiplication factor N*/ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#else /* Configure the PLLSAI1 Division factor P and Multiplication factor N*/ #if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) MODIFY_REG(RCC->PLLSAI1CFGR, @@ -2625,24 +3030,44 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos)); #endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ } else if(Divider == DIVIDER_Q_UPDATE) { assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Division factor M, Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else /* Configure the PLLSAI1 Division factor Q and Multiplication factor N*/ MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q, (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | (((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos)); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ } else { assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Division factor M, R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else /* Configure the PLLSAI1 Division factor R and Multiplication factor N*/ MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R, (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos)); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ } /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ @@ -2652,7 +3077,7 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u tickstart = HAL_GetTick(); /* Wait till PLLSAI1 is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == 0U) { if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) { @@ -2670,9 +3095,10 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u } return status; -#endif } +#endif /* RCC_PLLSAI1_SUPPORT */ + #if defined(RCC_PLLSAI2_SUPPORT) /** @@ -2687,7 +3113,7 @@ static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, u */ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider) { - uint32_t tickstart = 0U; + uint32_t tickstart; HAL_StatusTypeDef status = HAL_OK; /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */ @@ -2704,8 +3130,10 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai2->PLLSAI2Source) || (PllSai2->PLLSAI2Source == RCC_PLLSOURCE_NONE) +#if !defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) || (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai2->PLLSAI2M) +#endif ) { status = HAL_ERROR; @@ -2729,9 +3157,12 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u } break; case RCC_PLLSOURCE_HSE: - if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY)) { - status = HAL_ERROR; + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + { + status = HAL_ERROR; + } } break; default: @@ -2741,8 +3172,13 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u if(status == HAL_OK) { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Set PLLSAI2 clock source */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai2->PLLSAI2Source); +#else /* Set PLLSAI2 clock source and divider M */ MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai2->PLLSAI2Source | (PllSai2->PLLSAI2M - 1U) << RCC_PLLCFGR_PLLM_Pos); +#endif } } @@ -2755,7 +3191,7 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u tickstart = HAL_GetTick(); /* Wait till PLLSAI2 is ready to be updated */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U) { if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) { @@ -2769,20 +3205,76 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u if(Divider == DIVIDER_P_UPDATE) { assert_param(IS_RCC_PLLSAI2P_VALUE(PllSai2->PLLSAI2P)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + + /* Configure the PLLSAI2 Division factor M, P and Multiplication factor N*/ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + ((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#else /* Configure the PLLSAI2 Division factor P and Multiplication factor N*/ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)); +#else MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P, (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | ((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos)); +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ } +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + else if(Divider == DIVIDER_Q_UPDATE) + { + assert_param(IS_RCC_PLLSAI2Q_VALUE(PllSai2->PLLSAI2Q)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Division factor M, Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + /* Configure the PLLSAI2 Division factor Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos)); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ else { assert_param(IS_RCC_PLLSAI2R_VALUE(PllSai2->PLLSAI2R)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Division factor M, R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else /* Configure the PLLSAI2 Division factor R and Multiplication factor N*/ MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R, (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | (((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos)); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ } /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/ @@ -2792,7 +3284,7 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u tickstart = HAL_GetTick(); /* Wait till PLLSAI2 is ready */ - while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == 0U) { if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) { @@ -2814,6 +3306,238 @@ static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, u #endif /* RCC_PLLSAI2_SUPPORT */ +#if defined(SAI1) + +static uint32_t RCCEx_GetSAIxPeriphCLKFreq(uint32_t PeriphClk, uint32_t InputFrequency) +{ + uint32_t frequency = 0U; + uint32_t srcclk = 0U; + uint32_t pllvco, plln; /* no init needed */ +#if defined(RCC_PLLP_SUPPORT) + uint32_t pllp = 0U; +#endif /* RCC_PLLP_SUPPORT */ + + /* Handle SAIs */ + if(PeriphClk == RCC_PERIPHCLK_SAI1) + { + srcclk = __HAL_RCC_GET_SAI1_SOURCE(); + if(srcclk == RCC_SAI1CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI1_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } +#if defined(SAI2) + else + { + if(PeriphClk == RCC_PERIPHCLK_SAI2) + { + srcclk = __HAL_RCC_GET_SAI2_SOURCE(); + if(srcclk == RCC_SAI2CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI2_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + } +#endif /* SAI2 */ + + if(frequency == 0U) + { + pllvco = InputFrequency; + +#if defined(SAI2) + if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && (__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != 0U)) + { + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } + else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && (__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != 0U)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */ + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#else + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != 0U) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + else if((srcclk == RCC_SAI1CLKSOURCE_HSI) || (srcclk == RCC_SAI2CLKSOURCE_HSI)) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + } +#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#else + if(srcclk == RCC_SAI1CLKSOURCE_PLL) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && (__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI2CLK) != 0U)) + { + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLLSAI2CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + /* HSI automatically selected as clock source if PLLs not enabled */ + frequency = HSI_VALUE; + } + else + { + /* No clock source, frequency default init at 0 */ + } + } + else if(srcclk == RCC_SAI1CLKSOURCE_PLLSAI1) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && (__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != 0U)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */ + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#else + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != 0U) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + /* HSI automatically selected as clock source if PLLs not enabled */ + frequency = HSI_VALUE; + } + else + { + /* No clock source, frequency default init at 0 */ + } + } +#endif /* SAI2 */ + +#if defined(RCC_PLLSAI2_SUPPORT) + + else if((srcclk == RCC_SAI1CLKSOURCE_PLLSAI2) || (srcclk == RCC_SAI2CLKSOURCE_PLLSAI2)) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI2RDY) && (__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_SAI2CLK) != 0U)) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* PLLSAI2M exists: apply PLLSAI2M divider for PLLSAI2 output computation */ + /* f(PLLSAI2 Source) / PLLSAI2M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)); +#else + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLSAI2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2P */ + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PDIV) >> RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) != 0U) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } + +#endif /* RCC_PLLSAI2_SUPPORT */ + + else + { + /* No clock source, frequency default init at 0 */ + } + } + + + return frequency; +} + +#endif /* SAI1 */ + /** * @} */ diff --git a/stm32/mk4-bootloader/stm32l4xx_hal_usart.c b/stm32/mk4-bootloader/stm32l4xx_hal_usart.c index 1618d89a..1299d50d 100644 --- a/stm32/mk4-bootloader/stm32l4xx_hal_usart.c +++ b/stm32/mk4-bootloader/stm32l4xx_hal_usart.c @@ -2,8 +2,6 @@ ****************************************************************************** * @file stm32l4xx_hal_usart.c * @author MCD Application Team - * @version V1.7.2 - * @date 16-June-2017 * @brief USART HAL module driver. * This file provides firmware functions to manage the following * functionalities of the Universal Synchronous/Asynchronous Receiver Transmitter @@ -41,10 +39,11 @@ (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. (+++) Configure the DMA Tx/Rx channel. (+++) Associate the initialized DMA handle to the USART DMA Tx/Rx handle. - (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel. + (+++) Configure the priority and enable the NVIC for the transfer + complete interrupt on the DMA Tx/Rx channel. - (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware - flow control and Mode (Receiver/Transmitter) in the husart handle Init structure. + (#) Program the Baud Rate, Word Length, Stop Bit, Parity, and Mode + (Receiver/Transmitter) in the husart handle Init structure. (#) Initialize the USART registers by calling the HAL_USART_Init() API: (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc) @@ -55,33 +54,84 @@ HAL_UARTEx_StopModeWakeUpSourceConfig(), HAL_UARTEx_EnableStopMode() and HAL_UARTEx_DisableStopMode() in casting the USART handle to UART type UART_HandleTypeDef. + ##### Callback registration ##### + ================================== + + [..] + The compilation define USE_HAL_USART_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use Function @ref HAL_USART_RegisterCallback() to register a user callback. + Function @ref HAL_USART_RegisterCallback() allows to register following callbacks: + (+) TxHalfCpltCallback : Tx Half Complete Callback. + (+) TxCpltCallback : Tx Complete Callback. + (+) RxHalfCpltCallback : Rx Half Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) TxRxCpltCallback : Tx Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) RxFifoFullCallback : Rx Fifo Full Callback. + (+) TxFifoEmptyCallback : Tx Fifo Empty Callback. + (+) MspInitCallback : USART MspInit. + (+) MspDeInitCallback : USART MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function @ref HAL_USART_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + @ref HAL_USART_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxHalfCpltCallback : Tx Half Complete Callback. + (+) TxCpltCallback : Tx Complete Callback. + (+) RxHalfCpltCallback : Rx Half Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) TxRxCpltCallback : Tx Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) RxFifoFullCallback : Rx Fifo Full Callback. + (+) TxFifoEmptyCallback : Tx Fifo Empty Callback. + (+) MspInitCallback : USART MspInit. + (+) MspDeInitCallback : USART MspDeInit. + + [..] + By default, after the @ref HAL_USART_Init() and when the state is HAL_USART_STATE_RESET + all callbacks are set to the corresponding weak (surcharged) functions: + examples @ref HAL_USART_TxCpltCallback(), @ref HAL_USART_RxHalfCpltCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the @ref HAL_USART_Init() + and @ref HAL_USART_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the @ref HAL_USART_Init() and @ref HAL_USART_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_USART_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_USART_STATE_READY or HAL_USART_STATE_RESET state, thus registered (user) + MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using @ref HAL_USART_RegisterCallback() before calling @ref HAL_USART_DeInit() + or @ref HAL_USART_Init() function. + + [..] + When The compilation define USE_HAL_USART_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2017 STMicroelectronics

+ *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

* - * 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. + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ @@ -106,11 +156,26 @@ * @{ */ #define USART_DUMMY_DATA ((uint16_t) 0xFFFF) /*!< USART transmitted dummy data */ -#define USART_TEACK_REACK_TIMEOUT ((uint32_t) 1000) /*!< USART TX or RX enable acknowledge time-out value */ +#define USART_TEACK_REACK_TIMEOUT 1000U /*!< USART TX or RX enable acknowledge time-out value */ +#if defined(USART_CR1_FIFOEN) +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8 | \ + USART_CR1_FIFOEN )) /*!< USART CR1 fields of parameters set by USART_SetConfig API */ + +#define USART_CR2_FIELDS ((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ + USART_CR2_LBCL | USART_CR2_STOP | USART_CR2_SLVEN | \ + USART_CR2_DIS_NSS)) /*!< USART CR2 fields of parameters set by USART_SetConfig API */ + +#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< USART or USART CR3 fields of parameters set by USART_SetConfig API */ +#else #define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) /*!< USART CR1 fields of parameters set by USART_SetConfig API */ #define USART_CR2_FIELDS ((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | \ USART_CR2_CLKEN | USART_CR2_LBCL | USART_CR2_STOP)) /*!< USART CR2 fields of parameters set by USART_SetConfig API */ +#endif /* USART_CR1_FIFOEN */ + +#define USART_BRR_MIN 0x10U /* USART BRR minimum authorized value */ +#define USART_BRR_MAX 0xFFFFU /* USART BRR maximum authorized value */ /** * @} */ @@ -122,6 +187,9 @@ * @{ */ #if 0 +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ static void USART_EndTransfer(USART_HandleTypeDef *husart); static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma); static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); @@ -132,15 +200,25 @@ static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma); static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); #endif -static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout); +static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout); static HAL_StatusTypeDef USART_SetConfig(USART_HandleTypeDef *husart); static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart); -#if 0 -static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart); -static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart); -static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart); -static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart); -#endif +static void USART_TxISR_8BIT(USART_HandleTypeDef *husart); +static void USART_TxISR_16BIT(USART_HandleTypeDef *husart); +#if defined(USART_CR1_FIFOEN) +static void USART_TxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart); +static void USART_TxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart); +#endif /* USART_CR1_FIFOEN */ +static void USART_EndTransmit_IT(USART_HandleTypeDef *husart); +static void USART_RxISR_8BIT(USART_HandleTypeDef *husart); +static void USART_RxISR_16BIT(USART_HandleTypeDef *husart); +#if defined(USART_CR1_FIFOEN) +static void USART_RxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart); +static void USART_RxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart); +#endif /* USART_CR1_FIFOEN */ + + /** * @} */ @@ -152,7 +230,7 @@ static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart); */ /** @defgroup USART_Exported_Functions_Group1 Initialization and de-initialization functions - * @brief Initialization and Configuration functions + * @brief Initialization and Configuration functions * @verbatim =============================================================================== @@ -211,7 +289,7 @@ static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart); HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart) { /* Check the USART handle allocation */ - if(husart == NULL) + if (husart == NULL) { return HAL_ERROR; } @@ -219,13 +297,25 @@ HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart) /* Check the parameters */ assert_param(IS_USART_INSTANCE(husart->Instance)); - if(husart->State == HAL_USART_STATE_RESET) + if (husart->State == HAL_USART_STATE_RESET) { /* Allocate lock resource and initialize it */ husart->Lock = HAL_UNLOCKED; +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + USART_InitCallbacksToDefault(husart); + + if (husart->MspInitCallback == NULL) + { + husart->MspInitCallback = HAL_USART_MspInit; + } + + /* Init the low level hardware */ + husart->MspInitCallback(husart); +#else /* Init the low level hardware : GPIO, CLOCK */ HAL_USART_MspInit(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } husart->State = HAL_USART_STATE_BUSY; @@ -253,14 +343,14 @@ HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart) } /** - * @brief DeInitialize the USART peripheral. + * @brief DeInitialize the USART peripheral. * @param husart USART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart) { /* Check the USART handle allocation */ - if(husart == NULL) + if (husart == NULL) { return HAL_ERROR; } @@ -270,12 +360,21 @@ HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart) husart->State = HAL_USART_STATE_BUSY; - husart->Instance->CR1 = 0x0; - husart->Instance->CR2 = 0x0; - husart->Instance->CR3 = 0x0; + husart->Instance->CR1 = 0x0U; + husart->Instance->CR2 = 0x0U; + husart->Instance->CR3 = 0x0U; +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + if (husart->MspDeInitCallback == NULL) + { + husart->MspDeInitCallback = HAL_USART_MspDeInit; + } + /* DeInit the low level hardware */ + husart->MspDeInitCallback(husart); +#else /* DeInit the low level hardware */ HAL_USART_MspDeInit(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_RESET; @@ -288,7 +387,7 @@ HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart) /** * @brief Initialize the USART MSP. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_MspInit(USART_HandleTypeDef *husart) @@ -303,7 +402,7 @@ __weak void HAL_USART_MspInit(USART_HandleTypeDef *husart) /** * @brief DeInitialize the USART MSP. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart) @@ -316,12 +415,268 @@ __weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart) */ } +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User USART Callback + * To be used instead of the weak predefined callback + * @param husart usart handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_USART_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID + * @arg @ref HAL_USART_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID + * @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status ++ */ +HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID, + pUSART_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(husart); + + if (husart->State == HAL_USART_STATE_READY) + { + switch (CallbackID) + { + case HAL_USART_TX_HALFCOMPLETE_CB_ID : + husart->TxHalfCpltCallback = pCallback; + break; + + case HAL_USART_TX_COMPLETE_CB_ID : + husart->TxCpltCallback = pCallback; + break; + + case HAL_USART_RX_HALFCOMPLETE_CB_ID : + husart->RxHalfCpltCallback = pCallback; + break; + + case HAL_USART_RX_COMPLETE_CB_ID : + husart->RxCpltCallback = pCallback; + break; + + case HAL_USART_TX_RX_COMPLETE_CB_ID : + husart->TxRxCpltCallback = pCallback; + break; + + case HAL_USART_ERROR_CB_ID : + husart->ErrorCallback = pCallback; + break; + + case HAL_USART_ABORT_COMPLETE_CB_ID : + husart->AbortCpltCallback = pCallback; + break; + +#if defined(USART_CR1_FIFOEN) + case HAL_USART_RX_FIFO_FULL_CB_ID : + husart->RxFifoFullCallback = pCallback; + break; + + case HAL_USART_TX_FIFO_EMPTY_CB_ID : + husart->TxFifoEmptyCallback = pCallback; + break; +#endif /* USART_CR1_FIFOEN */ + + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = pCallback; + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (husart->State == HAL_USART_STATE_RESET) + { + switch (CallbackID) + { + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = pCallback; + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(husart); + + return status; +} + +#if 0 +/** + * @brief Unregister an USART Callback + * USART callaback is redirected to the weak predefined callback + * @param husart usart handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_USART_RX_FIFO_FULL_CB_ID Rx Fifo Full Callback ID + * @arg @ref HAL_USART_TX_FIFO_EMPTY_CB_ID Tx Fifo Empty Callback ID + * @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(husart); + + if (HAL_USART_STATE_READY == husart->State) + { + switch (CallbackID) + { + case HAL_USART_TX_HALFCOMPLETE_CB_ID : + husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_USART_TX_COMPLETE_CB_ID : + husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_USART_RX_HALFCOMPLETE_CB_ID : + husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + + case HAL_USART_RX_COMPLETE_CB_ID : + husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_USART_TX_RX_COMPLETE_CB_ID : + husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + break; + + case HAL_USART_ERROR_CB_ID : + husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_USART_ABORT_COMPLETE_CB_ID : + husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + +#if defined(USART_CR1_FIFOEN) + case HAL_USART_RX_FIFO_FULL_CB_ID : + husart->RxFifoFullCallback = HAL_USARTEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */ + break; + + case HAL_USART_TX_FIFO_EMPTY_CB_ID : + husart->TxFifoEmptyCallback = HAL_USARTEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */ + break; +#endif /* USART_CR1_FIFOEN */ + + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = HAL_USART_MspInit; /* Legacy weak MspInitCallback */ + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = HAL_USART_MspDeInit; /* Legacy weak MspDeInitCallback */ + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_USART_STATE_RESET == husart->State) + { + switch (CallbackID) + { + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = HAL_USART_MspInit; + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = HAL_USART_MspDeInit; + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(husart); + + return status; +} +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +#endif + + /** * @} */ /** @defgroup USART_Exported_Functions_Group2 IO operation functions - * @brief USART Transmit and Receive functions + * @brief USART Transmit and Receive functions * @verbatim =============================================================================== @@ -333,32 +688,34 @@ __weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart) [..] The USART supports master mode only: it cannot receive or send data related to an input clock (SCLK is always an output). + [..] + (#) There are two modes of transfer: - (++) Blocking mode: The communication is performed in polling mode. - The HAL status of all data processing is returned by the same function - after finishing transfer. - (++) No-Blocking mode: The communication is performed using Interrupts - or DMA, These API's return the HAL status. - The end of the data processing will be indicated through the - dedicated USART IRQ when using Interrupt mode or the DMA IRQ when - using DMA mode. - The HAL_USART_TxCpltCallback(), HAL_USART_RxCpltCallback() and HAL_USART_TxRxCpltCallback() user callbacks - will be executed respectively at the end of the transmit or Receive process - The HAL_USART_ErrorCallback()user callback will be executed when a communication error is detected + (++) Blocking mode: The communication is performed in polling mode. + The HAL status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode: The communication is performed using Interrupts + or DMA, These API's return the HAL status. + The end of the data processing will be indicated through the + dedicated USART IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_USART_TxCpltCallback(), HAL_USART_RxCpltCallback() and HAL_USART_TxRxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_USART_ErrorCallback()user callback will be executed when a communication error is detected (#) Blocking mode API's are : - (++) HAL_USART_Transmit()in simplex mode + (++) HAL_USART_Transmit() in simplex mode (++) HAL_USART_Receive() in full duplex receive only (++) HAL_USART_TransmitReceive() in full duplex mode (#) Non-Blocking mode API's with Interrupt are : - (++) HAL_USART_Transmit_IT()in simplex mode + (++) HAL_USART_Transmit_IT() in simplex mode (++) HAL_USART_Receive_IT() in full duplex receive only - (++) HAL_USART_TransmitReceive_IT()in full duplex mode + (++) HAL_USART_TransmitReceive_IT() in full duplex mode (++) HAL_USART_IRQHandler() (#) No-Blocking mode API's with DMA are : - (++) HAL_USART_Transmit_DMA()in simplex mode + (++) HAL_USART_Transmit_DMA() in simplex mode (++) HAL_USART_Receive_DMA() in full duplex receive only (++) HAL_USART_TransmitReceive_DMA() in full duplex mode (++) HAL_USART_DMAPause() @@ -374,22 +731,25 @@ __weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart) (++) HAL_USART_TxRxCpltCallback() (#) Non-Blocking mode transfers could be aborted using Abort API's : - (+) HAL_USART_Abort() - (+) HAL_USART_Abort_IT() + (++) HAL_USART_Abort() + (++) HAL_USART_Abort_IT() (#) For Abort services based on interrupts (HAL_USART_Abort_IT), a Abort Complete Callbacks is provided: - (+) HAL_USART_AbortCpltCallback() + (++) HAL_USART_AbortCpltCallback() (#) In Non-Blocking mode transfers, possible errors are split into 2 categories. Errors are handled as follows : - (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is - to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception . - Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type, - and HAL_USART_ErrorCallback() user callback is executed. Transfer is kept ongoing on USART side. - If user wants to abort it, Abort services should be called by user. - (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted. - This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode. - Error code is set to allow user to identify error type, and HAL_USART_ErrorCallback() user callback is executed. + (++) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is + to be evaluated by user : this concerns Frame Error, + Parity Error or Noise Error in Interrupt mode reception . + Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify + error type, and HAL_USART_ErrorCallback() user callback is executed. + Transfer is kept ongoing on USART side. + If user wants to abort it, Abort services should be called by user. + (++) Error is considered as Blocking : Transfer could not be completed properly and is aborted. + This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode. + Error code is set to allow user to identify error type, + and HAL_USART_ErrorCallback() user callback is executed. @endverbatim * @{ @@ -397,20 +757,24 @@ __weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart) /** * @brief Simplex send an amount of data in blocking mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pTxData. * @param husart USART handle. - * @param pTxData Pointer to data buffer. - * @param Size Amount of data to be sent. + * @param pTxData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent. * @param Timeout Timeout duration. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size, uint32_t Timeout) { - uint16_t* tmp; - uint32_t tickstart = 0; + uint8_t *ptxdata8bits; + uint16_t *ptxdata16bits; + uint32_t tickstart; - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pTxData == NULL) || (Size == 0)) + if ((pTxData == NULL) || (Size == 0U)) { return HAL_ERROR; } @@ -421,37 +785,58 @@ HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxDa husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_TX; - /* Init tickstart for timeout managment*/ + /* Init tickstart for timeout management */ tickstart = HAL_GetTick(); husart->TxXferSize = Size; husart->TxXferCount = Size; - /* Check the remaining data to be sent */ - while(husart->TxXferCount > 0) + /* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) { - husart->TxXferCount--; - if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + ptxdata8bits = NULL; + ptxdata16bits = (uint16_t *) pTxData; + } + else + { + ptxdata8bits = pTxData; + ptxdata16bits = NULL; + } + + /* Check the remaining data to be sent */ + while (husart->TxXferCount > 0U) + { + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) { return HAL_TIMEOUT; } - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + if (ptxdata8bits == NULL) { - tmp = (uint16_t*) pTxData; - husart->Instance->TDR = (*tmp & (uint16_t)0x01FF); - pTxData += 2; + husart->Instance->TDR = (uint16_t)(*ptxdata16bits & 0x01FFU); + ptxdata16bits++; } else { - husart->Instance->TDR = (*pTxData++ & (uint8_t)0xFF); + husart->Instance->TDR = (uint8_t)(*ptxdata8bits & 0xFFU); + ptxdata8bits++; } + + husart->TxXferCount--; } - if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) { return HAL_TIMEOUT; } + /* Clear Transmission Complete Flag */ + __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF); + + /* Clear overrun flag and discard the received data */ + __HAL_USART_CLEAR_OREFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + /* At end of Tx process, restore husart->State to Ready */ husart->State = HAL_USART_STATE_READY; @@ -468,22 +853,26 @@ HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, uint8_t *pTxDa /** * @brief Receive an amount of data in blocking mode. - * @note To receive synchronous data, dummy data are simultaneously transmitted. + * @note To receive synchronous data, dummy data are simultaneously transmitted. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pRxData. * @param husart USART handle. - * @param pRxData Pointer to data buffer. - * @param Size Amount of data to be received. + * @param pRxData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. * @param Timeout Timeout duration. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout) { - uint16_t* tmp; + uint8_t *prxdata8bits; + uint16_t *prxdata16bits; uint16_t uhMask; - uint32_t tickstart = 0; + uint32_t tickstart; - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pRxData == NULL) || (Size == 0)) + if ((pRxData == NULL) || (Size == 0U)) { return HAL_ERROR; } @@ -494,7 +883,7 @@ HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxDat husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_RX; - /* Init tickstart for timeout managment*/ + /* Init tickstart for timeout management */ tickstart = HAL_GetTick(); husart->RxXferSize = Size; @@ -504,39 +893,66 @@ HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxDat USART_MASK_COMPUTATION(husart); uhMask = husart->Mask; - /* as long as data have to be received */ - while(husart->RxXferCount > 0) + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) { - husart->RxXferCount--; + prxdata8bits = NULL; + prxdata16bits = (uint16_t *) pRxData; + } + else + { + prxdata8bits = pRxData; + prxdata16bits = NULL; + } - /* Wait until TC flag is set to send dummy byte in order to generate the - * clock for the slave to send data. - * Whatever the frame length (7, 8 or 9-bit long), the same dummy value - * can be written for all the cases. */ - if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + /* as long as data have to be received */ + while (husart->RxXferCount > 0U) + { +#if defined(USART_CR2_SLVEN) + if (husart->SlaveMode == USART_SLAVEMODE_DISABLE) +#endif /* USART_CR2_SLVEN */ { - return HAL_TIMEOUT; + /* Wait until TXE flag is set to send dummy byte in order to generate the + * clock for the slave to send data. + * Whatever the frame length (7, 8 or 9-bit long), the same dummy value + * can be written for all the cases. */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x0FF); } - husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x0FF); /* Wait for RXNE Flag */ - if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) { return HAL_TIMEOUT; } - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + if (prxdata8bits == NULL) { - tmp = (uint16_t*) pRxData ; - *tmp = (uint16_t)(husart->Instance->RDR & uhMask); - pRxData +=2; + *prxdata16bits = (uint16_t)(husart->Instance->RDR & uhMask); + prxdata16bits++; } else { - *pRxData++ = (uint8_t)(husart->Instance->RDR & (uint8_t)uhMask); + *prxdata8bits = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU)); + prxdata8bits++; } + + husart->RxXferCount--; + } +#if defined(USART_CR2_SLVEN) + /* Clear SPI slave underrun flag and discard transmit data */ + if (husart->SlaveMode == USART_SLAVEMODE_ENABLE) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR2_SLVEN */ + /* At end of Rx process, restore husart->State to Ready */ husart->State = HAL_USART_STATE_READY; @@ -551,34 +967,44 @@ HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxDat } } +#if 0 /** - * @brief Full-Duplex Send and Receive an amount of data in blocking mode. + * @brief Full-Duplex Send and Receive an amount of data in blocking mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number + * of u16 available through pTxData and through pRxData. * @param husart USART handle. - * @param pTxData pointer to TX data buffer. - * @param pRxData pointer to RX data buffer. - * @param Size amount of data to be sent (same amount to be received). + * @param pTxData pointer to TX data buffer (u8 or u16 data elements). + * @param pRxData pointer to RX data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be sent (same amount to be received). * @param Timeout Timeout duration. * @retval HAL status */ -HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout) +HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size, uint32_t Timeout) { - uint16_t* tmp; + uint8_t *prxdata8bits; + uint16_t *prxdata16bits; + uint8_t *ptxdata8bits; + uint16_t *ptxdata16bits; uint16_t uhMask; - uint32_t tickstart = 0; + uint16_t rxdatacount; + uint32_t tickstart; - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pTxData == NULL) || (pRxData == NULL) || (Size == 0)) + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) { return HAL_ERROR; } + /* Process Locked */ __HAL_LOCK(husart); husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_RX; - /* Init tickstart for timeout managment*/ + /* Init tickstart for timeout management */ tickstart = HAL_GetTick(); husart->RxXferSize = Size; @@ -590,44 +1016,95 @@ HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, uint8_t USART_MASK_COMPUTATION(husart); uhMask = husart->Mask; - /* Check the remain data to be sent */ - while(husart->TxXferCount > 0) + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) { + prxdata8bits = NULL; + ptxdata8bits = NULL; + ptxdata16bits = (uint16_t *) pTxData; + prxdata16bits = (uint16_t *) pRxData; + } + else + { + prxdata8bits = pRxData; + ptxdata8bits = pTxData; + ptxdata16bits = NULL; + prxdata16bits = NULL; + } + +#if defined(USART_CR2_SLVEN) + if ((husart->TxXferCount == 0x01U) || (husart->SlaveMode == USART_SLAVEMODE_ENABLE)) +#else + if (husart->TxXferCount == 0x01U) +#endif /* USART_CR2_SLVEN */ + { + /* Wait until TXE flag is set to send data */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if (ptxdata8bits == NULL) + { + husart->Instance->TDR = (uint16_t)(*ptxdata16bits & uhMask); + ptxdata16bits++; + } + else + { + husart->Instance->TDR = (uint8_t)(*ptxdata8bits & (uint8_t)(uhMask & 0xFFU)); + ptxdata8bits++; + } + husart->TxXferCount--; - husart->RxXferCount--; + } - /* Wait until TC flag is set to send data */ - if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + /* Check the remain data to be sent */ + /* rxdatacount is a temporary variable for MISRAC2012-Rule-13.5 */ + rxdatacount = husart->RxXferCount; + while ((husart->TxXferCount > 0U) || (rxdatacount > 0U)) + { + if (husart->TxXferCount > 0U) { - return HAL_TIMEOUT; - } - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) - { - tmp = (uint16_t*) pTxData; - husart->Instance->TDR = (*tmp & uhMask); - pTxData += 2; - } - else - { - husart->Instance->TDR = (*pTxData++ & (uint8_t)uhMask); + /* Wait until TXE flag is set to send data */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if (ptxdata8bits == NULL) + { + husart->Instance->TDR = (uint16_t)(*ptxdata16bits & uhMask); + ptxdata16bits++; + } + else + { + husart->Instance->TDR = (uint8_t)(*ptxdata8bits & (uint8_t)(uhMask & 0xFFU)); + ptxdata8bits++; + } + + husart->TxXferCount--; } - /* Wait for RXNE Flag */ - if(USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + if (husart->RxXferCount > 0U) { - return HAL_TIMEOUT; - } + /* Wait for RXNE Flag */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) - { - tmp = (uint16_t*) pRxData ; - *tmp = (uint16_t)(husart->Instance->RDR & uhMask); - pRxData +=2; - } - else - { - *pRxData++ = (uint8_t)(husart->Instance->RDR & (uint8_t)uhMask); + if (prxdata8bits == NULL) + { + *prxdata16bits = (uint16_t)(husart->Instance->RDR & uhMask); + prxdata16bits++; + } + else + { + *prxdata8bits = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU)); + prxdata8bits++; + } + + husart->RxXferCount--; } + rxdatacount = husart->RxXferCount; } /* At end of TxRx process, restore husart->State to Ready */ @@ -644,19 +1121,21 @@ HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, uint8_t } } -#if 0 /** * @brief Send an amount of data in interrupt mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pTxData. * @param husart USART handle. - * @param pTxData pointer to data buffer. - * @param Size amount of data to be sent. + * @param pTxData pointer to data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be sent. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size) { - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pTxData == NULL ) || (Size == 0)) + if ((pTxData == NULL) || (Size == 0U)) { return HAL_ERROR; } @@ -664,12 +1143,13 @@ HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, uint8_t *pT /* Process Locked */ __HAL_LOCK(husart); - husart->pTxBuffPtr = pTxData; - husart->TxXferSize = Size; + husart->pTxBuffPtr = pTxData; + husart->TxXferSize = Size; husart->TxXferCount = Size; + husart->TxISR = NULL; husart->ErrorCode = HAL_USART_ERROR_NONE; - husart->State = HAL_USART_STATE_BUSY_TX; + husart->State = HAL_USART_STATE_BUSY_TX; /* The USART Error Interrupts: (Frame error, noise error, overrun error) are not managed by the USART Transmit Process to avoid the overrun interrupt @@ -677,11 +1157,45 @@ HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, uint8_t *pT to benefit for the frame error and noise interrupts the usart mode should be configured only for transmit "USART_MODE_TX" */ - /* Process Unlocked */ - __HAL_UNLOCK(husart); +#if defined(USART_CR1_FIFOEN) + /* Configure Tx interrupt processing */ + if (husart->FifoMode == USART_FIFOMODE_ENABLE) + { + /* Set the Tx ISR function pointer according to the data word length */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + husart->TxISR = USART_TxISR_16BIT_FIFOEN; + } + else + { + husart->TxISR = USART_TxISR_8BIT_FIFOEN; + } - /* Enable the USART Transmit Data Register Empty Interrupt */ - __HAL_USART_ENABLE_IT(husart, USART_IT_TXE); + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the TX FIFO threshold interrupt */ + __HAL_USART_ENABLE_IT(husart, USART_IT_TXFT); + } + else +#endif /* USART_CR1_FIFOEN */ + { + /* Set the Tx ISR function pointer according to the data word length */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + husart->TxISR = USART_TxISR_16BIT; + } + else + { + husart->TxISR = USART_TxISR_8BIT; + } + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the USART Transmit Data Register Empty Interrupt */ + __HAL_USART_ENABLE_IT(husart, USART_IT_TXE); + } return HAL_OK; } @@ -692,18 +1206,25 @@ HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, uint8_t *pT } /** - * @brief Receive an amount of data in interrupt mode. + * @brief Receive an amount of data in interrupt mode. * @note To receive synchronous data, dummy data are simultaneously transmitted. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pRxData. * @param husart USART handle. - * @param pRxData pointer to data buffer. - * @param Size amount of data to be received. + * @param pRxData pointer to data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be received. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size) { - if(husart->State == HAL_USART_STATE_READY) +#if defined(USART_CR1_FIFOEN) + uint16_t nb_dummy_data; +#endif /* USART_CR1_FIFOEN */ + + if (husart->State == HAL_USART_STATE_READY) { - if((pRxData == NULL ) || (Size == 0)) + if ((pRxData == NULL) || (Size == 0U)) { return HAL_ERROR; } @@ -711,32 +1232,85 @@ HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRx /* Process Locked */ __HAL_LOCK(husart); - husart->pRxBuffPtr = pRxData; - husart->RxXferSize = Size; + husart->pRxBuffPtr = pRxData; + husart->RxXferSize = Size; husart->RxXferCount = Size; + husart->RxISR = NULL; USART_MASK_COMPUTATION(husart); husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_RX; - /* Process Unlocked */ - __HAL_UNLOCK(husart); - - /* Enable the USART Parity Error and Data Register not empty Interrupts */ - SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); - /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ SET_BIT(husart->Instance->CR3, USART_CR3_EIE); - /* Send dummy byte in order to generate the clock for the Slave to send the next data */ - if(husart->Init.WordLength == USART_WORDLENGTH_9B) +#if defined(USART_CR1_FIFOEN) + /* Configure Rx interrupt processing */ + if ((husart->FifoMode == USART_FIFOMODE_ENABLE) && (Size >= husart->NbRxDataToProcess)) { - husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x01FF); + /* Set the Rx ISR function pointer according to the data word length */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + husart->RxISR = USART_RxISR_16BIT_FIFOEN; + } + else + { + husart->RxISR = USART_RxISR_8BIT_FIFOEN; + } + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the USART Parity Error interrupt and RX FIFO Threshold interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(husart->Instance->CR3, USART_CR3_RXFTIE); } else +#endif /* USART_CR1_FIFOEN */ { - husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + /* Set the Rx ISR function pointer according to the data word length */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + husart->RxISR = USART_RxISR_16BIT; + } + else + { + husart->RxISR = USART_RxISR_8BIT; + } + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the USART Parity Error and Data Register not empty Interrupts */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE); +#else + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); +#endif /* USART_CR1_FIFOEN */ + } + +#if defined(USART_CR2_SLVEN) + if (husart->SlaveMode == USART_SLAVEMODE_DISABLE) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy data in order to generate the clock for the Slave to send the next data. + When FIFO mode is disabled only one data must be transferred. + When FIFO mode is enabled data must be transmitted until the RX FIFO reaches its threshold. + */ +#if defined(USART_CR1_FIFOEN) + if ((husart->FifoMode == USART_FIFOMODE_ENABLE) && (Size >= husart->NbRxDataToProcess)) + { + for (nb_dummy_data = husart->NbRxDataToProcess ; nb_dummy_data > 0U ; nb_dummy_data--) + { + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + } + else +#endif /* USART_CR1_FIFOEN */ + { + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } } return HAL_OK; @@ -748,22 +1322,27 @@ HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRx } /** - * @brief Full-Duplex Send and Receive an amount of data in interrupt mode. + * @brief Full-Duplex Send and Receive an amount of data in interrupt mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number + * of u16 available through pTxData and through pRxData. * @param husart USART handle. - * @param pTxData pointer to TX data buffer. - * @param pRxData pointer to RX data buffer. - * @param Size amount of data to be sent (same amount to be received). + * @param pTxData pointer to TX data buffer (u8 or u16 data elements). + * @param pRxData pointer to RX data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be sent (same amount to be received). * @retval HAL status */ -HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size) +HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) { - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pTxData == NULL) || (pRxData == NULL) || (Size == 0)) + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) { return HAL_ERROR; } + /* Process Locked */ __HAL_LOCK(husart); @@ -780,17 +1359,68 @@ HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, uint husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_TX_RX; - /* Process Unlocked */ - __HAL_UNLOCK(husart); +#if defined(USART_CR1_FIFOEN) + /* Configure TxRx interrupt processing */ + if ((husart->FifoMode == USART_FIFOMODE_ENABLE) && (Size >= husart->NbRxDataToProcess)) + { + /* Set the Rx ISR function pointer according to the data word length */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + husart->TxISR = USART_TxISR_16BIT_FIFOEN; + husart->RxISR = USART_RxISR_16BIT_FIFOEN; + } + else + { + husart->TxISR = USART_TxISR_8BIT_FIFOEN; + husart->RxISR = USART_RxISR_8BIT_FIFOEN; + } - /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ - SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + /* Process Locked */ + __HAL_UNLOCK(husart); - /* Enable the USART Parity Error and USART Data Register not empty Interrupts */ - SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); - /* Enable the USART Transmit Data Register Empty Interrupt */ - SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE); + /* Enable the USART Parity Error interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + + /* Enable the TX and RX FIFO Threshold interrupts */ + SET_BIT(husart->Instance->CR3, (USART_CR3_TXFTIE | USART_CR3_RXFTIE)); + } + else +#endif /* USART_CR1_FIFOEN */ + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + husart->TxISR = USART_TxISR_16BIT; + husart->RxISR = USART_RxISR_16BIT; + } + else + { + husart->TxISR = USART_TxISR_8BIT; + husart->RxISR = USART_RxISR_8BIT; + } + + /* Process Locked */ + __HAL_UNLOCK(husart); + + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Enable the USART Parity Error and USART Data Register not empty Interrupts */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE); +#else + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); +#endif /* USART_CR1_FIFOEN */ + + /* Enable the USART Transmit Data Register Empty Interrupt */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE); +#endif /* USART_CR1_FIFOEN */ + } return HAL_OK; } @@ -799,24 +1429,31 @@ HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, uint return HAL_BUSY; } } +#endif +#if 0 /** - * @brief Send an amount of data in DMA mode. + * @brief Send an amount of data in DMA mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data is handled as a set of u16. In this case, Size must indicate the number + * of u16 provided through pTxData. * @param husart USART handle. - * @param pTxData pointer to data buffer. - * @param Size amount of data to be sent. + * @param pTxData pointer to data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be sent. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, uint8_t *pTxData, uint16_t Size) { + HAL_StatusTypeDef status = HAL_OK; uint32_t *tmp; - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pTxData == NULL ) || (Size == 0)) + if ((pTxData == NULL) || (Size == 0U)) { return HAL_ERROR; } + /* Process Locked */ __HAL_LOCK(husart); @@ -827,30 +1464,49 @@ HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, uint8_t *p husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_TX; - /* Set the USART DMA transfer complete callback */ - husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt; + if (husart->hdmatx != NULL) + { + /* Set the USART DMA transfer complete callback */ + husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt; - /* Set the USART DMA Half transfer complete callback */ - husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt; + /* Set the USART DMA Half transfer complete callback */ + husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt; - /* Set the DMA error callback */ - husart->hdmatx->XferErrorCallback = USART_DMAError; + /* Set the DMA error callback */ + husart->hdmatx->XferErrorCallback = USART_DMAError; - /* Enable the USART transmit DMA channel */ - tmp = (uint32_t*)&pTxData; - HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t*)tmp, (uint32_t)&husart->Instance->TDR, Size); + /* Enable the USART transmit DMA channel */ + tmp = (uint32_t *)&pTxData; + status = HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->TDR, Size); + } - /* Clear the TC flag in the ICR register */ - __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF); + if (status == HAL_OK) + { + /* Clear the TC flag in the ICR register */ + __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF); - /* Process Unlocked */ - __HAL_UNLOCK(husart); + /* Process Unlocked */ + __HAL_UNLOCK(husart); - /* Enable the DMA transfer for transmit request by setting the DMAT bit - in the USART CR3 register */ - SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); - return HAL_OK; + return HAL_OK; + } + else + { + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Restore husart->State to ready */ + husart->State = HAL_USART_STATE_READY; + + return HAL_ERROR; + } } else { @@ -859,23 +1515,27 @@ HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, uint8_t *p } /** - * @brief Receive an amount of data in DMA mode. - * @param husart USART handle. - * @param pRxData pointer to data buffer. - * @param Size amount of data to be received. + * @brief Receive an amount of data in DMA mode. * @note When the USART parity is enabled (PCE = 1), the received data contain * the parity bit (MSB position). * @note The USART DMA transmit channel must be configured in order to generate the clock for the slave. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the received data is handled as a set of u16. In this case, Size must indicate the number + * of u16 available through pRxData. + * @param husart USART handle. + * @param pRxData pointer to data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be received. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size) { - uint32_t *tmp; + HAL_StatusTypeDef status = HAL_OK; + uint32_t *tmp = (uint32_t *)&pRxData; /* Check that a Rx process is not already ongoing */ - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pRxData == NULL ) || (Size == 0)) + if ((pRxData == NULL) || (Size == 0U)) { return HAL_ERROR; } @@ -891,46 +1551,82 @@ HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pR husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_RX; - /* Set the USART DMA Rx transfer complete callback */ - husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt; + if (husart->hdmarx != NULL) + { + /* Set the USART DMA Rx transfer complete callback */ + husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt; - /* Set the USART DMA Half transfer complete callback */ - husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt; + /* Set the USART DMA Half transfer complete callback */ + husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt; - /* Set the USART DMA Rx transfer error callback */ - husart->hdmarx->XferErrorCallback = USART_DMAError; + /* Set the USART DMA Rx transfer error callback */ + husart->hdmarx->XferErrorCallback = USART_DMAError; - /* Enable the USART receive DMA channel */ - tmp = (uint32_t*)&pRxData; - HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->RDR, *(uint32_t*)tmp, Size); + /* Enable the USART receive DMA channel */ + status = HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->RDR, *(uint32_t *)tmp, Size); + } - /* Enable the USART transmit DMA channel: the transmit channel is used in order - to generate in the non-blocking mode the clock to the slave device, - this mode isn't a simplex receive mode but a full-duplex receive mode */ - /* Set the USART DMA Tx Complete and Error callback to Null */ - husart->hdmatx->XferErrorCallback = NULL; - husart->hdmatx->XferHalfCpltCallback = NULL; - husart->hdmatx->XferCpltCallback = NULL; - HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t*)tmp, (uint32_t)&husart->Instance->TDR, Size); +#if defined(USART_CR2_SLVEN) + if ((status == HAL_OK) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#endif /* USART_CR2_SLVEN */ + { + /* Enable the USART transmit DMA channel: the transmit channel is used in order + to generate in the non-blocking mode the clock to the slave device, + this mode isn't a simplex receive mode but a full-duplex receive mode */ - /* Process Unlocked */ - __HAL_UNLOCK(husart); + /* Set the USART DMA Tx Complete and Error callback to Null */ + if (husart->hdmatx != NULL) + { + husart->hdmatx->XferErrorCallback = NULL; + husart->hdmatx->XferHalfCpltCallback = NULL; + husart->hdmatx->XferCpltCallback = NULL; + status = HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->TDR, Size); + } + } - /* Enable the USART Parity Error Interrupt */ - SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + if (status == HAL_OK) + { + /* Process Unlocked */ + __HAL_UNLOCK(husart); - /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ - SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + /* Enable the USART Parity Error Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); - /* Enable the DMA transfer for the receiver request by setting the DMAR bit - in the USART CR3 register */ - SET_BIT(husart->Instance->CR3, USART_CR3_DMAR); + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); - /* Enable the DMA transfer for transmit request by setting the DMAT bit - in the USART CR3 register */ - SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAR); - return HAL_OK; + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + if (husart->hdmarx != NULL) + { + status = HAL_DMA_Abort(husart->hdmarx); + } + + /* No need to check on error code */ + UNUSED(status); + + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Restore husart->State to ready */ + husart->State = HAL_USART_STATE_READY; + + return HAL_ERROR; + } } else { @@ -939,24 +1635,30 @@ HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pR } /** - * @brief Full-Duplex Transmit Receive an amount of data in non-blocking mode. - * @param husart USART handle. - * @param pTxData pointer to TX data buffer. - * @param pRxData pointer to RX data buffer. - * @param Size amount of data to be received/sent. + * @brief Full-Duplex Transmit Receive an amount of data in non-blocking mode. * @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number + * of u16 available through pTxData and through pRxData. + * @param husart USART handle. + * @param pTxData pointer to TX data buffer (u8 or u16 data elements). + * @param pRxData pointer to RX data buffer (u8 or u16 data elements). + * @param Size amount of data elements (u8 or u16) to be received/sent. * @retval HAL status */ -HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size) +HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) { + HAL_StatusTypeDef status; uint32_t *tmp; - if(husart->State == HAL_USART_STATE_READY) + if (husart->State == HAL_USART_STATE_READY) { - if((pTxData == NULL) || (pRxData == NULL) || (Size == 0)) + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) { return HAL_ERROR; } + /* Process Locked */ __HAL_LOCK(husart); @@ -968,53 +1670,87 @@ HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, uin husart->ErrorCode = HAL_USART_ERROR_NONE; husart->State = HAL_USART_STATE_BUSY_TX_RX; - /* Set the USART DMA Rx transfer complete callback */ - husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt; + if ((husart->hdmarx != NULL) && (husart->hdmatx != NULL)) + { + /* Set the USART DMA Rx transfer complete callback */ + husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt; - /* Set the USART DMA Half transfer complete callback */ - husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt; + /* Set the USART DMA Half transfer complete callback */ + husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt; - /* Set the USART DMA Tx transfer complete callback */ - husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt; + /* Set the USART DMA Tx transfer complete callback */ + husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt; - /* Set the USART DMA Half transfer complete callback */ - husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt; + /* Set the USART DMA Half transfer complete callback */ + husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt; - /* Set the USART DMA Tx transfer error callback */ - husart->hdmatx->XferErrorCallback = USART_DMAError; + /* Set the USART DMA Tx transfer error callback */ + husart->hdmatx->XferErrorCallback = USART_DMAError; - /* Set the USART DMA Rx transfer error callback */ - husart->hdmarx->XferErrorCallback = USART_DMAError; + /* Set the USART DMA Rx transfer error callback */ + husart->hdmarx->XferErrorCallback = USART_DMAError; - /* Enable the USART receive DMA channel */ - tmp = (uint32_t*)&pRxData; - HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->RDR, *(uint32_t*)tmp, Size); + /* Enable the USART receive DMA channel */ + tmp = (uint32_t *)&pRxData; + status = HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->RDR, *(uint32_t *)tmp, Size); - /* Enable the USART transmit DMA channel */ - tmp = (uint32_t*)&pTxData; - HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t*)tmp, (uint32_t)&husart->Instance->TDR, Size); + /* Enable the USART transmit DMA channel */ + if (status == HAL_OK) + { + tmp = (uint32_t *)&pTxData; + status = HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->TDR, Size); + } + } + else + { + status = HAL_ERROR; + } - /* Process Unlocked */ - __HAL_UNLOCK(husart); + if (status == HAL_OK) + { + /* Process Unlocked */ + __HAL_UNLOCK(husart); - /* Enable the USART Parity Error Interrupt */ - SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + /* Enable the USART Parity Error Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); - /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ - SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); - /* Clear the TC flag in the ICR register */ - __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF); + /* Clear the TC flag in the ICR register */ + __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_TCF); - /* Enable the DMA transfer for the receiver request by setting the DMAR bit - in the USART CR3 register */ - SET_BIT(husart->Instance->CR3, USART_CR3_DMAR); + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAR); - /* Enable the DMA transfer for transmit request by setting the DMAT bit - in the USART CR3 register */ - SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); - return HAL_OK; + return HAL_OK; + } + else + { + if (husart->hdmarx != NULL) + { + status = HAL_DMA_Abort(husart->hdmarx); + } + + /* No need to check on error code */ + UNUSED(status); + + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Restore husart->State to ready */ + husart->State = HAL_USART_STATE_READY; + + return HAL_ERROR; + } } else { @@ -1023,23 +1759,25 @@ HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, uin } /** - * @brief Pause the DMA Transfer. + * @brief Pause the DMA Transfer. * @param husart USART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart) { + const HAL_USART_StateTypeDef state = husart->State; + /* Process Locked */ __HAL_LOCK(husart); - if( (husart->State == HAL_USART_STATE_BUSY_TX) && - (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))) + if ((HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) && + (state == HAL_USART_STATE_BUSY_TX)) { /* Disable the USART DMA Tx request */ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); } - else if( (husart->State == HAL_USART_STATE_BUSY_RX) || - (husart->State == HAL_USART_STATE_BUSY_TX_RX) ) + else if ((state == HAL_USART_STATE_BUSY_RX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) { if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) { @@ -1056,6 +1794,10 @@ HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart) CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); } } + else + { + /* Nothing to do */ + } /* Process Unlocked */ __HAL_UNLOCK(husart); @@ -1064,27 +1806,29 @@ HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart) } /** - * @brief Resume the DMA Transfer. + * @brief Resume the DMA Transfer. * @param husart USART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart) { + const HAL_USART_StateTypeDef state = husart->State; + /* Process Locked */ __HAL_LOCK(husart); - if(husart->State == HAL_USART_STATE_BUSY_TX) + if (state == HAL_USART_STATE_BUSY_TX) { /* Enable the USART DMA Tx request */ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); } - else if( (husart->State == HAL_USART_STATE_BUSY_RX) || - (husart->State == HAL_USART_STATE_BUSY_TX_RX) ) + else if ((state == HAL_USART_STATE_BUSY_RX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) { /* Clear the Overrun flag before resuming the Rx transfer*/ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF); - /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */ + /* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */ SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); SET_BIT(husart->Instance->CR3, USART_CR3_EIE); @@ -1094,6 +1838,10 @@ HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart) /* Enable the USART DMA Tx request */ SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); } + else + { + /* Nothing to do */ + } /* Process Unlocked */ __HAL_UNLOCK(husart); @@ -1102,7 +1850,7 @@ HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart) } /** - * @brief Stop the DMA Transfer. + * @brief Stop the DMA Transfer. * @param husart USART handle. * @retval HAL status */ @@ -1120,14 +1868,32 @@ HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart) CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); /* Abort the USART DMA tx channel */ - if(husart->hdmatx != NULL) + if (husart->hdmatx != NULL) { - HAL_DMA_Abort(husart->hdmatx); + if (HAL_DMA_Abort(husart->hdmatx) != HAL_OK) + { + if (HAL_DMA_GetError(husart->hdmatx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } } /* Abort the USART DMA rx channel */ - if(husart->hdmarx != NULL) + if (husart->hdmarx != NULL) { - HAL_DMA_Abort(husart->hdmarx); + if (HAL_DMA_Abort(husart->hdmarx) != HAL_OK) + { + if (HAL_DMA_GetError(husart->hdmarx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } } USART_EndTransfer(husart); @@ -1147,12 +1913,18 @@ HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart) * - Set handle State to READY * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. * @retval HAL status -*/ + */ HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart) { - /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + /* Disable TXEIE, TCIE, RXNE, RXFT, TXFT, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | + USART_CR1_TCIE)); + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE)); +#else CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); +#endif /* USART_CR1_FIFOEN */ /* Disable the USART DMA Tx request if enabled */ if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) @@ -1160,13 +1932,22 @@ HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart) CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); /* Abort the USART DMA Tx channel : use blocking DMA Abort API (no callback) */ - if(husart->hdmatx != NULL) + if (husart->hdmatx != NULL) { /* Set the USART DMA Abort callback to Null. No call back execution at end of DMA abort procedure */ husart->hdmatx->XferAbortCallback = NULL; - HAL_DMA_Abort(husart->hdmatx); + if (HAL_DMA_Abort(husart->hdmatx) != HAL_OK) + { + if (HAL_DMA_GetError(husart->hdmatx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } } } @@ -1176,23 +1957,43 @@ HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart) CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); /* Abort the USART DMA Rx channel : use blocking DMA Abort API (no callback) */ - if(husart->hdmarx != NULL) + if (husart->hdmarx != NULL) { /* Set the USART DMA Abort callback to Null. No call back execution at end of DMA abort procedure */ husart->hdmarx->XferAbortCallback = NULL; - HAL_DMA_Abort(husart->hdmarx); + if (HAL_DMA_Abort(husart->hdmarx) != HAL_OK) + { + if (HAL_DMA_GetError(husart->hdmarx) == HAL_DMA_ERROR_TIMEOUT) + { + /* Set error code to DMA */ + husart->ErrorCode = HAL_USART_ERROR_DMA; + + return HAL_TIMEOUT; + } + } } } /* Reset Tx and Rx transfer counters */ - husart->TxXferCount = 0; - husart->RxXferCount = 0; + husart->TxXferCount = 0U; + husart->RxXferCount = 0U; /* Clear the Error flags in the ICR register */ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF); +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (husart->FifoMode == USART_FIFOMODE_ENABLE) + { + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR1_FIFOEN */ + + /* Discard the received data */ + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); + /* Restore husart->State to Ready */ husart->State = HAL_USART_STATE_READY; @@ -1215,23 +2016,29 @@ HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart) * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be * considered as completed only when user abort complete callback is executed (not when exiting function). * @retval HAL status -*/ + */ HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart) { - uint32_t abortcplt = 1; + uint32_t abortcplt = 1U; - /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + /* Disable TXEIE, TCIE, RXNE, RXFT, TXFT, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | + USART_CR1_TCIE)); + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE)); +#else CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); +#endif /* USART_CR1_FIFOEN */ /* If DMA Tx and/or DMA Rx Handles are associated to USART Handle, DMA Abort complete callbacks should be initialised before any call to DMA Abort functions */ /* DMA Tx Handle is valid */ - if(husart->hdmatx != NULL) + if (husart->hdmatx != NULL) { /* Set DMA Abort Complete callback if USART DMA Tx request if enabled. Otherwise, set it to NULL */ - if(HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) { husart->hdmatx->XferAbortCallback = USART_DMATxAbortCallback; } @@ -1241,11 +2048,11 @@ HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart) } } /* DMA Rx Handle is valid */ - if(husart->hdmarx != NULL) + if (husart->hdmarx != NULL) { /* Set DMA Abort Complete callback if USART DMA Rx request if enabled. Otherwise, set it to NULL */ - if(HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) { husart->hdmarx->XferAbortCallback = USART_DMARxAbortCallback; } @@ -1256,25 +2063,25 @@ HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart) } /* Disable the USART DMA Tx request if enabled */ - if(HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) { /* Disable DMA Tx at USART level */ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); /* Abort the USART DMA Tx channel : use non blocking DMA Abort API (callback) */ - if(husart->hdmatx != NULL) + if (husart->hdmatx != NULL) { /* USART Tx DMA Abort callback has already been initialised : will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */ /* Abort DMA TX */ - if(HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK) + if (HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK) { husart->hdmatx->XferAbortCallback = NULL; } else { - abortcplt = 0; + abortcplt = 0U; } } } @@ -1285,30 +2092,30 @@ HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart) CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); /* Abort the USART DMA Rx channel : use non blocking DMA Abort API (callback) */ - if(husart->hdmarx != NULL) + if (husart->hdmarx != NULL) { /* USART Rx DMA Abort callback has already been initialised : will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */ /* Abort DMA RX */ - if(HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK) + if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK) { husart->hdmarx->XferAbortCallback = NULL; - abortcplt = 1; + abortcplt = 1U; } else { - abortcplt = 0; + abortcplt = 0U; } } } /* if no DMA abort complete callback execution is required => call user Abort Complete callback */ - if (abortcplt == 1) + if (abortcplt == 1U) { /* Reset Tx and Rx transfer counters */ - husart->TxXferCount = 0; - husart->RxXferCount = 0; + husart->TxXferCount = 0U; + husart->RxXferCount = 0U; /* Reset errorCode */ husart->ErrorCode = HAL_USART_ERROR_NONE; @@ -1316,11 +2123,28 @@ HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart) /* Clear the Error flags in the ICR register */ __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF); +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (husart->FifoMode == USART_FIFOMODE_ENABLE) + { + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR1_FIFOEN */ + + /* Discard the received data */ + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); + /* Restore husart->State to Ready */ husart->State = HAL_USART_STATE_READY; /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Complete Callback */ + husart->AbortCpltCallback(husart); +#else + /* Call legacy weak Abort Complete Callback */ HAL_USART_AbortCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } return HAL_OK; @@ -1335,36 +2159,50 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) { uint32_t isrflags = READ_REG(husart->Instance->ISR); uint32_t cr1its = READ_REG(husart->Instance->CR1); - uint32_t cr3its; + uint32_t cr3its = READ_REG(husart->Instance->CR3); + uint32_t errorflags; + uint32_t errorcode; /* If no error occurs */ +#if defined(USART_CR2_SLVEN) + errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE | USART_ISR_UDR)); +#else errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); - if (errorflags == RESET) +#endif /* USART_CR2_SLVEN */ + if (errorflags == 0U) { /* USART in mode Receiver ---------------------------------------------------*/ - if(((isrflags & USART_ISR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) +#if defined(USART_CR1_FIFOEN) + if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) + && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) + || ((cr3its & USART_CR3_RXFTIE) != 0U))) +#else + if (((isrflags & USART_ISR_RXNE) != 0U) + && ((cr1its & USART_CR1_RXNEIE) != 0U)) +#endif /* USART_CR1_FIFOEN */ { - if(husart->State == HAL_USART_STATE_BUSY_RX) + if (husart->RxISR != NULL) { - USART_Receive_IT(husart); - } - else - { - USART_TransmitReceive_IT(husart); + husart->RxISR(husart); } return; } } /* If some errors occur */ - cr3its = READ_REG(husart->Instance->CR3); - if( (errorflags != RESET) - && ( ((cr3its & USART_CR3_EIE) != RESET) - || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)) ) +#if defined(USART_CR1_FIFOEN) + if ((errorflags != 0U) + && (((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U) + || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != 0U))) +#else + if ((errorflags != 0U) + && (((cr3its & USART_CR3_EIE) != 0U) + || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != 0U))) +#endif /* USART_CR1_FIFOEN */ { /* USART parity error interrupt occurred -------------------------------------*/ - if(((isrflags & USART_ISR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U)) { __HAL_USART_CLEAR_IT(husart, USART_CLEAR_PEF); @@ -1372,7 +2210,7 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) } /* USART frame error interrupt occurred --------------------------------------*/ - if(((isrflags & USART_ISR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U)) { __HAL_USART_CLEAR_IT(husart, USART_CLEAR_FEF); @@ -1380,7 +2218,7 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) } /* USART noise error interrupt occurred --------------------------------------*/ - if(((isrflags & USART_ISR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + if (((isrflags & USART_ISR_NE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U)) { __HAL_USART_CLEAR_IT(husart, USART_CLEAR_NEF); @@ -1388,34 +2226,63 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) } /* USART Over-Run interrupt occurred -----------------------------------------*/ - if(((isrflags & USART_ISR_ORE) != RESET) && - (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET))) +#if defined(USART_CR1_FIFOEN) + if (((isrflags & USART_ISR_ORE) != 0U) + && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) || + ((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U))) +#else + if (((isrflags & USART_ISR_ORE) != 0U) + && (((cr1its & USART_CR1_RXNEIE) != 0U) || + ((cr3its & USART_CR3_EIE) != 0U))) +#endif /* USART_CR1_FIFOEN */ { __HAL_USART_CLEAR_IT(husart, USART_CLEAR_OREF); husart->ErrorCode |= HAL_USART_ERROR_ORE; } +#if defined(USART_CR2_SLVEN) + /* USART SPI slave underrun error interrupt occurred -------------------------*/ + if (((isrflags & USART_ISR_UDR) != 0U) && ((cr3its & USART_CR3_EIE) != 0U)) + { + /* Ignore SPI slave underrun errors when reception is going on */ + if (husart->State == HAL_USART_STATE_BUSY_RX) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + return; + } + else + { + __HAL_USART_CLEAR_UDRFLAG(husart); + husart->ErrorCode |= HAL_USART_ERROR_UDR; + } + } +#endif /* USART_CR2_SLVEN */ + /* Call USART Error Call back function if need be --------------------------*/ - if(husart->ErrorCode != HAL_USART_ERROR_NONE) + if (husart->ErrorCode != HAL_USART_ERROR_NONE) { /* USART in mode Receiver ---------------------------------------------------*/ - if(((isrflags & USART_ISR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) +#if defined(USART_CR1_FIFOEN) + if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U) + && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) + || ((cr3its & USART_CR3_RXFTIE) != 0U))) +#else + if (((isrflags & USART_ISR_RXNE) != 0U) + && ((cr1its & USART_CR1_RXNEIE) != 0U)) +#endif /* USART_CR1_FIFOEN */ { - if(husart->State == HAL_USART_STATE_BUSY_RX) + if (husart->RxISR != NULL) { - USART_Receive_IT(husart); - } - else - { - USART_TransmitReceive_IT(husart); + husart->RxISR(husart); } } /* If Overrun error occurs, or if any error occurs in DMA mode reception, consider error as blocking */ - if (((husart->ErrorCode & HAL_USART_ERROR_ORE) != RESET) || - (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))) + errorcode = husart->ErrorCode & HAL_USART_ERROR_ORE; + if ((HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) || + (errorcode != 0U)) { /* Blocking error : transfer is aborted Set the USART state ready to be able to start again the process, @@ -1428,25 +2295,25 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR | USART_CR3_DMAR); /* Abort the USART DMA Tx channel */ - if(husart->hdmatx != NULL) + if (husart->hdmatx != NULL) { /* Set the USART Tx DMA Abort callback to NULL : no callback executed at end of DMA abort procedure */ husart->hdmatx->XferAbortCallback = NULL; /* Abort DMA TX */ - HAL_DMA_Abort_IT(husart->hdmatx); + (void)HAL_DMA_Abort_IT(husart->hdmatx); } /* Abort the USART DMA Rx channel */ - if(husart->hdmarx != NULL) + if (husart->hdmarx != NULL) { /* Set the USART Rx DMA Abort callback : will lead to call HAL_USART_ErrorCallback() at end of DMA abort procedure */ husart->hdmarx->XferAbortCallback = USART_DMAAbortOnError; /* Abort DMA RX */ - if(HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK) + if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK) { /* Call Directly husart->hdmarx->XferAbortCallback function in case of error */ husart->hdmarx->XferAbortCallback(husart->hdmarx); @@ -1455,20 +2322,38 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) else { /* Call user error callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } } else { /* Call user error callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } } else { /* Non Blocking error : transfer could go on. Error is notified to user through user error callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ husart->ErrorCode = HAL_USART_ERROR_NONE; } } @@ -1478,32 +2363,61 @@ void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) /* USART in mode Transmitter ------------------------------------------------*/ - if(((isrflags & USART_ISR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) +#if defined(USART_CR1_FIFOEN) + if (((isrflags & USART_ISR_TXE_TXFNF) != 0U) + && (((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U) + || ((cr3its & USART_CR3_TXFTIE) != 0U))) +#else + if (((isrflags & USART_ISR_TXE) != 0U) + && ((cr1its & USART_CR1_TXEIE) != 0U)) +#endif /* USART_CR1_FIFOEN */ { - if(husart->State == HAL_USART_STATE_BUSY_TX) + if (husart->TxISR != NULL) { - USART_Transmit_IT(husart); - } - else - { - USART_TransmitReceive_IT(husart); + husart->TxISR(husart); } return; } /* USART in mode Transmitter (transmission end) -----------------------------*/ - if(((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + if (((isrflags & USART_ISR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U)) { USART_EndTransmit_IT(husart); return; } +#if defined(USART_CR1_FIFOEN) + /* USART TX Fifo Empty occurred ----------------------------------------------*/ + if (((isrflags & USART_ISR_TXFE) != 0U) && ((cr1its & USART_CR1_TXFEIE) != 0U)) + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Fifo Empty Callback */ + husart->TxFifoEmptyCallback(husart); +#else + /* Call legacy weak Tx Fifo Empty Callback */ + HAL_USARTEx_TxFifoEmptyCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + return; + } + + /* USART RX Fifo Full occurred ----------------------------------------------*/ + if (((isrflags & USART_ISR_RXFF) != 0U) && ((cr1its & USART_CR1_RXFFIE) != 0U)) + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Fifo Full Callback */ + husart->RxFifoFullCallback(husart); +#else + /* Call legacy weak Rx Fifo Full Callback */ + HAL_USARTEx_RxFifoFullCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + return; + } +#endif /* USART_CR1_FIFOEN */ } -#endif /** * @brief Tx Transfer completed callback. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart) @@ -1518,7 +2432,7 @@ __weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart) /** * @brief Tx Half Transfer completed callback. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart) @@ -1533,7 +2447,7 @@ __weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart) /** * @brief Rx Transfer completed callback. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart) @@ -1548,7 +2462,7 @@ __weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart) /** * @brief Rx Half Transfer completed callback. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart) @@ -1563,7 +2477,7 @@ __weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart) /** * @brief Tx/Rx Transfers completed callback for the non-blocking process. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart) @@ -1578,7 +2492,7 @@ __weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart) /** * @brief USART error callback. - * @param husart: USART handle. + * @param husart USART handle. * @retval None */ __weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart) @@ -1596,7 +2510,7 @@ __weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart) * @param husart USART handle. * @retval None */ -__weak void HAL_USART_AbortCpltCallback (USART_HandleTypeDef *husart) +__weak void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart) { /* Prevent unused argument(s) compilation warning */ UNUSED(husart); @@ -1611,8 +2525,8 @@ __weak void HAL_USART_AbortCpltCallback (USART_HandleTypeDef *husart) */ /** @defgroup USART_Exported_Functions_Group4 Peripheral State and Error functions - * @brief USART Peripheral State and Error functions - * + * @brief USART Peripheral State and Error functions + * @verbatim ============================================================================== ##### Peripheral State and Error functions ##### @@ -1629,7 +2543,7 @@ __weak void HAL_USART_AbortCpltCallback (USART_HandleTypeDef *husart) /** * @brief Return the USART handle state. - * @param husart : pointer to a USART_HandleTypeDef structure that contains + * @param husart pointer to a USART_HandleTypeDef structure that contains * the configuration information for the specified USART. * @retval USART handle state */ @@ -1640,7 +2554,7 @@ HAL_USART_StateTypeDef HAL_USART_GetState(USART_HandleTypeDef *husart) /** * @brief Return the USART error code. - * @param husart : pointer to a USART_HandleTypeDef structure that contains + * @param husart pointer to a USART_HandleTypeDef structure that contains * the configuration information for the specified USART. * @retval USART handle Error Code */ @@ -1648,6 +2562,7 @@ uint32_t HAL_USART_GetError(USART_HandleTypeDef *husart) { return husart->ErrorCode; } +#endif /** * @} @@ -1658,10 +2573,33 @@ uint32_t HAL_USART_GetError(USART_HandleTypeDef *husart) */ /** @defgroup USART_Private_Functions USART Private Functions - * @{ - */ + * @{ + */ #if 0 +/** + * @brief Initialize the callbacks to their default values. + * @param husart USART handle. + * @retval none + */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart) +{ + /* Init the USART Callback settings */ + husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */ + husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */ + husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */ + husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ +#if defined(USART_CR1_FIFOEN) + husart->RxFifoFullCallback = HAL_USARTEx_RxFifoFullCallback; /* Legacy weak RxFifoFullCallback */ + husart->TxFifoEmptyCallback = HAL_USARTEx_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */ +#endif /* USART_CR1_FIFOEN */ +} +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + /** * @brief End ongoing transfer on USART peripheral (following error detection or Transfer completion). * @param husart USART handle. @@ -1669,30 +2607,36 @@ uint32_t HAL_USART_GetError(USART_HandleTypeDef *husart) */ static void USART_EndTransfer(USART_HandleTypeDef *husart) { - /* Disable TXEIE and TCIE interrupts */ - /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ - CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | USART_CR1_PEIE)); +#if defined(USART_CR1_FIFOEN) + /* Disable TXEIE, TCIE, RXNE, RXFT, TXFT, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | + USART_CR1_TCIE)); + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE | USART_CR3_TXFTIE)); +#else + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); +#endif /* USART_CR1_FIFOEN */ /* At end of process, restore husart->State to Ready */ husart->State = HAL_USART_STATE_READY; } /** - * @brief DMA USART transmit process complete callback. + * @brief DMA USART transmit process complete callback. * @param hdma DMA handle. * @retval None */ static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef*)(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); /* DMA Normal mode */ - if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + if (HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC)) { - husart->TxXferCount = 0; + husart->TxXferCount = 0U; - if(husart->State == HAL_USART_STATE_BUSY_TX) + if (husart->State == HAL_USART_STATE_BUSY_TX) { /* Disable the DMA transfer for transmit request by resetting the DMAT bit in the USART CR3 register */ @@ -1705,38 +2649,50 @@ static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma) /* DMA Circular mode */ else { - if(husart->State == HAL_USART_STATE_BUSY_TX) + if (husart->State == HAL_USART_STATE_BUSY_TX) { - HAL_USART_TxCpltCallback(husart); - } - } +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Complete Callback */ + husart->TxCpltCallback(husart); +#else + /* Call legacy weak Tx Complete Callback */ + HAL_USART_TxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + } } /** - * @brief DMA USART transmit process half complete callback. + * @brief DMA USART transmit process half complete callback. * @param hdma DMA handle. * @retval None */ static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef*)(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Half Complete Callback */ + husart->TxHalfCpltCallback(husart); +#else + /* Call legacy weak Tx Half Complete Callback */ HAL_USART_TxHalfCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } /** - * @brief DMA USART receive process complete callback. + * @brief DMA USART receive process complete callback. * @param hdma DMA handle. * @retval None */ static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef*)(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); /* DMA Normal mode */ - if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + if (HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC)) { - husart->RxXferCount = 0; + husart->RxXferCount = 0U; /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); @@ -1749,62 +2705,97 @@ static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) clock to the slave device */ CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); - if(husart->State == HAL_USART_STATE_BUSY_RX) + if (husart->State == HAL_USART_STATE_BUSY_RX) { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } /* The USART state is HAL_USART_STATE_BUSY_TX_RX */ else { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } - husart->State= HAL_USART_STATE_READY; + husart->State = HAL_USART_STATE_READY; } /* DMA circular mode */ else { - if(husart->State == HAL_USART_STATE_BUSY_RX) + if (husart->State == HAL_USART_STATE_BUSY_RX) { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } /* The USART state is HAL_USART_STATE_BUSY_TX_RX */ else { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } } - } /** - * @brief DMA USART receive process half complete callback. + * @brief DMA USART receive process half complete callback. * @param hdma DMA handle. * @retval None */ static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef*)(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Half Complete Callback */ + husart->RxHalfCpltCallback(husart); +#else + /* Call legacy weak Rx Half Complete Callback */ HAL_USART_RxHalfCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } /** * @brief DMA USART communication error callback. - * @param hdma: DMA handle. + * @param hdma DMA handle. * @retval None */ static void USART_DMAError(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef*)(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); - husart->RxXferCount = 0; - husart->TxXferCount = 0; + husart->RxXferCount = 0U; + husart->TxXferCount = 0U; USART_EndTransfer(husart); husart->ErrorCode |= HAL_USART_ERROR_DMA; - husart->State= HAL_USART_STATE_READY; + husart->State = HAL_USART_STATE_READY; +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } /** @@ -1815,11 +2806,17 @@ static void USART_DMAError(DMA_HandleTypeDef *hdma) */ static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef*)(hdma->Parent); - husart->RxXferCount = 0; - husart->TxXferCount = 0; + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); + husart->RxXferCount = 0U; + husart->TxXferCount = 0U; +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } /** @@ -1832,22 +2829,22 @@ static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma) */ static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef* )(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); husart->hdmatx->XferAbortCallback = NULL; /* Check if an Abort process is still ongoing */ - if(husart->hdmarx != NULL) + if (husart->hdmarx != NULL) { - if(husart->hdmarx->XferAbortCallback != NULL) + if (husart->hdmarx->XferAbortCallback != NULL) { return; } } /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ - husart->TxXferCount = 0; - husart->RxXferCount = 0; + husart->TxXferCount = 0U; + husart->RxXferCount = 0U; /* Reset errorCode */ husart->ErrorCode = HAL_USART_ERROR_NONE; @@ -1856,10 +2853,17 @@ static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) __HAL_USART_CLEAR_FLAG(husart, USART_CLEAR_OREF | USART_CLEAR_NEF | USART_CLEAR_PEF | USART_CLEAR_FEF); /* Restore husart->State to Ready */ - husart->State = HAL_USART_STATE_READY; + husart->State = HAL_USART_STATE_READY; /* Call user Abort complete callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Complete Callback */ + husart->AbortCpltCallback(husart); +#else + /* Call legacy weak Abort Complete Callback */ HAL_USART_AbortCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } @@ -1873,22 +2877,22 @@ static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) */ static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) { - USART_HandleTypeDef* husart = (USART_HandleTypeDef* )(hdma->Parent); + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)(hdma->Parent); husart->hdmarx->XferAbortCallback = NULL; /* Check if an Abort process is still ongoing */ - if(husart->hdmatx != NULL) + if (husart->hdmatx != NULL) { - if(husart->hdmatx->XferAbortCallback != NULL) + if (husart->hdmatx->XferAbortCallback != NULL) { return; } } /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ - husart->TxXferCount = 0; - husart->RxXferCount = 0; + husart->TxXferCount = 0U; + husart->RxXferCount = 0U; /* Reset errorCode */ husart->ErrorCode = HAL_USART_ERROR_NONE; @@ -1900,9 +2904,14 @@ static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) husart->State = HAL_USART_STATE_READY; /* Call user Abort complete callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Complete Callback */ + husart->AbortCpltCallback(husart); +#else + /* Call legacy weak Abort Complete Callback */ HAL_USART_AbortCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ } -#endif /** @@ -1914,21 +2923,18 @@ static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) * @param Timeout timeout duration. * @retval HAL status */ -static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) +static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout) { /* Wait until flag is set */ - while((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status) + while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status) { /* Check for the Timeout */ - if(Timeout != HAL_MAX_DELAY) + if (Timeout != HAL_MAX_DELAY) { - if((Timeout == 0) || ((HAL_GetTick()-Tickstart) > Timeout)) + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) { - /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ - CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); - CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); - - husart->State= HAL_USART_STATE_READY; + husart->State = HAL_USART_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(husart); @@ -1939,19 +2945,21 @@ static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husar } return HAL_OK; } +#endif /** * @brief Configure the USART peripheral. - * @param husart: USART handle. + * @param husart USART handle. * @retval HAL status */ static HAL_StatusTypeDef USART_SetConfig(USART_HandleTypeDef *husart) { - uint32_t tmpreg = 0x0; - USART_ClockSourceTypeDef clocksource = USART_CLOCKSOURCE_UNDEFINED; + uint32_t tmpreg; + USART_ClockSourceTypeDef clocksource; HAL_StatusTypeDef ret = HAL_OK; - uint16_t brrtemp = 0x0000; - uint16_t usartdiv = 0x0000; + uint16_t brrtemp; + uint32_t usartdiv = 0x00000000; + uint32_t pclk; /* Check the parameters */ assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity)); @@ -1962,95 +2970,143 @@ static HAL_StatusTypeDef USART_SetConfig(USART_HandleTypeDef *husart) assert_param(IS_USART_STOPBITS(husart->Init.StopBits)); assert_param(IS_USART_PARITY(husart->Init.Parity)); assert_param(IS_USART_MODE(husart->Init.Mode)); - +#if defined(USART_PRESC_PRESCALER) + assert_param(IS_USART_PRESCALER(husart->Init.ClockPrescaler)); +#endif /* USART_PRESC_PRESCALER */ /*-------------------------- USART CR1 Configuration -----------------------*/ - /* Clear M, PCE, PS, TE and RE bits and configure - * the USART Word Length, Parity and Mode: - * set the M bits according to husart->Init.WordLength value - * set PCE and PS bits according to husart->Init.Parity value - * set TE and RE bits according to husart->Init.Mode value - * force OVER8 to 1 to allow to reach the maximum speed (Fclock/8) */ + /* Clear M, PCE, PS, TE and RE bits and configure + * the USART Word Length, Parity and Mode: + * set the M bits according to husart->Init.WordLength value + * set PCE and PS bits according to husart->Init.Parity value + * set TE and RE bits according to husart->Init.Mode value + * force OVER8 to 1 to allow to reach the maximum speed (Fclock/8) */ tmpreg = (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode | USART_CR1_OVER8; MODIFY_REG(husart->Instance->CR1, USART_CR1_FIELDS, tmpreg); /*---------------------------- USART CR2 Configuration ---------------------*/ - /* Clear and configure the USART Clock, CPOL, CPHA, LBCL and STOP bits: + /* Clear and configure the USART Clock, CPOL, CPHA, LBCL STOP and SLVEN bits: * set CPOL bit according to husart->Init.CLKPolarity value * set CPHA bit according to husart->Init.CLKPhase value - * set LBCL bit according to husart->Init.CLKLastBit value + * set LBCL bit according to husart->Init.CLKLastBit value (used in SPI master mode only) * set STOP[13:12] bits according to husart->Init.StopBits value */ tmpreg = (uint32_t)(USART_CLOCK_ENABLE); + tmpreg |= (uint32_t)husart->Init.CLKLastBit; tmpreg |= ((uint32_t)husart->Init.CLKPolarity | (uint32_t)husart->Init.CLKPhase); - tmpreg |= ((uint32_t)husart->Init.CLKLastBit | (uint32_t)husart->Init.StopBits); + tmpreg |= (uint32_t)husart->Init.StopBits; MODIFY_REG(husart->Instance->CR2, USART_CR2_FIELDS, tmpreg); - /*-------------------------- USART CR3 Configuration -----------------------*/ - /* no CR3 register configuration */ +#if defined(USART_PRESC_PRESCALER) + /*-------------------------- USART PRESC Configuration -----------------------*/ + /* Configure + * - USART Clock Prescaler : set PRESCALER according to husart->Init.ClockPrescaler value */ + MODIFY_REG(husart->Instance->PRESC, USART_PRESC_PRESCALER, husart->Init.ClockPrescaler); +#endif /* USART_PRESC_PRESCALER */ /*-------------------------- USART BRR Configuration -----------------------*/ /* BRR is filled-up according to OVER8 bit setting which is forced to 1 */ USART_GETCLOCKSOURCE(husart, clocksource); + switch (clocksource) { case USART_CLOCKSOURCE_PCLK1: - usartdiv = (uint16_t)(((2*HAL_RCC_GetPCLK1Freq()) + (husart->Init.BaudRate/2)) / husart->Init.BaudRate); + pclk = HAL_RCC_GetPCLK1Freq(); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ break; case USART_CLOCKSOURCE_PCLK2: - usartdiv = (uint16_t)(((2*HAL_RCC_GetPCLK2Freq()) + (husart->Init.BaudRate/2)) / husart->Init.BaudRate); + pclk = HAL_RCC_GetPCLK2Freq(); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ break; case USART_CLOCKSOURCE_HSI: - usartdiv = (uint16_t)(((2*HSI_VALUE) + (husart->Init.BaudRate/2)) / husart->Init.BaudRate); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(HSI_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(HSI_VALUE, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ break; case USART_CLOCKSOURCE_SYSCLK: - usartdiv = (uint16_t)(((2*HAL_RCC_GetSysClockFreq()) + (husart->Init.BaudRate/2)) / husart->Init.BaudRate); + pclk = HAL_RCC_GetSysClockFreq(); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(pclk, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ break; case USART_CLOCKSOURCE_LSE: - usartdiv = (uint16_t)(((2*LSE_VALUE) + (husart->Init.BaudRate/2)) / husart->Init.BaudRate); +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(LSE_VALUE, husart->Init.BaudRate, husart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(USART_DIV_SAMPLING8(LSE_VALUE, husart->Init.BaudRate)); +#endif /* USART_PRESC_PRESCALER */ break; - case USART_CLOCKSOURCE_UNDEFINED: default: ret = HAL_ERROR; break; } - brrtemp = usartdiv & 0xFFF0; - brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000F) >> 1U); - husart->Instance->BRR = brrtemp; + /* USARTDIV must be greater than or equal to 0d16 and smaller than or equal to ffff */ + if ((usartdiv >= USART_BRR_MIN) && (usartdiv <= USART_BRR_MAX)) + { + brrtemp = (uint16_t)(usartdiv & 0xFFF0U); + brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); + husart->Instance->BRR = brrtemp; + } + else + { + ret = HAL_ERROR; + } + +#if defined(USART_CR1_FIFOEN) + /* Initialize the number of data to process during RX/TX ISR execution */ + husart->NbTxDataToProcess = 1U; + husart->NbRxDataToProcess = 1U; +#endif /* USART_CR1_FIFOEN */ + + /* Clear ISR function pointers */ + husart->RxISR = NULL; + husart->TxISR = NULL; return ret; } /** * @brief Check the USART Idle State. - * @param husart: USART handle. + * @param husart USART handle. * @retval HAL status */ static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart) { - uint32_t tickstart = 0; + uint32_t tickstart; /* Initialize the USART ErrorCode */ husart->ErrorCode = HAL_USART_ERROR_NONE; - /* Init tickstart for timeout managment*/ + /* Init tickstart for timeout management */ tickstart = HAL_GetTick(); /* Check if the Transmitter is enabled */ - if((husart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) + if ((husart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) { /* Wait until TEACK flag is set */ - if(USART_WaitOnFlagUntilTimeout(husart, USART_ISR_TEACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK) + if (USART_WaitOnFlagUntilTimeout(husart, USART_ISR_TEACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK) { /* Timeout occurred */ return HAL_TIMEOUT; } } /* Check if the Receiver is enabled */ - if((husart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) + if ((husart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) { /* Wait until REACK flag is set */ - if(USART_WaitOnFlagUntilTimeout(husart, USART_ISR_REACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK) + if (USART_WaitOnFlagUntilTimeout(husart, USART_ISR_REACK, RESET, tickstart, USART_TEACK_REACK_TIMEOUT) != HAL_OK) { /* Timeout occurred */ return HAL_TIMEOUT; @@ -2058,7 +3114,7 @@ static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart) } /* Initialize the USART state*/ - husart->State= HAL_USART_STATE_READY; + husart->State = HAL_USART_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(husart); @@ -2066,65 +3122,180 @@ static HAL_StatusTypeDef USART_CheckIdleState(USART_HandleTypeDef *husart) return HAL_OK; } +/** + * @brief Simplex send an amount of data in non-blocking mode. + * @note Function called under interruption only, once + * interruptions have been enabled by HAL_USART_Transmit_IT(). + * @note The USART errors are not managed to avoid the overrun error. + * @note ISR function executed when FIFO mode is disabled and when the + * data word length is less than 9 bits long. + * @param husart USART handle. + * @retval None + */ +static void USART_TxISR_8BIT(USART_HandleTypeDef *husart) +{ + const HAL_USART_StateTypeDef state = husart->State; + + /* Check that a Tx process is ongoing */ + if ((state == HAL_USART_STATE_BUSY_TX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) + { + if (husart->TxXferCount == 0U) + { + /* Disable the USART Transmit data register empty interrupt */ + __HAL_USART_DISABLE_IT(husart, USART_IT_TXE); + + /* Enable the USART Transmit Complete Interrupt */ + __HAL_USART_ENABLE_IT(husart, USART_IT_TC); + } + else + { + husart->Instance->TDR = (uint8_t)(*husart->pTxBuffPtr & (uint8_t)0xFF); + husart->pTxBuffPtr++; + husart->TxXferCount--; + } + } +} + #if 0 /** * @brief Simplex send an amount of data in non-blocking mode. * @note Function called under interruption only, once * interruptions have been enabled by HAL_USART_Transmit_IT(). * @note The USART errors are not managed to avoid the overrun error. + * @note ISR function executed when FIFO mode is disabled and when the + * data word length is 9 bits long. * @param husart USART handle. - * @retval HAL status + * @retval None */ -static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart) +static void USART_TxISR_16BIT(USART_HandleTypeDef *husart) { - uint16_t* tmp; + const HAL_USART_StateTypeDef state = husart->State; + uint16_t *tmp; - /* Check that a Tx process is ongoing */ - if(husart->State == HAL_USART_STATE_BUSY_TX) + if ((state == HAL_USART_STATE_BUSY_TX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) { - - if(husart->TxXferCount == 0) + if (husart->TxXferCount == 0U) { /* Disable the USART Transmit data register empty interrupt */ __HAL_USART_DISABLE_IT(husart, USART_IT_TXE); /* Enable the USART Transmit Complete Interrupt */ __HAL_USART_ENABLE_IT(husart, USART_IT_TC); - - return HAL_OK; } else { - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + tmp = (uint16_t *) husart->pTxBuffPtr; + husart->Instance->TDR = (uint16_t)(*tmp & 0x01FFU); + husart->pTxBuffPtr += 2U; + husart->TxXferCount--; + } + } +} +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Simplex send an amount of data in non-blocking mode. + * @note Function called under interruption only, once + * interruptions have been enabled by HAL_USART_Transmit_IT(). + * @note The USART errors are not managed to avoid the overrun error. + * @note ISR function executed when FIFO mode is enabled and when the + * data word length is less than 9 bits long. + * @param husart USART handle. + * @retval None + */ +static void USART_TxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart) +{ + const HAL_USART_StateTypeDef state = husart->State; + uint16_t nb_tx_data; + + /* Check that a Tx process is ongoing */ + if ((state == HAL_USART_STATE_BUSY_TX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) + { + for (nb_tx_data = husart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--) + { + if (husart->TxXferCount == 0U) { - tmp = (uint16_t*) husart->pTxBuffPtr; - husart->Instance->TDR = (*tmp & (uint16_t)0x01FF); - husart->pTxBuffPtr += 2; + /* Disable the TX FIFO threshold interrupt */ + __HAL_USART_DISABLE_IT(husart, USART_IT_TXFT); + + /* Enable the USART Transmit Complete Interrupt */ + __HAL_USART_ENABLE_IT(husart, USART_IT_TC); + + break; /* force exit loop */ + } + else if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXFNF) == SET) + { + husart->Instance->TDR = (uint8_t)(*husart->pTxBuffPtr & (uint8_t)0xFF); + husart->pTxBuffPtr++; + husart->TxXferCount--; } else { - husart->Instance->TDR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0xFF); + /* Nothing to do */ } - - husart->TxXferCount--; - - return HAL_OK; } } - else - { - return HAL_BUSY; - } } +/** + * @brief Simplex send an amount of data in non-blocking mode. + * @note Function called under interruption only, once + * interruptions have been enabled by HAL_USART_Transmit_IT(). + * @note The USART errors are not managed to avoid the overrun error. + * @note ISR function executed when FIFO mode is enabled and when the + * data word length is 9 bits long. + * @param husart USART handle. + * @retval None + */ +static void USART_TxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart) +{ + const HAL_USART_StateTypeDef state = husart->State; + uint16_t *tmp; + uint16_t nb_tx_data; + + /* Check that a Tx process is ongoing */ + if ((state == HAL_USART_STATE_BUSY_TX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) + { + for (nb_tx_data = husart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--) + { + if (husart->TxXferCount == 0U) + { + /* Disable the TX FIFO threshold interrupt */ + __HAL_USART_DISABLE_IT(husart, USART_IT_TXFT); + + /* Enable the USART Transmit Complete Interrupt */ + __HAL_USART_ENABLE_IT(husart, USART_IT_TC); + + break; /* force exit loop */ + } + else if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXFNF) == SET) + { + tmp = (uint16_t *) husart->pTxBuffPtr; + husart->Instance->TDR = (uint16_t)(*tmp & 0x01FFU); + husart->pTxBuffPtr += 2U; + husart->TxXferCount--; + } + else + { + /* Nothing to do */ + } + } + } +} +#endif /* USART_CR1_FIFOEN */ /** * @brief Wraps up transmission in non-blocking mode. * @param husart Pointer to a USART_HandleTypeDef structure that contains * the configuration information for the specified USART module. - * @retval HAL status + * @retval None */ -static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart) +static void USART_EndTransmit_IT(USART_HandleTypeDef *husart) { /* Disable the USART Transmit Complete Interrupt */ __HAL_USART_DISABLE_IT(husart, USART_IT_TC); @@ -2132,12 +3303,43 @@ static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart) /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ __HAL_USART_DISABLE_IT(husart, USART_IT_ERR); - /* Tx process is ended, restore husart->State to Ready */ - husart->State = HAL_USART_STATE_READY; + /* Clear TxISR function pointer */ + husart->TxISR = NULL; - HAL_USART_TxCpltCallback(husart); + if (husart->State == HAL_USART_STATE_BUSY_TX) + { + /* Clear overrun flag and discard the received data */ + __HAL_USART_CLEAR_OREFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); - return HAL_OK; + /* Tx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Complete Callback */ + husart->TxCpltCallback(husart); +#else + /* Call legacy weak Tx Complete Callback */ + HAL_USART_TxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else if (husart->RxXferCount == 0U) + { + /* TxRx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } } @@ -2145,136 +3347,519 @@ static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart) * @brief Simplex receive an amount of data in non-blocking mode. * @note Function called under interruption only, once * interruptions have been enabled by HAL_USART_Receive_IT(). + * @note ISR function executed when FIFO mode is disabled and when the + * data word length is less than 9 bits long. * @param husart USART handle - * @retval HAL status + * @retval None */ -static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart) +static void USART_RxISR_8BIT(USART_HandleTypeDef *husart) { - uint16_t* tmp; + const HAL_USART_StateTypeDef state = husart->State; + uint16_t txdatacount; uint16_t uhMask = husart->Mask; +#if defined(USART_CR1_FIFOEN) + uint32_t txftie; +#endif /* USART_CR1_FIFOEN */ - if(husart->State == HAL_USART_STATE_BUSY_RX) + if ((state == HAL_USART_STATE_BUSY_RX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) { + *husart->pRxBuffPtr = (uint8_t)(husart->Instance->RDR & (uint8_t)uhMask); + husart->pRxBuffPtr++; + husart->RxXferCount--; - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) - { - tmp = (uint16_t*) husart->pRxBuffPtr; - *tmp = (uint16_t)(husart->Instance->RDR & uhMask); - husart->pRxBuffPtr += 2; - } - else - { - *husart->pRxBuffPtr++ = (uint8_t)(husart->Instance->RDR & (uint8_t)uhMask); - } - /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ - husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); - - if(--husart->RxXferCount == 0) + if (husart->RxXferCount == 0U) { /* Disable the USART Parity Error Interrupt and RXNE interrupt*/ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif /* USART_CR1_FIFOEN */ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); - /* Rx process is completed, restore husart->State to Ready */ - husart->State = HAL_USART_STATE_READY; + /* Clear RxISR function pointer */ + husart->RxISR = NULL; - HAL_USART_RxCpltCallback(husart); +#if defined(USART_CR1_FIFOEN) + /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */ + txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE); +#else + /* txdatacount is a temporary variable for MISRAC2012-Rule-13.5 */ +#endif /* USART_CR1_FIFOEN */ + txdatacount = husart->TxXferCount; - return HAL_OK; + if (state == HAL_USART_STATE_BUSY_RX) + { +#if defined(USART_CR2_SLVEN) + /* Clear SPI slave underrun flag and discard transmit data */ + if (husart->SlaveMode == USART_SLAVEMODE_ENABLE) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR2_SLVEN */ + + /* Rx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } +#if defined(USART_CR1_FIFOEN) + else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) && + (txftie != USART_CR3_TXFTIE) && + (txdatacount == 0U)) +#else + else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) && + (txdatacount == 0U)) +#endif /* USART_CR1_FIFOEN */ + { + /* TxRx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } +#if defined(USART_CR2_SLVEN) + else if ((state == HAL_USART_STATE_BUSY_RX) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#else + else if (state == HAL_USART_STATE_BUSY_RX) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + else + { + /* Nothing to do */ } - - return HAL_OK; - } - else - { - return HAL_BUSY; } } /** - * @brief Full-Duplex Send receive an amount of data in full-duplex mode (non-blocking). + * @brief Simplex receive an amount of data in non-blocking mode. * @note Function called under interruption only, once - * interruptions have been enabled by HAL_USART_TransmitReceive_IT(). - * @param husart: USART handle. - * @retval HAL status + * interruptions have been enabled by HAL_USART_Receive_IT(). + * @note ISR function executed when FIFO mode is disabled and when the + * data word length is 9 bits long. + * @param husart USART handle + * @retval None */ -static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart) +static void USART_RxISR_16BIT(USART_HandleTypeDef *husart) { - uint16_t* tmp; + const HAL_USART_StateTypeDef state = husart->State; + uint16_t txdatacount; + uint16_t *tmp; uint16_t uhMask = husart->Mask; +#if defined(USART_CR1_FIFOEN) + uint32_t txftie; +#endif /* USART_CR1_FIFOEN */ - if(husart->State == HAL_USART_STATE_BUSY_TX_RX) + if ((state == HAL_USART_STATE_BUSY_RX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) { + tmp = (uint16_t *) husart->pRxBuffPtr; + *tmp = (uint16_t)(husart->Instance->RDR & uhMask); + husart->pRxBuffPtr += 2U; + husart->RxXferCount--; - if(husart->TxXferCount != 0x00) - { - if(__HAL_USART_GET_FLAG(husart, USART_FLAG_TXE) != RESET) - { - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) - { - tmp = (uint16_t*) husart->pTxBuffPtr; - husart->Instance->TDR = (uint16_t)(*tmp & uhMask); - husart->pTxBuffPtr += 2; - } - else - { - husart->Instance->TDR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)uhMask); - } - husart->TxXferCount--; - - /* Check the latest data transmitted */ - if(husart->TxXferCount == 0) - { - __HAL_USART_DISABLE_IT(husart, USART_IT_TXE); - } - } - } - - if(husart->RxXferCount != 0x00) - { - if(__HAL_USART_GET_FLAG(husart, USART_FLAG_RXNE) != RESET) - { - if((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) - { - tmp = (uint16_t*) husart->pRxBuffPtr; - *tmp = (uint16_t)(husart->Instance->RDR & uhMask); - husart->pRxBuffPtr += 2; - } - else - { - *husart->pRxBuffPtr++ = (uint8_t)(husart->Instance->RDR & (uint8_t)uhMask); - } - husart->RxXferCount--; - } - } - - /* Check the latest data received */ - if(husart->RxXferCount == 0) + if (husart->RxXferCount == 0U) { /* Disable the USART Parity Error Interrupt and RXNE interrupt*/ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif /* USART_CR1_FIFOEN */ /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); - /* Rx process is completed, restore husart->State to Ready */ - husart->State = HAL_USART_STATE_READY; + /* Clear RxISR function pointer */ + husart->RxISR = NULL; - HAL_USART_TxRxCpltCallback(husart); +#if defined(USART_CR1_FIFOEN) + /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */ + txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE); +#else + /* txdatacount is a temporary variable for MISRAC2012-Rule-13.5 */ +#endif /* USART_CR1_FIFOEN */ + txdatacount = husart->TxXferCount; - return HAL_OK; + if (state == HAL_USART_STATE_BUSY_RX) + { +#if defined(USART_CR2_SLVEN) + /* Clear SPI slave underrun flag and discard transmit data */ + if (husart->SlaveMode == USART_SLAVEMODE_ENABLE) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR2_SLVEN */ + + /* Rx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } +#if defined(USART_CR1_FIFOEN) + else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) && + (txftie != USART_CR3_TXFTIE) && + (txdatacount == 0U)) +#else + else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) && + (txdatacount == 0U)) +#endif /* USART_CR1_FIFOEN */ + { + /* TxRx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } +#if defined(USART_CR2_SLVEN) + else if ((state == HAL_USART_STATE_BUSY_RX) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#else + else if (state == HAL_USART_STATE_BUSY_RX) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + else + { + /* Nothing to do */ + } + } +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Simplex receive an amount of data in non-blocking mode. + * @note Function called under interruption only, once + * interruptions have been enabled by HAL_USART_Receive_IT(). + * @note ISR function executed when FIFO mode is enabled and when the + * data word length is less than 9 bits long. + * @param husart USART handle + * @retval None + */ +static void USART_RxISR_8BIT_FIFOEN(USART_HandleTypeDef *husart) +{ + HAL_USART_StateTypeDef state = husart->State; + uint16_t txdatacount; + uint16_t rxdatacount; + uint16_t uhMask = husart->Mask; + uint16_t nb_rx_data; + uint32_t txftie; + + /* Check that a Rx process is ongoing */ + if ((state == HAL_USART_STATE_BUSY_RX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) + { + for (nb_rx_data = husart->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--) + { + if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXFNE) == SET) + { + *husart->pRxBuffPtr = (uint8_t)(husart->Instance->RDR & (uint8_t)(uhMask & 0xFFU)); + husart->pRxBuffPtr++; + husart->RxXferCount--; + + if (husart->RxXferCount == 0U) + { + /* Disable the USART Parity Error Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) + and RX FIFO Threshold interrupt */ + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)); + + /* Clear RxISR function pointer */ + husart->RxISR = NULL; + + /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */ + txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE); + txdatacount = husart->TxXferCount; + + if (state == HAL_USART_STATE_BUSY_RX) + { +#if defined(USART_CR2_SLVEN) + /* Clear SPI slave underrun flag and discard transmit data */ + if (husart->SlaveMode == USART_SLAVEMODE_ENABLE) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR2_SLVEN */ + + /* Rx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + state = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) && + (txftie != USART_CR3_TXFTIE) && + (txdatacount == 0U)) + { + /* TxRx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + state = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } +#if defined(USART_CR2_SLVEN) + else if ((state == HAL_USART_STATE_BUSY_RX) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#else + else if (state == HAL_USART_STATE_BUSY_RX) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + else + { + /* Nothing to do */ + } + } } - return HAL_OK; + /* When remaining number of bytes to receive is less than the RX FIFO + threshold, next incoming frames are processed as if FIFO mode was + disabled (i.e. one interrupt per received frame). + */ + rxdatacount = husart->RxXferCount; + if (((rxdatacount != 0U)) && (rxdatacount < husart->NbRxDataToProcess)) + { + /* Disable the USART RXFT interrupt*/ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_RXFTIE); + + /* Update the RxISR function pointer */ + husart->RxISR = USART_RxISR_8BIT; + + /* Enable the USART Data Register Not Empty interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE); + +#if defined(USART_CR2_SLVEN) + if ((husart->TxXferCount == 0U) && + (state == HAL_USART_STATE_BUSY_TX_RX) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#else + if ((husart->TxXferCount == 0U) && + (state == HAL_USART_STATE_BUSY_TX_RX)) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + } } else { - return HAL_BUSY; + /* Clear RXNE interrupt flag */ + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); } } -#endif + +/** + * @brief Simplex receive an amount of data in non-blocking mode. + * @note Function called under interruption only, once + * interruptions have been enabled by HAL_USART_Receive_IT(). + * @note ISR function executed when FIFO mode is enabled and when the + * data word length is 9 bits long. + * @param husart USART handle + * @retval None + */ +static void USART_RxISR_16BIT_FIFOEN(USART_HandleTypeDef *husart) +{ + HAL_USART_StateTypeDef state = husart->State; + uint16_t txdatacount; + uint16_t rxdatacount; + uint16_t *tmp; + uint16_t uhMask = husart->Mask; + uint16_t nb_rx_data; + uint32_t txftie; + + /* Check that a Tx process is ongoing */ + if ((state == HAL_USART_STATE_BUSY_RX) || + (state == HAL_USART_STATE_BUSY_TX_RX)) + { + for (nb_rx_data = husart->NbRxDataToProcess ; nb_rx_data > 0U ; nb_rx_data--) + { + if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXFNE) == SET) + { + tmp = (uint16_t *) husart->pRxBuffPtr; + *tmp = (uint16_t)(husart->Instance->RDR & uhMask); + husart->pRxBuffPtr += 2U; + husart->RxXferCount--; + + if (husart->RxXferCount == 0U) + { + /* Disable the USART Parity Error Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) + and RX FIFO Threshold interrupt */ + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)); + + /* Clear RxISR function pointer */ + husart->RxISR = NULL; + + /* txftie and txdatacount are temporary variables for MISRAC2012-Rule-13.5 */ + txftie = READ_BIT(husart->Instance->CR3, USART_CR3_TXFTIE); + txdatacount = husart->TxXferCount; + + if (state == HAL_USART_STATE_BUSY_RX) + { +#if defined(USART_CR2_SLVEN) + /* Clear SPI slave underrun flag and discard transmit data */ + if (husart->SlaveMode == USART_SLAVEMODE_ENABLE) + { + __HAL_USART_CLEAR_UDRFLAG(husart); + __HAL_USART_SEND_REQ(husart, USART_TXDATA_FLUSH_REQUEST); + } +#endif /* USART_CR2_SLVEN */ + + /* Rx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + state = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else if ((READ_BIT(husart->Instance->CR1, USART_CR1_TCIE) != USART_CR1_TCIE) && + (txftie != USART_CR3_TXFTIE) && + (txdatacount == 0U)) + { + /* TxRx process is completed, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + state = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } +#if defined(USART_CR2_SLVEN) + else if ((state == HAL_USART_STATE_BUSY_RX) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#else + else if (state == HAL_USART_STATE_BUSY_RX) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + else + { + /* Nothing to do */ + } + } + } + + /* When remaining number of bytes to receive is less than the RX FIFO + threshold, next incoming frames are processed as if FIFO mode was + disabled (i.e. one interrupt per received frame). + */ + rxdatacount = husart->RxXferCount; + if (((rxdatacount != 0U)) && (rxdatacount < husart->NbRxDataToProcess)) + { + /* Disable the USART RXFT interrupt*/ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_RXFTIE); + + /* Update the RxISR function pointer */ + husart->RxISR = USART_RxISR_16BIT; + + /* Enable the USART Data Register Not Empty interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE); + +#if defined(USART_CR2_SLVEN) + if ((husart->TxXferCount == 0U) && + (state == HAL_USART_STATE_BUSY_TX_RX) && + (husart->SlaveMode == USART_SLAVEMODE_DISABLE)) +#else + if ((husart->TxXferCount == 0U) && + (state == HAL_USART_STATE_BUSY_TX_RX)) +#endif /* USART_CR2_SLVEN */ + { + /* Send dummy byte in order to generate the clock for the Slave to Send the next data */ + husart->Instance->TDR = (USART_DUMMY_DATA & (uint16_t)0x00FF); + } + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_USART_SEND_REQ(husart, USART_RXDATA_FLUSH_REQUEST); + } +} +#endif /* USART_CR1_FIFOEN */ /** * @} diff --git a/stm32/mk4-bootloader/storage.c b/stm32/mk4-bootloader/storage.c index ff95d04f..d31cce0a 100644 --- a/stm32/mk4-bootloader/storage.c +++ b/stm32/mk4-bootloader/storage.c @@ -54,20 +54,10 @@ _flash_wait_done(void) // busy wait } - if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || - (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || - (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || - (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || - (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || -#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ - defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) - (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) -#else - (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) -#endif - ) { - // Save an error code; somewhat random - return FLASH->SR; + uint32_t error = (FLASH->SR & FLASH_FLAG_SR_ERRORS); + if(error) { + // Save an error code; somewhat random, depends on chip details + return error; } // Check FLASH End of Operation flag