From 49090c2be3a9b6191a6ce6289710ffdf10269d6c Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Tue, 02 Sep 2025 19:58:15 +0800
Subject: [PATCH] SPI之W25Q Flash存储

---
 ISKBoard.ioc                                            |   58 
 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi_ex.h |   73 
 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi.h    |  855 ++++
 Core/Src/main.c                                         |    7 
 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi.c    | 4472 ++++++++++++++++++++++++++
 Core/Src/spi.c                                          |  121 
 Core/Inc/stm32l4xx_hal_conf.h                           |    2 
 /dev/null                                               | 2279 -------------
 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h     | 1433 ++++++++
 Core/Src/board/w25q.c                                   |  638 +++
 Core/Src/board/w25q.h                                   |  174 +
 Core/Src/gpio.c                                         |    2 
 Core/Inc/spi.h                                          |   52 
 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi_ex.c |  112 
 14 files changed, 7,977 insertions(+), 2,301 deletions(-)

diff --git a/Core/Inc/spi.h b/Core/Inc/spi.h
new file mode 100644
index 0000000..bf3fa2d
--- /dev/null
+++ b/Core/Inc/spi.h
@@ -0,0 +1,52 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    spi.h
+  * @brief   This file contains all the function prototypes for
+  *          the spi.c file
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2025 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPI_H__
+#define __SPI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+extern SPI_HandleTypeDef hspi1;
+
+/* USER CODE BEGIN Private defines */
+
+/* USER CODE END Private defines */
+
+void MX_SPI1_Init(void);
+
+/* USER CODE BEGIN Prototypes */
+
+/* USER CODE END Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SPI_H__ */
+
diff --git a/Core/Inc/stm32l4xx_hal_conf.h b/Core/Inc/stm32l4xx_hal_conf.h
index a8c2870..73ae7ff 100644
--- a/Core/Inc/stm32l4xx_hal_conf.h
+++ b/Core/Inc/stm32l4xx_hal_conf.h
@@ -74,7 +74,7 @@
 /*#define HAL_SD_MODULE_ENABLED   */
 /*#define HAL_SMBUS_MODULE_ENABLED   */
 /*#define HAL_SMARTCARD_MODULE_ENABLED   */
-/*#define HAL_SPI_MODULE_ENABLED   */
+#define HAL_SPI_MODULE_ENABLED
 /*#define HAL_SRAM_MODULE_ENABLED   */
 /*#define HAL_SWPMI_MODULE_ENABLED   */
 #define HAL_TIM_MODULE_ENABLED
diff --git a/Core/Src/board/w25q.c b/Core/Src/board/w25q.c
new file mode 100644
index 0000000..4e33ffc
--- /dev/null
+++ b/Core/Src/board/w25q.c
@@ -0,0 +1,638 @@
+/**********************************************************************
+ *   Copyright: (C)2024 LingYun IoT System Studio
+ *      Author: GuoWenxue<guowenxue@gmail.com>
+ *
+ * Description: Winbond W25Q32 SPI norflash compatible driver on ISKBoard
+ * Reference datasheet: <<W25Q256JV.pdf>>
+ *
+ *   ChangeLog:
+ *        Version    Date       Author            Description
+ *        V1.0.0  2024.08.29    GuoWenxue      Release initial version
+ *
+ ***********************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "main.h"
+#include "w25q.h"
+#include "spi.h"
+
+#define CONFIG_DEBUG_W25Q /* Enable W25Q norflash debug */
+
+#ifdef CONFIG_DEBUG_W25Q
+#define spinor_print(format,args...) printf(format, ##args)
+#else
+#define spinor_print(format,args...) do{} while(0)
+#endif
+
+__attribute__((unused)) static void dump_buf(const char *prompt, uint8_t *buf, uint32_t size)
+{
+    int      i;
+
+    if(!buf)
+        return ;
+
+    if(prompt)
+        printf("%s\r\n", prompt);
+
+    for(i=0; i<size; i++)
+        printf("%02x ", buf[i]);
+
+    printf("\r\n");
+}
+
+#ifdef USE_FREERTOS
+#include "cmsis_os.h"
+#define mdelay(ms) osDelay(ms)
+#else
+#define mdelay(ms) HAL_Delay(ms)
+#endif
+
+/*+-----------------------+
+ *|   SPI API Functions   |
+ *+-----------------------+*/
+
+#define W25Q_SPI               &hspi1
+#define W25Q_CS_PORT            GPIOA
+#define W25Q_CS_PIN             GPIO_PIN_4
+
+#define SPI_DUMMY_BYTE          0xA5
+
+void spinor_gpio_init(struct spi_info *spi)
+{
+    GPIO_InitTypeDef    GPIO_InitStruct = {0};
+
+    /* Initial W25Q Norflash SPI CS pin */
+    HAL_GPIO_WritePin(spi->cs_gpio, spi->cs_pin, GPIO_PIN_SET);
+    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+    GPIO_InitStruct.Pin = spi->cs_pin;
+    HAL_GPIO_Init(spi->cs_gpio, &GPIO_InitStruct);
+}
+
+void spi_cs_enable(struct spi_info *spi)
+{
+    HAL_GPIO_WritePin(spi->cs_gpio, spi->cs_pin, GPIO_PIN_RESET);
+}
+
+void spi_cs_disable(struct spi_info *spi)
+{
+    HAL_GPIO_WritePin(spi->cs_gpio, spi->cs_pin, GPIO_PIN_SET);
+}
+
+uint8_t spi_xfer(struct spi_info *spi, uint8_t data)
+{
+    uint8_t       rxbyte;
+    HAL_SPI_TransmitReceive(spi->hspi, &data, &rxbyte, 1, 100);
+    return rxbyte;
+}
+
+void spi_send(struct spi_info *spi, uint8_t *data, uint32_t bytes)
+{
+    HAL_SPI_Transmit(spi->hspi, data, bytes, 100);
+}
+
+void spi_recv(struct spi_info *spi, uint8_t *buf, uint32_t size)
+{
+    HAL_SPI_Receive(spi->hspi, buf, size, 100);
+}
+
+#define SPI_INFO(_hspi, _cs_gpio, _cs_pin) {\
+        .hspi       = _hspi,            \
+        .cs_gpio    = _cs_gpio,         \
+        .cs_pin     = _cs_pin,          \
+        .select     = spi_cs_enable,    \
+        .deselect   = spi_cs_disable,   \
+        .xfer       = spi_xfer,         \
+        .send       = spi_send,         \
+        .recv       = spi_recv,         \
+    }
+
+static struct spi_info spinor_spi = SPI_INFO(W25Q_SPI, W25Q_CS_PORT, W25Q_CS_PIN);
+
+/*+-----------------------+
+ *|  W25Q SPI Norflash ID |
+ *+-----------------------+*/
+
+#define W25Q_PAGSIZE            256     /* 1Page=256B */
+#define W25Q_SECSIZE            4096    /* 1Sector=16Pages=4KB */
+#define W25Q_BLKSIZE            65536   /* 1Block=16Sector=64KB */
+
+#define ARRAY_SIZE(x)           (sizeof(x)/sizeof(x[0]))
+
+/* JEDEC ID the 3rd bytes is the storage capacity */
+#pragma GCC diagnostic ignored "-Wshift-count-overflow"
+#define CAPCITY_ID(id)          (1UL<<(id&0xFF))
+#define NOR_INFO(_name, _jedec_id) \
+        .name       = _name,                                \
+        .jedec_id   = _jedec_id,                            \
+        .block_size = W25Q_BLKSIZE,                         \
+        .sector_size= W25Q_SECSIZE,                         \
+        .page_size  = W25Q_PAGSIZE,                         \
+        .capacity   = CAPCITY_ID(_jedec_id),                \
+        .n_blocks   = CAPCITY_ID(_jedec_id)/W25Q_BLKSIZE,   \
+        .n_sectors  = CAPCITY_ID(_jedec_id)/W25Q_SECSIZE,   \
+        .n_pages    = CAPCITY_ID(_jedec_id)/W25Q_PAGSIZE,   \
+
+static struct flash_info spinor_ids[] = {
+        { NOR_INFO("W25Q512", 0xef4020) },
+        { NOR_INFO("W25Q256", 0xef4019) },
+        { NOR_INFO("W25Q128", 0xef4018) },
+        { NOR_INFO("W25Q64",  0xef4017) },
+        { NOR_INFO("W25Q32",  0xef4016) },
+        { NOR_INFO("W25Q16",  0xef4015) },
+        { NOR_INFO("W25Q80",  0xef4014) },
+        { NOR_INFO("W25Q40",  0xef4013) },
+        { NOR_INFO("W25Q20",  0xef4012) },
+        { NOR_INFO("W25Q10",  0xef4011) },
+};
+
+/*+-------------------------------+
+ *|   SPI Norflash HighLevel API  |
+ *+-------------------------------+*/
+
+/* SPI Norflash API test function */
+void spinor_test(void)
+{
+    spinor_info_t          spinor;
+    int                    i;
+    uint8_t                buf[W25Q_PAGSIZE*2];
+
+    if( spinor_init(&spinor) < 0 )
+        return ;
+
+    //spinor_erase_chip(&spinor);
+    //spinor_erase_block(&spinor, 1, W25Q_BLKSIZE);
+    spinor_erase_sector(&spinor, 1, W25Q_SECSIZE);
+
+    memset(buf, 0, sizeof(buf));
+    spinor_read(&spinor, 0, buf, sizeof(buf));
+    dump_buf("<<<Read data after erase:\n", buf, sizeof(buf));
+
+    /* Read/Write data test on address not page align */
+    for(i=0; i<sizeof(buf); i++)
+        buf[i] = i;
+    spinor_write(&spinor, 8, buf, W25Q_PAGSIZE);
+
+    memset(buf, 0, sizeof(buf));
+    spinor_read(&spinor, 0, buf, sizeof(buf));
+    dump_buf("<<<Read data after write:\n", buf, sizeof(buf));
+
+    return ;
+}
+
+/* Initial SPI and detect the flash chip. */
+int spinor_init(struct spinor_info *spinor)
+{
+    spinor->spi = &spinor_spi;
+
+    spinor_gpio_init(spinor->spi);
+
+    if( !spinor_detect_by_jedec(spinor) )
+        return -1;
+
+    printf("Norflash %s detected, capacity %lu KB, %lu blocks, %lu sectors, %lu pages.\r\n",
+            spinor->flash->name, spinor->flash->capacity>>10,
+            spinor->flash->n_blocks, spinor->flash->n_sectors, spinor->flash->n_pages);
+
+    return 0;
+}
+
+/* Description:  Erase whole flash chip.
+ * Reference  :  P60, 8.2.32 Chip Erase (C7h / 60h)
+ */
+int spinor_erase_chip(struct spinor_info *spinor)
+{
+    struct spi_info *spi = spinor->spi;
+
+    while (spinor->lock == 1)
+        mdelay(1);
+
+    spinor->lock = 1;
+
+#ifdef CONFIG_DEBUG_W25Q
+    uint32_t StartTime = HAL_GetTick();
+    printf("Norflash EraseChip Begin...\r\n");
+#endif
+
+    spinor_write_enable(spi);
+
+    spi->select(spi);
+    spi->xfer(spi, SPINOR_OP_CHIP_ERASE);
+    spi->deselect(spi);
+    spinor_WaitForWriteEnd(spi);
+
+#ifdef CONFIG_DEBUG_W25Q
+    printf("Norflash EraseChip done after %ld ms!\r\n", HAL_GetTick() - StartTime);
+#endif
+
+    mdelay(10);
+    spinor->lock = 0;
+
+    return 0;
+}
+
+/* Description:  Erase blocks by 64KiB,
+ * Reference  :  P59, 8.2.31 64KB Block Erase with 4-Byte Address (DCh)
+ *  @address is the erase start physical address, which can be not block alignment such as 0x10001.
+ *  @size is the erase size, which can be larger than a block such as 4097, and it will erase 2 blocks;
+ */
+int spinor_erase_block(struct spinor_info *spinor, uint32_t address, uint32_t size)
+{
+    struct spi_info    *spi = spinor->spi;
+    struct flash_info  *flash = spinor->flash;
+    uint32_t            block, first, last;
+    uint32_t            addr;
+
+    while (spinor->lock == 1)
+        mdelay(1);
+
+    spinor->lock = 1;
+
+    /* find first and last erase block */
+    first = address / flash->block_size;
+    last  = (address+size-1) / flash->block_size;
+
+#ifdef CONFIG_DEBUG_W25Q
+    printf("Norflash Erase %ld Bytes Block@0x%lx Begin...\r\n", size, address);
+    uint32_t StartTime = HAL_GetTick();
+#endif
+
+    /* start erase all the blocks */
+    for( block=first; block<=last; block++)
+    {
+        addr = block * flash->sector_size;
+#ifdef CONFIG_DEBUG_W25Q
+        printf("Norflash Erase Block@%lx ...\r\n", addr);
+#endif
+        spinor_WaitForWriteEnd(spi);
+        spinor_write_enable(spi);
+
+        spi->select(spi);
+        if (spinor->flash->n_blocks >= 512 ) /* larger than W25Q256 */
+        {
+            spi->xfer(spi, SPINOR_OP_BE_4K_4B);
+            spi->xfer(spi, (addr & 0xFF000000) >> 24);
+        }
+        else
+        {
+            spi->xfer(spi, SPINOR_OP_BE_4K);
+        }
+
+        spi->xfer(spi, (addr & 0xFF0000) >> 16);
+        spi->xfer(spi, (addr & 0xFF00) >> 8);
+        spi->xfer(spi, addr & 0xFF);
+        spi->deselect(spi);
+
+        spinor_WaitForWriteEnd(spi);
+    }
+
+#ifdef CONFIG_DEBUG_W25Q
+    printf("Norflash EraseBlock@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime);
+    mdelay(100);
+#endif
+
+    mdelay(1);
+    spinor->lock = 0;
+
+    return 0;
+}
+
+/* Description:  Erase sectors by 4KiB
+ * Reference  :  P56, 8.2.28 Sector Erase with 4-Byte Address (21h)
+ *  @address is the erase start physical address, which can be not sector alignment such as 0x1001.
+ *  @size is the erase size, which can be larger than a sector such as 4097, and it will erase 2 sectors;
+ */
+int spinor_erase_sector(struct spinor_info *spinor, uint32_t address, uint32_t size)
+{
+    struct spi_info    *spi = spinor->spi;
+    struct flash_info  *flash = spinor->flash;
+    uint32_t            sector, first, last;
+    uint32_t            addr;
+
+    while (spinor->lock == 1)
+        mdelay(1);
+
+    spinor->lock = 1;
+
+    /* find first and last erase sector */
+    first = address / flash->sector_size;
+    last  = (address+size-1) / flash->sector_size;
+
+#ifdef CONFIG_DEBUG_W25Q
+    uint32_t StartTime = HAL_GetTick();
+    printf("Norflash Erase %ld Bytes Sector@0x%lx Begin...\r\n", size, address);
+#endif
+
+    /* start erase all the sectors */
+    for( sector=first; sector<=last; sector++)
+    {
+        addr = sector * flash->sector_size;
+#ifdef CONFIG_DEBUG_W25Q
+        printf("Norflash Erase Sector@%lx ...\r\n", addr);
+#endif
+
+        spinor_WaitForWriteEnd(spi);
+        spinor_write_enable(spi);
+
+        spi->select(spi);
+        if (spinor->flash->n_blocks >= 512 ) /* larger than W25Q256 */
+        {
+            spi->xfer(spi, SPINOR_OP_SE_4B);
+            spi->xfer(spi, (addr & 0xFF000000) >> 24);
+        }
+        else
+        {
+            spi->xfer(spi, SPINOR_OP_SE);
+        }
+        spi->xfer(spi, (addr & 0xFF0000) >> 16);
+        spi->xfer(spi, (addr & 0xFF00) >> 8);
+        spi->xfer(spi, addr & 0xFF);
+        spi->deselect(spi);
+
+        spinor_WaitForWriteEnd(spi);
+    }
+
+#ifdef CONFIG_DEBUG_W25Q
+    printf("Norflash EraseSector@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime);
+#endif
+
+    mdelay(1);
+    spinor->lock = 0;
+
+    return 0;
+}
+
+/* P32: 10.2.14 Page Program (02h) */
+int spinor_write(struct spinor_info *spinor, uint32_t address, uint8_t *data, uint32_t bytes)
+{
+    struct spi_info    *spi = spinor->spi;
+    struct flash_info  *flash = spinor->flash;
+    uint32_t            page, first, last;
+    uint32_t            addr, ofset, len;
+
+    while (spinor->lock == 1)
+        mdelay(1);
+
+    spinor->lock = 1;
+
+    /* find first and last write page */
+    first = address / flash->page_size;
+    last  = (address+bytes-1) / flash->page_size;
+
+#ifdef CONFIG_DEBUG_W25Q
+    uint32_t StartTime = HAL_GetTick();
+    printf("Norflash Write %ld Bytes to addr@0x%lx Begin...\r\n", bytes, address);
+#endif
+
+    /* address in page and offset in buffer */
+    addr = address;
+    ofset = 0;
+
+    /* start write all the pages */
+    for( page=first; page<=last; page++)
+    {
+        len = flash->page_size - (addr%flash->page_size);
+        len = len > bytes ? bytes : len;
+#ifdef CONFIG_DEBUG_W25Q
+        printf("Norflash write addr@0x%lx, %lu bytes\r\n", addr, len);
+#endif
+
+        spinor_WaitForWriteEnd(spi);
+        spinor_write_enable(spi);
+
+        spi->select(spi);
+        if (spinor->flash->n_blocks >= 512 )
+        {
+            spi->xfer(spi, SPINOR_OP_PP_4B);
+            spi->xfer(spi, (addr & 0xFF000000) >> 24);
+        }
+        else
+        {
+            spi->xfer(spi, SPINOR_OP_PP);
+        }
+        spi->xfer(spi, (addr & 0xFF0000) >> 16);
+        spi->xfer(spi, (addr & 0xFF00) >> 8);
+        spi->xfer(spi, addr & 0xFF);
+
+        /* send data */
+        spi->send(spi, data+ofset, len);
+
+        spi->deselect(spi);
+        spinor_WaitForWriteEnd(spi);
+
+        addr  += len;
+        ofset += len;
+        bytes  -= len;
+    }
+
+#ifdef CONFIG_DEBUG_W25Q
+    printf("Norflash WriteByte@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime);
+#endif
+
+    mdelay(1);
+    spinor->lock = 0;
+
+    return 0;
+}
+
+/* Description:  The Fast Read instruction can read the entire memory chip.
+ * Reference  :  P41, 8.2.13 Fast Read with 4-Byte Address (0Ch)
+ *  @address is the read start physical address, which can be not page alignment such as 0x101.
+ *  @size is the read size, which can be larger than a page such as 257, and it will read 2 pages;
+ */
+int spinor_read(struct spinor_info *spinor, uint32_t address, uint8_t *buf, uint32_t bytes)
+{
+    struct spi_info *spi = spinor->spi;
+
+    while (spinor->lock == 1)
+        mdelay(1);
+
+    spinor->lock = 1;
+
+#ifdef CONFIG_DEBUG_W25Q
+    uint32_t StartTime = HAL_GetTick();
+    printf("Norflash Read %ld Bytes from addr@0x%lx Begin...\r\n", bytes, address);
+#endif
+
+    spi->select(spi);
+
+    /* send instruction and address */
+    if (spinor->flash->n_blocks >= 512 )
+    {
+        spi->xfer(spi, SPINOR_OP_READ_FAST_4B);
+        spi->xfer(spi, (address & 0xFF000000) >> 24);
+    }
+    else
+    {
+        spi->xfer(spi, SPINOR_OP_READ_FAST);
+    }
+    spi->xfer(spi, (address & 0xFF0000) >> 16);
+    spi->xfer(spi, (address & 0xFF00) >> 8);
+    spi->xfer(spi, address & 0xFF);
+
+    /* read data */
+    spi->xfer(spi, SPI_DUMMY_BYTE);
+    spi->recv(spi, buf, bytes);
+
+    spi->deselect(spi);
+
+#ifdef CONFIG_DEBUG_W25Q
+    printf("Norflash ReadBytes@0x%lx done after %ld ms\r\n", address, HAL_GetTick() - StartTime);
+#endif
+    spinor->lock = 0;
+
+    return 0;
+}
+
+/*+-------------------------------+
+ *|   SPI Norflash LowLevel API   |
+ *+-------------------------------+*/
+
+/* Detect the norflash by JEDEC ID */
+int spinor_detect_by_jedec(struct spinor_info *spinor)
+{
+    uint32_t            jedec_id;
+    int                 i, found = 0;
+
+    jedec_id = spinor_read_jedecid(spinor->spi);
+
+    for(i=0; i<ARRAY_SIZE(spinor_ids); i++)
+    {
+        if(spinor_ids[i].jedec_id == jedec_id)
+        {
+            found = 1;
+            spinor->flash = &spinor_ids[i];
+            break;
+        }
+    }
+
+    printf("Detect JEDEC ID[0x%lx], Norflash %s found\r\n", jedec_id, found?spinor->flash->name:"not");
+    return found;
+}
+
+/* Description:  Read the chipset UNIQUE ID.
+ * Reference  :  P68, 8.2.40 Read Unique ID Number (4Bh)
+ */
+int spinor_read_uniqid(struct spi_info *spi, uint8_t *uniq_id)
+{
+    uint8_t              i;
+    uint8_t              id;
+
+    if( !uniq_id )
+        return -1;
+
+    spi->select(spi);
+    spi->xfer(spi, SPINOR_OP_RDUID);
+
+    /* Skip 4 bytes dummy bytes */
+    for (i=0; i<4; i++)
+        spi->xfer(spi, SPI_DUMMY_BYTE);
+
+    for (i=0; i<8; i++)
+    {
+        id = spi->xfer(spi, SPI_DUMMY_BYTE);
+        uniq_id[i] = id;
+    }
+
+    spi->deselect(spi);
+
+    return 0;
+}
+
+/* Description:  Read the chipset JEDEC ID.
+ * Reference  :  P69, 8.2.41 Read JEDEC ID (9Fh)
+ */
+uint32_t spinor_read_jedecid(struct spi_info *spi)
+{
+    uint32_t            jedec_id = 0x0;
+    uint8_t             id[3];
+
+    spi->select(spi);
+    spi->xfer(spi, SPINOR_OP_RDID);
+    id[0] = spi->xfer(spi, SPI_DUMMY_BYTE); /* Vendor ID */
+    id[1] = spi->xfer(spi, SPI_DUMMY_BYTE); /* Memory Type */
+    id[2] = spi->xfer(spi, SPI_DUMMY_BYTE); /* Storage Capacity */
+    spi->deselect(spi);
+
+    jedec_id = (id[0] << 16) | (id[1] << 8) | id[2];
+    return jedec_id;
+}
+
+/* Description:  Write Enable
+ * Reference  :  P31, 8.2.1 Write Enable (06h)
+ */
+void spinor_write_enable(struct spi_info *spi)
+{
+    spi->select(spi);
+    spi->xfer(spi, SPINOR_OP_WREN);
+    spi->deselect(spi);
+
+    mdelay(1);
+}
+
+/* Description:  Write Disable
+ * Reference  :  P32, 8.2.3 Write Disable (04h)
+ */
+void spinor_write_disable(struct spi_info *spi)
+{
+    spi->select(spi);
+    spi->xfer(spi, SPINOR_OP_WRDI);
+    spi->deselect(spi);
+
+    mdelay(1);
+}
+
+/* Description:  Read Status Register
+ * Reference  :  P32, 8.2.4 Read Status Register-1 (05h), Status Register-2 (35h) & Status Register-3 (15h)
+ */
+uint8_t spinor_read_status_reg(struct spi_info *spi, uint8_t reg)
+{
+    uint8_t value = 0;
+    uint8_t cmd[REG_STATUS_MAX] = { SPINOR_OP_RDSR1 , SPINOR_OP_RDSR2, SPINOR_OP_RDSR3 }; /* Status Register 1~3 */
+
+    if( reg>= REG_STATUS_MAX )
+        return 0xFF;
+
+    spi->select(spi);
+    spi->xfer(spi, cmd[reg]);
+    value = spi->xfer(spi, SPI_DUMMY_BYTE);
+    spi->deselect(spi);
+
+    return value;
+}
+
+/* Description:  Write Status Register
+ * Reference  :  P33, 8.2.5 Write Status Register-1 (01h), Status Register-2 (31h) & Status Register-3 (11h)
+ */
+void spinor_write_status_reg(struct spi_info *spi, uint8_t reg, uint8_t value)
+{
+    uint8_t cmd[REG_STATUS_MAX] = { SPINOR_OP_WRSR1 , SPINOR_OP_WRSR2, SPINOR_OP_WRSR3 }; /* Status Register 1~3 */
+
+    if( reg>= REG_STATUS_MAX )
+        return ;
+
+    spi->select(spi);
+    spi->xfer(spi, cmd[reg]);
+    value = spi->xfer(spi, value);
+    spi->deselect(spi);
+}
+
+/* Description:  Wait flash program/erase finished by read Status Register for BUSY bit
+ * Reference  :  P15, 7.1 Status Registers
+ */
+void spinor_WaitForWriteEnd(struct spi_info *spi)
+{
+    uint8_t value = 0;
+    mdelay(1);
+
+    spi->select(spi);
+    spi->xfer(spi, SPINOR_OP_RDSR1);
+
+    do
+    {
+        value = spi->xfer(spi, SPI_DUMMY_BYTE);
+        mdelay(1);
+    } while ((value & 0x01) == 0x01);
+
+    spi->deselect(spi);
+}
diff --git a/Core/Src/board/w25q.h b/Core/Src/board/w25q.h
new file mode 100644
index 0000000..0af7c13
--- /dev/null
+++ b/Core/Src/board/w25q.h
@@ -0,0 +1,174 @@
+/**********************************************************************
+ *   Copyright: (C)2024 LingYun IoT System Studio
+ *      Author: GuoWenxue<guowenxue@gmail.com>
+ *
+ * Description: Winbond W25Q32 SPI norflash compatible driver on ISKBoard
+ * Reference datasheet: <<W25Q256JV.pdf>>
+ *
+ *   ChangeLog:
+ *        Version    Date       Author            Description
+ *        V1.0.0  2024.08.29    GuoWenxue      Release initial version
+ *
+ ***********************************************************************/
+
+#ifndef __W25Q_H_
+#define __W25Q_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+/* Flash opcodes. Refer to <<W25Q256JV.pdf>> P26 Table 8.1.2 Instruction Set Table */
+#define SPINOR_OP_RDID          0x9f    /* Read JEDEC ID */
+#define SPINOR_OP_RDUID         0x4b    /* Read unique ID */
+#define SPINOR_OP_WRSR1         0x01    /* Write status register-1 */
+#define SPINOR_OP_WRSR2         0x31    /* Write status register-2 */
+#define SPINOR_OP_WRSR3         0x11    /* Write status register-3 */
+#define SPINOR_OP_BP            0x02    /* Byte program */
+#define SPINOR_OP_READ          0x03    /* Read data bytes (low frequency) */
+#define SPINOR_OP_WRDI          0x04    /* Write disable */
+#define SPINOR_OP_RDSR1         0x05    /* Read status register-1 */
+#define SPINOR_OP_RDSR2         0x35    /* Read status register-2 */
+#define SPINOR_OP_RDSR3         0x15    /* Read status register-3 */
+#define SPINOR_OP_WREN          0x06    /* Write enable */
+#define SPINOR_OP_READ_FAST     0x0b    /* Read data bytes (high frequency) */
+#define SPINOR_OP_READ_FAST_4B  0x0c    /* Read data bytes (high frequency) */
+
+#define SPINOR_OP_CHIP_ERASE    0xc7    /* Erase whole flash chip */
+#define SPINOR_OP_BE_4K_4B      0xdc    /* Block erase (64KiB) with 4-Byte Address */
+#define SPINOR_OP_BE_4K         0xd8    /* Block erase (64KiB) */
+#define SPINOR_OP_SE_4B         0x21    /* Sector erase (4KiB) with 4-Byte Address */
+#define SPINOR_OP_SE            0x20    /* Sector erase (4KiB)  */
+#define SPINOR_OP_PP_4B         0x12    /* Page Program (up to 256 bytes) with 4-Byte Address */
+#define SPINOR_OP_PP            0x02    /* Page program (up to 256 bytes) */
+#define SPINOR_OP_SRSTEN        0x66    /* Software Reset Enable */
+#define SPINOR_OP_SRST          0x99    /* Software Reset */
+
+typedef struct spi_info
+{
+    SPI_HandleTypeDef    *hspi;     /* SPI port */
+    GPIO_TypeDef         *cs_gpio;  /* CS GPIO group */
+    uint16_t              cs_pin;   /* CS GPIO pin */
+
+    void    (*select)(struct spi_info *spi);    /* CS enable function  */
+    void    (*deselect)(struct spi_info *spi);  /* CS disable function */
+    uint8_t (*xfer)(struct spi_info *spi, uint8_t data); /* Transmit and Receive one byte */
+    void    (*send)(struct spi_info *spi, uint8_t *data, uint32_t bytes); /* Transmit $bytes data */
+    void    (*recv)(struct spi_info *spi, uint8_t *buf, uint32_t size);   /* Receive $size data */
+} spi_info_t;
+
+typedef struct flash_info
+{
+    char            *name;          /* Chip name */
+    uint32_t         jedec_id;      /* JEDEC ID, 3 bytes */
+    uint32_t         capacity;      /* Chip   size in bytes */
+    uint32_t         block_size;    /* Block  size in bytes */
+    uint32_t         sector_size;   /* Sector size in bytes */
+    uint32_t         page_size;     /* Page   size in bytes */
+    uint32_t         n_blocks;      /* Number of blocks */
+    uint32_t         n_sectors;     /* Number of sectors */
+    uint32_t         n_pages;       /* Number of pages */
+} flash_info_t;
+
+
+typedef struct spinor_info
+{
+    spi_info_t      *spi;
+    flash_info_t    *flash;
+    uint8_t          lock;
+} spinor_info_t;
+
+
+/* Status registers */
+enum
+{
+    REG_STATUS1,
+    REG_STATUS2,
+    REG_STATUS3,
+    REG_STATUS_MAX,
+};
+
+/*+-------------------------------+
+ *|   SPI Norflash HighLevel API  |
+ *+-------------------------------+*/
+
+/* SPI Norflash API test function */
+extern void spinor_test(void);
+
+/* Initial SPI and detect the flash chip */
+extern int spinor_init(struct spinor_info *spinor);
+
+/* Description:  Erase whole flash chip.
+ * Reference  :  P60, 8.2.32 Chip Erase (C7h / 60h)
+ */
+extern int spinor_erase_chip(struct spinor_info *spinor);
+
+/* Description:  Erase blocks by 64KiB,
+ * Reference  :  P59, 8.2.31 64KB Block Erase with 4-Byte Address (DCh)
+ *  @address is the erase start physical address, which can be not block alignment such as 0x10001.
+ *  @size is the erase size, which can be larger than a block such as 4097, and it will erase 2 blocks;
+ */
+extern int spinor_erase_block(struct spinor_info *spinor, uint32_t address, uint32_t size);
+
+/* Description:  Erase sectors by 4KiB
+ * Reference  :  P56, 8.2.28 Sector Erase with 4-Byte Address (21h)
+ *  @address is the erase start physical address, which can be not sector alignment such as 0x1001.
+ *  @size is the erase size, which can be larger than a sector such as 4097, and it will erase 2 sectors;
+ */
+extern int spinor_erase_sector(struct spinor_info *spinor, uint32_t address, uint32_t size);
+
+/* Description:  Page random write by 256B
+ *  @addr is the write start physical address, which can be not page alignment such as 0x101.
+ *  @size is the write size, which can be larger than a page such as 257, and it will write 2 pages;
+ */
+extern int spinor_write(struct spinor_info *spinor, uint32_t address, uint8_t *data, uint32_t bytes);
+
+/* Description:  The Fast Read instruction can read the entire memory chip.
+ * Reference  :  P41, 8.2.13 Fast Read with 4-Byte Address (0Ch)
+ *  @address is the read start physical address, which can be not page alignment such as 0x101.
+ *  @size is the read size, which can be larger than a page such as 257, and it will read 2 pages;
+ */
+extern int spinor_read(struct spinor_info *spinor, uint32_t address, uint8_t *buf, uint32_t bytes);
+
+/*+-------------------------------+
+ *|   SPI Norflash LowLevel API   |
+ *+-------------------------------+*/
+
+/* Detect the norflash by JEDEC ID */
+int spinor_detect_by_jedec(struct spinor_info *spinor);
+
+/* Description:  Read the chipset UNIQUE ID.
+ * Reference  :  P68, 8.2.40 Read Unique ID Number (4Bh)
+ */
+int spinor_read_uniqid(struct spi_info *spi, uint8_t *uniq_id);
+
+/* Description:  Read the chipset JEDEC ID.
+ * Reference  :  P69, 8.2.41 Read JEDEC ID (9Fh)
+ */
+uint32_t spinor_read_jedecid(struct spi_info *spi);
+
+/* Description:  Write Enable
+ * Reference  :  P31, 8.2.1 Write Enable (06h)
+ */
+void spinor_write_enable(struct spi_info *spi);
+
+/* Description:  Write Disable
+ * Reference  :  P32, 8.2.3 Write Disable (04h)
+ */
+void spinor_write_disable(struct spi_info *spi);
+
+/* Description:  Read Status Register
+ * Reference  :  P32, 8.2.4 Read Status Register-1 (05h), Status Register-2 (35h) & Status Register-3 (15h)
+ */
+uint8_t spinor_read_status_reg(struct spi_info *spi, uint8_t reg);
+
+/* Description:  Write Status Register
+ * Reference  :  P33, 8.2.5 Write Status Register-1 (01h), Status Register-2 (31h) & Status Register-3 (11h)
+ */
+void spinor_write_status_reg(struct spi_info *spi, uint8_t reg, uint8_t value);
+
+/* Description:  Wait flash program/erase finished by read Status Register for BUSY bit
+ * Reference  :  P15, 7.1 Status Registers
+ */
+void spinor_WaitForWriteEnd(struct spi_info *spi);
+
+#endif
diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c
index a56fe75..064f342 100644
--- a/Core/Src/gpio.c
+++ b/Core/Src/gpio.c
@@ -46,9 +46,9 @@
 
   /* GPIO Ports Clock Enable */
   __HAL_RCC_GPIOH_CLK_ENABLE();
+  __HAL_RCC_GPIOA_CLK_ENABLE();
   __HAL_RCC_GPIOB_CLK_ENABLE();
   __HAL_RCC_GPIOC_CLK_ENABLE();
-  __HAL_RCC_GPIOA_CLK_ENABLE();
   __HAL_RCC_GPIOD_CLK_ENABLE();
 
   /*Configure GPIO pin Output Level */
diff --git a/Core/Src/main.c b/Core/Src/main.c
index b10af19..3344439 100644
--- a/Core/Src/main.c
+++ b/Core/Src/main.c
@@ -19,6 +19,7 @@
 /* Includes ------------------------------------------------------------------*/
 #include "main.h"
 #include "adc.h"
+#include "spi.h"
 #include "tim.h"
 #include "usart.h"
 #include "gpio.h"
@@ -27,6 +28,7 @@
 /* USER CODE BEGIN Includes */
 #include "miscdev.h"
 #include "sht20.h"
+#include "w25q.h"
 /* USER CODE END Includes */
 
 /* Private typedef -----------------------------------------------------------*/
@@ -95,8 +97,13 @@
   MX_ADC1_Init();
   MX_TIM6_Init();
   MX_TIM1_Init();
+  MX_SPI1_Init();
   /* USER CODE BEGIN 2 */
   beep_start(2, 300);
+
+  spinor_test();
+
+  do {} while(1);
   /* USER CODE END 2 */
 
   /* Infinite loop */
diff --git a/Core/Src/spi.c b/Core/Src/spi.c
new file mode 100644
index 0000000..64c3b78
--- /dev/null
+++ b/Core/Src/spi.c
@@ -0,0 +1,121 @@
+/* USER CODE BEGIN Header */
+/**
+  ******************************************************************************
+  * @file    spi.c
+  * @brief   This file provides code for the configuration
+  *          of the SPI instances.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2025 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+/* USER CODE END Header */
+/* Includes ------------------------------------------------------------------*/
+#include "spi.h"
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+SPI_HandleTypeDef hspi1;
+
+/* SPI1 init function */
+void MX_SPI1_Init(void)
+{
+
+  /* USER CODE BEGIN SPI1_Init 0 */
+
+  /* USER CODE END SPI1_Init 0 */
+
+  /* USER CODE BEGIN SPI1_Init 1 */
+
+  /* USER CODE END SPI1_Init 1 */
+  hspi1.Instance = SPI1;
+  hspi1.Init.Mode = SPI_MODE_MASTER;
+  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
+  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
+  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
+  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
+  hspi1.Init.NSS = SPI_NSS_SOFT;
+  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
+  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
+  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
+  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+  hspi1.Init.CRCPolynomial = 7;
+  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
+  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
+  if (HAL_SPI_Init(&hspi1) != HAL_OK)
+  {
+    Error_Handler();
+  }
+  /* USER CODE BEGIN SPI1_Init 2 */
+
+  /* USER CODE END SPI1_Init 2 */
+
+}
+
+void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
+{
+
+  GPIO_InitTypeDef GPIO_InitStruct = {0};
+  if(spiHandle->Instance==SPI1)
+  {
+  /* USER CODE BEGIN SPI1_MspInit 0 */
+
+  /* USER CODE END SPI1_MspInit 0 */
+    /* SPI1 clock enable */
+    __HAL_RCC_SPI1_CLK_ENABLE();
+
+    __HAL_RCC_GPIOA_CLK_ENABLE();
+    /**SPI1 GPIO Configuration
+    PA5     ------> SPI1_SCK
+    PA6     ------> SPI1_MISO
+    PA7     ------> SPI1_MOSI
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+  /* USER CODE BEGIN SPI1_MspInit 1 */
+
+  /* USER CODE END SPI1_MspInit 1 */
+  }
+}
+
+void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
+{
+
+  if(spiHandle->Instance==SPI1)
+  {
+  /* USER CODE BEGIN SPI1_MspDeInit 0 */
+
+  /* USER CODE END SPI1_MspDeInit 0 */
+    /* Peripheral clock disable */
+    __HAL_RCC_SPI1_CLK_DISABLE();
+
+    /**SPI1 GPIO Configuration
+    PA5     ------> SPI1_SCK
+    PA6     ------> SPI1_MISO
+    PA7     ------> SPI1_MOSI
+    */
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
+
+  /* USER CODE BEGIN SPI1_MspDeInit 1 */
+
+  /* USER CODE END SPI1_MspDeInit 1 */
+  }
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi.h
new file mode 100644
index 0000000..c139d46
--- /dev/null
+++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi.h
@@ -0,0 +1,855 @@
+/**
+  ******************************************************************************
+  * @file    stm32l4xx_hal_spi.h
+  * @author  MCD Application Team
+  * @brief   Header file of SPI HAL module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32L4xx_HAL_SPI_H
+#define STM32L4xx_HAL_SPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal_def.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup SPI
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup SPI_Exported_Types SPI Exported Types
+  * @{
+  */
+
+/**
+  * @brief  SPI Configuration Structure definition
+  */
+typedef struct
+{
+  uint32_t Mode;                /*!< Specifies the SPI operating mode.
+                                     This parameter can be a value of @ref SPI_Mode */
+
+  uint32_t Direction;           /*!< Specifies the SPI bidirectional mode state.
+                                     This parameter can be a value of @ref SPI_Direction */
+
+  uint32_t DataSize;            /*!< Specifies the SPI data size.
+                                     This parameter can be a value of @ref SPI_Data_Size */
+
+  uint32_t CLKPolarity;         /*!< Specifies the serial clock steady state.
+                                     This parameter can be a value of @ref SPI_Clock_Polarity */
+
+  uint32_t CLKPhase;            /*!< Specifies the clock active edge for the bit capture.
+                                     This parameter can be a value of @ref SPI_Clock_Phase */
+
+  uint32_t NSS;                 /*!< Specifies whether the NSS signal is managed by
+                                     hardware (NSS pin) or by software using the SSI bit.
+                                     This parameter can be a value of @ref SPI_Slave_Select_management */
+
+  uint32_t BaudRatePrescaler;   /*!< Specifies the Baud Rate prescaler value which will be
+                                     used to configure the transmit and receive SCK clock.
+                                     This parameter can be a value of @ref SPI_BaudRate_Prescaler
+                                     @note The communication clock is derived from the master
+                                     clock. The slave clock does not need to be set. */
+
+  uint32_t FirstBit;            /*!< Specifies whether data transfers start from MSB or LSB bit.
+                                     This parameter can be a value of @ref SPI_MSB_LSB_transmission */
+
+  uint32_t TIMode;              /*!< Specifies if the TI mode is enabled or not.
+                                     This parameter can be a value of @ref SPI_TI_mode */
+
+  uint32_t CRCCalculation;      /*!< Specifies if the CRC calculation is enabled or not.
+                                     This parameter can be a value of @ref SPI_CRC_Calculation */
+
+  uint32_t CRCPolynomial;       /*!< Specifies the polynomial used for the CRC calculation.
+                                     This parameter must be an odd number between Min_Data = 1 and Max_Data = 65535 */
+
+  uint32_t CRCLength;           /*!< Specifies the CRC Length used for the CRC calculation.
+                                     CRC Length is only used with Data8 and Data16, not other data size
+                                     This parameter can be a value of @ref SPI_CRC_length */
+
+  uint32_t NSSPMode;            /*!< Specifies whether the NSSP signal is enabled or not .
+                                     This parameter can be a value of @ref SPI_NSSP_Mode
+                                     This mode is activated by the NSSP bit in the SPIx_CR2 register and
+                                     it takes effect only if the SPI interface is configured as Motorola SPI
+                                     master (FRF=0) with capture on the first edge (SPIx_CR1 CPHA = 0,
+                                     CPOL setting is ignored).. */
+} SPI_InitTypeDef;
+
+/**
+  * @brief  HAL SPI State structure definition
+  */
+typedef enum
+{
+  HAL_SPI_STATE_RESET      = 0x00U,    /*!< Peripheral not Initialized                         */
+  HAL_SPI_STATE_READY      = 0x01U,    /*!< Peripheral Initialized and ready for use           */
+  HAL_SPI_STATE_BUSY       = 0x02U,    /*!< an internal process is ongoing                     */
+  HAL_SPI_STATE_BUSY_TX    = 0x03U,    /*!< Data Transmission process is ongoing               */
+  HAL_SPI_STATE_BUSY_RX    = 0x04U,    /*!< Data Reception process is ongoing                  */
+  HAL_SPI_STATE_BUSY_TX_RX = 0x05U,    /*!< Data Transmission and Reception process is ongoing */
+  HAL_SPI_STATE_ERROR      = 0x06U,    /*!< SPI error state                                    */
+  HAL_SPI_STATE_ABORT      = 0x07U     /*!< SPI abort is ongoing                               */
+} HAL_SPI_StateTypeDef;
+
+/**
+  * @brief  SPI handle Structure definition
+  */
+typedef struct __SPI_HandleTypeDef
+{
+  SPI_TypeDef                *Instance;      /*!< SPI registers base address               */
+
+  SPI_InitTypeDef            Init;           /*!< SPI communication parameters             */
+
+  const uint8_t              *pTxBuffPtr;    /*!< Pointer to SPI Tx transfer Buffer        */
+
+  uint16_t                   TxXferSize;     /*!< SPI Tx Transfer size                     */
+
+  __IO uint16_t              TxXferCount;    /*!< SPI Tx Transfer Counter                  */
+
+  uint8_t                    *pRxBuffPtr;    /*!< Pointer to SPI Rx transfer Buffer        */
+
+  uint16_t                   RxXferSize;     /*!< SPI Rx Transfer size                     */
+
+  __IO uint16_t              RxXferCount;    /*!< SPI Rx Transfer Counter                  */
+
+  uint32_t                   CRCSize;        /*!< SPI CRC size used for the transfer       */
+
+  void (*RxISR)(struct __SPI_HandleTypeDef *hspi);   /*!< function pointer on Rx ISR       */
+
+  void (*TxISR)(struct __SPI_HandleTypeDef *hspi);   /*!< function pointer on Tx ISR       */
+
+  DMA_HandleTypeDef          *hdmatx;        /*!< SPI Tx DMA Handle parameters             */
+
+  DMA_HandleTypeDef          *hdmarx;        /*!< SPI Rx DMA Handle parameters             */
+
+  HAL_LockTypeDef            Lock;           /*!< Locking object                           */
+
+  __IO HAL_SPI_StateTypeDef  State;          /*!< SPI communication state                  */
+
+  __IO uint32_t              ErrorCode;      /*!< SPI Error code                           */
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  void (* TxCpltCallback)(struct __SPI_HandleTypeDef *hspi);             /*!< SPI Tx Completed callback          */
+  void (* RxCpltCallback)(struct __SPI_HandleTypeDef *hspi);             /*!< SPI Rx Completed callback          */
+  void (* TxRxCpltCallback)(struct __SPI_HandleTypeDef *hspi);           /*!< SPI TxRx Completed callback        */
+  void (* TxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi);         /*!< SPI Tx Half Completed callback     */
+  void (* RxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi);         /*!< SPI Rx Half Completed callback     */
+  void (* TxRxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi);       /*!< SPI TxRx Half Completed callback   */
+  void (* ErrorCallback)(struct __SPI_HandleTypeDef *hspi);              /*!< SPI Error callback                 */
+  void (* AbortCpltCallback)(struct __SPI_HandleTypeDef *hspi);          /*!< SPI Abort callback                 */
+  void (* MspInitCallback)(struct __SPI_HandleTypeDef *hspi);            /*!< SPI Msp Init callback              */
+  void (* MspDeInitCallback)(struct __SPI_HandleTypeDef *hspi);          /*!< SPI Msp DeInit callback            */
+
+#endif  /* USE_HAL_SPI_REGISTER_CALLBACKS */
+} SPI_HandleTypeDef;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+/**
+  * @brief  HAL SPI Callback ID enumeration definition
+  */
+typedef enum
+{
+  HAL_SPI_TX_COMPLETE_CB_ID             = 0x00U,    /*!< SPI Tx Completed callback ID         */
+  HAL_SPI_RX_COMPLETE_CB_ID             = 0x01U,    /*!< SPI Rx Completed callback ID         */
+  HAL_SPI_TX_RX_COMPLETE_CB_ID          = 0x02U,    /*!< SPI TxRx Completed callback ID       */
+  HAL_SPI_TX_HALF_COMPLETE_CB_ID        = 0x03U,    /*!< SPI Tx Half Completed callback ID    */
+  HAL_SPI_RX_HALF_COMPLETE_CB_ID        = 0x04U,    /*!< SPI Rx Half Completed callback ID    */
+  HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID     = 0x05U,    /*!< SPI TxRx Half Completed callback ID  */
+  HAL_SPI_ERROR_CB_ID                   = 0x06U,    /*!< SPI Error callback ID                */
+  HAL_SPI_ABORT_CB_ID                   = 0x07U,    /*!< SPI Abort callback ID                */
+  HAL_SPI_MSPINIT_CB_ID                 = 0x08U,    /*!< SPI Msp Init callback ID             */
+  HAL_SPI_MSPDEINIT_CB_ID               = 0x09U     /*!< SPI Msp DeInit callback ID           */
+
+} HAL_SPI_CallbackIDTypeDef;
+
+/**
+  * @brief  HAL SPI Callback pointer definition
+  */
+typedef  void (*pSPI_CallbackTypeDef)(SPI_HandleTypeDef *hspi); /*!< pointer to an SPI callback function */
+
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+/**
+  * @}
+  */
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup SPI_Exported_Constants SPI Exported Constants
+  * @{
+  */
+
+/** @defgroup SPI_Error_Code SPI Error Code
+  * @{
+  */
+#define HAL_SPI_ERROR_NONE              (0x00000000U)   /*!< No error                               */
+#define HAL_SPI_ERROR_MODF              (0x00000001U)   /*!< MODF error                             */
+#define HAL_SPI_ERROR_CRC               (0x00000002U)   /*!< CRC error                              */
+#define HAL_SPI_ERROR_OVR               (0x00000004U)   /*!< OVR error                              */
+#define HAL_SPI_ERROR_FRE               (0x00000008U)   /*!< FRE error                              */
+#define HAL_SPI_ERROR_DMA               (0x00000010U)   /*!< DMA transfer error                     */
+#define HAL_SPI_ERROR_FLAG              (0x00000020U)   /*!< Error on RXNE/TXE/BSY/FTLVL/FRLVL Flag */
+#define HAL_SPI_ERROR_ABORT             (0x00000040U)   /*!< Error during SPI Abort procedure       */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+#define HAL_SPI_ERROR_INVALID_CALLBACK  (0x00000080U)   /*!< Invalid Callback error                 */
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Mode SPI Mode
+  * @{
+  */
+#define SPI_MODE_SLAVE                  (0x00000000U)
+#define SPI_MODE_MASTER                 (SPI_CR1_MSTR | SPI_CR1_SSI)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Direction SPI Direction Mode
+  * @{
+  */
+#define SPI_DIRECTION_2LINES            (0x00000000U)
+#define SPI_DIRECTION_2LINES_RXONLY     SPI_CR1_RXONLY
+#define SPI_DIRECTION_1LINE             SPI_CR1_BIDIMODE
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Data_Size SPI Data Size
+  * @{
+  */
+#define SPI_DATASIZE_4BIT               (0x00000300U)
+#define SPI_DATASIZE_5BIT               (0x00000400U)
+#define SPI_DATASIZE_6BIT               (0x00000500U)
+#define SPI_DATASIZE_7BIT               (0x00000600U)
+#define SPI_DATASIZE_8BIT               (0x00000700U)
+#define SPI_DATASIZE_9BIT               (0x00000800U)
+#define SPI_DATASIZE_10BIT              (0x00000900U)
+#define SPI_DATASIZE_11BIT              (0x00000A00U)
+#define SPI_DATASIZE_12BIT              (0x00000B00U)
+#define SPI_DATASIZE_13BIT              (0x00000C00U)
+#define SPI_DATASIZE_14BIT              (0x00000D00U)
+#define SPI_DATASIZE_15BIT              (0x00000E00U)
+#define SPI_DATASIZE_16BIT              (0x00000F00U)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Clock_Polarity SPI Clock Polarity
+  * @{
+  */
+#define SPI_POLARITY_LOW                (0x00000000U)
+#define SPI_POLARITY_HIGH               SPI_CR1_CPOL
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Clock_Phase SPI Clock Phase
+  * @{
+  */
+#define SPI_PHASE_1EDGE                 (0x00000000U)
+#define SPI_PHASE_2EDGE                 SPI_CR1_CPHA
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Slave_Select_management SPI Slave Select Management
+  * @{
+  */
+#define SPI_NSS_SOFT                    SPI_CR1_SSM
+#define SPI_NSS_HARD_INPUT              (0x00000000U)
+#define SPI_NSS_HARD_OUTPUT             (SPI_CR2_SSOE << 16U)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_NSSP_Mode SPI NSS Pulse Mode
+  * @{
+  */
+#define SPI_NSS_PULSE_ENABLE            SPI_CR2_NSSP
+#define SPI_NSS_PULSE_DISABLE           (0x00000000U)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_BaudRate_Prescaler SPI BaudRate Prescaler
+  * @{
+  */
+#define SPI_BAUDRATEPRESCALER_2         (0x00000000U)
+#define SPI_BAUDRATEPRESCALER_4         (SPI_CR1_BR_0)
+#define SPI_BAUDRATEPRESCALER_8         (SPI_CR1_BR_1)
+#define SPI_BAUDRATEPRESCALER_16        (SPI_CR1_BR_1 | SPI_CR1_BR_0)
+#define SPI_BAUDRATEPRESCALER_32        (SPI_CR1_BR_2)
+#define SPI_BAUDRATEPRESCALER_64        (SPI_CR1_BR_2 | SPI_CR1_BR_0)
+#define SPI_BAUDRATEPRESCALER_128       (SPI_CR1_BR_2 | SPI_CR1_BR_1)
+#define SPI_BAUDRATEPRESCALER_256       (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_MSB_LSB_transmission SPI MSB LSB Transmission
+  * @{
+  */
+#define SPI_FIRSTBIT_MSB                (0x00000000U)
+#define SPI_FIRSTBIT_LSB                SPI_CR1_LSBFIRST
+/**
+  * @}
+  */
+
+/** @defgroup SPI_TI_mode SPI TI Mode
+  * @{
+  */
+#define SPI_TIMODE_DISABLE              (0x00000000U)
+#define SPI_TIMODE_ENABLE               SPI_CR2_FRF
+/**
+  * @}
+  */
+
+/** @defgroup SPI_CRC_Calculation SPI CRC Calculation
+  * @{
+  */
+#define SPI_CRCCALCULATION_DISABLE      (0x00000000U)
+#define SPI_CRCCALCULATION_ENABLE       SPI_CR1_CRCEN
+/**
+  * @}
+  */
+
+/** @defgroup SPI_CRC_length SPI CRC Length
+  * @{
+  * This parameter can be one of the following values:
+  *     SPI_CRC_LENGTH_DATASIZE: aligned with the data size
+  *     SPI_CRC_LENGTH_8BIT    : CRC 8bit
+  *     SPI_CRC_LENGTH_16BIT   : CRC 16bit
+  */
+#define SPI_CRC_LENGTH_DATASIZE         (0x00000000U)
+#define SPI_CRC_LENGTH_8BIT             (0x00000001U)
+#define SPI_CRC_LENGTH_16BIT            (0x00000002U)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_FIFO_reception_threshold SPI FIFO Reception Threshold
+  * @{
+  * This parameter can be one of the following values:
+  *     SPI_RXFIFO_THRESHOLD or SPI_RXFIFO_THRESHOLD_QF :
+  *          RXNE event is generated if the FIFO
+  *          level is greater or equal to 1/4(8-bits).
+  *     SPI_RXFIFO_THRESHOLD_HF: RXNE event is generated if the FIFO
+  *          level is greater or equal to 1/2(16 bits). */
+#define SPI_RXFIFO_THRESHOLD            SPI_CR2_FRXTH
+#define SPI_RXFIFO_THRESHOLD_QF         SPI_CR2_FRXTH
+#define SPI_RXFIFO_THRESHOLD_HF         (0x00000000U)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Interrupt_definition SPI Interrupt Definition
+  * @{
+  */
+#define SPI_IT_TXE                      SPI_CR2_TXEIE
+#define SPI_IT_RXNE                     SPI_CR2_RXNEIE
+#define SPI_IT_ERR                      SPI_CR2_ERRIE
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Flags_definition SPI Flags Definition
+  * @{
+  */
+#define SPI_FLAG_RXNE                   SPI_SR_RXNE   /* SPI status flag: Rx buffer not empty flag       */
+#define SPI_FLAG_TXE                    SPI_SR_TXE    /* SPI status flag: Tx buffer empty flag           */
+#define SPI_FLAG_BSY                    SPI_SR_BSY    /* SPI status flag: Busy flag                      */
+#define SPI_FLAG_CRCERR                 SPI_SR_CRCERR /* SPI Error flag: CRC error flag                  */
+#define SPI_FLAG_MODF                   SPI_SR_MODF   /* SPI Error flag: Mode fault flag                 */
+#define SPI_FLAG_OVR                    SPI_SR_OVR    /* SPI Error flag: Overrun flag                    */
+#define SPI_FLAG_FRE                    SPI_SR_FRE    /* SPI Error flag: TI mode frame format error flag */
+#define SPI_FLAG_FTLVL                  SPI_SR_FTLVL  /* SPI fifo transmission level                     */
+#define SPI_FLAG_FRLVL                  SPI_SR_FRLVL  /* SPI fifo reception level                        */
+#define SPI_FLAG_MASK                   (SPI_SR_RXNE | SPI_SR_TXE | SPI_SR_BSY | SPI_SR_CRCERR\
+                                         | SPI_SR_MODF | SPI_SR_OVR | SPI_SR_FRE | SPI_SR_FTLVL | SPI_SR_FRLVL)
+/**
+  * @}
+  */
+
+/** @defgroup SPI_transmission_fifo_status_level SPI Transmission FIFO Status Level
+  * @{
+  */
+#define SPI_FTLVL_EMPTY                 (0x00000000U)
+#define SPI_FTLVL_QUARTER_FULL          (0x00000800U)
+#define SPI_FTLVL_HALF_FULL             (0x00001000U)
+#define SPI_FTLVL_FULL                  (0x00001800U)
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_reception_fifo_status_level SPI Reception FIFO Status Level
+  * @{
+  */
+#define SPI_FRLVL_EMPTY                 (0x00000000U)
+#define SPI_FRLVL_QUARTER_FULL          (0x00000200U)
+#define SPI_FRLVL_HALF_FULL             (0x00000400U)
+#define SPI_FRLVL_FULL                  (0x00000600U)
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macros -----------------------------------------------------------*/
+/** @defgroup SPI_Exported_Macros SPI Exported Macros
+  * @{
+  */
+
+/** @brief  Reset SPI handle state.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__)      \
+  do{                                                 \
+    (__HANDLE__)->State = HAL_SPI_STATE_RESET;        \
+    (__HANDLE__)->MspInitCallback = NULL;             \
+    (__HANDLE__)->MspDeInitCallback = NULL;           \
+  } while(0)
+#else
+#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SPI_STATE_RESET)
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+
+/** @brief  Enable the specified SPI interrupts.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @param  __INTERRUPT__ specifies the interrupt source to enable.
+  *         This parameter can be one of the following values:
+  *            @arg SPI_IT_TXE: Tx buffer empty interrupt enable
+  *            @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
+  *            @arg SPI_IT_ERR: Error interrupt enable
+  * @retval None
+  */
+#define __HAL_SPI_ENABLE_IT(__HANDLE__, __INTERRUPT__)   SET_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__))
+
+/** @brief  Disable the specified SPI interrupts.
+  * @param  __HANDLE__ specifies the SPI handle.
+  *         This parameter can be SPIx where x: 1, 2, or 3 to select the SPI peripheral.
+  * @param  __INTERRUPT__ specifies the interrupt source to disable.
+  *         This parameter can be one of the following values:
+  *            @arg SPI_IT_TXE: Tx buffer empty interrupt enable
+  *            @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
+  *            @arg SPI_IT_ERR: Error interrupt enable
+  * @retval None
+  */
+#define __HAL_SPI_DISABLE_IT(__HANDLE__, __INTERRUPT__)  CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__))
+
+/** @brief  Check whether the specified SPI interrupt source is enabled or not.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @param  __INTERRUPT__ specifies the SPI interrupt source to check.
+  *          This parameter can be one of the following values:
+  *            @arg SPI_IT_TXE: Tx buffer empty interrupt enable
+  *            @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
+  *            @arg SPI_IT_ERR: Error interrupt enable
+  * @retval The new state of __IT__ (TRUE or FALSE).
+  */
+#define __HAL_SPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2\
+                                                              & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET)
+
+/** @brief  Check whether the specified SPI flag is set or not.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @param  __FLAG__ specifies the flag to check.
+  *         This parameter can be one of the following values:
+  *            @arg SPI_FLAG_RXNE: Receive buffer not empty flag
+  *            @arg SPI_FLAG_TXE: Transmit buffer empty flag
+  *            @arg SPI_FLAG_CRCERR: CRC error flag
+  *            @arg SPI_FLAG_MODF: Mode fault flag
+  *            @arg SPI_FLAG_OVR: Overrun flag
+  *            @arg SPI_FLAG_BSY: Busy flag
+  *            @arg SPI_FLAG_FRE: Frame format error flag
+  *            @arg SPI_FLAG_FTLVL: SPI fifo transmission level
+  *            @arg SPI_FLAG_FRLVL: SPI fifo reception level
+  * @retval The new state of __FLAG__ (TRUE or FALSE).
+  */
+#define __HAL_SPI_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__))
+
+/** @brief  Clear the SPI CRCERR pending flag.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define __HAL_SPI_CLEAR_CRCERRFLAG(__HANDLE__) ((__HANDLE__)->Instance->SR = (uint16_t)(~SPI_FLAG_CRCERR))
+
+/** @brief  Clear the SPI MODF pending flag.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define __HAL_SPI_CLEAR_MODFFLAG(__HANDLE__)             \
+  do{                                                    \
+    __IO uint32_t tmpreg_modf = 0x00U;                   \
+    tmpreg_modf = (__HANDLE__)->Instance->SR;            \
+    CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE); \
+    UNUSED(tmpreg_modf);                                 \
+  } while(0U)
+
+/** @brief  Clear the SPI OVR pending flag.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define __HAL_SPI_CLEAR_OVRFLAG(__HANDLE__)        \
+  do{                                              \
+    __IO uint32_t tmpreg_ovr = 0x00U;              \
+    tmpreg_ovr = (__HANDLE__)->Instance->DR;       \
+    tmpreg_ovr = (__HANDLE__)->Instance->SR;       \
+    UNUSED(tmpreg_ovr);                            \
+  } while(0U)
+
+/** @brief  Clear the SPI FRE pending flag.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define __HAL_SPI_CLEAR_FREFLAG(__HANDLE__)        \
+  do{                                              \
+    __IO uint32_t tmpreg_fre = 0x00U;              \
+    tmpreg_fre = (__HANDLE__)->Instance->SR;       \
+    UNUSED(tmpreg_fre);                            \
+  } while(0U)
+
+/** @brief  Enable the SPI peripheral.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define __HAL_SPI_ENABLE(__HANDLE__)  SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE)
+
+/** @brief  Disable the SPI peripheral.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define __HAL_SPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE)
+
+/**
+  * @}
+  */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup SPI_Private_Macros SPI Private Macros
+  * @{
+  */
+
+/** @brief  Set the SPI transmit-only mode.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define SPI_1LINE_TX(__HANDLE__)  SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE)
+
+/** @brief  Set the SPI receive-only mode.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define SPI_1LINE_RX(__HANDLE__)  CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE)
+
+/** @brief  Reset the CRC calculation of the SPI.
+  * @param  __HANDLE__ specifies the SPI Handle.
+  *         This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral.
+  * @retval None
+  */
+#define SPI_RESET_CRC(__HANDLE__)                           \
+  do{                                                       \
+    CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN);  \
+    SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN);    \
+  } while(0U)
+
+/** @brief  Check whether the specified SPI flag is set or not.
+  * @param  __SR__  copy of SPI SR register.
+  * @param  __FLAG__ specifies the flag to check.
+  *         This parameter can be one of the following values:
+  *            @arg SPI_FLAG_RXNE: Receive buffer not empty flag
+  *            @arg SPI_FLAG_TXE: Transmit buffer empty flag
+  *            @arg SPI_FLAG_CRCERR: CRC error flag
+  *            @arg SPI_FLAG_MODF: Mode fault flag
+  *            @arg SPI_FLAG_OVR: Overrun flag
+  *            @arg SPI_FLAG_BSY: Busy flag
+  *            @arg SPI_FLAG_FRE: Frame format error flag
+  *            @arg SPI_FLAG_FTLVL: SPI fifo transmission level
+  *            @arg SPI_FLAG_FRLVL: SPI fifo reception level
+  * @retval SET or RESET.
+  */
+#define SPI_CHECK_FLAG(__SR__, __FLAG__) ((((__SR__) & ((__FLAG__) & SPI_FLAG_MASK)) == \
+                                           ((__FLAG__) & SPI_FLAG_MASK)) ? SET : RESET)
+
+/** @brief  Check whether the specified SPI Interrupt is set or not.
+  * @param  __CR2__  copy of SPI CR2 register.
+  * @param  __INTERRUPT__ specifies the SPI interrupt source to check.
+  *         This parameter can be one of the following values:
+  *            @arg SPI_IT_TXE: Tx buffer empty interrupt enable
+  *            @arg SPI_IT_RXNE: RX buffer not empty interrupt enable
+  *            @arg SPI_IT_ERR: Error interrupt enable
+  * @retval SET or RESET.
+  */
+#define SPI_CHECK_IT_SOURCE(__CR2__, __INTERRUPT__) ((((__CR2__) & (__INTERRUPT__)) == \
+                                                      (__INTERRUPT__)) ? SET : RESET)
+
+/** @brief  Checks if SPI Mode parameter is in allowed range.
+  * @param  __MODE__ specifies the SPI Mode.
+  *         This parameter can be a value of @ref SPI_Mode
+  * @retval None
+  */
+#define IS_SPI_MODE(__MODE__)      (((__MODE__) == SPI_MODE_SLAVE)   || \
+                                    ((__MODE__) == SPI_MODE_MASTER))
+
+/** @brief  Checks if SPI Direction Mode parameter is in allowed range.
+  * @param  __MODE__ specifies the SPI Direction Mode.
+  *         This parameter can be a value of @ref SPI_Direction
+  * @retval None
+  */
+#define IS_SPI_DIRECTION(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES)        || \
+                                    ((__MODE__) == SPI_DIRECTION_2LINES_RXONLY) || \
+                                    ((__MODE__) == SPI_DIRECTION_1LINE))
+
+/** @brief  Checks if SPI Direction Mode parameter is 2 lines.
+  * @param  __MODE__ specifies the SPI Direction Mode.
+  * @retval None
+  */
+#define IS_SPI_DIRECTION_2LINES(__MODE__) ((__MODE__) == SPI_DIRECTION_2LINES)
+
+/** @brief  Checks if SPI Direction Mode parameter is 1 or 2 lines.
+  * @param  __MODE__ specifies the SPI Direction Mode.
+  * @retval None
+  */
+#define IS_SPI_DIRECTION_2LINES_OR_1LINE(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \
+                                                    ((__MODE__) == SPI_DIRECTION_1LINE))
+
+/** @brief  Checks if SPI Data Size parameter is in allowed range.
+  * @param  __DATASIZE__ specifies the SPI Data Size.
+  *         This parameter can be a value of @ref SPI_Data_Size
+  * @retval None
+  */
+#define IS_SPI_DATASIZE(__DATASIZE__) (((__DATASIZE__) == SPI_DATASIZE_16BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_15BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_14BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_13BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_12BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_11BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_10BIT) || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_9BIT)  || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_8BIT)  || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_7BIT)  || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_6BIT)  || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_5BIT)  || \
+                                       ((__DATASIZE__) == SPI_DATASIZE_4BIT))
+
+/** @brief  Checks if SPI Serial clock steady state parameter is in allowed range.
+  * @param  __CPOL__ specifies the SPI serial clock steady state.
+  *         This parameter can be a value of @ref SPI_Clock_Polarity
+  * @retval None
+  */
+#define IS_SPI_CPOL(__CPOL__)      (((__CPOL__) == SPI_POLARITY_LOW) || \
+                                    ((__CPOL__) == SPI_POLARITY_HIGH))
+
+/** @brief  Checks if SPI Clock Phase parameter is in allowed range.
+  * @param  __CPHA__ specifies the SPI Clock Phase.
+  *         This parameter can be a value of @ref SPI_Clock_Phase
+  * @retval None
+  */
+#define IS_SPI_CPHA(__CPHA__)      (((__CPHA__) == SPI_PHASE_1EDGE) || \
+                                    ((__CPHA__) == SPI_PHASE_2EDGE))
+
+/** @brief  Checks if SPI Slave Select parameter is in allowed range.
+  * @param  __NSS__ specifies the SPI Slave Select management parameter.
+  *         This parameter can be a value of @ref SPI_Slave_Select_management
+  * @retval None
+  */
+#define IS_SPI_NSS(__NSS__)        (((__NSS__) == SPI_NSS_SOFT)       || \
+                                    ((__NSS__) == SPI_NSS_HARD_INPUT) || \
+                                    ((__NSS__) == SPI_NSS_HARD_OUTPUT))
+
+/** @brief  Checks if SPI NSS Pulse parameter is in allowed range.
+  * @param  __NSSP__ specifies the SPI NSS Pulse Mode parameter.
+  *         This parameter can be a value of @ref SPI_NSSP_Mode
+  * @retval None
+  */
+#define IS_SPI_NSSP(__NSSP__)      (((__NSSP__) == SPI_NSS_PULSE_ENABLE) || \
+                                    ((__NSSP__) == SPI_NSS_PULSE_DISABLE))
+
+/** @brief  Checks if SPI Baudrate prescaler parameter is in allowed range.
+  * @param  __PRESCALER__ specifies the SPI Baudrate prescaler.
+  *         This parameter can be a value of @ref SPI_BaudRate_Prescaler
+  * @retval None
+  */
+#define IS_SPI_BAUDRATE_PRESCALER(__PRESCALER__) (((__PRESCALER__) == SPI_BAUDRATEPRESCALER_2)   || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_4)   || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_8)   || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_16)  || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_32)  || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_64)  || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_128) || \
+                                                  ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_256))
+
+/** @brief  Checks if SPI MSB LSB transmission parameter is in allowed range.
+  * @param  __BIT__ specifies the SPI MSB LSB transmission (whether data transfer starts from MSB or LSB bit).
+  *         This parameter can be a value of @ref SPI_MSB_LSB_transmission
+  * @retval None
+  */
+#define IS_SPI_FIRST_BIT(__BIT__)  (((__BIT__) == SPI_FIRSTBIT_MSB) || \
+                                    ((__BIT__) == SPI_FIRSTBIT_LSB))
+
+/** @brief  Checks if SPI TI mode parameter is in allowed range.
+  * @param  __MODE__ specifies the SPI TI mode.
+  *         This parameter can be a value of @ref SPI_TI_mode
+  * @retval None
+  */
+#define IS_SPI_TIMODE(__MODE__)    (((__MODE__) == SPI_TIMODE_DISABLE) || \
+                                    ((__MODE__) == SPI_TIMODE_ENABLE))
+
+/** @brief  Checks if SPI CRC calculation enabled state is in allowed range.
+  * @param  __CALCULATION__ specifies the SPI CRC calculation enable state.
+  *         This parameter can be a value of @ref SPI_CRC_Calculation
+  * @retval None
+  */
+#define IS_SPI_CRC_CALCULATION(__CALCULATION__) (((__CALCULATION__) == SPI_CRCCALCULATION_DISABLE) || \
+                                                 ((__CALCULATION__) == SPI_CRCCALCULATION_ENABLE))
+
+/** @brief  Checks if SPI CRC length is in allowed range.
+  * @param  __LENGTH__ specifies the SPI CRC length.
+  *         This parameter can be a value of @ref SPI_CRC_length
+  * @retval None
+  */
+#define IS_SPI_CRC_LENGTH(__LENGTH__) (((__LENGTH__) == SPI_CRC_LENGTH_DATASIZE) || \
+                                       ((__LENGTH__) == SPI_CRC_LENGTH_8BIT)     || \
+                                       ((__LENGTH__) == SPI_CRC_LENGTH_16BIT))
+
+/** @brief  Checks if SPI polynomial value to be used for the CRC calculation, is in allowed range.
+  * @param  __POLYNOMIAL__ specifies the SPI polynomial value to be used for the CRC calculation.
+  *         This parameter must be a number between Min_Data = 0 and Max_Data = 65535
+  * @retval None
+  */
+#define IS_SPI_CRC_POLYNOMIAL(__POLYNOMIAL__) (((__POLYNOMIAL__) >= 0x1U)    && \
+                                               ((__POLYNOMIAL__) <= 0xFFFFU) && \
+                                               (((__POLYNOMIAL__)&0x1U) != 0U))
+
+/** @brief  Checks if DMA handle is valid.
+  * @param  __HANDLE__ specifies a DMA Handle.
+  * @retval None
+  */
+#define IS_SPI_DMA_HANDLE(__HANDLE__) ((__HANDLE__) != NULL)
+
+/**
+  * @}
+  */
+
+/* Include SPI HAL Extended module */
+#include "stm32l4xx_hal_spi_ex.h"
+
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SPI_Exported_Functions
+  * @{
+  */
+
+/** @addtogroup SPI_Exported_Functions_Group1
+  * @{
+  */
+/* Initialization/de-initialization functions  ********************************/
+HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi);
+HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi);
+void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi);
+void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi);
+
+/* Callbacks Register/UnRegister functions  ***********************************/
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID,
+                                           pSPI_CallbackTypeDef pCallback);
+HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+/**
+  * @}
+  */
+
+/** @addtogroup SPI_Exported_Functions_Group2
+  * @{
+  */
+/* I/O operation functions  ***************************************************/
+HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout);
+HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
+HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+                                          uint16_t Size, uint32_t Timeout);
+HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+                                             uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+                                              uint16_t Size);
+HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi);
+HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi);
+HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi);
+/* Transfer Abort functions */
+HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi);
+HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi);
+
+void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi);
+void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
+void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi);
+/**
+  * @}
+  */
+
+/** @addtogroup SPI_Exported_Functions_Group3
+  * @{
+  */
+/* Peripheral State and Error functions ***************************************/
+HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi);
+uint32_t             HAL_SPI_GetError(const SPI_HandleTypeDef *hspi);
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32L4xx_HAL_SPI_H */
+
diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi_ex.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi_ex.h
new file mode 100644
index 0000000..d600652
--- /dev/null
+++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_spi_ex.h
@@ -0,0 +1,73 @@
+/**
+  ******************************************************************************
+  * @file    stm32l4xx_hal_spi_ex.h
+  * @author  MCD Application Team
+  * @brief   Header file of SPI HAL Extended module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32L4xx_HAL_SPI_EX_H
+#define STM32L4xx_HAL_SPI_EX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal_def.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+  * @{
+  */
+
+/** @addtogroup SPIEx
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup SPIEx_Exported_Functions
+  * @{
+  */
+
+/* Initialization and de-initialization functions  ****************************/
+/* IO operation functions *****************************************************/
+/** @addtogroup SPIEx_Exported_Functions_Group1
+  * @{
+  */
+HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi);
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32L4xx_HAL_SPI_EX_H */
+
diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h
deleted file mode 100644
index 612bc76..0000000
--- a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h
+++ /dev/null
@@ -1,2279 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    stm32l4xx_ll_i2c.h
-  * @author  MCD Application Team
-  * @brief   Header file of I2C LL module.
-  ******************************************************************************
-  * @attention
-  *
-  * Copyright (c) 2017 STMicroelectronics.
-  * All rights reserved.
-  *
-  * This software is licensed under terms that can be found in the LICENSE file
-  * in the root directory of this software component.
-  * If no LICENSE file comes with this software, it is provided AS-IS.
-  *
-  ******************************************************************************
-  */
-
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef STM32L4xx_LL_I2C_H
-#define STM32L4xx_LL_I2C_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Includes ------------------------------------------------------------------*/
-#include "stm32l4xx.h"
-
-/** @addtogroup STM32L4xx_LL_Driver
-  * @{
-  */
-
-#if defined (I2C1) || defined (I2C2) || defined (I2C3) || defined (I2C4)
-
-/** @defgroup I2C_LL I2C
-  * @{
-  */
-
-/* Private types -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-
-/* Private constants ---------------------------------------------------------*/
-/** @defgroup I2C_LL_Private_Constants I2C Private Constants
-  * @{
-  */
-/**
-  * @}
-  */
-
-/* Private macros ------------------------------------------------------------*/
-#if defined(USE_FULL_LL_DRIVER)
-/** @defgroup I2C_LL_Private_Macros I2C Private Macros
-  * @{
-  */
-/**
-  * @}
-  */
-#endif /*USE_FULL_LL_DRIVER*/
-
-/* Exported types ------------------------------------------------------------*/
-#if defined(USE_FULL_LL_DRIVER)
-/** @defgroup I2C_LL_ES_INIT I2C Exported Init structure
-  * @{
-  */
-typedef struct
-{
-  uint32_t PeripheralMode;      /*!< Specifies the peripheral mode.
-                                     This parameter can be a value of @ref I2C_LL_EC_PERIPHERAL_MODE.
-
-                                     This feature can be modified afterwards using unitary function
-                                     @ref LL_I2C_SetMode(). */
-
-  uint32_t Timing;              /*!< Specifies the SDA setup, hold time and the SCL high, low period values.
-                                     This parameter must be set by referring to the STM32CubeMX Tool and
-                                     the helper macro @ref __LL_I2C_CONVERT_TIMINGS().
-
-                                     This feature can be modified afterwards using unitary function
-                                     @ref LL_I2C_SetTiming(). */
-
-  uint32_t AnalogFilter;        /*!< Enables or disables analog noise filter.
-                                     This parameter can be a value of @ref I2C_LL_EC_ANALOGFILTER_SELECTION.
-
-                                     This feature can be modified afterwards using unitary functions
-                                     @ref LL_I2C_EnableAnalogFilter() or LL_I2C_DisableAnalogFilter(). */
-
-  uint32_t DigitalFilter;       /*!< Configures the digital noise filter.
-                                     This parameter can be a number between Min_Data = 0x00 and Max_Data = 0x0F.
-
-                                     This feature can be modified afterwards using unitary function
-                                     @ref LL_I2C_SetDigitalFilter(). */
-
-  uint32_t OwnAddress1;         /*!< Specifies the device own address 1.
-                                     This parameter must be a value between Min_Data = 0x00 and Max_Data = 0x3FF.
-
-                                     This feature can be modified afterwards using unitary function
-                                     @ref LL_I2C_SetOwnAddress1(). */
-
-  uint32_t TypeAcknowledge;     /*!< Specifies the ACKnowledge or Non ACKnowledge condition after the address receive
-                                     match code or next received byte.
-                                     This parameter can be a value of @ref I2C_LL_EC_I2C_ACKNOWLEDGE.
-
-                                     This feature can be modified afterwards using unitary function
-                                     @ref LL_I2C_AcknowledgeNextData(). */
-
-  uint32_t OwnAddrSize;         /*!< Specifies the device own address 1 size (7-bit or 10-bit).
-                                     This parameter can be a value of @ref I2C_LL_EC_OWNADDRESS1.
-
-                                     This feature can be modified afterwards using unitary function
-                                     @ref LL_I2C_SetOwnAddress1(). */
-} LL_I2C_InitTypeDef;
-/**
-  * @}
-  */
-#endif /*USE_FULL_LL_DRIVER*/
-
-/* Exported constants --------------------------------------------------------*/
-/** @defgroup I2C_LL_Exported_Constants I2C Exported Constants
-  * @{
-  */
-
-/** @defgroup I2C_LL_EC_CLEAR_FLAG Clear Flags Defines
-  * @brief    Flags defines which can be used with LL_I2C_WriteReg function
-  * @{
-  */
-#define LL_I2C_ICR_ADDRCF                   I2C_ICR_ADDRCF          /*!< Address Matched flag   */
-#define LL_I2C_ICR_NACKCF                   I2C_ICR_NACKCF          /*!< Not Acknowledge flag   */
-#define LL_I2C_ICR_STOPCF                   I2C_ICR_STOPCF          /*!< Stop detection flag    */
-#define LL_I2C_ICR_BERRCF                   I2C_ICR_BERRCF          /*!< Bus error flag         */
-#define LL_I2C_ICR_ARLOCF                   I2C_ICR_ARLOCF          /*!< Arbitration Lost flag  */
-#define LL_I2C_ICR_OVRCF                    I2C_ICR_OVRCF           /*!< Overrun/Underrun flag  */
-#define LL_I2C_ICR_PECCF                    I2C_ICR_PECCF           /*!< PEC error flag         */
-#define LL_I2C_ICR_TIMOUTCF                 I2C_ICR_TIMOUTCF        /*!< Timeout detection flag */
-#define LL_I2C_ICR_ALERTCF                  I2C_ICR_ALERTCF         /*!< Alert flag             */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_GET_FLAG Get Flags Defines
-  * @brief    Flags defines which can be used with LL_I2C_ReadReg function
-  * @{
-  */
-#define LL_I2C_ISR_TXE                      I2C_ISR_TXE             /*!< Transmit data register empty        */
-#define LL_I2C_ISR_TXIS                     I2C_ISR_TXIS            /*!< Transmit interrupt status           */
-#define LL_I2C_ISR_RXNE                     I2C_ISR_RXNE            /*!< Receive data register not empty     */
-#define LL_I2C_ISR_ADDR                     I2C_ISR_ADDR            /*!< Address matched (slave mode)        */
-#define LL_I2C_ISR_NACKF                    I2C_ISR_NACKF           /*!< Not Acknowledge received flag       */
-#define LL_I2C_ISR_STOPF                    I2C_ISR_STOPF           /*!< Stop detection flag                 */
-#define LL_I2C_ISR_TC                       I2C_ISR_TC              /*!< Transfer Complete (master mode)     */
-#define LL_I2C_ISR_TCR                      I2C_ISR_TCR             /*!< Transfer Complete Reload            */
-#define LL_I2C_ISR_BERR                     I2C_ISR_BERR            /*!< Bus error                           */
-#define LL_I2C_ISR_ARLO                     I2C_ISR_ARLO            /*!< Arbitration lost                    */
-#define LL_I2C_ISR_OVR                      I2C_ISR_OVR             /*!< Overrun/Underrun (slave mode)       */
-#define LL_I2C_ISR_PECERR                   I2C_ISR_PECERR          /*!< PEC Error in reception (SMBus mode) */
-#define LL_I2C_ISR_TIMEOUT                  I2C_ISR_TIMEOUT         /*!< Timeout detection flag (SMBus mode) */
-#define LL_I2C_ISR_ALERT                    I2C_ISR_ALERT           /*!< SMBus alert (SMBus mode)            */
-#define LL_I2C_ISR_BUSY                     I2C_ISR_BUSY            /*!< Bus busy                            */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_IT IT Defines
-  * @brief    IT defines which can be used with LL_I2C_ReadReg and  LL_I2C_WriteReg functions
-  * @{
-  */
-#define LL_I2C_CR1_TXIE                     I2C_CR1_TXIE            /*!< TX Interrupt enable                         */
-#define LL_I2C_CR1_RXIE                     I2C_CR1_RXIE            /*!< RX Interrupt enable                         */
-#define LL_I2C_CR1_ADDRIE                   I2C_CR1_ADDRIE          /*!< Address match Interrupt enable (slave only) */
-#define LL_I2C_CR1_NACKIE                   I2C_CR1_NACKIE          /*!< Not acknowledge received Interrupt enable   */
-#define LL_I2C_CR1_STOPIE                   I2C_CR1_STOPIE          /*!< STOP detection Interrupt enable             */
-#define LL_I2C_CR1_TCIE                     I2C_CR1_TCIE            /*!< Transfer Complete interrupt enable          */
-#define LL_I2C_CR1_ERRIE                    I2C_CR1_ERRIE           /*!< Error interrupts enable                     */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_PERIPHERAL_MODE Peripheral Mode
-  * @{
-  */
-#define LL_I2C_MODE_I2C                    0x00000000U              /*!< I2C Master or Slave mode                 */
-#define LL_I2C_MODE_SMBUS_HOST             I2C_CR1_SMBHEN           /*!< SMBus Host address acknowledge           */
-#define LL_I2C_MODE_SMBUS_DEVICE           0x00000000U              /*!< SMBus Device default mode
-                                                                         (Default address not acknowledge)        */
-#define LL_I2C_MODE_SMBUS_DEVICE_ARP       I2C_CR1_SMBDEN           /*!< SMBus Device Default address acknowledge */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_ANALOGFILTER_SELECTION Analog Filter Selection
-  * @{
-  */
-#define LL_I2C_ANALOGFILTER_ENABLE          0x00000000U             /*!< Analog filter is enabled.  */
-#define LL_I2C_ANALOGFILTER_DISABLE         I2C_CR1_ANFOFF          /*!< Analog filter is disabled. */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_ADDRESSING_MODE Master Addressing Mode
-  * @{
-  */
-#define LL_I2C_ADDRESSING_MODE_7BIT         0x00000000U              /*!< Master operates in 7-bit addressing mode. */
-#define LL_I2C_ADDRESSING_MODE_10BIT        I2C_CR2_ADD10            /*!< Master operates in 10-bit addressing mode.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_OWNADDRESS1 Own Address 1 Length
-  * @{
-  */
-#define LL_I2C_OWNADDRESS1_7BIT             0x00000000U             /*!< Own address 1 is a 7-bit address. */
-#define LL_I2C_OWNADDRESS1_10BIT            I2C_OAR1_OA1MODE        /*!< Own address 1 is a 10-bit address.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_OWNADDRESS2 Own Address 2 Masks
-  * @{
-  */
-#define LL_I2C_OWNADDRESS2_NOMASK           I2C_OAR2_OA2NOMASK      /*!< Own Address2 No mask.                 */
-#define LL_I2C_OWNADDRESS2_MASK01           I2C_OAR2_OA2MASK01      /*!< Only Address2 bits[7:2] are compared. */
-#define LL_I2C_OWNADDRESS2_MASK02           I2C_OAR2_OA2MASK02      /*!< Only Address2 bits[7:3] are compared. */
-#define LL_I2C_OWNADDRESS2_MASK03           I2C_OAR2_OA2MASK03      /*!< Only Address2 bits[7:4] are compared. */
-#define LL_I2C_OWNADDRESS2_MASK04           I2C_OAR2_OA2MASK04      /*!< Only Address2 bits[7:5] are compared. */
-#define LL_I2C_OWNADDRESS2_MASK05           I2C_OAR2_OA2MASK05      /*!< Only Address2 bits[7:6] are compared. */
-#define LL_I2C_OWNADDRESS2_MASK06           I2C_OAR2_OA2MASK06      /*!< Only Address2 bits[7] are compared.   */
-#define LL_I2C_OWNADDRESS2_MASK07           I2C_OAR2_OA2MASK07      /*!< No comparison is done.
-                                                                         All Address2 are acknowledged.        */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_I2C_ACKNOWLEDGE Acknowledge Generation
-  * @{
-  */
-#define LL_I2C_ACK                          0x00000000U              /*!< ACK is sent after current received byte. */
-#define LL_I2C_NACK                         I2C_CR2_NACK             /*!< NACK is sent after current received byte.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_ADDRSLAVE Slave Address Length
-  * @{
-  */
-#define LL_I2C_ADDRSLAVE_7BIT               0x00000000U              /*!< Slave Address in 7-bit. */
-#define LL_I2C_ADDRSLAVE_10BIT              I2C_CR2_ADD10            /*!< Slave Address in 10-bit.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_REQUEST Transfer Request Direction
-  * @{
-  */
-#define LL_I2C_REQUEST_WRITE                0x00000000U              /*!< Master request a write transfer. */
-#define LL_I2C_REQUEST_READ                 I2C_CR2_RD_WRN           /*!< Master request a read transfer.  */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_MODE Transfer End Mode
-  * @{
-  */
-#define LL_I2C_MODE_RELOAD                  I2C_CR2_RELOAD           /*!< Enable I2C Reload mode.     */
-#define LL_I2C_MODE_AUTOEND                 I2C_CR2_AUTOEND          /*!< Enable I2C Automatic end mode
-                                                                          with no HW PEC comparison.  */
-#define LL_I2C_MODE_SOFTEND                 0x00000000U              /*!< Enable I2C Software end mode
-                                                                          with no HW PEC comparison.  */
-#define LL_I2C_MODE_SMBUS_RELOAD            LL_I2C_MODE_RELOAD       /*!< Enable SMBUS Automatic end mode
-                                                                          with HW PEC comparison.     */
-#define LL_I2C_MODE_SMBUS_AUTOEND_NO_PEC    LL_I2C_MODE_AUTOEND      /*!< Enable SMBUS Automatic end mode
-                                                                          with HW PEC comparison.     */
-#define LL_I2C_MODE_SMBUS_SOFTEND_NO_PEC    LL_I2C_MODE_SOFTEND      /*!< Enable SMBUS Software end mode
-                                                                          with HW PEC comparison.     */
-#define LL_I2C_MODE_SMBUS_AUTOEND_WITH_PEC  (uint32_t)(LL_I2C_MODE_AUTOEND | I2C_CR2_PECBYTE)
-/*!< Enable SMBUS Automatic end mode with HW PEC comparison.   */
-#define LL_I2C_MODE_SMBUS_SOFTEND_WITH_PEC  (uint32_t)(LL_I2C_MODE_SOFTEND | I2C_CR2_PECBYTE)
-/*!< Enable SMBUS Software end mode with HW PEC comparison.    */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_GENERATE Start And Stop Generation
-  * @{
-  */
-#define LL_I2C_GENERATE_NOSTARTSTOP         0x00000000U
-/*!< Don't Generate Stop and Start condition. */
-#define LL_I2C_GENERATE_STOP                (uint32_t)(0x80000000U | I2C_CR2_STOP)
-/*!< Generate Stop condition (Size should be set to 0).      */
-#define LL_I2C_GENERATE_START_READ          (uint32_t)(0x80000000U | I2C_CR2_START | I2C_CR2_RD_WRN)
-/*!< Generate Start for read request. */
-#define LL_I2C_GENERATE_START_WRITE         (uint32_t)(0x80000000U | I2C_CR2_START)
-/*!< Generate Start for write request. */
-#define LL_I2C_GENERATE_RESTART_7BIT_READ   (uint32_t)(0x80000000U | I2C_CR2_START | I2C_CR2_RD_WRN)
-/*!< Generate Restart for read request, slave 7Bit address.  */
-#define LL_I2C_GENERATE_RESTART_7BIT_WRITE  (uint32_t)(0x80000000U | I2C_CR2_START)
-/*!< Generate Restart for write request, slave 7Bit address. */
-#define LL_I2C_GENERATE_RESTART_10BIT_READ  (uint32_t)(0x80000000U | I2C_CR2_START | \
-                                                       I2C_CR2_RD_WRN | I2C_CR2_HEAD10R)
-/*!< Generate Restart for read request, slave 10Bit address. */
-#define LL_I2C_GENERATE_RESTART_10BIT_WRITE (uint32_t)(0x80000000U | I2C_CR2_START)
-/*!< Generate Restart for write request, slave 10Bit address.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_DIRECTION Read Write Direction
-  * @{
-  */
-#define LL_I2C_DIRECTION_WRITE              0x00000000U              /*!< Write transfer request by master,
-                                                                          slave enters receiver mode.  */
-#define LL_I2C_DIRECTION_READ               I2C_ISR_DIR              /*!< Read transfer request by master,
-                                                                          slave enters transmitter mode.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_DMA_REG_DATA DMA Register Data
-  * @{
-  */
-#define LL_I2C_DMA_REG_DATA_TRANSMIT        0x00000000U              /*!< Get address of data register used for
-                                                                          transmission */
-#define LL_I2C_DMA_REG_DATA_RECEIVE         0x00000001U              /*!< Get address of data register used for
-                                                                          reception */
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_SMBUS_TIMEOUTA_MODE SMBus TimeoutA Mode SCL SDA Timeout
-  * @{
-  */
-#define LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW      0x00000000U          /*!< TimeoutA is used to detect
-                                                                          SCL low level timeout.              */
-#define LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH I2C_TIMEOUTR_TIDLE   /*!< TimeoutA is used to detect
-                                                                          both SCL and SDA high level timeout.*/
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EC_SMBUS_TIMEOUT_SELECTION SMBus Timeout Selection
-  * @{
-  */
-#define LL_I2C_SMBUS_TIMEOUTA               I2C_TIMEOUTR_TIMOUTEN                 /*!< TimeoutA enable bit          */
-#define LL_I2C_SMBUS_TIMEOUTB               I2C_TIMEOUTR_TEXTEN                   /*!< TimeoutB (extended clock)
-                                                                                       enable bit                   */
-#define LL_I2C_SMBUS_ALL_TIMEOUT            (uint32_t)(I2C_TIMEOUTR_TIMOUTEN | \
-                                                       I2C_TIMEOUTR_TEXTEN)       /*!< TimeoutA and TimeoutB
-(extended clock) enable bits */
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/* Exported macro ------------------------------------------------------------*/
-/** @defgroup I2C_LL_Exported_Macros I2C Exported Macros
-  * @{
-  */
-
-/** @defgroup I2C_LL_EM_WRITE_READ Common Write and read registers Macros
-  * @{
-  */
-
-/**
-  * @brief  Write a value in I2C register
-  * @param  __INSTANCE__ I2C Instance
-  * @param  __REG__ Register to be written
-  * @param  __VALUE__ Value to be written in the register
-  * @retval None
-  */
-#define LL_I2C_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__))
-
-/**
-  * @brief  Read a value in I2C register
-  * @param  __INSTANCE__ I2C Instance
-  * @param  __REG__ Register to be read
-  * @retval Register value
-  */
-#define LL_I2C_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__)
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EM_CONVERT_TIMINGS Convert SDA SCL timings
-  * @{
-  */
-/**
-  * @brief  Configure the SDA setup, hold time and the SCL high, low period.
-  * @param  __PRESCALER__ This parameter must be a value between  Min_Data=0 and Max_Data=0xF.
-  * @param  __SETUP_TIME__ This parameter must be a value between Min_Data=0 and Max_Data=0xF.
-                           (tscldel = (SCLDEL+1)xtpresc)
-  * @param  __HOLD_TIME__  This parameter must be a value between Min_Data=0 and Max_Data=0xF.
-                           (tsdadel = SDADELxtpresc)
-  * @param  __SCLH_PERIOD__ This parameter must be a value between Min_Data=0 and Max_Data=0xFF.
-                            (tsclh = (SCLH+1)xtpresc)
-  * @param  __SCLL_PERIOD__ This parameter must be a value between  Min_Data=0 and Max_Data=0xFF.
-                            (tscll = (SCLL+1)xtpresc)
-  * @retval Value between Min_Data=0 and Max_Data=0xFFFFFFFF
-  */
-#define __LL_I2C_CONVERT_TIMINGS(__PRESCALER__, __SETUP_TIME__, __HOLD_TIME__, __SCLH_PERIOD__, __SCLL_PERIOD__) \
-  ((((uint32_t)(__PRESCALER__)    << I2C_TIMINGR_PRESC_Pos)  & I2C_TIMINGR_PRESC)   | \
-   (((uint32_t)(__SETUP_TIME__)   << I2C_TIMINGR_SCLDEL_Pos) & I2C_TIMINGR_SCLDEL)  | \
-   (((uint32_t)(__HOLD_TIME__)    << I2C_TIMINGR_SDADEL_Pos) & I2C_TIMINGR_SDADEL)  | \
-   (((uint32_t)(__SCLH_PERIOD__)  << I2C_TIMINGR_SCLH_Pos)   & I2C_TIMINGR_SCLH)    | \
-   (((uint32_t)(__SCLL_PERIOD__)  << I2C_TIMINGR_SCLL_Pos)   & I2C_TIMINGR_SCLL))
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/* Exported functions --------------------------------------------------------*/
-/** @defgroup I2C_LL_Exported_Functions I2C Exported Functions
-  * @{
-  */
-
-/** @defgroup I2C_LL_EF_Configuration Configuration
-  * @{
-  */
-
-/**
-  * @brief  Enable I2C peripheral (PE = 1).
-  * @rmtoll CR1          PE            LL_I2C_Enable
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_Enable(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_PE);
-}
-
-/**
-  * @brief  Disable I2C peripheral (PE = 0).
-  * @note   When PE = 0, the I2C SCL and SDA lines are released.
-  *         Internal state machines and status bits are put back to their reset value.
-  *         When cleared, PE must be kept low for at least 3 APB clock cycles.
-  * @rmtoll CR1          PE            LL_I2C_Disable
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_Disable(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_PE);
-}
-
-/**
-  * @brief  Check if the I2C peripheral is enabled or disabled.
-  * @rmtoll CR1          PE            LL_I2C_IsEnabled
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabled(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_PE) == (I2C_CR1_PE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Configure Noise Filters (Analog and Digital).
-  * @note   If the analog filter is also enabled, the digital filter is added to analog filter.
-  *         The filters can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll CR1          ANFOFF        LL_I2C_ConfigFilters\n
-  *         CR1          DNF           LL_I2C_ConfigFilters
-  * @param  I2Cx I2C Instance.
-  * @param  AnalogFilter This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_ANALOGFILTER_ENABLE
-  *         @arg @ref LL_I2C_ANALOGFILTER_DISABLE
-  * @param  DigitalFilter This parameter must be a value between Min_Data=0x00 (Digital filter disabled)
-                          and Max_Data=0x0F (Digital filter enabled and filtering capability up to 15*ti2cclk).
-  *         This parameter is used to configure the digital noise filter on SDA and SCL input.
-  *         The digital filter will filter spikes with a length of up to DNF[3:0]*ti2cclk.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ConfigFilters(I2C_TypeDef *I2Cx, uint32_t AnalogFilter, uint32_t DigitalFilter)
-{
-  MODIFY_REG(I2Cx->CR1, I2C_CR1_ANFOFF | I2C_CR1_DNF, AnalogFilter | (DigitalFilter << I2C_CR1_DNF_Pos));
-}
-
-/**
-  * @brief  Configure Digital Noise Filter.
-  * @note   If the analog filter is also enabled, the digital filter is added to analog filter.
-  *         This filter can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll CR1          DNF           LL_I2C_SetDigitalFilter
-  * @param  I2Cx I2C Instance.
-  * @param  DigitalFilter This parameter must be a value between Min_Data=0x00 (Digital filter disabled)
-                          and Max_Data=0x0F (Digital filter enabled and filtering capability up to 15*ti2cclk).
-  *         This parameter is used to configure the digital noise filter on SDA and SCL input.
-  *         The digital filter will filter spikes with a length of up to DNF[3:0]*ti2cclk.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetDigitalFilter(I2C_TypeDef *I2Cx, uint32_t DigitalFilter)
-{
-  MODIFY_REG(I2Cx->CR1, I2C_CR1_DNF, DigitalFilter << I2C_CR1_DNF_Pos);
-}
-
-/**
-  * @brief  Get the current Digital Noise Filter configuration.
-  * @rmtoll CR1          DNF           LL_I2C_GetDigitalFilter
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x0 and Max_Data=0xF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetDigitalFilter(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->CR1, I2C_CR1_DNF) >> I2C_CR1_DNF_Pos);
-}
-
-/**
-  * @brief  Enable Analog Noise Filter.
-  * @note   This filter can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll CR1          ANFOFF        LL_I2C_EnableAnalogFilter
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableAnalogFilter(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_ANFOFF);
-}
-
-/**
-  * @brief  Disable Analog Noise Filter.
-  * @note   This filter can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll CR1          ANFOFF        LL_I2C_DisableAnalogFilter
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableAnalogFilter(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_ANFOFF);
-}
-
-/**
-  * @brief  Check if Analog Noise Filter is enabled or disabled.
-  * @rmtoll CR1          ANFOFF        LL_I2C_IsEnabledAnalogFilter
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledAnalogFilter(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_ANFOFF) != (I2C_CR1_ANFOFF)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable DMA transmission requests.
-  * @rmtoll CR1          TXDMAEN       LL_I2C_EnableDMAReq_TX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableDMAReq_TX(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_TXDMAEN);
-}
-
-/**
-  * @brief  Disable DMA transmission requests.
-  * @rmtoll CR1          TXDMAEN       LL_I2C_DisableDMAReq_TX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableDMAReq_TX(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_TXDMAEN);
-}
-
-/**
-  * @brief  Check if DMA transmission requests are enabled or disabled.
-  * @rmtoll CR1          TXDMAEN       LL_I2C_IsEnabledDMAReq_TX
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledDMAReq_TX(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_TXDMAEN) == (I2C_CR1_TXDMAEN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable DMA reception requests.
-  * @rmtoll CR1          RXDMAEN       LL_I2C_EnableDMAReq_RX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableDMAReq_RX(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_RXDMAEN);
-}
-
-/**
-  * @brief  Disable DMA reception requests.
-  * @rmtoll CR1          RXDMAEN       LL_I2C_DisableDMAReq_RX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableDMAReq_RX(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_RXDMAEN);
-}
-
-/**
-  * @brief  Check if DMA reception requests are enabled or disabled.
-  * @rmtoll CR1          RXDMAEN       LL_I2C_IsEnabledDMAReq_RX
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledDMAReq_RX(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_RXDMAEN) == (I2C_CR1_RXDMAEN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Get the data register address used for DMA transfer
-  * @rmtoll TXDR         TXDATA        LL_I2C_DMA_GetRegAddr\n
-  *         RXDR         RXDATA        LL_I2C_DMA_GetRegAddr
-  * @param  I2Cx I2C Instance
-  * @param  Direction This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_DMA_REG_DATA_TRANSMIT
-  *         @arg @ref LL_I2C_DMA_REG_DATA_RECEIVE
-  * @retval Address of data register
-  */
-__STATIC_INLINE uint32_t LL_I2C_DMA_GetRegAddr(const I2C_TypeDef *I2Cx, uint32_t Direction)
-{
-  uint32_t data_reg_addr;
-
-  if (Direction == LL_I2C_DMA_REG_DATA_TRANSMIT)
-  {
-    /* return address of TXDR register */
-    data_reg_addr = (uint32_t) &(I2Cx->TXDR);
-  }
-  else
-  {
-    /* return address of RXDR register */
-    data_reg_addr = (uint32_t) &(I2Cx->RXDR);
-  }
-
-  return data_reg_addr;
-}
-
-/**
-  * @brief  Enable Clock stretching.
-  * @note   This bit can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll CR1          NOSTRETCH     LL_I2C_EnableClockStretching
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableClockStretching(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH);
-}
-
-/**
-  * @brief  Disable Clock stretching.
-  * @note   This bit can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll CR1          NOSTRETCH     LL_I2C_DisableClockStretching
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableClockStretching(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH);
-}
-
-/**
-  * @brief  Check if Clock stretching is enabled or disabled.
-  * @rmtoll CR1          NOSTRETCH     LL_I2C_IsEnabledClockStretching
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledClockStretching(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH) != (I2C_CR1_NOSTRETCH)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable hardware byte control in slave mode.
-  * @rmtoll CR1          SBC           LL_I2C_EnableSlaveByteControl
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableSlaveByteControl(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_SBC);
-}
-
-/**
-  * @brief  Disable hardware byte control in slave mode.
-  * @rmtoll CR1          SBC           LL_I2C_DisableSlaveByteControl
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableSlaveByteControl(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_SBC);
-}
-
-/**
-  * @brief  Check if hardware byte control in slave mode is enabled or disabled.
-  * @rmtoll CR1          SBC           LL_I2C_IsEnabledSlaveByteControl
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledSlaveByteControl(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_SBC) == (I2C_CR1_SBC)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable Wakeup from STOP.
-  * @note   The macro IS_I2C_WAKEUP_FROMSTOP_INSTANCE(I2Cx) can be used to check whether or not
-  *         WakeUpFromStop feature is supported by the I2Cx Instance.
-  * @note   This bit can only be programmed when Digital Filter is disabled.
-  * @rmtoll CR1          WUPEN         LL_I2C_EnableWakeUpFromStop
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableWakeUpFromStop(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_WUPEN);
-}
-
-/**
-  * @brief  Disable Wakeup from STOP.
-  * @note   The macro IS_I2C_WAKEUP_FROMSTOP_INSTANCE(I2Cx) can be used to check whether or not
-  *         WakeUpFromStop feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          WUPEN         LL_I2C_DisableWakeUpFromStop
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableWakeUpFromStop(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_WUPEN);
-}
-
-/**
-  * @brief  Check if Wakeup from STOP is enabled or disabled.
-  * @note   The macro IS_I2C_WAKEUP_FROMSTOP_INSTANCE(I2Cx) can be used to check whether or not
-  *         WakeUpFromStop feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          WUPEN         LL_I2C_IsEnabledWakeUpFromStop
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledWakeUpFromStop(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_WUPEN) == (I2C_CR1_WUPEN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable General Call.
-  * @note   When enabled the Address 0x00 is ACKed.
-  * @rmtoll CR1          GCEN          LL_I2C_EnableGeneralCall
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableGeneralCall(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_GCEN);
-}
-
-/**
-  * @brief  Disable General Call.
-  * @note   When disabled the Address 0x00 is NACKed.
-  * @rmtoll CR1          GCEN          LL_I2C_DisableGeneralCall
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableGeneralCall(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_GCEN);
-}
-
-/**
-  * @brief  Check if General Call is enabled or disabled.
-  * @rmtoll CR1          GCEN          LL_I2C_IsEnabledGeneralCall
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledGeneralCall(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_GCEN) == (I2C_CR1_GCEN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Configure the Master to operate in 7-bit or 10-bit addressing mode.
-  * @note   Changing this bit is not allowed, when the START bit is set.
-  * @rmtoll CR2          ADD10         LL_I2C_SetMasterAddressingMode
-  * @param  I2Cx I2C Instance.
-  * @param  AddressingMode This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_ADDRESSING_MODE_7BIT
-  *         @arg @ref LL_I2C_ADDRESSING_MODE_10BIT
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetMasterAddressingMode(I2C_TypeDef *I2Cx, uint32_t AddressingMode)
-{
-  MODIFY_REG(I2Cx->CR2, I2C_CR2_ADD10, AddressingMode);
-}
-
-/**
-  * @brief  Get the Master addressing mode.
-  * @rmtoll CR2          ADD10         LL_I2C_GetMasterAddressingMode
-  * @param  I2Cx I2C Instance.
-  * @retval Returned value can be one of the following values:
-  *         @arg @ref LL_I2C_ADDRESSING_MODE_7BIT
-  *         @arg @ref LL_I2C_ADDRESSING_MODE_10BIT
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetMasterAddressingMode(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_ADD10));
-}
-
-/**
-  * @brief  Set the Own Address1.
-  * @rmtoll OAR1         OA1           LL_I2C_SetOwnAddress1\n
-  *         OAR1         OA1MODE       LL_I2C_SetOwnAddress1
-  * @param  I2Cx I2C Instance.
-  * @param  OwnAddress1 This parameter must be a value between Min_Data=0 and Max_Data=0x3FF.
-  * @param  OwnAddrSize This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_OWNADDRESS1_7BIT
-  *         @arg @ref LL_I2C_OWNADDRESS1_10BIT
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetOwnAddress1(I2C_TypeDef *I2Cx, uint32_t OwnAddress1, uint32_t OwnAddrSize)
-{
-  MODIFY_REG(I2Cx->OAR1, I2C_OAR1_OA1 | I2C_OAR1_OA1MODE, OwnAddress1 | OwnAddrSize);
-}
-
-/**
-  * @brief  Enable acknowledge on Own Address1 match address.
-  * @rmtoll OAR1         OA1EN         LL_I2C_EnableOwnAddress1
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableOwnAddress1(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->OAR1, I2C_OAR1_OA1EN);
-}
-
-/**
-  * @brief  Disable acknowledge on Own Address1 match address.
-  * @rmtoll OAR1         OA1EN         LL_I2C_DisableOwnAddress1
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableOwnAddress1(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->OAR1, I2C_OAR1_OA1EN);
-}
-
-/**
-  * @brief  Check if Own Address1 acknowledge is enabled or disabled.
-  * @rmtoll OAR1         OA1EN         LL_I2C_IsEnabledOwnAddress1
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledOwnAddress1(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->OAR1, I2C_OAR1_OA1EN) == (I2C_OAR1_OA1EN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Set the 7bits Own Address2.
-  * @note   This action has no effect if own address2 is enabled.
-  * @rmtoll OAR2         OA2           LL_I2C_SetOwnAddress2\n
-  *         OAR2         OA2MSK        LL_I2C_SetOwnAddress2
-  * @param  I2Cx I2C Instance.
-  * @param  OwnAddress2 Value between Min_Data=0 and Max_Data=0x7F.
-  * @param  OwnAddrMask This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_OWNADDRESS2_NOMASK
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK01
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK02
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK03
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK04
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK05
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK06
-  *         @arg @ref LL_I2C_OWNADDRESS2_MASK07
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetOwnAddress2(I2C_TypeDef *I2Cx, uint32_t OwnAddress2, uint32_t OwnAddrMask)
-{
-  MODIFY_REG(I2Cx->OAR2, I2C_OAR2_OA2 | I2C_OAR2_OA2MSK, OwnAddress2 | OwnAddrMask);
-}
-
-/**
-  * @brief  Enable acknowledge on Own Address2 match address.
-  * @rmtoll OAR2         OA2EN         LL_I2C_EnableOwnAddress2
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableOwnAddress2(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->OAR2, I2C_OAR2_OA2EN);
-}
-
-/**
-  * @brief  Disable  acknowledge on Own Address2 match address.
-  * @rmtoll OAR2         OA2EN         LL_I2C_DisableOwnAddress2
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableOwnAddress2(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->OAR2, I2C_OAR2_OA2EN);
-}
-
-/**
-  * @brief  Check if Own Address1 acknowledge is enabled or disabled.
-  * @rmtoll OAR2         OA2EN         LL_I2C_IsEnabledOwnAddress2
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledOwnAddress2(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->OAR2, I2C_OAR2_OA2EN) == (I2C_OAR2_OA2EN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Configure the SDA setup, hold time and the SCL high, low period.
-  * @note   This bit can only be programmed when the I2C is disabled (PE = 0).
-  * @rmtoll TIMINGR      TIMINGR       LL_I2C_SetTiming
-  * @param  I2Cx I2C Instance.
-  * @param  Timing This parameter must be a value between Min_Data=0 and Max_Data=0xFFFFFFFF.
-  * @note   This parameter is computed with the STM32CubeMX Tool.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetTiming(I2C_TypeDef *I2Cx, uint32_t Timing)
-{
-  WRITE_REG(I2Cx->TIMINGR, Timing);
-}
-
-/**
-  * @brief  Get the Timing Prescaler setting.
-  * @rmtoll TIMINGR      PRESC         LL_I2C_GetTimingPrescaler
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x0 and Max_Data=0xF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetTimingPrescaler(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_PRESC) >> I2C_TIMINGR_PRESC_Pos);
-}
-
-/**
-  * @brief  Get the SCL low period setting.
-  * @rmtoll TIMINGR      SCLL          LL_I2C_GetClockLowPeriod
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x00 and Max_Data=0xFF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetClockLowPeriod(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SCLL) >> I2C_TIMINGR_SCLL_Pos);
-}
-
-/**
-  * @brief  Get the SCL high period setting.
-  * @rmtoll TIMINGR      SCLH          LL_I2C_GetClockHighPeriod
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x00 and Max_Data=0xFF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetClockHighPeriod(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SCLH) >> I2C_TIMINGR_SCLH_Pos);
-}
-
-/**
-  * @brief  Get the SDA hold time.
-  * @rmtoll TIMINGR      SDADEL        LL_I2C_GetDataHoldTime
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x0 and Max_Data=0xF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetDataHoldTime(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SDADEL) >> I2C_TIMINGR_SDADEL_Pos);
-}
-
-/**
-  * @brief  Get the SDA setup time.
-  * @rmtoll TIMINGR      SCLDEL        LL_I2C_GetDataSetupTime
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x0 and Max_Data=0xF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetDataSetupTime(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SCLDEL) >> I2C_TIMINGR_SCLDEL_Pos);
-}
-
-/**
-  * @brief  Configure peripheral mode.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          SMBHEN        LL_I2C_SetMode\n
-  *         CR1          SMBDEN        LL_I2C_SetMode
-  * @param  I2Cx I2C Instance.
-  * @param  PeripheralMode This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_MODE_I2C
-  *         @arg @ref LL_I2C_MODE_SMBUS_HOST
-  *         @arg @ref LL_I2C_MODE_SMBUS_DEVICE
-  *         @arg @ref LL_I2C_MODE_SMBUS_DEVICE_ARP
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetMode(I2C_TypeDef *I2Cx, uint32_t PeripheralMode)
-{
-  MODIFY_REG(I2Cx->CR1, I2C_CR1_SMBHEN | I2C_CR1_SMBDEN, PeripheralMode);
-}
-
-/**
-  * @brief  Get peripheral mode.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          SMBHEN        LL_I2C_GetMode\n
-  *         CR1          SMBDEN        LL_I2C_GetMode
-  * @param  I2Cx I2C Instance.
-  * @retval Returned value can be one of the following values:
-  *         @arg @ref LL_I2C_MODE_I2C
-  *         @arg @ref LL_I2C_MODE_SMBUS_HOST
-  *         @arg @ref LL_I2C_MODE_SMBUS_DEVICE
-  *         @arg @ref LL_I2C_MODE_SMBUS_DEVICE_ARP
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetMode(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->CR1, I2C_CR1_SMBHEN | I2C_CR1_SMBDEN));
-}
-
-/**
-  * @brief  Enable SMBus alert (Host or Device mode)
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   SMBus Device mode:
-  *         - SMBus Alert pin is drived low and
-  *           Alert Response Address Header acknowledge is enabled.
-  *         SMBus Host mode:
-  *         - SMBus Alert pin management is supported.
-  * @rmtoll CR1          ALERTEN       LL_I2C_EnableSMBusAlert
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableSMBusAlert(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_ALERTEN);
-}
-
-/**
-  * @brief  Disable SMBus alert (Host or Device mode)
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   SMBus Device mode:
-  *         - SMBus Alert pin is not drived (can be used as a standard GPIO) and
-  *           Alert Response Address Header acknowledge is disabled.
-  *         SMBus Host mode:
-  *         - SMBus Alert pin management is not supported.
-  * @rmtoll CR1          ALERTEN       LL_I2C_DisableSMBusAlert
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableSMBusAlert(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_ALERTEN);
-}
-
-/**
-  * @brief  Check if SMBus alert (Host or Device mode) is enabled or disabled.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          ALERTEN       LL_I2C_IsEnabledSMBusAlert
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusAlert(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_ALERTEN) == (I2C_CR1_ALERTEN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable SMBus Packet Error Calculation (PEC).
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          PECEN         LL_I2C_EnableSMBusPEC
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableSMBusPEC(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_PECEN);
-}
-
-/**
-  * @brief  Disable SMBus Packet Error Calculation (PEC).
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          PECEN         LL_I2C_DisableSMBusPEC
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableSMBusPEC(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_PECEN);
-}
-
-/**
-  * @brief  Check if SMBus Packet Error Calculation (PEC) is enabled or disabled.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR1          PECEN         LL_I2C_IsEnabledSMBusPEC
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPEC(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_PECEN) == (I2C_CR1_PECEN)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Configure the SMBus Clock Timeout.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   This configuration can only be programmed when associated Timeout is disabled (TimeoutA and/orTimeoutB).
-  * @rmtoll TIMEOUTR     TIMEOUTA      LL_I2C_ConfigSMBusTimeout\n
-  *         TIMEOUTR     TIDLE         LL_I2C_ConfigSMBusTimeout\n
-  *         TIMEOUTR     TIMEOUTB      LL_I2C_ConfigSMBusTimeout
-  * @param  I2Cx I2C Instance.
-  * @param  TimeoutA This parameter must be a value between  Min_Data=0 and Max_Data=0xFFF.
-  * @param  TimeoutAMode This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH
-  * @param  TimeoutB
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ConfigSMBusTimeout(I2C_TypeDef *I2Cx, uint32_t TimeoutA, uint32_t TimeoutAMode,
-                                               uint32_t TimeoutB)
-{
-  MODIFY_REG(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIMEOUTA | I2C_TIMEOUTR_TIDLE | I2C_TIMEOUTR_TIMEOUTB,
-             TimeoutA | TimeoutAMode | (TimeoutB << I2C_TIMEOUTR_TIMEOUTB_Pos));
-}
-
-/**
-  * @brief  Configure the SMBus Clock TimeoutA (SCL low timeout or SCL and SDA high timeout depends on TimeoutA mode).
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   These bits can only be programmed when TimeoutA is disabled.
-  * @rmtoll TIMEOUTR     TIMEOUTA      LL_I2C_SetSMBusTimeoutA
-  * @param  I2Cx I2C Instance.
-  * @param  TimeoutA This parameter must be a value between  Min_Data=0 and Max_Data=0xFFF.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetSMBusTimeoutA(I2C_TypeDef *I2Cx, uint32_t TimeoutA)
-{
-  WRITE_REG(I2Cx->TIMEOUTR, TimeoutA);
-}
-
-/**
-  * @brief  Get the SMBus Clock TimeoutA setting.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll TIMEOUTR     TIMEOUTA      LL_I2C_GetSMBusTimeoutA
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0 and Max_Data=0xFFF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetSMBusTimeoutA(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIMEOUTA));
-}
-
-/**
-  * @brief  Set the SMBus Clock TimeoutA mode.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   This bit can only be programmed when TimeoutA is disabled.
-  * @rmtoll TIMEOUTR     TIDLE         LL_I2C_SetSMBusTimeoutAMode
-  * @param  I2Cx I2C Instance.
-  * @param  TimeoutAMode This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetSMBusTimeoutAMode(I2C_TypeDef *I2Cx, uint32_t TimeoutAMode)
-{
-  WRITE_REG(I2Cx->TIMEOUTR, TimeoutAMode);
-}
-
-/**
-  * @brief  Get the SMBus Clock TimeoutA mode.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll TIMEOUTR     TIDLE         LL_I2C_GetSMBusTimeoutAMode
-  * @param  I2Cx I2C Instance.
-  * @retval Returned value can be one of the following values:
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetSMBusTimeoutAMode(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIDLE));
-}
-
-/**
-  * @brief  Configure the SMBus Extended Cumulative Clock TimeoutB (Master or Slave mode).
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   These bits can only be programmed when TimeoutB is disabled.
-  * @rmtoll TIMEOUTR     TIMEOUTB      LL_I2C_SetSMBusTimeoutB
-  * @param  I2Cx I2C Instance.
-  * @param  TimeoutB This parameter must be a value between  Min_Data=0 and Max_Data=0xFFF.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetSMBusTimeoutB(I2C_TypeDef *I2Cx, uint32_t TimeoutB)
-{
-  WRITE_REG(I2Cx->TIMEOUTR, TimeoutB << I2C_TIMEOUTR_TIMEOUTB_Pos);
-}
-
-/**
-  * @brief  Get the SMBus Extended Cumulative Clock TimeoutB setting.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll TIMEOUTR     TIMEOUTB      LL_I2C_GetSMBusTimeoutB
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0 and Max_Data=0xFFF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetSMBusTimeoutB(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIMEOUTB) >> I2C_TIMEOUTR_TIMEOUTB_Pos);
-}
-
-/**
-  * @brief  Enable the SMBus Clock Timeout.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll TIMEOUTR     TIMOUTEN      LL_I2C_EnableSMBusTimeout\n
-  *         TIMEOUTR     TEXTEN        LL_I2C_EnableSMBusTimeout
-  * @param  I2Cx I2C Instance.
-  * @param  ClockTimeout This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTB
-  *         @arg @ref LL_I2C_SMBUS_ALL_TIMEOUT
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableSMBusTimeout(I2C_TypeDef *I2Cx, uint32_t ClockTimeout)
-{
-  SET_BIT(I2Cx->TIMEOUTR, ClockTimeout);
-}
-
-/**
-  * @brief  Disable the SMBus Clock Timeout.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll TIMEOUTR     TIMOUTEN      LL_I2C_DisableSMBusTimeout\n
-  *         TIMEOUTR     TEXTEN        LL_I2C_DisableSMBusTimeout
-  * @param  I2Cx I2C Instance.
-  * @param  ClockTimeout This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTB
-  *         @arg @ref LL_I2C_SMBUS_ALL_TIMEOUT
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableSMBusTimeout(I2C_TypeDef *I2Cx, uint32_t ClockTimeout)
-{
-  CLEAR_BIT(I2Cx->TIMEOUTR, ClockTimeout);
-}
-
-/**
-  * @brief  Check if the SMBus Clock Timeout is enabled or disabled.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll TIMEOUTR     TIMOUTEN      LL_I2C_IsEnabledSMBusTimeout\n
-  *         TIMEOUTR     TEXTEN        LL_I2C_IsEnabledSMBusTimeout
-  * @param  I2Cx I2C Instance.
-  * @param  ClockTimeout This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTA
-  *         @arg @ref LL_I2C_SMBUS_TIMEOUTB
-  *         @arg @ref LL_I2C_SMBUS_ALL_TIMEOUT
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusTimeout(const I2C_TypeDef *I2Cx, uint32_t ClockTimeout)
-{
-  return ((READ_BIT(I2Cx->TIMEOUTR, (I2C_TIMEOUTR_TIMOUTEN | I2C_TIMEOUTR_TEXTEN)) == \
-           (ClockTimeout)) ? 1UL : 0UL);
-}
-
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EF_IT_Management IT_Management
-  * @{
-  */
-
-/**
-  * @brief  Enable TXIS interrupt.
-  * @rmtoll CR1          TXIE          LL_I2C_EnableIT_TX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_TX(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_TXIE);
-}
-
-/**
-  * @brief  Disable TXIS interrupt.
-  * @rmtoll CR1          TXIE          LL_I2C_DisableIT_TX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_TX(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_TXIE);
-}
-
-/**
-  * @brief  Check if the TXIS Interrupt is enabled or disabled.
-  * @rmtoll CR1          TXIE          LL_I2C_IsEnabledIT_TX
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_TX(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_TXIE) == (I2C_CR1_TXIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable RXNE interrupt.
-  * @rmtoll CR1          RXIE          LL_I2C_EnableIT_RX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_RX(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_RXIE);
-}
-
-/**
-  * @brief  Disable RXNE interrupt.
-  * @rmtoll CR1          RXIE          LL_I2C_DisableIT_RX
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_RX(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_RXIE);
-}
-
-/**
-  * @brief  Check if the RXNE Interrupt is enabled or disabled.
-  * @rmtoll CR1          RXIE          LL_I2C_IsEnabledIT_RX
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_RX(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_RXIE) == (I2C_CR1_RXIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable Address match interrupt (slave mode only).
-  * @rmtoll CR1          ADDRIE        LL_I2C_EnableIT_ADDR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_ADDR(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_ADDRIE);
-}
-
-/**
-  * @brief  Disable Address match interrupt (slave mode only).
-  * @rmtoll CR1          ADDRIE        LL_I2C_DisableIT_ADDR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_ADDR(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_ADDRIE);
-}
-
-/**
-  * @brief  Check if Address match interrupt is enabled or disabled.
-  * @rmtoll CR1          ADDRIE        LL_I2C_IsEnabledIT_ADDR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_ADDR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_ADDRIE) == (I2C_CR1_ADDRIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable Not acknowledge received interrupt.
-  * @rmtoll CR1          NACKIE        LL_I2C_EnableIT_NACK
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_NACK(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_NACKIE);
-}
-
-/**
-  * @brief  Disable Not acknowledge received interrupt.
-  * @rmtoll CR1          NACKIE        LL_I2C_DisableIT_NACK
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_NACK(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_NACKIE);
-}
-
-/**
-  * @brief  Check if Not acknowledge received interrupt is enabled or disabled.
-  * @rmtoll CR1          NACKIE        LL_I2C_IsEnabledIT_NACK
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_NACK(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_NACKIE) == (I2C_CR1_NACKIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable STOP detection interrupt.
-  * @rmtoll CR1          STOPIE        LL_I2C_EnableIT_STOP
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_STOP(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_STOPIE);
-}
-
-/**
-  * @brief  Disable STOP detection interrupt.
-  * @rmtoll CR1          STOPIE        LL_I2C_DisableIT_STOP
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_STOP(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_STOPIE);
-}
-
-/**
-  * @brief  Check if STOP detection interrupt is enabled or disabled.
-  * @rmtoll CR1          STOPIE        LL_I2C_IsEnabledIT_STOP
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_STOP(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_STOPIE) == (I2C_CR1_STOPIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable Transfer Complete interrupt.
-  * @note   Any of these events will generate interrupt :
-  *         Transfer Complete (TC)
-  *         Transfer Complete Reload (TCR)
-  * @rmtoll CR1          TCIE          LL_I2C_EnableIT_TC
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_TC(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_TCIE);
-}
-
-/**
-  * @brief  Disable Transfer Complete interrupt.
-  * @note   Any of these events will generate interrupt :
-  *         Transfer Complete (TC)
-  *         Transfer Complete Reload (TCR)
-  * @rmtoll CR1          TCIE          LL_I2C_DisableIT_TC
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_TC(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_TCIE);
-}
-
-/**
-  * @brief  Check if Transfer Complete interrupt is enabled or disabled.
-  * @rmtoll CR1          TCIE          LL_I2C_IsEnabledIT_TC
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_TC(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_TCIE) == (I2C_CR1_TCIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable Error interrupts.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   Any of these errors will generate interrupt :
-  *         Arbitration Loss (ARLO)
-  *         Bus Error detection (BERR)
-  *         Overrun/Underrun (OVR)
-  *         SMBus Timeout detection (TIMEOUT)
-  *         SMBus PEC error detection (PECERR)
-  *         SMBus Alert pin event detection (ALERT)
-  * @rmtoll CR1          ERRIE         LL_I2C_EnableIT_ERR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableIT_ERR(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR1, I2C_CR1_ERRIE);
-}
-
-/**
-  * @brief  Disable Error interrupts.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   Any of these errors will generate interrupt :
-  *         Arbitration Loss (ARLO)
-  *         Bus Error detection (BERR)
-  *         Overrun/Underrun (OVR)
-  *         SMBus Timeout detection (TIMEOUT)
-  *         SMBus PEC error detection (PECERR)
-  *         SMBus Alert pin event detection (ALERT)
-  * @rmtoll CR1          ERRIE         LL_I2C_DisableIT_ERR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableIT_ERR(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR1, I2C_CR1_ERRIE);
-}
-
-/**
-  * @brief  Check if Error interrupts are enabled or disabled.
-  * @rmtoll CR1          ERRIE         LL_I2C_IsEnabledIT_ERR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_ERR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR1, I2C_CR1_ERRIE) == (I2C_CR1_ERRIE)) ? 1UL : 0UL);
-}
-
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EF_FLAG_management FLAG_management
-  * @{
-  */
-
-/**
-  * @brief  Indicate the status of Transmit data register empty flag.
-  * @note   RESET: When next data is written in Transmit data register.
-  *         SET: When Transmit data register is empty.
-  * @rmtoll ISR          TXE           LL_I2C_IsActiveFlag_TXE
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TXE(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_TXE) == (I2C_ISR_TXE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Transmit interrupt flag.
-  * @note   RESET: When next data is written in Transmit data register.
-  *         SET: When Transmit data register is empty.
-  * @rmtoll ISR          TXIS          LL_I2C_IsActiveFlag_TXIS
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TXIS(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_TXIS) == (I2C_ISR_TXIS)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Receive data register not empty flag.
-  * @note   RESET: When Receive data register is read.
-  *         SET: When the received data is copied in Receive data register.
-  * @rmtoll ISR          RXNE          LL_I2C_IsActiveFlag_RXNE
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_RXNE(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_RXNE) == (I2C_ISR_RXNE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Address matched flag (slave mode).
-  * @note   RESET: Clear default value.
-  *         SET: When the received slave address matched with one of the enabled slave address.
-  * @rmtoll ISR          ADDR          LL_I2C_IsActiveFlag_ADDR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ADDR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_ADDR) == (I2C_ISR_ADDR)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Not Acknowledge received flag.
-  * @note   RESET: Clear default value.
-  *         SET: When a NACK is received after a byte transmission.
-  * @rmtoll ISR          NACKF         LL_I2C_IsActiveFlag_NACK
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_NACK(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_NACKF) == (I2C_ISR_NACKF)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Stop detection flag.
-  * @note   RESET: Clear default value.
-  *         SET: When a Stop condition is detected.
-  * @rmtoll ISR          STOPF         LL_I2C_IsActiveFlag_STOP
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_STOP(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_STOPF) == (I2C_ISR_STOPF)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Transfer complete flag (master mode).
-  * @note   RESET: Clear default value.
-  *         SET: When RELOAD=0, AUTOEND=0 and NBYTES date have been transferred.
-  * @rmtoll ISR          TC            LL_I2C_IsActiveFlag_TC
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TC(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_TC) == (I2C_ISR_TC)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Transfer complete flag (master mode).
-  * @note   RESET: Clear default value.
-  *         SET: When RELOAD=1 and NBYTES date have been transferred.
-  * @rmtoll ISR          TCR           LL_I2C_IsActiveFlag_TCR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TCR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_TCR) == (I2C_ISR_TCR)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Bus error flag.
-  * @note   RESET: Clear default value.
-  *         SET: When a misplaced Start or Stop condition is detected.
-  * @rmtoll ISR          BERR          LL_I2C_IsActiveFlag_BERR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BERR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_BERR) == (I2C_ISR_BERR)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Arbitration lost flag.
-  * @note   RESET: Clear default value.
-  *         SET: When arbitration lost.
-  * @rmtoll ISR          ARLO          LL_I2C_IsActiveFlag_ARLO
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ARLO(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_ARLO) == (I2C_ISR_ARLO)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Overrun/Underrun flag (slave mode).
-  * @note   RESET: Clear default value.
-  *         SET: When an overrun/underrun error occurs (Clock Stretching Disabled).
-  * @rmtoll ISR          OVR           LL_I2C_IsActiveFlag_OVR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_OVR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_OVR) == (I2C_ISR_OVR)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of SMBus PEC error flag in reception.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   RESET: Clear default value.
-  *         SET: When the received PEC does not match with the PEC register content.
-  * @rmtoll ISR          PECERR        LL_I2C_IsActiveSMBusFlag_PECERR
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_PECERR(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_PECERR) == (I2C_ISR_PECERR)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of SMBus Timeout detection flag.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   RESET: Clear default value.
-  *         SET: When a timeout or extended clock timeout occurs.
-  * @rmtoll ISR          TIMEOUT       LL_I2C_IsActiveSMBusFlag_TIMEOUT
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_TIMEOUT(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_TIMEOUT) == (I2C_ISR_TIMEOUT)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of SMBus alert flag.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   RESET: Clear default value.
-  *         SET: When SMBus host configuration, SMBus alert enabled and
-  *              a falling edge event occurs on SMBA pin.
-  * @rmtoll ISR          ALERT         LL_I2C_IsActiveSMBusFlag_ALERT
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_ALERT(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_ALERT) == (I2C_ISR_ALERT)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Indicate the status of Bus Busy flag.
-  * @note   RESET: Clear default value.
-  *         SET: When a Start condition is detected.
-  * @rmtoll ISR          BUSY          LL_I2C_IsActiveFlag_BUSY
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BUSY(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->ISR, I2C_ISR_BUSY) == (I2C_ISR_BUSY)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Clear Address Matched flag.
-  * @rmtoll ICR          ADDRCF        LL_I2C_ClearFlag_ADDR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_ADDR(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_ADDRCF);
-}
-
-/**
-  * @brief  Clear Not Acknowledge flag.
-  * @rmtoll ICR          NACKCF        LL_I2C_ClearFlag_NACK
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_NACK(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_NACKCF);
-}
-
-/**
-  * @brief  Clear Stop detection flag.
-  * @rmtoll ICR          STOPCF        LL_I2C_ClearFlag_STOP
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_STOP(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_STOPCF);
-}
-
-/**
-  * @brief  Clear Transmit data register empty flag (TXE).
-  * @note   This bit can be clear by software in order to flush the transmit data register (TXDR).
-  * @rmtoll ISR          TXE           LL_I2C_ClearFlag_TXE
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_TXE(I2C_TypeDef *I2Cx)
-{
-  WRITE_REG(I2Cx->ISR, I2C_ISR_TXE);
-}
-
-/**
-  * @brief  Clear Bus error flag.
-  * @rmtoll ICR          BERRCF        LL_I2C_ClearFlag_BERR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_BERR(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_BERRCF);
-}
-
-/**
-  * @brief  Clear Arbitration lost flag.
-  * @rmtoll ICR          ARLOCF        LL_I2C_ClearFlag_ARLO
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_ARLO(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_ARLOCF);
-}
-
-/**
-  * @brief  Clear Overrun/Underrun flag.
-  * @rmtoll ICR          OVRCF         LL_I2C_ClearFlag_OVR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearFlag_OVR(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_OVRCF);
-}
-
-/**
-  * @brief  Clear SMBus PEC error flag.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll ICR          PECCF         LL_I2C_ClearSMBusFlag_PECERR
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearSMBusFlag_PECERR(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_PECCF);
-}
-
-/**
-  * @brief  Clear SMBus Timeout detection flag.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll ICR          TIMOUTCF      LL_I2C_ClearSMBusFlag_TIMEOUT
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearSMBusFlag_TIMEOUT(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_TIMOUTCF);
-}
-
-/**
-  * @brief  Clear SMBus Alert flag.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll ICR          ALERTCF       LL_I2C_ClearSMBusFlag_ALERT
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_ClearSMBusFlag_ALERT(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->ICR, I2C_ICR_ALERTCF);
-}
-
-/**
-  * @}
-  */
-
-/** @defgroup I2C_LL_EF_Data_Management Data_Management
-  * @{
-  */
-
-/**
-  * @brief  Enable automatic STOP condition generation (master mode).
-  * @note   Automatic end mode : a STOP condition is automatically sent when NBYTES data are transferred.
-  *         This bit has no effect in slave mode or when RELOAD bit is set.
-  * @rmtoll CR2          AUTOEND       LL_I2C_EnableAutoEndMode
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableAutoEndMode(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR2, I2C_CR2_AUTOEND);
-}
-
-/**
-  * @brief  Disable automatic STOP condition generation (master mode).
-  * @note   Software end mode : TC flag is set when NBYTES data are transferre, stretching SCL low.
-  * @rmtoll CR2          AUTOEND       LL_I2C_DisableAutoEndMode
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableAutoEndMode(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR2, I2C_CR2_AUTOEND);
-}
-
-/**
-  * @brief  Check if automatic STOP condition is enabled or disabled.
-  * @rmtoll CR2          AUTOEND       LL_I2C_IsEnabledAutoEndMode
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledAutoEndMode(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR2, I2C_CR2_AUTOEND) == (I2C_CR2_AUTOEND)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Enable reload mode (master mode).
-  * @note   The transfer is not completed after the NBYTES data transfer, NBYTES will be reloaded when TCR flag is set.
-  * @rmtoll CR2          RELOAD       LL_I2C_EnableReloadMode
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableReloadMode(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR2, I2C_CR2_RELOAD);
-}
-
-/**
-  * @brief  Disable reload mode (master mode).
-  * @note   The transfer is completed after the NBYTES data transfer(STOP or RESTART will follow).
-  * @rmtoll CR2          RELOAD       LL_I2C_DisableReloadMode
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableReloadMode(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR2, I2C_CR2_RELOAD);
-}
-
-/**
-  * @brief  Check if reload mode is enabled or disabled.
-  * @rmtoll CR2          RELOAD       LL_I2C_IsEnabledReloadMode
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledReloadMode(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR2, I2C_CR2_RELOAD) == (I2C_CR2_RELOAD)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Configure the number of bytes for transfer.
-  * @note   Changing these bits when START bit is set is not allowed.
-  * @rmtoll CR2          NBYTES           LL_I2C_SetTransferSize
-  * @param  I2Cx I2C Instance.
-  * @param  TransferSize This parameter must be a value between Min_Data=0x00 and Max_Data=0xFF.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetTransferSize(I2C_TypeDef *I2Cx, uint32_t TransferSize)
-{
-  MODIFY_REG(I2Cx->CR2, I2C_CR2_NBYTES, TransferSize << I2C_CR2_NBYTES_Pos);
-}
-
-/**
-  * @brief  Get the number of bytes configured for transfer.
-  * @rmtoll CR2          NBYTES           LL_I2C_GetTransferSize
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x0 and Max_Data=0xFF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetTransferSize(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_NBYTES) >> I2C_CR2_NBYTES_Pos);
-}
-
-/**
-  * @brief  Prepare the generation of a ACKnowledge or Non ACKnowledge condition after the address receive match code
-            or next received byte.
-  * @note   Usage in Slave mode only.
-  * @rmtoll CR2          NACK          LL_I2C_AcknowledgeNextData
-  * @param  I2Cx I2C Instance.
-  * @param  TypeAcknowledge This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_ACK
-  *         @arg @ref LL_I2C_NACK
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_AcknowledgeNextData(I2C_TypeDef *I2Cx, uint32_t TypeAcknowledge)
-{
-  MODIFY_REG(I2Cx->CR2, I2C_CR2_NACK, TypeAcknowledge);
-}
-
-/**
-  * @brief  Generate a START or RESTART condition
-  * @note   The START bit can be set even if bus is BUSY or I2C is in slave mode.
-  *         This action has no effect when RELOAD is set.
-  * @rmtoll CR2          START           LL_I2C_GenerateStartCondition
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_GenerateStartCondition(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR2, I2C_CR2_START);
-}
-
-/**
-  * @brief  Generate a STOP condition after the current byte transfer (master mode).
-  * @rmtoll CR2          STOP          LL_I2C_GenerateStopCondition
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_GenerateStopCondition(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR2, I2C_CR2_STOP);
-}
-
-/**
-  * @brief  Enable automatic RESTART Read request condition for 10bit address header (master mode).
-  * @note   The master sends the complete 10bit slave address read sequence :
-  *         Start + 2 bytes 10bit address in Write direction + Restart + first 7 bits of 10bit address
-            in Read direction.
-  * @rmtoll CR2          HEAD10R       LL_I2C_EnableAuto10BitRead
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableAuto10BitRead(I2C_TypeDef *I2Cx)
-{
-  CLEAR_BIT(I2Cx->CR2, I2C_CR2_HEAD10R);
-}
-
-/**
-  * @brief  Disable automatic RESTART Read request condition for 10bit address header (master mode).
-  * @note   The master only sends the first 7 bits of 10bit address in Read direction.
-  * @rmtoll CR2          HEAD10R       LL_I2C_DisableAuto10BitRead
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_DisableAuto10BitRead(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR2, I2C_CR2_HEAD10R);
-}
-
-/**
-  * @brief  Check if automatic RESTART Read request condition for 10bit address header is enabled or disabled.
-  * @rmtoll CR2          HEAD10R       LL_I2C_IsEnabledAuto10BitRead
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledAuto10BitRead(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR2, I2C_CR2_HEAD10R) != (I2C_CR2_HEAD10R)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Configure the transfer direction (master mode).
-  * @note   Changing these bits when START bit is set is not allowed.
-  * @rmtoll CR2          RD_WRN           LL_I2C_SetTransferRequest
-  * @param  I2Cx I2C Instance.
-  * @param  TransferRequest This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_REQUEST_WRITE
-  *         @arg @ref LL_I2C_REQUEST_READ
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetTransferRequest(I2C_TypeDef *I2Cx, uint32_t TransferRequest)
-{
-  MODIFY_REG(I2Cx->CR2, I2C_CR2_RD_WRN, TransferRequest);
-}
-
-/**
-  * @brief  Get the transfer direction requested (master mode).
-  * @rmtoll CR2          RD_WRN           LL_I2C_GetTransferRequest
-  * @param  I2Cx I2C Instance.
-  * @retval Returned value can be one of the following values:
-  *         @arg @ref LL_I2C_REQUEST_WRITE
-  *         @arg @ref LL_I2C_REQUEST_READ
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetTransferRequest(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_RD_WRN));
-}
-
-/**
-  * @brief  Configure the slave address for transfer (master mode).
-  * @note   Changing these bits when START bit is set is not allowed.
-  * @rmtoll CR2          SADD           LL_I2C_SetSlaveAddr
-  * @param  I2Cx I2C Instance.
-  * @param  SlaveAddr This parameter must be a value between Min_Data=0x00 and Max_Data=0x3F.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_SetSlaveAddr(I2C_TypeDef *I2Cx, uint32_t SlaveAddr)
-{
-  MODIFY_REG(I2Cx->CR2, I2C_CR2_SADD, SlaveAddr);
-}
-
-/**
-  * @brief  Get the slave address programmed for transfer.
-  * @rmtoll CR2          SADD           LL_I2C_GetSlaveAddr
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x0 and Max_Data=0x3F
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetSlaveAddr(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_SADD));
-}
-
-/**
-  * @brief  Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
-  * @rmtoll CR2          SADD          LL_I2C_HandleTransfer\n
-  *         CR2          ADD10         LL_I2C_HandleTransfer\n
-  *         CR2          RD_WRN        LL_I2C_HandleTransfer\n
-  *         CR2          START         LL_I2C_HandleTransfer\n
-  *         CR2          STOP          LL_I2C_HandleTransfer\n
-  *         CR2          RELOAD        LL_I2C_HandleTransfer\n
-  *         CR2          NBYTES        LL_I2C_HandleTransfer\n
-  *         CR2          AUTOEND       LL_I2C_HandleTransfer\n
-  *         CR2          HEAD10R       LL_I2C_HandleTransfer
-  * @param  I2Cx I2C Instance.
-  * @param  SlaveAddr Specifies the slave address to be programmed.
-  * @param  SlaveAddrSize This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_ADDRSLAVE_7BIT
-  *         @arg @ref LL_I2C_ADDRSLAVE_10BIT
-  * @param  TransferSize Specifies the number of bytes to be programmed.
-  *                       This parameter must be a value between Min_Data=0 and Max_Data=255.
-  * @param  EndMode This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_MODE_RELOAD
-  *         @arg @ref LL_I2C_MODE_AUTOEND
-  *         @arg @ref LL_I2C_MODE_SOFTEND
-  *         @arg @ref LL_I2C_MODE_SMBUS_RELOAD
-  *         @arg @ref LL_I2C_MODE_SMBUS_AUTOEND_NO_PEC
-  *         @arg @ref LL_I2C_MODE_SMBUS_SOFTEND_NO_PEC
-  *         @arg @ref LL_I2C_MODE_SMBUS_AUTOEND_WITH_PEC
-  *         @arg @ref LL_I2C_MODE_SMBUS_SOFTEND_WITH_PEC
-  * @param  Request This parameter can be one of the following values:
-  *         @arg @ref LL_I2C_GENERATE_NOSTARTSTOP
-  *         @arg @ref LL_I2C_GENERATE_STOP
-  *         @arg @ref LL_I2C_GENERATE_START_READ
-  *         @arg @ref LL_I2C_GENERATE_START_WRITE
-  *         @arg @ref LL_I2C_GENERATE_RESTART_7BIT_READ
-  *         @arg @ref LL_I2C_GENERATE_RESTART_7BIT_WRITE
-  *         @arg @ref LL_I2C_GENERATE_RESTART_10BIT_READ
-  *         @arg @ref LL_I2C_GENERATE_RESTART_10BIT_WRITE
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_HandleTransfer(I2C_TypeDef *I2Cx, uint32_t SlaveAddr, uint32_t SlaveAddrSize,
-                                           uint32_t TransferSize, uint32_t EndMode, uint32_t Request)
-{
-  /* Declaration of tmp to prevent undefined behavior of volatile usage */
-  uint32_t tmp = ((uint32_t)(((uint32_t)SlaveAddr & I2C_CR2_SADD) | \
-                             ((uint32_t)SlaveAddrSize & I2C_CR2_ADD10) | \
-                             (((uint32_t)TransferSize << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | \
-                             (uint32_t)EndMode | (uint32_t)Request) & (~0x80000000U));
-
-  /* update CR2 register */
-  MODIFY_REG(I2Cx->CR2, I2C_CR2_SADD | I2C_CR2_ADD10 |
-             (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) |
-             I2C_CR2_START | I2C_CR2_STOP | I2C_CR2_RELOAD |
-             I2C_CR2_NBYTES | I2C_CR2_AUTOEND | I2C_CR2_HEAD10R,
-             tmp);
-}
-
-/**
-  * @brief  Indicate the value of transfer direction (slave mode).
-  * @note   RESET: Write transfer, Slave enters in receiver mode.
-  *         SET: Read transfer, Slave enters in transmitter mode.
-  * @rmtoll ISR          DIR           LL_I2C_GetTransferDirection
-  * @param  I2Cx I2C Instance.
-  * @retval Returned value can be one of the following values:
-  *         @arg @ref LL_I2C_DIRECTION_WRITE
-  *         @arg @ref LL_I2C_DIRECTION_READ
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetTransferDirection(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->ISR, I2C_ISR_DIR));
-}
-
-/**
-  * @brief  Return the slave matched address.
-  * @rmtoll ISR          ADDCODE       LL_I2C_GetAddressMatchCode
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x00 and Max_Data=0x3F
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetAddressMatchCode(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->ISR, I2C_ISR_ADDCODE) >> I2C_ISR_ADDCODE_Pos << 1);
-}
-
-/**
-  * @brief  Enable internal comparison of the SMBus Packet Error byte (transmission or reception mode).
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @note   This feature is cleared by hardware when the PEC byte is transferred, or when a STOP condition
-            or an Address Matched is received.
-  *         This bit has no effect when RELOAD bit is set.
-  *         This bit has no effect in device mode when SBC bit is not set.
-  * @rmtoll CR2          PECBYTE       LL_I2C_EnableSMBusPECCompare
-  * @param  I2Cx I2C Instance.
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_EnableSMBusPECCompare(I2C_TypeDef *I2Cx)
-{
-  SET_BIT(I2Cx->CR2, I2C_CR2_PECBYTE);
-}
-
-/**
-  * @brief  Check if the SMBus Packet Error byte internal comparison is requested or not.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll CR2          PECBYTE       LL_I2C_IsEnabledSMBusPECCompare
-  * @param  I2Cx I2C Instance.
-  * @retval State of bit (1 or 0).
-  */
-__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPECCompare(const I2C_TypeDef *I2Cx)
-{
-  return ((READ_BIT(I2Cx->CR2, I2C_CR2_PECBYTE) == (I2C_CR2_PECBYTE)) ? 1UL : 0UL);
-}
-
-/**
-  * @brief  Get the SMBus Packet Error byte calculated.
-  * @note   The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not
-  *         SMBus feature is supported by the I2Cx Instance.
-  * @rmtoll PECR         PEC           LL_I2C_GetSMBusPEC
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x00 and Max_Data=0xFF
-  */
-__STATIC_INLINE uint32_t LL_I2C_GetSMBusPEC(const I2C_TypeDef *I2Cx)
-{
-  return (uint32_t)(READ_BIT(I2Cx->PECR, I2C_PECR_PEC));
-}
-
-/**
-  * @brief  Read Receive Data register.
-  * @rmtoll RXDR         RXDATA        LL_I2C_ReceiveData8
-  * @param  I2Cx I2C Instance.
-  * @retval Value between Min_Data=0x00 and Max_Data=0xFF
-  */
-__STATIC_INLINE uint8_t LL_I2C_ReceiveData8(const I2C_TypeDef *I2Cx)
-{
-  return (uint8_t)(READ_BIT(I2Cx->RXDR, I2C_RXDR_RXDATA));
-}
-
-/**
-  * @brief  Write in Transmit Data Register .
-  * @rmtoll TXDR         TXDATA        LL_I2C_TransmitData8
-  * @param  I2Cx I2C Instance.
-  * @param  Data Value between Min_Data=0x00 and Max_Data=0xFF
-  * @retval None
-  */
-__STATIC_INLINE void LL_I2C_TransmitData8(I2C_TypeDef *I2Cx, uint8_t Data)
-{
-  WRITE_REG(I2Cx->TXDR, Data);
-}
-
-/**
-  * @}
-  */
-
-#if defined(USE_FULL_LL_DRIVER)
-/** @defgroup I2C_LL_EF_Init Initialization and de-initialization functions
-  * @{
-  */
-
-ErrorStatus LL_I2C_Init(I2C_TypeDef *I2Cx, const LL_I2C_InitTypeDef *I2C_InitStruct);
-ErrorStatus LL_I2C_DeInit(const I2C_TypeDef *I2Cx);
-void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct);
-
-
-/**
-  * @}
-  */
-#endif /* USE_FULL_LL_DRIVER */
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-#endif /* I2C1 || I2C2 || I2C3 || I2C4 */
-
-/**
-  * @}
-  */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* STM32L4xx_LL_I2C_H */
diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h
new file mode 100644
index 0000000..ffc750e
--- /dev/null
+++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h
@@ -0,0 +1,1433 @@
+/**
+  ******************************************************************************
+  * @file    stm32l4xx_ll_spi.h
+  * @author  MCD Application Team
+  * @brief   Header file of SPI LL module.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef STM32L4xx_LL_SPI_H
+#define STM32L4xx_LL_SPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx.h"
+
+/** @addtogroup STM32L4xx_LL_Driver
+  * @{
+  */
+
+#if defined (SPI1) || defined (SPI2) || defined (SPI3)
+
+/** @defgroup SPI_LL SPI
+  * @{
+  */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+
+/* Exported types ------------------------------------------------------------*/
+#if defined(USE_FULL_LL_DRIVER)
+/** @defgroup SPI_LL_ES_INIT SPI Exported Init structure
+  * @{
+  */
+
+/**
+  * @brief  SPI Init structures definition
+  */
+typedef struct
+{
+  uint32_t TransferDirection;       /*!< Specifies the SPI unidirectional or bidirectional data mode.
+                                         This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetTransferDirection().*/
+
+  uint32_t Mode;                    /*!< Specifies the SPI mode (Master/Slave).
+                                         This parameter can be a value of @ref SPI_LL_EC_MODE.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetMode().*/
+
+  uint32_t DataWidth;               /*!< Specifies the SPI data width.
+                                         This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetDataWidth().*/
+
+  uint32_t ClockPolarity;           /*!< Specifies the serial clock steady state.
+                                         This parameter can be a value of @ref SPI_LL_EC_POLARITY.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetClockPolarity().*/
+
+  uint32_t ClockPhase;              /*!< Specifies the clock active edge for the bit capture.
+                                         This parameter can be a value of @ref SPI_LL_EC_PHASE.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetClockPhase().*/
+
+  uint32_t NSS;                     /*!< Specifies whether the NSS signal is managed by hardware (NSS pin)
+                                         or by software using the SSI bit.
+                                         This parameter can be a value of @ref SPI_LL_EC_NSS_MODE.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetNSSMode().*/
+
+  uint32_t BaudRate;                /*!< Specifies the BaudRate prescaler value which will be used
+                                         to configure the transmit and receive SCK clock.
+                                         This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER.
+                                         @note The communication clock is derived from the master clock.
+                                               The slave clock does not need to be set.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetBaudRatePrescaler().*/
+
+  uint32_t BitOrder;                /*!< Specifies whether data transfers start from MSB or LSB bit.
+                                         This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetTransferBitOrder().*/
+
+  uint32_t CRCCalculation;          /*!< Specifies if the CRC calculation is enabled or not.
+                                         This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION.
+
+                                         This feature can be modified afterwards using unitary
+                                         functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/
+
+  uint32_t CRCPoly;                 /*!< Specifies the polynomial used for the CRC calculation.
+                                         This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF.
+
+                                         This feature can be modified afterwards using unitary
+                                         function @ref LL_SPI_SetCRCPolynomial().*/
+
+} LL_SPI_InitTypeDef;
+
+/**
+  * @}
+  */
+#endif /* USE_FULL_LL_DRIVER */
+
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup SPI_LL_Exported_Constants SPI Exported Constants
+  * @{
+  */
+
+/** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines
+  * @brief    Flags defines which can be used with LL_SPI_ReadReg function
+  * @{
+  */
+#define LL_SPI_SR_RXNE                     SPI_SR_RXNE               /*!< Rx buffer not empty flag         */
+#define LL_SPI_SR_TXE                      SPI_SR_TXE                /*!< Tx buffer empty flag             */
+#define LL_SPI_SR_BSY                      SPI_SR_BSY                /*!< Busy flag                        */
+#define LL_SPI_SR_CRCERR                   SPI_SR_CRCERR             /*!< CRC error flag                   */
+#define LL_SPI_SR_MODF                     SPI_SR_MODF               /*!< Mode fault flag                  */
+#define LL_SPI_SR_OVR                      SPI_SR_OVR                /*!< Overrun flag                     */
+#define LL_SPI_SR_FRE                      SPI_SR_FRE                /*!< TI mode frame format error flag  */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_IT IT Defines
+  * @brief    IT defines which can be used with LL_SPI_ReadReg and  LL_SPI_WriteReg functions
+  * @{
+  */
+#define LL_SPI_CR2_RXNEIE                  SPI_CR2_RXNEIE            /*!< Rx buffer not empty interrupt enable */
+#define LL_SPI_CR2_TXEIE                   SPI_CR2_TXEIE             /*!< Tx buffer empty interrupt enable     */
+#define LL_SPI_CR2_ERRIE                   SPI_CR2_ERRIE             /*!< Error interrupt enable               */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_MODE Operation Mode
+  * @{
+  */
+#define LL_SPI_MODE_MASTER                 (SPI_CR1_MSTR | SPI_CR1_SSI)    /*!< Master configuration  */
+#define LL_SPI_MODE_SLAVE                  0x00000000U                     /*!< Slave configuration   */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_PROTOCOL Serial Protocol
+  * @{
+  */
+#define LL_SPI_PROTOCOL_MOTOROLA           0x00000000U               /*!< Motorola mode. Used as default value */
+#define LL_SPI_PROTOCOL_TI                 (SPI_CR2_FRF)             /*!< TI mode                              */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_PHASE Clock Phase
+  * @{
+  */
+#define LL_SPI_PHASE_1EDGE                 0x00000000U               /*!< First clock transition is the first data capture edge  */
+#define LL_SPI_PHASE_2EDGE                 (SPI_CR1_CPHA)            /*!< Second clock transition is the first data capture edge */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_POLARITY Clock Polarity
+  * @{
+  */
+#define LL_SPI_POLARITY_LOW                0x00000000U               /*!< Clock to 0 when idle */
+#define LL_SPI_POLARITY_HIGH               (SPI_CR1_CPOL)            /*!< Clock to 1 when idle */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler
+  * @{
+  */
+#define LL_SPI_BAUDRATEPRESCALER_DIV2      0x00000000U                                    /*!< BaudRate control equal to fPCLK/2   */
+#define LL_SPI_BAUDRATEPRESCALER_DIV4      (SPI_CR1_BR_0)                                 /*!< BaudRate control equal to fPCLK/4   */
+#define LL_SPI_BAUDRATEPRESCALER_DIV8      (SPI_CR1_BR_1)                                 /*!< BaudRate control equal to fPCLK/8   */
+#define LL_SPI_BAUDRATEPRESCALER_DIV16     (SPI_CR1_BR_1 | SPI_CR1_BR_0)                  /*!< BaudRate control equal to fPCLK/16  */
+#define LL_SPI_BAUDRATEPRESCALER_DIV32     (SPI_CR1_BR_2)                                 /*!< BaudRate control equal to fPCLK/32  */
+#define LL_SPI_BAUDRATEPRESCALER_DIV64     (SPI_CR1_BR_2 | SPI_CR1_BR_0)                  /*!< BaudRate control equal to fPCLK/64  */
+#define LL_SPI_BAUDRATEPRESCALER_DIV128    (SPI_CR1_BR_2 | SPI_CR1_BR_1)                  /*!< BaudRate control equal to fPCLK/128 */
+#define LL_SPI_BAUDRATEPRESCALER_DIV256    (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)   /*!< BaudRate control equal to fPCLK/256 */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order
+  * @{
+  */
+#define LL_SPI_LSB_FIRST                   (SPI_CR1_LSBFIRST)        /*!< Data is transmitted/received with the LSB first */
+#define LL_SPI_MSB_FIRST                   0x00000000U               /*!< Data is transmitted/received with the MSB first */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode
+  * @{
+  */
+#define LL_SPI_FULL_DUPLEX                 0x00000000U                          /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */
+#define LL_SPI_SIMPLEX_RX                  (SPI_CR1_RXONLY)                     /*!< Simplex Rx mode.  Rx transfer only on 1 line    */
+#define LL_SPI_HALF_DUPLEX_RX              (SPI_CR1_BIDIMODE)                   /*!< Half-Duplex Rx mode. Rx transfer on 1 line      */
+#define LL_SPI_HALF_DUPLEX_TX              (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)  /*!< Half-Duplex Tx mode. Tx transfer on 1 line      */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode
+  * @{
+  */
+#define LL_SPI_NSS_SOFT                    (SPI_CR1_SSM)                     /*!< NSS managed internally. NSS pin not used and free              */
+#define LL_SPI_NSS_HARD_INPUT              0x00000000U                       /*!< NSS pin used in Input. Only used in Master mode                */
+#define LL_SPI_NSS_HARD_OUTPUT             (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_DATAWIDTH Datawidth
+  * @{
+  */
+#define LL_SPI_DATAWIDTH_4BIT              (SPI_CR2_DS_0 | SPI_CR2_DS_1)                               /*!< Data length for SPI transfer:  4 bits */
+#define LL_SPI_DATAWIDTH_5BIT              (SPI_CR2_DS_2)                                              /*!< Data length for SPI transfer:  5 bits */
+#define LL_SPI_DATAWIDTH_6BIT              (SPI_CR2_DS_2 | SPI_CR2_DS_0)                               /*!< Data length for SPI transfer:  6 bits */
+#define LL_SPI_DATAWIDTH_7BIT              (SPI_CR2_DS_2 | SPI_CR2_DS_1)                               /*!< Data length for SPI transfer:  7 bits */
+#define LL_SPI_DATAWIDTH_8BIT              (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0)                /*!< Data length for SPI transfer:  8 bits */
+#define LL_SPI_DATAWIDTH_9BIT              (SPI_CR2_DS_3)                                              /*!< Data length for SPI transfer:  9 bits */
+#define LL_SPI_DATAWIDTH_10BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_0)                               /*!< Data length for SPI transfer: 10 bits */
+#define LL_SPI_DATAWIDTH_11BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_1)                               /*!< Data length for SPI transfer: 11 bits */
+#define LL_SPI_DATAWIDTH_12BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0)                /*!< Data length for SPI transfer: 12 bits */
+#define LL_SPI_DATAWIDTH_13BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_2)                               /*!< Data length for SPI transfer: 13 bits */
+#define LL_SPI_DATAWIDTH_14BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_0)                /*!< Data length for SPI transfer: 14 bits */
+#define LL_SPI_DATAWIDTH_15BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1)                /*!< Data length for SPI transfer: 15 bits */
+#define LL_SPI_DATAWIDTH_16BIT             (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 16 bits */
+/**
+  * @}
+  */
+#if defined(USE_FULL_LL_DRIVER)
+
+/** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation
+  * @{
+  */
+#define LL_SPI_CRCCALCULATION_DISABLE      0x00000000U               /*!< CRC calculation disabled */
+#define LL_SPI_CRCCALCULATION_ENABLE       (SPI_CR1_CRCEN)           /*!< CRC calculation enabled  */
+/**
+  * @}
+  */
+#endif /* USE_FULL_LL_DRIVER */
+
+/** @defgroup SPI_LL_EC_CRC_LENGTH CRC Length
+  * @{
+  */
+#define LL_SPI_CRC_8BIT                    0x00000000U               /*!<  8-bit CRC length */
+#define LL_SPI_CRC_16BIT                   (SPI_CR1_CRCL)            /*!< 16-bit CRC length */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_RX_FIFO_TH RX FIFO Threshold
+  * @{
+  */
+#define LL_SPI_RX_FIFO_TH_HALF             0x00000000U               /*!< RXNE event is generated if FIFO level is greater than or equal to 1/2 (16-bit) */
+#define LL_SPI_RX_FIFO_TH_QUARTER          (SPI_CR2_FRXTH)           /*!< RXNE event is generated if FIFO level is greater than or equal to 1/4 (8-bit)  */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_RX_FIFO RX FIFO Level
+  * @{
+  */
+#define LL_SPI_RX_FIFO_EMPTY               0x00000000U                       /*!< FIFO reception empty */
+#define LL_SPI_RX_FIFO_QUARTER_FULL        (SPI_SR_FRLVL_0)                  /*!< FIFO reception 1/4   */
+#define LL_SPI_RX_FIFO_HALF_FULL           (SPI_SR_FRLVL_1)                  /*!< FIFO reception 1/2   */
+#define LL_SPI_RX_FIFO_FULL                (SPI_SR_FRLVL_1 | SPI_SR_FRLVL_0) /*!< FIFO reception full  */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_TX_FIFO TX FIFO Level
+  * @{
+  */
+#define LL_SPI_TX_FIFO_EMPTY               0x00000000U                       /*!< FIFO transmission empty */
+#define LL_SPI_TX_FIFO_QUARTER_FULL        (SPI_SR_FTLVL_0)                  /*!< FIFO transmission 1/4   */
+#define LL_SPI_TX_FIFO_HALF_FULL           (SPI_SR_FTLVL_1)                  /*!< FIFO transmission 1/2   */
+#define LL_SPI_TX_FIFO_FULL                (SPI_SR_FTLVL_1 | SPI_SR_FTLVL_0) /*!< FIFO transmission full  */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EC_DMA_PARITY DMA Parity
+  * @{
+  */
+#define LL_SPI_DMA_PARITY_EVEN             0x00000000U   /*!< Select DMA parity Even */
+#define LL_SPI_DMA_PARITY_ODD              0x00000001U   /*!< Select DMA parity Odd  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/** @defgroup SPI_LL_Exported_Macros SPI Exported Macros
+  * @{
+  */
+
+/** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros
+  * @{
+  */
+
+/**
+  * @brief  Write a value in SPI register
+  * @param  __INSTANCE__ SPI Instance
+  * @param  __REG__ Register to be written
+  * @param  __VALUE__ Value to be written in the register
+  * @retval None
+  */
+#define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__))
+
+/**
+  * @brief  Read a value in SPI register
+  * @param  __INSTANCE__ SPI Instance
+  * @param  __REG__ Register to be read
+  * @retval Register value
+  */
+#define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__)
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SPI_LL_Exported_Functions SPI Exported Functions
+  * @{
+  */
+
+/** @defgroup SPI_LL_EF_Configuration Configuration
+  * @{
+  */
+
+/**
+  * @brief  Enable SPI peripheral
+  * @rmtoll CR1          SPE           LL_SPI_Enable
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR1, SPI_CR1_SPE);
+}
+
+/**
+  * @brief  Disable SPI peripheral
+  * @note   When disabling the SPI, follow the procedure described in the Reference Manual.
+  * @rmtoll CR1          SPE           LL_SPI_Disable
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE);
+}
+
+/**
+  * @brief  Check if SPI peripheral is enabled
+  * @rmtoll CR1          SPE           LL_SPI_IsEnabled
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabled(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Set SPI operation mode to Master or Slave
+  * @note   This bit should not be changed when communication is ongoing.
+  * @rmtoll CR1          MSTR          LL_SPI_SetMode\n
+  *         CR1          SSI           LL_SPI_SetMode
+  * @param  SPIx SPI Instance
+  * @param  Mode This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_MODE_MASTER
+  *         @arg @ref LL_SPI_MODE_SLAVE
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode);
+}
+
+/**
+  * @brief  Get SPI operation mode (Master or Slave)
+  * @rmtoll CR1          MSTR          LL_SPI_GetMode\n
+  *         CR1          SSI           LL_SPI_GetMode
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_MODE_MASTER
+  *         @arg @ref LL_SPI_MODE_SLAVE
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetMode(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI));
+}
+
+/**
+  * @brief  Set serial protocol used
+  * @note   This bit should be written only when SPI is disabled (SPE = 0) for correct operation.
+  * @rmtoll CR2          FRF           LL_SPI_SetStandard
+  * @param  SPIx SPI Instance
+  * @param  Standard This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_PROTOCOL_MOTOROLA
+  *         @arg @ref LL_SPI_PROTOCOL_TI
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard)
+{
+  MODIFY_REG(SPIx->CR2, SPI_CR2_FRF, Standard);
+}
+
+/**
+  * @brief  Get serial protocol used
+  * @rmtoll CR2          FRF           LL_SPI_GetStandard
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_PROTOCOL_MOTOROLA
+  *         @arg @ref LL_SPI_PROTOCOL_TI
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetStandard(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRF));
+}
+
+/**
+  * @brief  Set clock phase
+  * @note   This bit should not be changed when communication is ongoing.
+  *         This bit is not used in SPI TI mode.
+  * @rmtoll CR1          CPHA          LL_SPI_SetClockPhase
+  * @param  SPIx SPI Instance
+  * @param  ClockPhase This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_PHASE_1EDGE
+  *         @arg @ref LL_SPI_PHASE_2EDGE
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase);
+}
+
+/**
+  * @brief  Get clock phase
+  * @rmtoll CR1          CPHA          LL_SPI_GetClockPhase
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_PHASE_1EDGE
+  *         @arg @ref LL_SPI_PHASE_2EDGE
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetClockPhase(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA));
+}
+
+/**
+  * @brief  Set clock polarity
+  * @note   This bit should not be changed when communication is ongoing.
+  *         This bit is not used in SPI TI mode.
+  * @rmtoll CR1          CPOL          LL_SPI_SetClockPolarity
+  * @param  SPIx SPI Instance
+  * @param  ClockPolarity This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_POLARITY_LOW
+  *         @arg @ref LL_SPI_POLARITY_HIGH
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity);
+}
+
+/**
+  * @brief  Get clock polarity
+  * @rmtoll CR1          CPOL          LL_SPI_GetClockPolarity
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_POLARITY_LOW
+  *         @arg @ref LL_SPI_POLARITY_HIGH
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL));
+}
+
+/**
+  * @brief  Set baud rate prescaler
+  * @note   These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler.
+  * @rmtoll CR1          BR            LL_SPI_SetBaudRatePrescaler
+  * @param  SPIx SPI Instance
+  * @param  BaudRate This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate);
+}
+
+/**
+  * @brief  Get baud rate prescaler
+  * @rmtoll CR1          BR            LL_SPI_GetBaudRatePrescaler
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128
+  *         @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR));
+}
+
+/**
+  * @brief  Set transfer bit order
+  * @note   This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode.
+  * @rmtoll CR1          LSBFIRST      LL_SPI_SetTransferBitOrder
+  * @param  SPIx SPI Instance
+  * @param  BitOrder This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_LSB_FIRST
+  *         @arg @ref LL_SPI_MSB_FIRST
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder);
+}
+
+/**
+  * @brief  Get transfer bit order
+  * @rmtoll CR1          LSBFIRST      LL_SPI_GetTransferBitOrder
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_LSB_FIRST
+  *         @arg @ref LL_SPI_MSB_FIRST
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST));
+}
+
+/**
+  * @brief  Set transfer direction mode
+  * @note   For Half-Duplex mode, Rx Direction is set by default.
+  *         In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex.
+  * @rmtoll CR1          RXONLY        LL_SPI_SetTransferDirection\n
+  *         CR1          BIDIMODE      LL_SPI_SetTransferDirection\n
+  *         CR1          BIDIOE        LL_SPI_SetTransferDirection
+  * @param  SPIx SPI Instance
+  * @param  TransferDirection This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_FULL_DUPLEX
+  *         @arg @ref LL_SPI_SIMPLEX_RX
+  *         @arg @ref LL_SPI_HALF_DUPLEX_RX
+  *         @arg @ref LL_SPI_HALF_DUPLEX_TX
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection);
+}
+
+/**
+  * @brief  Get transfer direction mode
+  * @rmtoll CR1          RXONLY        LL_SPI_GetTransferDirection\n
+  *         CR1          BIDIMODE      LL_SPI_GetTransferDirection\n
+  *         CR1          BIDIOE        LL_SPI_GetTransferDirection
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_FULL_DUPLEX
+  *         @arg @ref LL_SPI_SIMPLEX_RX
+  *         @arg @ref LL_SPI_HALF_DUPLEX_RX
+  *         @arg @ref LL_SPI_HALF_DUPLEX_TX
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE));
+}
+
+/**
+  * @brief  Set frame data width
+  * @rmtoll CR2          DS            LL_SPI_SetDataWidth
+  * @param  SPIx SPI Instance
+  * @param  DataWidth This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_DATAWIDTH_4BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_5BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_6BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_7BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_8BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_9BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_10BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_11BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_12BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_13BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_14BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_15BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_16BIT
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth)
+{
+  MODIFY_REG(SPIx->CR2, SPI_CR2_DS, DataWidth);
+}
+
+/**
+  * @brief  Get frame data width
+  * @rmtoll CR2          DS            LL_SPI_GetDataWidth
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_DATAWIDTH_4BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_5BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_6BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_7BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_8BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_9BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_10BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_11BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_12BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_13BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_14BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_15BIT
+  *         @arg @ref LL_SPI_DATAWIDTH_16BIT
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_DS));
+}
+
+/**
+  * @brief  Set threshold of RXFIFO that triggers an RXNE event
+  * @rmtoll CR2          FRXTH         LL_SPI_SetRxFIFOThreshold
+  * @param  SPIx SPI Instance
+  * @param  Threshold This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_RX_FIFO_TH_HALF
+  *         @arg @ref LL_SPI_RX_FIFO_TH_QUARTER
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetRxFIFOThreshold(SPI_TypeDef *SPIx, uint32_t Threshold)
+{
+  MODIFY_REG(SPIx->CR2, SPI_CR2_FRXTH, Threshold);
+}
+
+/**
+  * @brief  Get threshold of RXFIFO that triggers an RXNE event
+  * @rmtoll CR2          FRXTH         LL_SPI_GetRxFIFOThreshold
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_RX_FIFO_TH_HALF
+  *         @arg @ref LL_SPI_RX_FIFO_TH_QUARTER
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOThreshold(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRXTH));
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EF_CRC_Management CRC Management
+  * @{
+  */
+
+/**
+  * @brief  Enable CRC
+  * @note   This bit should be written only when SPI is disabled (SPE = 0) for correct operation.
+  * @rmtoll CR1          CRCEN         LL_SPI_EnableCRC
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR1, SPI_CR1_CRCEN);
+}
+
+/**
+  * @brief  Disable CRC
+  * @note   This bit should be written only when SPI is disabled (SPE = 0) for correct operation.
+  * @rmtoll CR1          CRCEN         LL_SPI_DisableCRC
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN);
+}
+
+/**
+  * @brief  Check if CRC is enabled
+  * @note   This bit should be written only when SPI is disabled (SPE = 0) for correct operation.
+  * @rmtoll CR1          CRCEN         LL_SPI_IsEnabledCRC
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Set CRC Length
+  * @note   This bit should be written only when SPI is disabled (SPE = 0) for correct operation.
+  * @rmtoll CR1          CRCL          LL_SPI_SetCRCWidth
+  * @param  SPIx SPI Instance
+  * @param  CRCLength This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_CRC_8BIT
+  *         @arg @ref LL_SPI_CRC_16BIT
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetCRCWidth(SPI_TypeDef *SPIx, uint32_t CRCLength)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_CRCL, CRCLength);
+}
+
+/**
+  * @brief  Get CRC Length
+  * @rmtoll CR1          CRCL          LL_SPI_GetCRCWidth
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_CRC_8BIT
+  *         @arg @ref LL_SPI_CRC_16BIT
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetCRCWidth(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CRCL));
+}
+
+/**
+  * @brief  Set CRCNext to transfer CRC on the line
+  * @note   This bit has to be written as soon as the last data is written in the SPIx_DR register.
+  * @rmtoll CR1          CRCNEXT       LL_SPI_SetCRCNext
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT);
+}
+
+/**
+  * @brief  Set polynomial for CRC calculation
+  * @rmtoll CRCPR        CRCPOLY       LL_SPI_SetCRCPolynomial
+  * @param  SPIx SPI Instance
+  * @param  CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly)
+{
+  WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly);
+}
+
+/**
+  * @brief  Get polynomial for CRC calculation
+  * @rmtoll CRCPR        CRCPOLY       LL_SPI_GetCRCPolynomial
+  * @param  SPIx SPI Instance
+  * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_REG(SPIx->CRCPR));
+}
+
+/**
+  * @brief  Get Rx CRC
+  * @rmtoll RXCRCR       RXCRC         LL_SPI_GetRxCRC
+  * @param  SPIx SPI Instance
+  * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetRxCRC(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_REG(SPIx->RXCRCR));
+}
+
+/**
+  * @brief  Get Tx CRC
+  * @rmtoll TXCRCR       TXCRC         LL_SPI_GetTxCRC
+  * @param  SPIx SPI Instance
+  * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetTxCRC(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_REG(SPIx->TXCRCR));
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management
+  * @{
+  */
+
+/**
+  * @brief  Set NSS mode
+  * @note   LL_SPI_NSS_SOFT Mode is not used in SPI TI mode.
+  * @rmtoll CR1          SSM           LL_SPI_SetNSSMode\n
+  * @rmtoll CR2          SSOE          LL_SPI_SetNSSMode
+  * @param  SPIx SPI Instance
+  * @param  NSS This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_NSS_SOFT
+  *         @arg @ref LL_SPI_NSS_HARD_INPUT
+  *         @arg @ref LL_SPI_NSS_HARD_OUTPUT
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS)
+{
+  MODIFY_REG(SPIx->CR1, SPI_CR1_SSM,  NSS);
+  MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U)));
+}
+
+/**
+  * @brief  Get NSS mode
+  * @rmtoll CR1          SSM           LL_SPI_GetNSSMode\n
+  * @rmtoll CR2          SSOE          LL_SPI_GetNSSMode
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_NSS_SOFT
+  *         @arg @ref LL_SPI_NSS_HARD_INPUT
+  *         @arg @ref LL_SPI_NSS_HARD_OUTPUT
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetNSSMode(const SPI_TypeDef *SPIx)
+{
+  uint32_t Ssm  = (READ_BIT(SPIx->CR1, SPI_CR1_SSM));
+  uint32_t Ssoe = (READ_BIT(SPIx->CR2,  SPI_CR2_SSOE) << 16U);
+  return (Ssm | Ssoe);
+}
+
+/**
+  * @brief  Enable NSS pulse management
+  * @note   This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode.
+  * @rmtoll CR2          NSSP          LL_SPI_EnableNSSPulseMgt
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableNSSPulseMgt(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR2, SPI_CR2_NSSP);
+}
+
+/**
+  * @brief  Disable NSS pulse management
+  * @note   This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode.
+  * @rmtoll CR2          NSSP          LL_SPI_DisableNSSPulseMgt
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableNSSPulseMgt(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR2, SPI_CR2_NSSP);
+}
+
+/**
+  * @brief  Check if NSS pulse is enabled
+  * @note   This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode.
+  * @rmtoll CR2          NSSP          LL_SPI_IsEnabledNSSPulse
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledNSSPulse(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR2, SPI_CR2_NSSP) == (SPI_CR2_NSSP)) ? 1UL : 0UL);
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EF_FLAG_Management FLAG Management
+  * @{
+  */
+
+/**
+  * @brief  Check if Rx buffer is not empty
+  * @rmtoll SR           RXNE          LL_SPI_IsActiveFlag_RXNE
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Check if Tx buffer is empty
+  * @rmtoll SR           TXE           LL_SPI_IsActiveFlag_TXE
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Get CRC error flag
+  * @rmtoll SR           CRCERR        LL_SPI_IsActiveFlag_CRCERR
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Get mode fault error flag
+  * @rmtoll SR           MODF          LL_SPI_IsActiveFlag_MODF
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Get overrun error flag
+  * @rmtoll SR           OVR           LL_SPI_IsActiveFlag_OVR
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Get busy flag
+  * @note   The BSY flag is cleared under any one of the following conditions:
+  * -When the SPI is correctly disabled
+  * -When a fault is detected in Master mode (MODF bit set to 1)
+  * -In Master mode, when it finishes a data transmission and no new data is ready to be
+  * sent
+  * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between
+  * each data transfer.
+  * @rmtoll SR           BSY           LL_SPI_IsActiveFlag_BSY
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Get frame format error flag
+  * @rmtoll SR           FRE           LL_SPI_IsActiveFlag_FRE
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_FRE(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->SR, SPI_SR_FRE) == (SPI_SR_FRE)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Get FIFO reception Level
+  * @rmtoll SR           FRLVL         LL_SPI_GetRxFIFOLevel
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_RX_FIFO_EMPTY
+  *         @arg @ref LL_SPI_RX_FIFO_QUARTER_FULL
+  *         @arg @ref LL_SPI_RX_FIFO_HALF_FULL
+  *         @arg @ref LL_SPI_RX_FIFO_FULL
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOLevel(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FRLVL));
+}
+
+/**
+  * @brief  Get FIFO Transmission Level
+  * @rmtoll SR           FTLVL         LL_SPI_GetTxFIFOLevel
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_TX_FIFO_EMPTY
+  *         @arg @ref LL_SPI_TX_FIFO_QUARTER_FULL
+  *         @arg @ref LL_SPI_TX_FIFO_HALF_FULL
+  *         @arg @ref LL_SPI_TX_FIFO_FULL
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetTxFIFOLevel(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FTLVL));
+}
+
+/**
+  * @brief  Clear CRC error flag
+  * @rmtoll SR           CRCERR        LL_SPI_ClearFlag_CRCERR
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR);
+}
+
+/**
+  * @brief  Clear mode fault error flag
+  * @note   Clearing this flag is done by a read access to the SPIx_SR
+  *         register followed by a write access to the SPIx_CR1 register
+  * @rmtoll SR           MODF          LL_SPI_ClearFlag_MODF
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx)
+{
+  __IO uint32_t tmpreg_sr;
+  tmpreg_sr = SPIx->SR;
+  (void) tmpreg_sr;
+  CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE);
+}
+
+/**
+  * @brief  Clear overrun error flag
+  * @note   Clearing this flag is done by a read access to the SPIx_DR
+  *         register followed by a read access to the SPIx_SR register
+  * @rmtoll SR           OVR           LL_SPI_ClearFlag_OVR
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx)
+{
+  __IO uint32_t tmpreg;
+  tmpreg = SPIx->DR;
+  (void) tmpreg;
+  tmpreg = SPIx->SR;
+  (void) tmpreg;
+}
+
+/**
+  * @brief  Clear frame format error flag
+  * @note   Clearing this flag is done by reading SPIx_SR register
+  * @rmtoll SR           FRE           LL_SPI_ClearFlag_FRE
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx)
+{
+  __IO uint32_t tmpreg;
+  tmpreg = SPIx->SR;
+  (void) tmpreg;
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EF_IT_Management Interrupt Management
+  * @{
+  */
+
+/**
+  * @brief  Enable error interrupt
+  * @note   This bit controls the generation of an interrupt when an error condition
+  *         occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode).
+  * @rmtoll CR2          ERRIE         LL_SPI_EnableIT_ERR
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR2, SPI_CR2_ERRIE);
+}
+
+/**
+  * @brief  Enable Rx buffer not empty interrupt
+  * @rmtoll CR2          RXNEIE        LL_SPI_EnableIT_RXNE
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE);
+}
+
+/**
+  * @brief  Enable Tx buffer empty interrupt
+  * @rmtoll CR2          TXEIE         LL_SPI_EnableIT_TXE
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR2, SPI_CR2_TXEIE);
+}
+
+/**
+  * @brief  Disable error interrupt
+  * @note   This bit controls the generation of an interrupt when an error condition
+  *         occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode).
+  * @rmtoll CR2          ERRIE         LL_SPI_DisableIT_ERR
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE);
+}
+
+/**
+  * @brief  Disable Rx buffer not empty interrupt
+  * @rmtoll CR2          RXNEIE        LL_SPI_DisableIT_RXNE
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE);
+}
+
+/**
+  * @brief  Disable Tx buffer empty interrupt
+  * @rmtoll CR2          TXEIE         LL_SPI_DisableIT_TXE
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE);
+}
+
+/**
+  * @brief  Check if error interrupt is enabled
+  * @rmtoll CR2          ERRIE         LL_SPI_IsEnabledIT_ERR
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Check if Rx buffer not empty interrupt is enabled
+  * @rmtoll CR2          RXNEIE        LL_SPI_IsEnabledIT_RXNE
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Check if Tx buffer empty interrupt
+  * @rmtoll CR2          TXEIE         LL_SPI_IsEnabledIT_TXE
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL);
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EF_DMA_Management DMA Management
+  * @{
+  */
+
+/**
+  * @brief  Enable DMA Rx
+  * @rmtoll CR2          RXDMAEN       LL_SPI_EnableDMAReq_RX
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN);
+}
+
+/**
+  * @brief  Disable DMA Rx
+  * @rmtoll CR2          RXDMAEN       LL_SPI_DisableDMAReq_RX
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN);
+}
+
+/**
+  * @brief  Check if DMA Rx is enabled
+  * @rmtoll CR2          RXDMAEN       LL_SPI_IsEnabledDMAReq_RX
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Enable DMA Tx
+  * @rmtoll CR2          TXDMAEN       LL_SPI_EnableDMAReq_TX
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx)
+{
+  SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN);
+}
+
+/**
+  * @brief  Disable DMA Tx
+  * @rmtoll CR2          TXDMAEN       LL_SPI_DisableDMAReq_TX
+  * @param  SPIx SPI Instance
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx)
+{
+  CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN);
+}
+
+/**
+  * @brief  Check if DMA Tx is enabled
+  * @rmtoll CR2          TXDMAEN       LL_SPI_IsEnabledDMAReq_TX
+  * @param  SPIx SPI Instance
+  * @retval State of bit (1 or 0).
+  */
+__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(const SPI_TypeDef *SPIx)
+{
+  return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL);
+}
+
+/**
+  * @brief  Set parity of  Last DMA reception
+  * @rmtoll CR2          LDMARX        LL_SPI_SetDMAParity_RX
+  * @param  SPIx SPI Instance
+  * @param  Parity This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_DMA_PARITY_ODD
+  *         @arg @ref LL_SPI_DMA_PARITY_EVEN
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetDMAParity_RX(SPI_TypeDef *SPIx, uint32_t Parity)
+{
+  MODIFY_REG(SPIx->CR2, SPI_CR2_LDMARX, (Parity << SPI_CR2_LDMARX_Pos));
+}
+
+/**
+  * @brief  Get parity configuration for  Last DMA reception
+  * @rmtoll CR2          LDMARX        LL_SPI_GetDMAParity_RX
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_DMA_PARITY_ODD
+  *         @arg @ref LL_SPI_DMA_PARITY_EVEN
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_RX(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMARX) >> SPI_CR2_LDMARX_Pos);
+}
+
+/**
+  * @brief  Set parity of  Last DMA transmission
+  * @rmtoll CR2          LDMATX        LL_SPI_SetDMAParity_TX
+  * @param  SPIx SPI Instance
+  * @param  Parity This parameter can be one of the following values:
+  *         @arg @ref LL_SPI_DMA_PARITY_ODD
+  *         @arg @ref LL_SPI_DMA_PARITY_EVEN
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_SetDMAParity_TX(SPI_TypeDef *SPIx, uint32_t Parity)
+{
+  MODIFY_REG(SPIx->CR2, SPI_CR2_LDMATX, (Parity << SPI_CR2_LDMATX_Pos));
+}
+
+/**
+  * @brief  Get parity configuration for Last DMA transmission
+  * @rmtoll CR2          LDMATX        LL_SPI_GetDMAParity_TX
+  * @param  SPIx SPI Instance
+  * @retval Returned value can be one of the following values:
+  *         @arg @ref LL_SPI_DMA_PARITY_ODD
+  *         @arg @ref LL_SPI_DMA_PARITY_EVEN
+  */
+__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_TX(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMATX) >> SPI_CR2_LDMATX_Pos);
+}
+
+/**
+  * @brief  Get the data register address used for DMA transfer
+  * @rmtoll DR           DR            LL_SPI_DMA_GetRegAddr
+  * @param  SPIx SPI Instance
+  * @retval Address of data register
+  */
+__STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(const SPI_TypeDef *SPIx)
+{
+  return (uint32_t) &(SPIx->DR);
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_LL_EF_DATA_Management DATA Management
+  * @{
+  */
+
+/**
+  * @brief  Read 8-Bits in the data register
+  * @rmtoll DR           DR            LL_SPI_ReceiveData8
+  * @param  SPIx SPI Instance
+  * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF
+  */
+__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx)
+{
+  return (*((__IO uint8_t *)&SPIx->DR));
+}
+
+/**
+  * @brief  Read 16-Bits in the data register
+  * @rmtoll DR           DR            LL_SPI_ReceiveData16
+  * @param  SPIx SPI Instance
+  * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF
+  */
+__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx)
+{
+  return (uint16_t)(READ_REG(SPIx->DR));
+}
+
+/**
+  * @brief  Write 8-Bits in the data register
+  * @rmtoll DR           DR            LL_SPI_TransmitData8
+  * @param  SPIx SPI Instance
+  * @param  TxData Value between Min_Data=0x00 and Max_Data=0xFF
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData)
+{
+#if defined (__GNUC__)
+  __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR);
+  *spidr = TxData;
+#else
+  *((__IO uint8_t *)&SPIx->DR) = TxData;
+#endif /* __GNUC__ */
+}
+
+/**
+  * @brief  Write 16-Bits in the data register
+  * @rmtoll DR           DR            LL_SPI_TransmitData16
+  * @param  SPIx SPI Instance
+  * @param  TxData Value between Min_Data=0x00 and Max_Data=0xFFFF
+  * @retval None
+  */
+__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData)
+{
+#if defined (__GNUC__)
+  __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR);
+  *spidr = TxData;
+#else
+  SPIx->DR = TxData;
+#endif /* __GNUC__ */
+}
+
+/**
+  * @}
+  */
+#if defined(USE_FULL_LL_DRIVER)
+/** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions
+  * @{
+  */
+
+ErrorStatus LL_SPI_DeInit(const SPI_TypeDef *SPIx);
+ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct);
+void        LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct);
+
+/**
+  * @}
+  */
+#endif /* USE_FULL_LL_DRIVER */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32L4xx_LL_SPI_H */
+
diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi.c
new file mode 100644
index 0000000..ffcd0ab
--- /dev/null
+++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi.c
@@ -0,0 +1,4472 @@
+/**
+  ******************************************************************************
+  * @file    stm32l4xx_hal_spi.c
+  * @author  MCD Application Team
+  * @brief   SPI HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          functionalities of the Serial Peripheral Interface (SPI) peripheral:
+  *           + Initialization and de-initialization functions
+  *           + IO operation functions
+  *           + Peripheral Control functions
+  *           + Peripheral State functions
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  @verbatim
+  ==============================================================================
+                        ##### How to use this driver #####
+  ==============================================================================
+    [..]
+      The SPI HAL driver can be used as follows:
+
+      (#) Declare a SPI_HandleTypeDef handle structure, for example:
+          SPI_HandleTypeDef  hspi;
+
+      (#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API:
+          (##) Enable the SPIx interface clock
+          (##) SPI pins configuration
+              (+++) Enable the clock for the SPI GPIOs
+              (+++) Configure these SPI pins as alternate function push-pull
+          (##) NVIC configuration if you need to use interrupt process
+              (+++) Configure the SPIx interrupt priority
+              (+++) Enable the NVIC SPI IRQ handle
+          (##) DMA Configuration if you need to use DMA process
+              (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel
+              (+++) Enable the DMAx clock
+              (+++) Configure the DMA handle parameters
+              (+++) Configure the DMA Tx or Rx Stream/Channel
+              (+++) Associate the initialized hdma_tx(or _rx)  handle to the hspi DMA Tx or Rx handle
+              (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx
+                    or Rx Stream/Channel
+
+      (#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS
+          management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure.
+
+      (#) Initialize the SPI registers by calling the HAL_SPI_Init() API:
+          (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
+              by calling the customized HAL_SPI_MspInit() API.
+     [..]
+       Circular mode restriction:
+      (#) The DMA circular mode cannot be used when the SPI is configured in these modes:
+          (##) Master 2Lines RxOnly
+          (##) Master 1Line Rx
+      (#) The CRC feature is not managed when the DMA circular mode is enabled
+      (#) When the SPI DMA Pause/Stop features are used, we must use the following APIs
+          the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks
+     [..]
+       Master Receive mode restriction:
+      (#) In Master unidirectional receive-only mode (MSTR =1, BIDIMODE=0, RXONLY=1) or
+          bidirectional receive mode (MSTR=1, BIDIMODE=1, BIDIOE=0), to ensure that the SPI
+          does not initiate a new transfer the following procedure has to be respected:
+          (##) HAL_SPI_DeInit()
+          (##) HAL_SPI_Init()
+     [..]
+       Callback registration:
+
+      (#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1U
+          allows the user to configure dynamically the driver callbacks.
+          Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback.
+
+          Function HAL_SPI_RegisterCallback() allows to register following callbacks:
+            (++) TxCpltCallback        : SPI Tx Completed callback
+            (++) RxCpltCallback        : SPI Rx Completed callback
+            (++) TxRxCpltCallback      : SPI TxRx Completed callback
+            (++) TxHalfCpltCallback    : SPI Tx Half Completed callback
+            (++) RxHalfCpltCallback    : SPI Rx Half Completed callback
+            (++) TxRxHalfCpltCallback  : SPI TxRx Half Completed callback
+            (++) ErrorCallback         : SPI Error callback
+            (++) AbortCpltCallback     : SPI Abort callback
+            (++) MspInitCallback       : SPI Msp Init callback
+            (++) MspDeInitCallback     : SPI Msp DeInit callback
+          This function takes as parameters the HAL peripheral handle, the Callback ID
+          and a pointer to the user callback function.
+
+
+      (#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default
+          weak function.
+          HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle,
+          and the Callback ID.
+          This function allows to reset following callbacks:
+            (++) TxCpltCallback        : SPI Tx Completed callback
+            (++) RxCpltCallback        : SPI Rx Completed callback
+            (++) TxRxCpltCallback      : SPI TxRx Completed callback
+            (++) TxHalfCpltCallback    : SPI Tx Half Completed callback
+            (++) RxHalfCpltCallback    : SPI Rx Half Completed callback
+            (++) TxRxHalfCpltCallback  : SPI TxRx Half Completed callback
+            (++) ErrorCallback         : SPI Error callback
+            (++) AbortCpltCallback     : SPI Abort callback
+            (++) MspInitCallback       : SPI Msp Init callback
+            (++) MspDeInitCallback     : SPI Msp DeInit callback
+
+       [..]
+       By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET
+       all callbacks are set to the corresponding weak functions:
+       examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback().
+       Exception done for MspInit and MspDeInit functions that are
+       reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when
+       these callbacks are null (not registered beforehand).
+       If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit()
+       keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+
+       [..]
+       Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only.
+       Exception done MspInit/MspDeInit functions that can be registered/unregistered
+       in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state,
+       thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
+       Then, the user first registers the MspInit/MspDeInit user callbacks
+       using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit()
+       or HAL_SPI_Init() function.
+
+       [..]
+       When the compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or
+       not defined, the callback registering feature is not available
+       and weak (surcharged) callbacks are used.
+
+     [..]
+       Using the HAL it is not possible to reach all supported SPI frequency with the different SPI Modes,
+       the following table resume the max SPI frequency reached with data size 8bits/16bits,
+         according to frequency of the APBx Peripheral Clock (fPCLK) used by the SPI instance.
+
+  @endverbatim
+
+  Additional table :
+
+       DataSize = SPI_DATASIZE_8BIT:
+       +----------------------------------------------------------------------------------------------+
+       |         |                | 2Lines Fullduplex   |     2Lines RxOnly    |         1Line        |
+       | Process | Transfer mode  |---------------------|----------------------|----------------------|
+       |         |                |  Master  |  Slave   |  Master   |  Slave   |  Master   |  Slave   |
+       |==============================================================================================|
+       |    T    |     Polling    | Fpclk/4  | Fpclk/8  |    NA     |    NA    |    NA     |   NA     |
+       |    X    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    /    |     Interrupt  | Fpclk/4  | Fpclk/16 |    NA     |    NA    |    NA     |   NA     |
+       |    R    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    X    |       DMA      | Fpclk/2  | Fpclk/2  |    NA     |    NA    |    NA     |   NA     |
+       |=========|================|==========|==========|===========|==========|===========|==========|
+       |         |     Polling    | Fpclk/4  | Fpclk/8  | Fpclk/16  | Fpclk/8  | Fpclk/8   | Fpclk/8  |
+       |         |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    R    |     Interrupt  | Fpclk/8  | Fpclk/16 | Fpclk/8   | Fpclk/8  | Fpclk/8   | Fpclk/4  |
+       |    X    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |         |       DMA      | Fpclk/4  | Fpclk/2  | Fpclk/2   | Fpclk/16 | Fpclk/2   | Fpclk/16 |
+       |=========|================|==========|==========|===========|==========|===========|==========|
+       |         |     Polling    | Fpclk/8  | Fpclk/2  |     NA    |    NA    | Fpclk/8   | Fpclk/8  |
+       |         |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    T    |     Interrupt  | Fpclk/2  | Fpclk/4  |     NA    |    NA    | Fpclk/16  | Fpclk/8  |
+       |    X    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |         |       DMA      | Fpclk/2  | Fpclk/2  |     NA    |    NA    | Fpclk/8   | Fpclk/16 |
+       +----------------------------------------------------------------------------------------------+
+
+       DataSize = SPI_DATASIZE_16BIT:
+       +----------------------------------------------------------------------------------------------+
+       |         |                | 2Lines Fullduplex   |     2Lines RxOnly    |         1Line        |
+       | Process | Transfer mode  |---------------------|----------------------|----------------------|
+       |         |                |  Master  |  Slave   |  Master   |  Slave   |  Master   |  Slave   |
+       |==============================================================================================|
+       |    T    |     Polling    | Fpclk/4  | Fpclk/8  |    NA     |    NA    |    NA     |   NA     |
+       |    X    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    /    |     Interrupt  | Fpclk/4  | Fpclk/16 |    NA     |    NA    |    NA     |   NA     |
+       |    R    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    X    |       DMA      | Fpclk/2  | Fpclk/2  |    NA     |    NA    |    NA     |   NA     |
+       |=========|================|==========|==========|===========|==========|===========|==========|
+       |         |     Polling    | Fpclk/4  | Fpclk/8  | Fpclk/16  | Fpclk/8  | Fpclk/8   | Fpclk/8  |
+       |         |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    R    |     Interrupt  | Fpclk/8  | Fpclk/16 | Fpclk/8   | Fpclk/8  | Fpclk/8   | Fpclk/4  |
+       |    X    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |         |       DMA      | Fpclk/4  | Fpclk/2  | Fpclk/2   | Fpclk/16 | Fpclk/2   | Fpclk/16 |
+       |=========|================|==========|==========|===========|==========|===========|==========|
+       |         |     Polling    | Fpclk/8  | Fpclk/2  |     NA    |    NA    | Fpclk/8   | Fpclk/8  |
+       |         |----------------|----------|----------|-----------|----------|-----------|----------|
+       |    T    |     Interrupt  | Fpclk/2  | Fpclk/4  |     NA    |    NA    | Fpclk/16  | Fpclk/8  |
+       |    X    |----------------|----------|----------|-----------|----------|-----------|----------|
+       |         |       DMA      | Fpclk/2  | Fpclk/2  |     NA    |    NA    | Fpclk/8   | Fpclk/16 |
+       +----------------------------------------------------------------------------------------------+
+       @note The max SPI frequency depend on SPI data size (4bits, 5bits,..., 8bits,...15bits, 16bits),
+             SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA).
+       @note
+            (#) TX/RX processes are HAL_SPI_TransmitReceive(), HAL_SPI_TransmitReceive_IT() and
+                HAL_SPI_TransmitReceive_DMA()
+            (#) RX processes are HAL_SPI_Receive(), HAL_SPI_Receive_IT() and HAL_SPI_Receive_DMA()
+            (#) TX processes are HAL_SPI_Transmit(), HAL_SPI_Transmit_IT() and HAL_SPI_Transmit_DMA()
+
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup SPI SPI
+  * @brief SPI HAL module driver
+  * @{
+  */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPI_Private_Constants SPI Private Constants
+  * @{
+  */
+#define SPI_DEFAULT_TIMEOUT 100U
+/**
+  * @}
+  */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup SPI_Private_Functions SPI Private Functions
+  * @{
+  */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma);
+static void SPI_DMAError(DMA_HandleTypeDef *hdma);
+static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma);
+static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
+static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
+                                                       uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
+                                                       uint32_t Timeout, uint32_t Tickstart);
+static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
+#if (USE_SPI_CRC != 0U)
+static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
+static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
+#endif /* USE_SPI_CRC */
+static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi);
+static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi);
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
+/**
+  * @}
+  */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SPI_Exported_Functions SPI Exported Functions
+  * @{
+  */
+
+/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions
+  *  @brief    Initialization and Configuration functions
+  *
+@verbatim
+ ===============================================================================
+              ##### Initialization and de-initialization functions #####
+ ===============================================================================
+    [..]  This subsection provides a set of functions allowing to initialize and
+          de-initialize the SPIx peripheral:
+
+      (+) User must implement HAL_SPI_MspInit() function in which he configures
+          all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+      (+) Call the function HAL_SPI_Init() to configure the selected device with
+          the selected configuration:
+        (++) Mode
+        (++) Direction
+        (++) Data Size
+        (++) Clock Polarity and Phase
+        (++) NSS Management
+        (++) BaudRate Prescaler
+        (++) FirstBit
+        (++) TIMode
+        (++) CRC Calculation
+        (++) CRC Polynomial if CRC enabled
+        (++) CRC Length, used only with Data8 and Data16
+        (++) FIFO reception threshold
+
+      (+) Call the function HAL_SPI_DeInit() to restore the default configuration
+          of the selected SPIx peripheral.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Initialize the SPI according to the specified parameters
+  *         in the SPI_InitTypeDef and initialize the associated handle.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
+{
+  uint32_t frxth;
+
+  /* Check the SPI handle allocation */
+  if (hspi == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check the parameters */
+  assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+  assert_param(IS_SPI_MODE(hspi->Init.Mode));
+  assert_param(IS_SPI_DIRECTION(hspi->Init.Direction));
+  assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize));
+  assert_param(IS_SPI_NSS(hspi->Init.NSS));
+  assert_param(IS_SPI_NSSP(hspi->Init.NSSPMode));
+  assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+  assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit));
+  assert_param(IS_SPI_TIMODE(hspi->Init.TIMode));
+  if (hspi->Init.TIMode == SPI_TIMODE_DISABLE)
+  {
+    assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity));
+    assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase));
+
+    if (hspi->Init.Mode == SPI_MODE_MASTER)
+    {
+      assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+    }
+    else
+    {
+      /* Baudrate prescaler not use in Motoraola Slave mode. force to default value */
+      hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+    }
+  }
+  else
+  {
+    assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
+
+    /* Force polarity and phase to TI protocaol requirements */
+    hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
+    hspi->Init.CLKPhase    = SPI_PHASE_1EDGE;
+  }
+#if (USE_SPI_CRC != 0U)
+  assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation));
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
+    assert_param(IS_SPI_CRC_LENGTH(hspi->Init.CRCLength));
+  }
+#else
+  hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+#endif /* USE_SPI_CRC */
+
+  if (hspi->State == HAL_SPI_STATE_RESET)
+  {
+    /* Allocate lock resource and initialize it */
+    hspi->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+    /* Init the SPI Callback settings */
+    hspi->TxCpltCallback       = HAL_SPI_TxCpltCallback;       /* Legacy weak TxCpltCallback       */
+    hspi->RxCpltCallback       = HAL_SPI_RxCpltCallback;       /* Legacy weak RxCpltCallback       */
+    hspi->TxRxCpltCallback     = HAL_SPI_TxRxCpltCallback;     /* Legacy weak TxRxCpltCallback     */
+    hspi->TxHalfCpltCallback   = HAL_SPI_TxHalfCpltCallback;   /* Legacy weak TxHalfCpltCallback   */
+    hspi->RxHalfCpltCallback   = HAL_SPI_RxHalfCpltCallback;   /* Legacy weak RxHalfCpltCallback   */
+    hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
+    hspi->ErrorCallback        = HAL_SPI_ErrorCallback;        /* Legacy weak ErrorCallback        */
+    hspi->AbortCpltCallback    = HAL_SPI_AbortCpltCallback;    /* Legacy weak AbortCpltCallback    */
+
+    if (hspi->MspInitCallback == NULL)
+    {
+      hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit  */
+    }
+
+    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+    hspi->MspInitCallback(hspi);
+#else
+    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+    HAL_SPI_MspInit(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+  }
+
+  hspi->State = HAL_SPI_STATE_BUSY;
+
+  /* Disable the selected SPI peripheral */
+  __HAL_SPI_DISABLE(hspi);
+
+  /* Align by default the rs fifo threshold on the data size */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    frxth = SPI_RXFIFO_THRESHOLD_HF;
+  }
+  else
+  {
+    frxth = SPI_RXFIFO_THRESHOLD_QF;
+  }
+
+  /* CRC calculation is valid only for 16Bit and 8 Bit */
+  if ((hspi->Init.DataSize != SPI_DATASIZE_16BIT) && (hspi->Init.DataSize != SPI_DATASIZE_8BIT))
+  {
+    /* CRC must be disabled */
+    hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+  }
+
+  /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
+  /* Configure : SPI Mode, Communication Mode, Clock polarity and phase, NSS management,
+  Communication speed, First bit and CRC calculation state */
+  WRITE_REG(hspi->Instance->CR1, ((hspi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) |
+                                  (hspi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) |
+                                  (hspi->Init.CLKPolarity & SPI_CR1_CPOL) |
+                                  (hspi->Init.CLKPhase & SPI_CR1_CPHA) |
+                                  (hspi->Init.NSS & SPI_CR1_SSM) |
+                                  (hspi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) |
+                                  (hspi->Init.FirstBit  & SPI_CR1_LSBFIRST) |
+                                  (hspi->Init.CRCCalculation & SPI_CR1_CRCEN)));
+#if (USE_SPI_CRC != 0U)
+  /*---------------------------- SPIx CRCL Configuration -------------------*/
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    /* Align the CRC Length on the data size */
+    if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
+    {
+      /* CRC Length aligned on the data size : value set by default */
+      if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+      {
+        hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
+      }
+      else
+      {
+        hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
+      }
+    }
+
+    /* Configure : CRC Length */
+    if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+    {
+      SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCL);
+    }
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Configure : NSS management, TI Mode, NSS Pulse, Data size and Rx Fifo threshold */
+  WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) |
+                                  (hspi->Init.TIMode & SPI_CR2_FRF) |
+                                  (hspi->Init.NSSPMode & SPI_CR2_NSSP) |
+                                  (hspi->Init.DataSize & SPI_CR2_DS_Msk) |
+                                  (frxth & SPI_CR2_FRXTH)));
+
+#if (USE_SPI_CRC != 0U)
+  /*---------------------------- SPIx CRCPOLY Configuration ------------------*/
+  /* Configure : CRC Polynomial */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    WRITE_REG(hspi->Instance->CRCPR, (hspi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk));
+  }
+#endif /* USE_SPI_CRC */
+
+#if defined(SPI_I2SCFGR_I2SMOD)
+  /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
+  CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
+#endif /* SPI_I2SCFGR_I2SMOD */
+
+  hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+  hspi->State     = HAL_SPI_STATE_READY;
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  De-Initialize the SPI peripheral.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
+{
+  /* Check the SPI handle allocation */
+  if (hspi == NULL)
+  {
+    return HAL_ERROR;
+  }
+
+  /* Check SPI Instance parameter */
+  assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
+
+  hspi->State = HAL_SPI_STATE_BUSY;
+
+  /* Disable the SPI Peripheral Clock */
+  __HAL_SPI_DISABLE(hspi);
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  if (hspi->MspDeInitCallback == NULL)
+  {
+    hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit  */
+  }
+
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+  hspi->MspDeInitCallback(hspi);
+#else
+  /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+  HAL_SPI_MspDeInit(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+
+  hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+  hspi->State = HAL_SPI_STATE_RESET;
+
+  /* Release Lock */
+  __HAL_UNLOCK(hspi);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initialize the SPI MSP.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_MspInit should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  De-Initialize the SPI MSP.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_MspDeInit should be implemented in the user file
+   */
+}
+
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+/**
+  * @brief  Register a User SPI Callback
+  *         To be used instead of the weak predefined callback
+  * @param  hspi Pointer to a SPI_HandleTypeDef structure that contains
+  *                the configuration information for the specified SPI.
+  * @param  CallbackID ID of the callback to be registered
+  * @param  pCallback pointer to the Callback function
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID,
+                                           pSPI_CallbackTypeDef pCallback)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  if (pCallback == NULL)
+  {
+    /* Update the error code */
+    hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK;
+
+    return HAL_ERROR;
+  }
+  /* Process locked */
+  __HAL_LOCK(hspi);
+
+  if (HAL_SPI_STATE_READY == hspi->State)
+  {
+    switch (CallbackID)
+    {
+      case HAL_SPI_TX_COMPLETE_CB_ID :
+        hspi->TxCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_RX_COMPLETE_CB_ID :
+        hspi->RxCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_TX_RX_COMPLETE_CB_ID :
+        hspi->TxRxCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
+        hspi->TxHalfCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
+        hspi->RxHalfCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
+        hspi->TxRxHalfCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_ERROR_CB_ID :
+        hspi->ErrorCallback = pCallback;
+        break;
+
+      case HAL_SPI_ABORT_CB_ID :
+        hspi->AbortCpltCallback = pCallback;
+        break;
+
+      case HAL_SPI_MSPINIT_CB_ID :
+        hspi->MspInitCallback = pCallback;
+        break;
+
+      case HAL_SPI_MSPDEINIT_CB_ID :
+        hspi->MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Update the error code */
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else if (HAL_SPI_STATE_RESET == hspi->State)
+  {
+    switch (CallbackID)
+    {
+      case HAL_SPI_MSPINIT_CB_ID :
+        hspi->MspInitCallback = pCallback;
+        break;
+
+      case HAL_SPI_MSPDEINIT_CB_ID :
+        hspi->MspDeInitCallback = pCallback;
+        break;
+
+      default :
+        /* Update the error code */
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Update the error code */
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hspi);
+  return status;
+}
+
+/**
+  * @brief  Unregister an SPI Callback
+  *         SPI callback is redirected to the weak predefined callback
+  * @param  hspi Pointer to a SPI_HandleTypeDef structure that contains
+  *                the configuration information for the specified SPI.
+  * @param  CallbackID ID of the callback to be unregistered
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  /* Process locked */
+  __HAL_LOCK(hspi);
+
+  if (HAL_SPI_STATE_READY == hspi->State)
+  {
+    switch (CallbackID)
+    {
+      case HAL_SPI_TX_COMPLETE_CB_ID :
+        hspi->TxCpltCallback = HAL_SPI_TxCpltCallback;             /* Legacy weak TxCpltCallback       */
+        break;
+
+      case HAL_SPI_RX_COMPLETE_CB_ID :
+        hspi->RxCpltCallback = HAL_SPI_RxCpltCallback;             /* Legacy weak RxCpltCallback       */
+        break;
+
+      case HAL_SPI_TX_RX_COMPLETE_CB_ID :
+        hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback;         /* Legacy weak TxRxCpltCallback     */
+        break;
+
+      case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
+        hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback;     /* Legacy weak TxHalfCpltCallback   */
+        break;
+
+      case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
+        hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback;     /* Legacy weak RxHalfCpltCallback   */
+        break;
+
+      case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
+        hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
+        break;
+
+      case HAL_SPI_ERROR_CB_ID :
+        hspi->ErrorCallback = HAL_SPI_ErrorCallback;               /* Legacy weak ErrorCallback        */
+        break;
+
+      case HAL_SPI_ABORT_CB_ID :
+        hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback;       /* Legacy weak AbortCpltCallback    */
+        break;
+
+      case HAL_SPI_MSPINIT_CB_ID :
+        hspi->MspInitCallback = HAL_SPI_MspInit;                   /* Legacy weak MspInit              */
+        break;
+
+      case HAL_SPI_MSPDEINIT_CB_ID :
+        hspi->MspDeInitCallback = HAL_SPI_MspDeInit;               /* Legacy weak MspDeInit            */
+        break;
+
+      default :
+        /* Update the error code */
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else if (HAL_SPI_STATE_RESET == hspi->State)
+  {
+    switch (CallbackID)
+    {
+      case HAL_SPI_MSPINIT_CB_ID :
+        hspi->MspInitCallback = HAL_SPI_MspInit;                   /* Legacy weak MspInit              */
+        break;
+
+      case HAL_SPI_MSPDEINIT_CB_ID :
+        hspi->MspDeInitCallback = HAL_SPI_MspDeInit;               /* Legacy weak MspDeInit            */
+        break;
+
+      default :
+        /* Update the error code */
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+        /* Return error status */
+        status =  HAL_ERROR;
+        break;
+    }
+  }
+  else
+  {
+    /* Update the error code */
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
+
+    /* Return error status */
+    status =  HAL_ERROR;
+  }
+
+  /* Release Lock */
+  __HAL_UNLOCK(hspi);
+  return status;
+}
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Exported_Functions_Group2 IO operation functions
+  *  @brief   Data transfers functions
+  *
+@verbatim
+  ==============================================================================
+                      ##### IO operation functions #####
+ ===============================================================================
+ [..]
+    This subsection provides a set of functions allowing to manage the SPI
+    data transfers.
+
+    [..] The SPI supports master and slave mode :
+
+    (#) 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 APIs return the HAL status.
+            The end of the data processing will be indicated through the
+            dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when
+            using DMA mode.
+            The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks
+            will be executed respectively at the end of the transmit or Receive process
+            The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected
+
+    (#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA)
+        exist for 1Line (simplex) and 2Lines (full duplex) modes.
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Transmit an amount of data in blocking mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pData pointer to data buffer
+  * @param  Size amount of data to be sent
+  * @param  Timeout Timeout duration
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+  uint32_t tickstart;
+  uint16_t initial_TxXferCount;
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+  initial_TxXferCount = Size;
+
+  if (hspi->State != HAL_SPI_STATE_READY)
+  {
+    return HAL_BUSY;
+  }
+
+  if ((pData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Set the transaction information */
+  hspi->State       = HAL_SPI_STATE_BUSY_TX;
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pTxBuffPtr  = (const uint8_t *)pData;
+  hspi->TxXferSize  = Size;
+  hspi->TxXferCount = Size;
+
+  /*Init field not used in handle to zero */
+  hspi->pRxBuffPtr  = (uint8_t *)NULL;
+  hspi->RxXferSize  = 0U;
+  hspi->RxXferCount = 0U;
+  hspi->TxISR       = NULL;
+  hspi->RxISR       = NULL;
+
+  /* Configure communication direction : 1Line */
+  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+  {
+    /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+    __HAL_SPI_DISABLE(hspi);
+    SPI_1LINE_TX(hspi);
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Transmit data in 16 Bit mode */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+    {
+      hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+      hspi->pTxBuffPtr += sizeof(uint16_t);
+      hspi->TxXferCount--;
+    }
+    /* Transmit data in 16 Bit mode */
+    while (hspi->TxXferCount > 0U)
+    {
+      /* Wait until TXE flag is set to send data */
+      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
+      {
+        hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+        hspi->pTxBuffPtr += sizeof(uint16_t);
+        hspi->TxXferCount--;
+      }
+      else
+      {
+        /* Timeout management */
+        if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+        {
+          hspi->State = HAL_SPI_STATE_READY;
+          __HAL_UNLOCK(hspi);
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+  /* Transmit data in 8 Bit mode */
+  else
+  {
+    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+    {
+      if (hspi->TxXferCount > 1U)
+      {
+        /* write on the data register in packing mode */
+        hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+        hspi->pTxBuffPtr += sizeof(uint16_t);
+        hspi->TxXferCount -= 2U;
+      }
+      else
+      {
+        *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
+        hspi->pTxBuffPtr ++;
+        hspi->TxXferCount--;
+      }
+    }
+    while (hspi->TxXferCount > 0U)
+    {
+      /* Wait until TXE flag is set to send data */
+      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
+      {
+        if (hspi->TxXferCount > 1U)
+        {
+          /* write on the data register in packing mode */
+          hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+          hspi->pTxBuffPtr += sizeof(uint16_t);
+          hspi->TxXferCount -= 2U;
+        }
+        else
+        {
+          *((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
+          hspi->pTxBuffPtr++;
+          hspi->TxXferCount--;
+        }
+      }
+      else
+      {
+        /* Timeout management */
+        if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+        {
+          hspi->State = HAL_SPI_STATE_READY;
+          __HAL_UNLOCK(hspi);
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+#if (USE_SPI_CRC != 0U)
+  /* Enable CRC Transmission */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Check the end of the transaction */
+  if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+  }
+
+  /* Clear overrun flag in 2 Lines communication mode because received is not read */
+  if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+  {
+    __HAL_SPI_CLEAR_OVRFLAG(hspi);
+  }
+
+  hspi->State = HAL_SPI_STATE_READY;
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+
+  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+  {
+    return HAL_ERROR;
+  }
+  else
+  {
+    return HAL_OK;
+  }
+}
+
+/**
+  * @brief  Receive an amount of data in blocking mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pData pointer to data buffer
+  * @param  Size amount of data to be received
+  * @param  Timeout Timeout duration
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+#if (USE_SPI_CRC != 0U)
+  __IO uint32_t tmpreg = 0U;
+  __IO uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+  uint32_t tickstart;
+
+  if (hspi->State != HAL_SPI_STATE_READY)
+  {
+    return HAL_BUSY;
+  }
+
+  if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
+  {
+    hspi->State = HAL_SPI_STATE_BUSY_RX;
+    /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+    return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
+  }
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+
+  if ((pData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Set the transaction information */
+  hspi->State       = HAL_SPI_STATE_BUSY_RX;
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pRxBuffPtr  = (uint8_t *)pData;
+  hspi->RxXferSize  = Size;
+  hspi->RxXferCount = Size;
+
+  /*Init field not used in handle to zero */
+  hspi->pTxBuffPtr  = (uint8_t *)NULL;
+  hspi->TxXferSize  = 0U;
+  hspi->TxXferCount = 0U;
+  hspi->RxISR       = NULL;
+  hspi->TxISR       = NULL;
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+    /* this is done to handle the CRCNEXT before the latest data */
+    hspi->RxXferCount--;
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Set the Rx Fifo threshold */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    /* Set RX Fifo threshold according the reception data length: 16bit */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+  else
+  {
+    /* Set RX Fifo threshold according the reception data length: 8bit */
+    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+
+  /* Configure communication direction: 1Line */
+  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+  {
+    /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+    __HAL_SPI_DISABLE(hspi);
+    SPI_1LINE_RX(hspi);
+  }
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Receive data in 8 Bit mode */
+  if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
+  {
+    /* Transfer loop */
+    while (hspi->RxXferCount > 0U)
+    {
+      /* Check the RXNE flag */
+      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
+      {
+        /* read the received data */
+        (* (uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
+        hspi->pRxBuffPtr += sizeof(uint8_t);
+        hspi->RxXferCount--;
+      }
+      else
+      {
+        /* Timeout management */
+        if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+        {
+          hspi->State = HAL_SPI_STATE_READY;
+          __HAL_UNLOCK(hspi);
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+  else
+  {
+    /* Transfer loop */
+    while (hspi->RxXferCount > 0U)
+    {
+      /* Check the RXNE flag */
+      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
+      {
+        *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+        hspi->pRxBuffPtr += sizeof(uint16_t);
+        hspi->RxXferCount--;
+      }
+      else
+      {
+        /* Timeout management */
+        if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
+        {
+          hspi->State = HAL_SPI_STATE_READY;
+          __HAL_UNLOCK(hspi);
+          return HAL_TIMEOUT;
+        }
+      }
+    }
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Handle the CRC Transmission */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    /* freeze the CRC before the latest data */
+    SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+
+    /* Read the latest data */
+    if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+    {
+      /* the latest data has not been received */
+      __HAL_UNLOCK(hspi);
+      return HAL_TIMEOUT;
+    }
+
+    /* Receive last data in 16 Bit mode */
+    if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+    {
+      *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+    }
+    /* Receive last data in 8 Bit mode */
+    else
+    {
+      (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
+    }
+
+    /* Wait the CRC data */
+    if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+      hspi->State = HAL_SPI_STATE_READY;
+      __HAL_UNLOCK(hspi);
+      return HAL_TIMEOUT;
+    }
+
+    /* Read CRC to Flush DR and RXNE flag */
+    if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+    {
+      /* Read 16bit CRC */
+      tmpreg = READ_REG(hspi->Instance->DR);
+      /* To avoid GCC warning */
+      UNUSED(tmpreg);
+    }
+    else
+    {
+      /* Initialize the 8bit temporary pointer */
+      ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+      /* Read 8bit CRC */
+      tmpreg8 = *ptmpreg8;
+      /* To avoid GCC warning */
+      UNUSED(tmpreg8);
+
+      if ((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+      {
+        if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+        {
+          /* Error on the CRC reception */
+          SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+          hspi->State = HAL_SPI_STATE_READY;
+          __HAL_UNLOCK(hspi);
+          return HAL_TIMEOUT;
+        }
+        /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */
+        tmpreg8 = *ptmpreg8;
+        /* To avoid GCC warning */
+        UNUSED(tmpreg8);
+      }
+    }
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Check the end of the transaction */
+  if (SPI_EndRxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Check if CRC error occurred */
+  if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+    __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+  hspi->State = HAL_SPI_STATE_READY;
+  /* Unlock the process */
+  __HAL_UNLOCK(hspi);
+  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+  {
+    return HAL_ERROR;
+  }
+  else
+  {
+    return HAL_OK;
+  }
+}
+
+/**
+  * @brief  Transmit and Receive an amount of data in blocking mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pTxData pointer to transmission data buffer
+  * @param  pRxData pointer to reception data buffer
+  * @param  Size amount of data to be sent and received
+  * @param  Timeout Timeout duration
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+                                          uint16_t Size, uint32_t Timeout)
+{
+  uint16_t             initial_TxXferCount;
+  uint16_t             initial_RxXferCount;
+  uint32_t             tmp_mode;
+  HAL_SPI_StateTypeDef tmp_state;
+  uint32_t             tickstart;
+#if (USE_SPI_CRC != 0U)
+  __IO uint32_t tmpreg = 0U;
+  uint32_t             spi_cr1;
+  uint32_t             spi_cr2;
+  __IO uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+
+  /* Variable used to alternate Rx and Tx during transfer */
+  uint32_t             txallowed = 1U;
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+
+  /* Init temporary variables */
+  tmp_state           = hspi->State;
+  tmp_mode            = hspi->Init.Mode;
+  initial_TxXferCount = Size;
+  initial_RxXferCount = Size;
+#if (USE_SPI_CRC != 0U)
+  spi_cr1             = READ_REG(hspi->Instance->CR1);
+  spi_cr2             = READ_REG(hspi->Instance->CR2);
+#endif /* USE_SPI_CRC */
+
+  if (!((tmp_state == HAL_SPI_STATE_READY) || \
+        ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
+         (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+  {
+    return HAL_BUSY;
+  }
+
+  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+  {
+    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+  }
+
+  /* Set the transaction information */
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
+  hspi->RxXferCount = Size;
+  hspi->RxXferSize  = Size;
+  hspi->pTxBuffPtr  = (const uint8_t *)pTxData;
+  hspi->TxXferCount = Size;
+  hspi->TxXferSize  = Size;
+
+  /*Init field not used in handle to zero */
+  hspi->RxISR       = NULL;
+  hspi->TxISR       = NULL;
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Set the Rx Fifo threshold */
+  if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (initial_RxXferCount > 1U))
+  {
+    /* Set fiforxthreshold according the reception data length: 16bit */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+  else
+  {
+    /* Set fiforxthreshold according the reception data length: 8bit */
+    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Transmit and Receive data in 16 Bit mode */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+    {
+      hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+      hspi->pTxBuffPtr += sizeof(uint16_t);
+      hspi->TxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+      /* Enable CRC Transmission */
+      if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+      {
+        /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+        if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+        {
+          SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+        }
+        SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+      }
+#endif /* USE_SPI_CRC */
+
+    }
+    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
+    {
+      /* Check TXE flag */
+      if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
+      {
+        hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+        hspi->pTxBuffPtr += sizeof(uint16_t);
+        hspi->TxXferCount--;
+        /* Next Data is a reception (Rx). Tx not allowed */
+        txallowed = 0U;
+
+#if (USE_SPI_CRC != 0U)
+        /* Enable CRC Transmission */
+        if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+        {
+          /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+          if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+          {
+            SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+          }
+          SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+        }
+#endif /* USE_SPI_CRC */
+      }
+
+      /* Check RXNE flag */
+      if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
+      {
+        *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+        hspi->pRxBuffPtr += sizeof(uint16_t);
+        hspi->RxXferCount--;
+        /* Next Data is a Transmission (Tx). Tx is allowed */
+        txallowed = 1U;
+      }
+      if (((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY))
+      {
+        hspi->State = HAL_SPI_STATE_READY;
+        __HAL_UNLOCK(hspi);
+        return HAL_TIMEOUT;
+      }
+    }
+  }
+  /* Transmit and Receive data in 8 Bit mode */
+  else
+  {
+    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
+    {
+      if (hspi->TxXferCount > 1U)
+      {
+        hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+        hspi->pTxBuffPtr += sizeof(uint16_t);
+        hspi->TxXferCount -= 2U;
+      }
+      else
+      {
+        *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+        hspi->pTxBuffPtr++;
+        hspi->TxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+        /* Enable CRC Transmission */
+        if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+        {
+          /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+          if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+          {
+            SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+          }
+          SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+        }
+#endif /* USE_SPI_CRC */
+      }
+    }
+    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
+    {
+      /* Check TXE flag */
+      if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
+      {
+        if (hspi->TxXferCount > 1U)
+        {
+          hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+          hspi->pTxBuffPtr += sizeof(uint16_t);
+          hspi->TxXferCount -= 2U;
+        }
+        else
+        {
+          *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+          hspi->pTxBuffPtr++;
+          hspi->TxXferCount--;
+        }
+        /* Next Data is a reception (Rx). Tx not allowed */
+        txallowed = 0U;
+
+#if (USE_SPI_CRC != 0U)
+        /* Enable CRC Transmission */
+        if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+        {
+          /* Set NSS Soft to received correctly the CRC on slave mode with NSS pulse activated */
+          if ((READ_BIT(spi_cr1, SPI_CR1_MSTR) == 0U) && (READ_BIT(spi_cr2, SPI_CR2_NSSP) == SPI_CR2_NSSP))
+          {
+            SET_BIT(hspi->Instance->CR1, SPI_CR1_SSM);
+          }
+          SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+        }
+#endif /* USE_SPI_CRC */
+      }
+
+      /* Wait until RXNE flag is reset */
+      if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
+      {
+        if (hspi->RxXferCount > 1U)
+        {
+          *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
+          hspi->pRxBuffPtr += sizeof(uint16_t);
+          hspi->RxXferCount -= 2U;
+          if (hspi->RxXferCount <= 1U)
+          {
+            /* Set RX Fifo threshold before to switch on 8 bit data size */
+            SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+          }
+        }
+        else
+        {
+          (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
+          hspi->pRxBuffPtr++;
+          hspi->RxXferCount--;
+        }
+        /* Next Data is a Transmission (Tx). Tx is allowed */
+        txallowed = 1U;
+      }
+      if ((((HAL_GetTick() - tickstart) >=  Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U))
+      {
+        hspi->State = HAL_SPI_STATE_READY;
+        __HAL_UNLOCK(hspi);
+        return HAL_TIMEOUT;
+      }
+    }
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Read CRC from DR to close CRC calculation process */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    /* Wait until TXE flag */
+    if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+    {
+      /* Error on the CRC reception */
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+      hspi->State = HAL_SPI_STATE_READY;
+      __HAL_UNLOCK(hspi);
+      return HAL_TIMEOUT;
+    }
+    /* Read CRC */
+    if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
+    {
+      /* Read 16bit CRC */
+      tmpreg = READ_REG(hspi->Instance->DR);
+      /* To avoid GCC warning */
+      UNUSED(tmpreg);
+    }
+    else
+    {
+      /* Initialize the 8bit temporary pointer */
+      ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+      /* Read 8bit CRC */
+      tmpreg8 = *ptmpreg8;
+      /* To avoid GCC warning */
+      UNUSED(tmpreg8);
+
+      if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+      {
+        if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
+        {
+          /* Error on the CRC reception */
+          SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+          hspi->State = HAL_SPI_STATE_READY;
+          __HAL_UNLOCK(hspi);
+          return HAL_TIMEOUT;
+        }
+        /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */
+        tmpreg8 = *ptmpreg8;
+        /* To avoid GCC warning */
+        UNUSED(tmpreg8);
+      }
+    }
+  }
+
+  /* Check if CRC error occurred */
+  if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+    /* Clear CRC Flag */
+    __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+    __HAL_UNLOCK(hspi);
+    return HAL_ERROR;
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Check the end of the transaction */
+  if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+    __HAL_UNLOCK(hspi);
+    return HAL_ERROR;
+  }
+
+
+  hspi->State = HAL_SPI_STATE_READY;
+  /* Unlock the process */
+  __HAL_UNLOCK(hspi);
+
+  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+  {
+    return HAL_ERROR;
+  }
+  else
+  {
+    return HAL_OK;
+  }
+}
+
+/**
+  * @brief  Transmit an amount of data in non-blocking mode with Interrupt.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pData pointer to data buffer
+  * @param  Size amount of data to be sent
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
+{
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+
+  if ((pData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  if (hspi->State != HAL_SPI_STATE_READY)
+  {
+    return HAL_BUSY;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Set the transaction information */
+  hspi->State       = HAL_SPI_STATE_BUSY_TX;
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pTxBuffPtr  = (const uint8_t *)pData;
+  hspi->TxXferSize  = Size;
+  hspi->TxXferCount = Size;
+
+  /* Init field not used in handle to zero */
+  hspi->pRxBuffPtr  = (uint8_t *)NULL;
+  hspi->RxXferSize  = 0U;
+  hspi->RxXferCount = 0U;
+  hspi->RxISR       = NULL;
+
+  /* Set the function for IT treatment */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    hspi->TxISR = SPI_TxISR_16BIT;
+  }
+  else
+  {
+    hspi->TxISR = SPI_TxISR_8BIT;
+  }
+
+  /* Configure communication direction : 1Line */
+  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+  {
+    /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+    __HAL_SPI_DISABLE(hspi);
+    SPI_1LINE_TX(hspi);
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+  /* Enable TXE and ERR interrupt */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Receive an amount of data in non-blocking mode with Interrupt.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pData pointer to data buffer
+  * @param  Size amount of data to be sent
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+
+  if (hspi->State != HAL_SPI_STATE_READY)
+  {
+    return HAL_BUSY;
+  }
+
+  if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+  {
+    hspi->State = HAL_SPI_STATE_BUSY_RX;
+    /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+    return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size);
+  }
+
+
+  if ((pData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Set the transaction information */
+  hspi->State       = HAL_SPI_STATE_BUSY_RX;
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pRxBuffPtr  = (uint8_t *)pData;
+  hspi->RxXferSize  = Size;
+  hspi->RxXferCount = Size;
+
+  /* Init field not used in handle to zero */
+  hspi->pTxBuffPtr  = (uint8_t *)NULL;
+  hspi->TxXferSize  = 0U;
+  hspi->TxXferCount = 0U;
+  hspi->TxISR       = NULL;
+
+  /* Check the data size to adapt Rx threshold and the set the function for IT treatment */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    /* Set RX Fifo threshold according the reception data length: 16 bit */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+    hspi->RxISR = SPI_RxISR_16BIT;
+  }
+  else
+  {
+    /* Set RX Fifo threshold according the reception data length: 8 bit */
+    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+    hspi->RxISR = SPI_RxISR_8BIT;
+  }
+
+  /* Configure communication direction : 1Line */
+  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+  {
+    /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+    __HAL_SPI_DISABLE(hspi);
+    SPI_1LINE_RX(hspi);
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    hspi->CRCSize = 1U;
+    if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+    {
+      hspi->CRCSize = 2U;
+    }
+    SPI_RESET_CRC(hspi);
+  }
+  else
+  {
+    hspi->CRCSize = 0U;
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Note : The SPI must be enabled after unlocking current process
+            to avoid the risk of SPI interrupt handle execution before current
+            process unlock */
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+  /* Enable RXNE and ERR interrupt */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Transmit and Receive an amount of data in non-blocking mode with Interrupt.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pTxData pointer to transmission data buffer
+  * @param  pRxData pointer to reception data buffer
+  * @param  Size amount of data to be sent and received
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+                                             uint16_t Size)
+{
+  uint32_t             tmp_mode;
+  HAL_SPI_StateTypeDef tmp_state;
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+  /* Init temporary variables */
+  tmp_state           = hspi->State;
+  tmp_mode            = hspi->Init.Mode;
+
+  if (!((tmp_state == HAL_SPI_STATE_READY) || \
+        ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
+         (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+  {
+    return HAL_BUSY;
+  }
+
+  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hspi);
+
+  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+  {
+    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+  }
+
+  /* Set the transaction information */
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pTxBuffPtr  = (const uint8_t *)pTxData;
+  hspi->TxXferSize  = Size;
+  hspi->TxXferCount = Size;
+  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
+  hspi->RxXferSize  = Size;
+  hspi->RxXferCount = Size;
+
+  /* Set the function for IT treatment */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    hspi->RxISR     = SPI_2linesRxISR_16BIT;
+    hspi->TxISR     = SPI_2linesTxISR_16BIT;
+  }
+  else
+  {
+    hspi->RxISR     = SPI_2linesRxISR_8BIT;
+    hspi->TxISR     = SPI_2linesTxISR_8BIT;
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    hspi->CRCSize = 1U;
+    if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT))
+    {
+      hspi->CRCSize = 2U;
+    }
+    SPI_RESET_CRC(hspi);
+  }
+  else
+  {
+    hspi->CRCSize = 0U;
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Check if packing mode is enabled and if there is more than 2 data to receive */
+  if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (Size >= 2U))
+  {
+    /* Set RX Fifo threshold according the reception data length: 16 bit */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+  else
+  {
+    /* Set RX Fifo threshold according the reception data length: 8 bit */
+    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+  /* Enable TXE, RXNE and ERR interrupt */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Transmit an amount of data in non-blocking mode with DMA.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pData pointer to data buffer
+  * @param  Size amount of data to be sent
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
+{
+
+  /* Check tx dma handle */
+  assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
+
+  if (hspi->State != HAL_SPI_STATE_READY)
+  {
+    return HAL_BUSY;
+  }
+
+  if ((pData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Set the transaction information */
+  hspi->State       = HAL_SPI_STATE_BUSY_TX;
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pTxBuffPtr  = (const uint8_t *)pData;
+  hspi->TxXferSize  = Size;
+  hspi->TxXferCount = Size;
+
+  /* Init field not used in handle to zero */
+  hspi->pRxBuffPtr  = (uint8_t *)NULL;
+  hspi->TxISR       = NULL;
+  hspi->RxISR       = NULL;
+  hspi->RxXferSize  = 0U;
+  hspi->RxXferCount = 0U;
+
+  /* Configure communication direction : 1Line */
+  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+  {
+    /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+    __HAL_SPI_DISABLE(hspi);
+    SPI_1LINE_TX(hspi);
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Set the SPI TxDMA Half transfer complete callback */
+  hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt;
+
+  /* Set the SPI TxDMA transfer complete callback */
+  hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt;
+
+  /* Set the DMA error callback */
+  hspi->hdmatx->XferErrorCallback = SPI_DMAError;
+
+  /* Set the DMA AbortCpltCallback */
+  hspi->hdmatx->XferAbortCallback = NULL;
+
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+  /* Packing mode is enabled only if the DMA setting is HALWORD */
+  if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD))
+  {
+    /* Check the even/odd of the data size + crc if enabled */
+    if ((hspi->TxXferCount & 0x1U) == 0U)
+    {
+      CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+      hspi->TxXferCount = (hspi->TxXferCount >> 1U);
+    }
+    else
+    {
+      SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+      hspi->TxXferCount = (hspi->TxXferCount >> 1U) + 1U;
+    }
+  }
+
+  /* Enable the Tx DMA Stream/Channel */
+  if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
+                                 hspi->TxXferCount))
+  {
+    /* Update SPI error code */
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+    /* Process Unlocked */
+    __HAL_UNLOCK(hspi);
+    return HAL_ERROR;
+  }
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+
+  /* Enable the SPI Error Interrupt Bit */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
+
+  /* Enable Tx DMA Request */
+  SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Receive an amount of data in non-blocking mode with DMA.
+  * @note   In case of MASTER mode and SPI_DIRECTION_2LINES direction, hdmatx shall be defined.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pData pointer to data buffer
+  * @note   When the CRC feature is enabled the pData Length must be Size + 1.
+  * @param  Size amount of data to be sent
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
+{
+  /* Check rx dma handle */
+  assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
+
+  if (hspi->State != HAL_SPI_STATE_READY)
+  {
+    return HAL_BUSY;
+  }
+
+  if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+  {
+    hspi->State = HAL_SPI_STATE_BUSY_RX;
+
+    /* Check tx dma handle */
+    assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
+
+    /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
+    return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size);
+  }
+
+  if ((pData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Set the transaction information */
+  hspi->State       = HAL_SPI_STATE_BUSY_RX;
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pRxBuffPtr  = (uint8_t *)pData;
+  hspi->RxXferSize  = Size;
+  hspi->RxXferCount = Size;
+
+  /*Init field not used in handle to zero */
+  hspi->RxISR       = NULL;
+  hspi->TxISR       = NULL;
+  hspi->TxXferSize  = 0U;
+  hspi->TxXferCount = 0U;
+
+  /* Configure communication direction : 1Line */
+  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
+  {
+    /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
+    __HAL_SPI_DISABLE(hspi);
+    SPI_1LINE_RX(hspi);
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    /* Set RX Fifo threshold according the reception data length: 16bit */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+  else
+  {
+    /* Set RX Fifo threshold according the reception data length: 8bit */
+    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+    if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+    {
+      /* Set RX Fifo threshold according the reception data length: 16bit */
+      CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+      if ((hspi->RxXferCount & 0x1U) == 0x0U)
+      {
+        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+        hspi->RxXferCount = hspi->RxXferCount >> 1U;
+      }
+      else
+      {
+        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+        hspi->RxXferCount = (hspi->RxXferCount >> 1U) + 1U;
+      }
+    }
+  }
+
+  /* Set the SPI RxDMA Half transfer complete callback */
+  hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+
+  /* Set the SPI Rx DMA transfer complete callback */
+  hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
+
+  /* Set the DMA error callback */
+  hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+  /* Set the DMA AbortCpltCallback */
+  hspi->hdmarx->XferAbortCallback = NULL;
+
+  /* Enable the Rx DMA Stream/Channel  */
+  if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
+                                 hspi->RxXferCount))
+  {
+    /* Update SPI error code */
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+    /* Process Unlocked */
+    __HAL_UNLOCK(hspi);
+    return HAL_ERROR;
+  }
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+
+  /* Enable the SPI Error Interrupt Bit */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
+
+  /* Enable Rx DMA Request */
+  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Transmit and Receive an amount of data in non-blocking mode with DMA.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  pTxData pointer to transmission data buffer
+  * @param  pRxData pointer to reception data buffer
+  * @note   When the CRC feature is enabled the pRxData Length must be Size + 1
+  * @param  Size amount of data to be sent
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
+                                              uint16_t Size)
+{
+  uint32_t             tmp_mode;
+  HAL_SPI_StateTypeDef tmp_state;
+
+  /* Check rx & tx dma handles */
+  assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
+  assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
+
+  /* Check Direction parameter */
+  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
+
+  /* Init temporary variables */
+  tmp_state           = hspi->State;
+  tmp_mode            = hspi->Init.Mode;
+
+  if (!((tmp_state == HAL_SPI_STATE_READY) ||
+        ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
+         (tmp_state == HAL_SPI_STATE_BUSY_RX))))
+  {
+    return HAL_BUSY;
+  }
+
+  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
+  {
+    return HAL_ERROR;
+  }
+
+  /* Process locked */
+  __HAL_LOCK(hspi);
+
+  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
+  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
+  {
+    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
+  }
+
+  /* Set the transaction information */
+  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
+  hspi->pTxBuffPtr  = (const uint8_t *)pTxData;
+  hspi->TxXferSize  = Size;
+  hspi->TxXferCount = Size;
+  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
+  hspi->RxXferSize  = Size;
+  hspi->RxXferCount = Size;
+
+  /* Init field not used in handle to zero */
+  hspi->RxISR       = NULL;
+  hspi->TxISR       = NULL;
+
+#if (USE_SPI_CRC != 0U)
+  /* Reset CRC Calculation */
+  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+  {
+    SPI_RESET_CRC(hspi);
+  }
+#endif /* USE_SPI_CRC */
+
+  /* Reset the threshold bit */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX | SPI_CR2_LDMARX);
+
+  /* The packing mode management is enabled by the DMA settings according the spi data size */
+  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+  {
+    /* Set fiforxthreshold according the reception data length: 16bit */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+  }
+  else
+  {
+    /* Set RX Fifo threshold according the reception data length: 8bit */
+    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+    if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+    {
+      if ((hspi->TxXferSize & 0x1U) == 0x0U)
+      {
+        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+        hspi->TxXferCount = hspi->TxXferCount >> 1U;
+      }
+      else
+      {
+        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
+        hspi->TxXferCount = (hspi->TxXferCount >> 1U) + 1U;
+      }
+    }
+
+    if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+    {
+      /* Set RX Fifo threshold according the reception data length: 16bit */
+      CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+
+      if ((hspi->RxXferCount & 0x1U) == 0x0U)
+      {
+        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+        hspi->RxXferCount = hspi->RxXferCount >> 1U;
+      }
+      else
+      {
+        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
+        hspi->RxXferCount = (hspi->RxXferCount >> 1U) + 1U;
+      }
+    }
+  }
+
+  /* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
+  if (hspi->State == HAL_SPI_STATE_BUSY_RX)
+  {
+    /* Set the SPI Rx DMA Half transfer complete callback */
+    hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
+    hspi->hdmarx->XferCpltCallback     = SPI_DMAReceiveCplt;
+  }
+  else
+  {
+    /* Set the SPI Tx/Rx DMA Half transfer complete callback */
+    hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
+    hspi->hdmarx->XferCpltCallback     = SPI_DMATransmitReceiveCplt;
+  }
+
+  /* Set the DMA error callback */
+  hspi->hdmarx->XferErrorCallback = SPI_DMAError;
+
+  /* Set the DMA AbortCpltCallback */
+  hspi->hdmarx->XferAbortCallback = NULL;
+
+  /* Enable the Rx DMA Stream/Channel  */
+  if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
+                                 hspi->RxXferCount))
+  {
+    /* Update SPI error code */
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+    /* Process Unlocked */
+    __HAL_UNLOCK(hspi);
+    return HAL_ERROR;
+  }
+
+  /* Enable Rx DMA Request */
+  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+  /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
+  is performed in DMA reception complete callback  */
+  hspi->hdmatx->XferHalfCpltCallback = NULL;
+  hspi->hdmatx->XferCpltCallback     = NULL;
+  hspi->hdmatx->XferErrorCallback    = NULL;
+  hspi->hdmatx->XferAbortCallback    = NULL;
+
+  /* Enable the Tx DMA Stream/Channel  */
+  if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
+                                 hspi->TxXferCount))
+  {
+    /* Update SPI error code */
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+    /* Process Unlocked */
+    __HAL_UNLOCK(hspi);
+    return HAL_ERROR;
+  }
+
+  /* Check if the SPI is already enabled */
+  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
+  {
+    /* Enable SPI peripheral */
+    __HAL_SPI_ENABLE(hspi);
+  }
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+
+  /* Enable the SPI Error Interrupt Bit */
+  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
+
+  /* Enable Tx DMA Request */
+  SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Abort ongoing transfer (blocking mode).
+  * @param  hspi SPI handle.
+  * @note   This procedure could be used for aborting any ongoing transfer (Tx and Rx),
+  *         started in Interrupt or DMA mode.
+  *         This procedure performs following operations :
+  *           - Disable SPI Interrupts (depending of transfer direction)
+  *           - Disable the DMA transfer in the peripheral register (if enabled)
+  *           - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
+  *           - 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_SPI_Abort(SPI_HandleTypeDef *hspi)
+{
+  HAL_StatusTypeDef errorcode;
+  __IO uint32_t count;
+  __IO uint32_t resetcount;
+
+  /* Initialized local variable  */
+  errorcode = HAL_OK;
+  resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+  count = resetcount;
+
+  /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
+
+  /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
+  {
+    hspi->TxISR = SPI_AbortTx_ISR;
+    /* Wait HAL_SPI_STATE_ABORT state */
+    do
+    {
+      if (count == 0U)
+      {
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+        break;
+      }
+      count--;
+    } while (hspi->State != HAL_SPI_STATE_ABORT);
+    /* Reset Timeout Counter */
+    count = resetcount;
+  }
+
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
+  {
+    hspi->RxISR = SPI_AbortRx_ISR;
+    /* Wait HAL_SPI_STATE_ABORT state */
+    do
+    {
+      if (count == 0U)
+      {
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+        break;
+      }
+      count--;
+    } while (hspi->State != HAL_SPI_STATE_ABORT);
+    /* Reset Timeout Counter */
+    count = resetcount;
+  }
+
+  /* Disable the SPI DMA Tx request if enabled */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
+  {
+    /* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */
+    if (hspi->hdmatx != NULL)
+    {
+      /* Set the SPI DMA Abort callback :
+      will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
+      hspi->hdmatx->XferAbortCallback = NULL;
+
+      /* Abort DMA Tx Handle linked to SPI Peripheral */
+      if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK)
+      {
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+
+      /* Disable Tx DMA Request */
+      CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN));
+
+      if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+      {
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+
+      /* Disable SPI Peripheral */
+      __HAL_SPI_DISABLE(hspi);
+
+      /* Empty the FRLVL fifo */
+      if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                        HAL_GetTick()) != HAL_OK)
+      {
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+    }
+  }
+
+  /* Disable the SPI DMA Rx request if enabled */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
+  {
+    /* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */
+    if (hspi->hdmarx != NULL)
+    {
+      /* Set the SPI DMA Abort callback :
+      will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
+      hspi->hdmarx->XferAbortCallback = NULL;
+
+      /* Abort DMA Rx Handle linked to SPI Peripheral */
+      if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK)
+      {
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+
+      /* Disable peripheral */
+      __HAL_SPI_DISABLE(hspi);
+
+      /* Control the BSY flag */
+      if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+      {
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+
+      /* Empty the FRLVL fifo */
+      if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                        HAL_GetTick()) != HAL_OK)
+      {
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+
+      /* Disable Rx DMA Request */
+      CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXDMAEN));
+    }
+  }
+  /* Reset Tx and Rx transfer counters */
+  hspi->RxXferCount = 0U;
+  hspi->TxXferCount = 0U;
+
+  /* Check error during Abort procedure */
+  if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
+  {
+    /* return HAL_Error in case of error during Abort procedure */
+    errorcode = HAL_ERROR;
+  }
+  else
+  {
+    /* Reset errorCode */
+    hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+  }
+
+  /* Clear the Error flags in the SR register */
+  __HAL_SPI_CLEAR_OVRFLAG(hspi);
+  __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+  /* Restore hspi->state to ready */
+  hspi->State = HAL_SPI_STATE_READY;
+
+  return errorcode;
+}
+
+/**
+  * @brief  Abort ongoing transfer (Interrupt mode).
+  * @param  hspi SPI handle.
+  * @note   This procedure could be used for aborting any ongoing transfer (Tx and Rx),
+  *         started in Interrupt or DMA mode.
+  *         This procedure performs following operations :
+  *           - Disable SPI Interrupts (depending of transfer direction)
+  *           - Disable the DMA transfer in the peripheral register (if enabled)
+  *           - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
+  *           - Set handle State to READY
+  *           - At abort completion, call user abort complete callback
+  * @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_SPI_Abort_IT(SPI_HandleTypeDef *hspi)
+{
+  HAL_StatusTypeDef errorcode;
+  uint32_t abortcplt ;
+  __IO uint32_t count;
+  __IO uint32_t resetcount;
+
+  /* Initialized local variable  */
+  errorcode = HAL_OK;
+  abortcplt = 1U;
+  resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+  count = resetcount;
+
+  /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
+
+  /* Change Rx and Tx Irq Handler to Disable TXEIE, RXNEIE and ERRIE interrupts */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
+  {
+    hspi->TxISR = SPI_AbortTx_ISR;
+    /* Wait HAL_SPI_STATE_ABORT state */
+    do
+    {
+      if (count == 0U)
+      {
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+        break;
+      }
+      count--;
+    } while (hspi->State != HAL_SPI_STATE_ABORT);
+    /* Reset Timeout Counter */
+    count = resetcount;
+  }
+
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
+  {
+    hspi->RxISR = SPI_AbortRx_ISR;
+    /* Wait HAL_SPI_STATE_ABORT state */
+    do
+    {
+      if (count == 0U)
+      {
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+        break;
+      }
+      count--;
+    } while (hspi->State != HAL_SPI_STATE_ABORT);
+    /* Reset Timeout Counter */
+    count = resetcount;
+  }
+
+  /* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialised
+     before any call to DMA Abort functions */
+  /* DMA Tx Handle is valid */
+  if (hspi->hdmatx != NULL)
+  {
+    /* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
+       Otherwise, set it to NULL */
+    if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
+    {
+      hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback;
+    }
+    else
+    {
+      hspi->hdmatx->XferAbortCallback = NULL;
+    }
+  }
+  /* DMA Rx Handle is valid */
+  if (hspi->hdmarx != NULL)
+  {
+    /* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
+       Otherwise, set it to NULL */
+    if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
+    {
+      hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback;
+    }
+    else
+    {
+      hspi->hdmarx->XferAbortCallback = NULL;
+    }
+  }
+
+  /* Disable the SPI DMA Tx request if enabled */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
+  {
+    /* Abort the SPI DMA Tx Stream/Channel */
+    if (hspi->hdmatx != NULL)
+    {
+      /* Abort DMA Tx Handle linked to SPI Peripheral */
+      if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK)
+      {
+        hspi->hdmatx->XferAbortCallback = NULL;
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+      else
+      {
+        abortcplt = 0U;
+      }
+    }
+  }
+  /* Disable the SPI DMA Rx request if enabled */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
+  {
+    /* Abort the SPI DMA Rx Stream/Channel */
+    if (hspi->hdmarx != NULL)
+    {
+      /* Abort DMA Rx Handle linked to SPI Peripheral */
+      if (HAL_DMA_Abort_IT(hspi->hdmarx) !=  HAL_OK)
+      {
+        hspi->hdmarx->XferAbortCallback = NULL;
+        hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+      }
+      else
+      {
+        abortcplt = 0U;
+      }
+    }
+  }
+
+  if (abortcplt == 1U)
+  {
+    /* Reset Tx and Rx transfer counters */
+    hspi->RxXferCount = 0U;
+    hspi->TxXferCount = 0U;
+
+    /* Check error during Abort procedure */
+    if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
+    {
+      /* return HAL_Error in case of error during Abort procedure */
+      errorcode = HAL_ERROR;
+    }
+    else
+    {
+      /* Reset errorCode */
+      hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+    }
+
+    /* Clear the Error flags in the SR register */
+    __HAL_SPI_CLEAR_OVRFLAG(hspi);
+    __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+    /* Restore hspi->State to Ready */
+    hspi->State = HAL_SPI_STATE_READY;
+
+    /* As no DMA to be aborted, call directly user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+    hspi->AbortCpltCallback(hspi);
+#else
+    HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+  }
+
+  return errorcode;
+}
+
+/**
+  * @brief  Pause the DMA Transfer.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for the specified SPI module.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
+{
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Disable the SPI DMA Tx & Rx requests */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Resume the DMA Transfer.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for the specified SPI module.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
+{
+  /* Process Locked */
+  __HAL_LOCK(hspi);
+
+  /* Enable the SPI DMA Tx & Rx requests */
+  SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+  /* Process Unlocked */
+  __HAL_UNLOCK(hspi);
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Stop the DMA Transfer.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for the specified SPI module.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
+{
+  HAL_StatusTypeDef errorcode = HAL_OK;
+  /* The Lock is not implemented on this API to allow the user application
+     to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
+     HAL_SPI_TxRxCpltCallback():
+     when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
+     and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
+     HAL_SPI_TxRxCpltCallback()
+     */
+
+  /* Abort the SPI DMA tx Stream/Channel  */
+  if (hspi->hdmatx != NULL)
+  {
+    if (HAL_OK != HAL_DMA_Abort(hspi->hdmatx))
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+      errorcode = HAL_ERROR;
+    }
+  }
+  /* Abort the SPI DMA rx Stream/Channel  */
+  if (hspi->hdmarx != NULL)
+  {
+    if (HAL_OK != HAL_DMA_Abort(hspi->hdmarx))
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+      errorcode = HAL_ERROR;
+    }
+  }
+
+  /* Disable the SPI DMA Tx & Rx requests */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+  hspi->State = HAL_SPI_STATE_READY;
+  return errorcode;
+}
+
+/**
+  * @brief  Handle SPI interrupt request.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for the specified SPI module.
+  * @retval None
+  */
+void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
+{
+  uint32_t itsource = hspi->Instance->CR2;
+  uint32_t itflag   = hspi->Instance->SR;
+
+  /* SPI in mode Receiver ----------------------------------------------------*/
+  if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) &&
+      (SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET))
+  {
+    hspi->RxISR(hspi);
+    return;
+  }
+
+  /* SPI in mode Transmitter -------------------------------------------------*/
+  if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET))
+  {
+    hspi->TxISR(hspi);
+    return;
+  }
+
+  /* SPI in Error Treatment --------------------------------------------------*/
+  if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
+       || (SPI_CHECK_FLAG(itflag, SPI_FLAG_FRE) != RESET)) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET))
+  {
+    /* SPI Overrun error interrupt occurred ----------------------------------*/
+    if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
+    {
+      if (hspi->State != HAL_SPI_STATE_BUSY_TX)
+      {
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
+        __HAL_SPI_CLEAR_OVRFLAG(hspi);
+      }
+      else
+      {
+        __HAL_SPI_CLEAR_OVRFLAG(hspi);
+        return;
+      }
+    }
+
+    /* SPI Mode Fault error interrupt occurred -------------------------------*/
+    if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
+      __HAL_SPI_CLEAR_MODFFLAG(hspi);
+    }
+
+    /* SPI Frame error interrupt occurred ------------------------------------*/
+    if (SPI_CHECK_FLAG(itflag, SPI_FLAG_FRE) != RESET)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FRE);
+      __HAL_SPI_CLEAR_FREFLAG(hspi);
+    }
+
+    if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+    {
+      /* Disable all interrupts */
+      __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
+
+      hspi->State = HAL_SPI_STATE_READY;
+      /* Disable the SPI DMA requests if enabled */
+      if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN)))
+      {
+        CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN));
+
+        /* Abort the SPI DMA Rx channel */
+        if (hspi->hdmarx != NULL)
+        {
+          /* Set the SPI DMA Abort callback :
+          will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
+          hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError;
+          if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx))
+          {
+            SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+          }
+        }
+        /* Abort the SPI DMA Tx channel */
+        if (hspi->hdmatx != NULL)
+        {
+          /* Set the SPI DMA Abort callback :
+          will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
+          hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError;
+          if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx))
+          {
+            SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+          }
+        }
+      }
+      else
+      {
+        /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+        hspi->ErrorCallback(hspi);
+#else
+        HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+      }
+    }
+    return;
+  }
+}
+
+/**
+  * @brief  Tx Transfer completed callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_TxCpltCallback should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Rx Transfer completed callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_RxCpltCallback should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Tx and Rx Transfer completed callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_TxRxCpltCallback should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Tx Half Transfer completed callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_TxHalfCpltCallback should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Rx Half Transfer completed callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Tx and Rx Half Transfer callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file
+   */
+}
+
+/**
+  * @brief  SPI error callback.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_ErrorCallback should be implemented in the user file
+   */
+  /* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes
+            and user can use HAL_SPI_GetError() API to check the latest error occurred
+   */
+}
+
+/**
+  * @brief  SPI Abort Complete callback.
+  * @param  hspi SPI handle.
+  * @retval None
+  */
+__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi)
+{
+  /* Prevent unused argument(s) compilation warning */
+  UNUSED(hspi);
+
+  /* NOTE : This function should not be modified, when the callback is needed,
+            the HAL_SPI_AbortCpltCallback can be implemented in the user file.
+   */
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions
+  * @brief   SPI control functions
+  *
+@verbatim
+ ===============================================================================
+                      ##### Peripheral State and Errors functions #####
+ ===============================================================================
+    [..]
+    This subsection provides a set of functions allowing to control the SPI.
+     (+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral
+     (+) HAL_SPI_GetError() check in run-time Errors occurring during communication
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Return the SPI handle state.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval SPI state
+  */
+HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi)
+{
+  /* Return SPI handle state */
+  return hspi->State;
+}
+
+/**
+  * @brief  Return the SPI error code.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval SPI error code in bitmap format
+  */
+uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi)
+{
+  /* Return SPI ErrorCode */
+  return hspi->ErrorCode;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @addtogroup SPI_Private_Functions
+  * @brief   Private functions
+  * @{
+  */
+
+/**
+  * @brief  DMA SPI transmit process complete callback.
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+  uint32_t tickstart;
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+
+  /* DMA Normal Mode */
+  if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+  {
+    /* Disable ERR interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+    /* Disable Tx DMA Request */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+    /* Check the end of the transaction */
+    if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+    }
+
+    /* Clear overrun flag in 2 Lines communication mode because received data is not read */
+    if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+    {
+      __HAL_SPI_CLEAR_OVRFLAG(hspi);
+    }
+
+    hspi->TxXferCount = 0U;
+    hspi->State = HAL_SPI_STATE_READY;
+
+    if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+    {
+      /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+      hspi->ErrorCallback(hspi);
+#else
+      HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+      return;
+    }
+  }
+  /* Call user Tx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->TxCpltCallback(hspi);
+#else
+  HAL_SPI_TxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI receive process complete callback.
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+  uint32_t tickstart;
+#if (USE_SPI_CRC != 0U)
+  __IO uint32_t tmpreg = 0U;
+  __IO uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+
+  /* DMA Normal Mode */
+  if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+  {
+    /* Disable ERR interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+#if (USE_SPI_CRC != 0U)
+    /* CRC handling */
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      /* Wait until RXNE flag */
+      if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+      {
+        /* Error on the CRC reception */
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+      }
+      /* Read CRC */
+      if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
+      {
+        /* Read 16bit CRC */
+        tmpreg = READ_REG(hspi->Instance->DR);
+        /* To avoid GCC warning */
+        UNUSED(tmpreg);
+      }
+      else
+      {
+        /* Initialize the 8bit temporary pointer */
+        ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+        /* Read 8bit CRC */
+        tmpreg8 = *ptmpreg8;
+        /* To avoid GCC warning */
+        UNUSED(tmpreg8);
+
+        if (hspi->Init.CRCLength == SPI_CRC_LENGTH_16BIT)
+        {
+          if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+          {
+            /* Error on the CRC reception */
+            SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+          }
+          /* Read 8bit CRC again in case of 16bit CRC in 8bit Data mode */
+          tmpreg8 = *ptmpreg8;
+          /* To avoid GCC warning */
+          UNUSED(tmpreg8);
+        }
+      }
+    }
+#endif /* USE_SPI_CRC */
+
+    /* Check if we are in Master RX 2 line mode */
+    if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
+    {
+      /* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */
+      CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+    }
+    else
+    {
+      /* Normal case */
+      CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+    }
+
+    /* Check the end of the transaction */
+    if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+    {
+      hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
+    }
+
+    hspi->RxXferCount = 0U;
+    hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_SPI_CRC != 0U)
+    /* Check if CRC error occurred */
+    if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+      __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+    }
+#endif /* USE_SPI_CRC */
+
+    if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+    {
+      /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+      hspi->ErrorCallback(hspi);
+#else
+      HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+      return;
+    }
+  }
+  /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->RxCpltCallback(hspi);
+#else
+  HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI transmit receive process complete callback.
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+  uint32_t tickstart;
+#if (USE_SPI_CRC != 0U)
+  __IO uint32_t tmpreg = 0U;
+  __IO uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+#endif /* USE_SPI_CRC */
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+
+  /* DMA Normal Mode */
+  if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
+  {
+    /* Disable ERR interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+#if (USE_SPI_CRC != 0U)
+    /* CRC handling */
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      if ((hspi->Init.DataSize == SPI_DATASIZE_8BIT) && (hspi->Init.CRCLength == SPI_CRC_LENGTH_8BIT))
+      {
+        if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_QUARTER_FULL, SPI_DEFAULT_TIMEOUT,
+                                          tickstart) != HAL_OK)
+        {
+          /* Error on the CRC reception */
+          SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+        }
+        /* Initialize the 8bit temporary pointer */
+        ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+        /* Read 8bit CRC */
+        tmpreg8 = *ptmpreg8;
+        /* To avoid GCC warning */
+        UNUSED(tmpreg8);
+      }
+      else
+      {
+        if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_HALF_FULL, SPI_DEFAULT_TIMEOUT,
+                                          tickstart) != HAL_OK)
+        {
+          /* Error on the CRC reception */
+          SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+        }
+        /* Read CRC to Flush DR and RXNE flag */
+        tmpreg = READ_REG(hspi->Instance->DR);
+        /* To avoid GCC warning */
+        UNUSED(tmpreg);
+      }
+    }
+#endif /* USE_SPI_CRC */
+
+    /* Check the end of the transaction */
+    if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+    }
+
+    /* Disable Rx/Tx DMA Request */
+    CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+    hspi->TxXferCount = 0U;
+    hspi->RxXferCount = 0U;
+    hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_SPI_CRC != 0U)
+    /* Check if CRC error occurred */
+    if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+      __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+    }
+#endif /* USE_SPI_CRC */
+
+    if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+    {
+      /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+      hspi->ErrorCallback(hspi);
+#else
+      HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+      return;
+    }
+  }
+  /* Call user TxRx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->TxRxCpltCallback(hspi);
+#else
+  HAL_SPI_TxRxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI half transmit process complete callback.
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+  /* Call user Tx half complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->TxHalfCpltCallback(hspi);
+#else
+  HAL_SPI_TxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI half receive process complete callback
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+  /* Call user Rx half complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->RxHalfCpltCallback(hspi);
+#else
+  HAL_SPI_RxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI half transmit receive process complete callback.
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+  /* Call user TxRx half complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->TxRxHalfCpltCallback(hspi);
+#else
+  HAL_SPI_TxRxHalfCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI communication error callback.
+  * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
+  *               the configuration information for the specified DMA module.
+  * @retval None
+  */
+static void SPI_DMAError(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+  /* Stop the disable DMA transfer on SPI side */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
+
+  SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
+  hspi->State = HAL_SPI_STATE_READY;
+  /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->ErrorCallback(hspi);
+#else
+  HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI communication abort callback, when initiated by HAL services on Error
+  *         (To be called at end of DMA Abort procedure following error occurrence).
+  * @param  hdma DMA handle.
+  * @retval None
+  */
+static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+  hspi->RxXferCount = 0U;
+  hspi->TxXferCount = 0U;
+
+  /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->ErrorCallback(hspi);
+#else
+  HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI Tx communication abort callback, when initiated by user
+  *         (To be called at end of DMA Tx Abort procedure following user abort request).
+  * @note   When this callback is executed, User Abort complete call back is called only if no
+  *         Abort still ongoing for Rx DMA Handle.
+  * @param  hdma DMA handle.
+  * @retval None
+  */
+static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+  hspi->hdmatx->XferAbortCallback = NULL;
+
+  /* Disable Tx DMA Request */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
+
+  if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Disable SPI Peripheral */
+  __HAL_SPI_DISABLE(hspi);
+
+  /* Empty the FRLVL fifo */
+  if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                    HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Check if an Abort process is still ongoing */
+  if (hspi->hdmarx != NULL)
+  {
+    if (hspi->hdmarx->XferAbortCallback != NULL)
+    {
+      return;
+    }
+  }
+
+  /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
+  hspi->RxXferCount = 0U;
+  hspi->TxXferCount = 0U;
+
+  /* Check no error during Abort procedure */
+  if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
+  {
+    /* Reset errorCode */
+    hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+  }
+
+  /* Clear the Error flags in the SR register */
+  __HAL_SPI_CLEAR_OVRFLAG(hspi);
+  __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+  /* Restore hspi->State to Ready */
+  hspi->State  = HAL_SPI_STATE_READY;
+
+  /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->AbortCpltCallback(hspi);
+#else
+  HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  DMA SPI Rx communication abort callback, when initiated by user
+  *         (To be called at end of DMA Rx Abort procedure following user abort request).
+  * @note   When this callback is executed, User Abort complete call back is called only if no
+  *         Abort still ongoing for Tx DMA Handle.
+  * @param  hdma DMA handle.
+  * @retval None
+  */
+static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
+{
+  SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+  /* Disable SPI Peripheral */
+  __HAL_SPI_DISABLE(hspi);
+
+  hspi->hdmarx->XferAbortCallback = NULL;
+
+  /* Disable Rx DMA Request */
+  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
+
+  /* Control the BSY flag */
+  if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Empty the FRLVL fifo */
+  if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                    HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Check if an Abort process is still ongoing */
+  if (hspi->hdmatx != NULL)
+  {
+    if (hspi->hdmatx->XferAbortCallback != NULL)
+    {
+      return;
+    }
+  }
+
+  /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
+  hspi->RxXferCount = 0U;
+  hspi->TxXferCount = 0U;
+
+  /* Check no error during Abort procedure */
+  if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
+  {
+    /* Reset errorCode */
+    hspi->ErrorCode = HAL_SPI_ERROR_NONE;
+  }
+
+  /* Clear the Error flags in the SR register */
+  __HAL_SPI_CLEAR_OVRFLAG(hspi);
+  __HAL_SPI_CLEAR_FREFLAG(hspi);
+
+  /* Restore hspi->State to Ready */
+  hspi->State  = HAL_SPI_STATE_READY;
+
+  /* Call user Abort complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+  hspi->AbortCpltCallback(hspi);
+#else
+  HAL_SPI_AbortCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+}
+
+/**
+  * @brief  Rx 8-bit handler for Transmit and Receive in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  /* Receive data in packing mode */
+  if (hspi->RxXferCount > 1U)
+  {
+    *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
+    hspi->pRxBuffPtr += sizeof(uint16_t);
+    hspi->RxXferCount -= 2U;
+    if (hspi->RxXferCount == 1U)
+    {
+      /* Set RX Fifo threshold according the reception data length: 8bit */
+      SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+    }
+  }
+  /* Receive data in 8 Bit mode */
+  else
+  {
+    *hspi->pRxBuffPtr = *((__IO uint8_t *)&hspi->Instance->DR);
+    hspi->pRxBuffPtr++;
+    hspi->RxXferCount--;
+  }
+
+  /* Check end of the reception */
+  if (hspi->RxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
+      hspi->RxISR =  SPI_2linesRxISR_8BITCRC;
+      return;
+    }
+#endif /* USE_SPI_CRC */
+
+    /* Disable RXNE  and ERR interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+    if (hspi->TxXferCount == 0U)
+    {
+      SPI_CloseRxTx_ISR(hspi);
+    }
+  }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+  * @brief  Rx 8-bit handler for Transmit and Receive in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+  __IO uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+
+  /* Initialize the 8bit temporary pointer */
+  ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+  /* Read 8bit CRC to flush Data Register */
+  tmpreg8 = *ptmpreg8;
+  /* To avoid GCC warning */
+  UNUSED(tmpreg8);
+
+  hspi->CRCSize--;
+
+  /* Check end of the reception */
+  if (hspi->CRCSize == 0U)
+  {
+    /* Disable RXNE and ERR interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+    if (hspi->TxXferCount == 0U)
+    {
+      SPI_CloseRxTx_ISR(hspi);
+    }
+  }
+}
+#endif /* USE_SPI_CRC */
+
+/**
+  * @brief  Tx 8-bit handler for Transmit and Receive in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  /* Transmit data in packing Bit mode */
+  if (hspi->TxXferCount >= 2U)
+  {
+    hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+    hspi->pTxBuffPtr += sizeof(uint16_t);
+    hspi->TxXferCount -= 2U;
+  }
+  /* Transmit data in 8 Bit mode */
+  else
+  {
+    *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+    hspi->pTxBuffPtr++;
+    hspi->TxXferCount--;
+  }
+
+  /* Check the end of the transmission */
+  if (hspi->TxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      /* Set CRC Next Bit to send CRC */
+      SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+      /* Disable TXE interrupt */
+      __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+      return;
+    }
+#endif /* USE_SPI_CRC */
+
+    /* Disable TXE interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+
+    if (hspi->RxXferCount == 0U)
+    {
+      SPI_CloseRxTx_ISR(hspi);
+    }
+  }
+}
+
+/**
+  * @brief  Rx 16-bit handler for Transmit and Receive in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  /* Receive data in 16 Bit mode */
+  *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
+  hspi->pRxBuffPtr += sizeof(uint16_t);
+  hspi->RxXferCount--;
+
+  if (hspi->RxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      hspi->RxISR =  SPI_2linesRxISR_16BITCRC;
+      return;
+    }
+#endif /* USE_SPI_CRC */
+
+    /* Disable RXNE interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+    if (hspi->TxXferCount == 0U)
+    {
+      SPI_CloseRxTx_ISR(hspi);
+    }
+  }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+  * @brief  Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+  __IO uint32_t tmpreg = 0U;
+
+  /* Read 16bit CRC to flush Data Register */
+  tmpreg = READ_REG(hspi->Instance->DR);
+  /* To avoid GCC warning */
+  UNUSED(tmpreg);
+
+  /* Disable RXNE interrupt */
+  __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
+
+  SPI_CloseRxTx_ISR(hspi);
+}
+#endif /* USE_SPI_CRC */
+
+/**
+  * @brief  Tx 16-bit handler for Transmit and Receive in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  /* Transmit data in 16 Bit mode */
+  hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+  hspi->pTxBuffPtr += sizeof(uint16_t);
+  hspi->TxXferCount--;
+
+  /* Enable CRC Transmission */
+  if (hspi->TxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      /* Set CRC Next Bit to send CRC */
+      SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+      /* Disable TXE interrupt */
+      __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+      return;
+    }
+#endif /* USE_SPI_CRC */
+
+    /* Disable TXE interrupt */
+    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
+
+    if (hspi->RxXferCount == 0U)
+    {
+      SPI_CloseRxTx_ISR(hspi);
+    }
+  }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+  * @brief  Manage the CRC 8-bit receive in Interrupt context.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+  __IO uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+
+  /* Initialize the 8bit temporary pointer */
+  ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+  /* Read 8bit CRC to flush Data Register */
+  tmpreg8 = *ptmpreg8;
+  /* To avoid GCC warning */
+  UNUSED(tmpreg8);
+
+  hspi->CRCSize--;
+
+  if (hspi->CRCSize == 0U)
+  {
+    SPI_CloseRx_ISR(hspi);
+  }
+}
+#endif /* USE_SPI_CRC */
+
+/**
+  * @brief  Manage the receive 8-bit in Interrupt context.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  *hspi->pRxBuffPtr = (*(__IO uint8_t *)&hspi->Instance->DR);
+  hspi->pRxBuffPtr++;
+  hspi->RxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+  /* Enable CRC Transmission */
+  if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+  {
+    SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+  }
+#endif /* USE_SPI_CRC */
+
+  if (hspi->RxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      hspi->RxISR =  SPI_RxISR_8BITCRC;
+      return;
+    }
+#endif /* USE_SPI_CRC */
+    SPI_CloseRx_ISR(hspi);
+  }
+}
+
+#if (USE_SPI_CRC != 0U)
+/**
+  * @brief  Manage the CRC 16-bit receive in Interrupt context.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
+{
+  __IO uint32_t tmpreg = 0U;
+
+  /* Read 16bit CRC to flush Data Register */
+  tmpreg = READ_REG(hspi->Instance->DR);
+  /* To avoid GCC warning */
+  UNUSED(tmpreg);
+
+  /* Disable RXNE and ERR interrupt */
+  __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+  SPI_CloseRx_ISR(hspi);
+}
+#endif /* USE_SPI_CRC */
+
+/**
+  * @brief  Manage the 16-bit receive in Interrupt context.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
+  hspi->pRxBuffPtr += sizeof(uint16_t);
+  hspi->RxXferCount--;
+
+#if (USE_SPI_CRC != 0U)
+  /* Enable CRC Transmission */
+  if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
+  {
+    SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+  }
+#endif /* USE_SPI_CRC */
+
+  if (hspi->RxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      hspi->RxISR = SPI_RxISR_16BITCRC;
+      return;
+    }
+#endif /* USE_SPI_CRC */
+    SPI_CloseRx_ISR(hspi);
+  }
+}
+
+/**
+  * @brief  Handle the data 8-bit transmit in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  *(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
+  hspi->pTxBuffPtr++;
+  hspi->TxXferCount--;
+
+  if (hspi->TxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      /* Enable CRC Transmission */
+      SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+    }
+#endif /* USE_SPI_CRC */
+    SPI_CloseTx_ISR(hspi);
+  }
+}
+
+/**
+  * @brief  Handle the data 16-bit transmit in Interrupt mode.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
+{
+  /* Transmit data in 16 Bit mode */
+  hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
+  hspi->pTxBuffPtr += sizeof(uint16_t);
+  hspi->TxXferCount--;
+
+  if (hspi->TxXferCount == 0U)
+  {
+#if (USE_SPI_CRC != 0U)
+    if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+    {
+      /* Enable CRC Transmission */
+      SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
+    }
+#endif /* USE_SPI_CRC */
+    SPI_CloseTx_ISR(hspi);
+  }
+}
+
+/**
+  * @brief  Handle SPI Communication Timeout.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *              the configuration information for SPI module.
+  * @param  Flag SPI flag to check
+  * @param  State flag state to check
+  * @param  Timeout Timeout duration
+  * @param  Tickstart tick start value
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
+                                                       uint32_t Timeout, uint32_t Tickstart)
+{
+  __IO uint32_t count;
+  uint32_t tmp_timeout;
+  uint32_t tmp_tickstart;
+
+  /* Adjust Timeout value  in case of end of transfer */
+  tmp_timeout   = Timeout - (HAL_GetTick() - Tickstart);
+  tmp_tickstart = HAL_GetTick();
+
+  /* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */
+  count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U);
+
+  while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
+  {
+    if (Timeout != HAL_MAX_DELAY)
+    {
+      if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
+      {
+        /* Disable the SPI and reset the CRC: the CRC value should be cleared
+           on both master and slave sides in order to resynchronize the master
+           and slave for their respective CRC calculation */
+
+        /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
+        __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+        if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+                                                     || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+        {
+          /* Disable SPI peripheral */
+          __HAL_SPI_DISABLE(hspi);
+        }
+
+        /* Reset CRC Calculation */
+        if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+        {
+          SPI_RESET_CRC(hspi);
+        }
+
+        hspi->State = HAL_SPI_STATE_READY;
+
+        /* Process Unlocked */
+        __HAL_UNLOCK(hspi);
+
+        return HAL_TIMEOUT;
+      }
+      /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
+      if (count == 0U)
+      {
+        tmp_timeout = 0U;
+      }
+      count--;
+    }
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Handle SPI FIFO Communication Timeout.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *              the configuration information for SPI module.
+  * @param  Fifo Fifo to check
+  * @param  State Fifo state to check
+  * @param  Timeout Timeout duration
+  * @param  Tickstart tick start value
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
+                                                       uint32_t Timeout, uint32_t Tickstart)
+{
+  __IO uint32_t count;
+  uint32_t tmp_timeout;
+  uint32_t tmp_tickstart;
+  __IO const uint8_t  *ptmpreg8;
+  __IO uint8_t  tmpreg8 = 0;
+
+  /* Adjust Timeout value  in case of end of transfer */
+  tmp_timeout = Timeout - (HAL_GetTick() - Tickstart);
+  tmp_tickstart = HAL_GetTick();
+
+  /* Initialize the 8bit temporary pointer */
+  ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
+
+  /* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */
+  count = tmp_timeout * ((SystemCoreClock * 35U) >> 20U);
+
+  while ((hspi->Instance->SR & Fifo) != State)
+  {
+    if ((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY))
+    {
+      /* Flush Data Register by a blank read */
+      tmpreg8 = *ptmpreg8;
+      /* To avoid GCC warning */
+      UNUSED(tmpreg8);
+    }
+
+    if (Timeout != HAL_MAX_DELAY)
+    {
+      if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
+      {
+        /* Disable the SPI and reset the CRC: the CRC value should be cleared
+           on both master and slave sides in order to resynchronize the master
+           and slave for their respective CRC calculation */
+
+        /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
+        __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
+
+        if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+                                                     || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+        {
+          /* Disable SPI peripheral */
+          __HAL_SPI_DISABLE(hspi);
+        }
+
+        /* Reset CRC Calculation */
+        if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
+        {
+          SPI_RESET_CRC(hspi);
+        }
+
+        hspi->State = HAL_SPI_STATE_READY;
+
+        /* Process Unlocked */
+        __HAL_UNLOCK(hspi);
+
+        return HAL_TIMEOUT;
+      }
+      /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
+      if (count == 0U)
+      {
+        tmp_timeout = 0U;
+      }
+      count--;
+    }
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Handle the check of the RX transaction complete.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @param  Timeout Timeout duration
+  * @param  Tickstart tick start value
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi,  uint32_t Timeout, uint32_t Tickstart)
+{
+  if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+                                               || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+  {
+    /* Disable SPI peripheral */
+    __HAL_SPI_DISABLE(hspi);
+  }
+
+  /* Control the BSY flag */
+  if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+    return HAL_TIMEOUT;
+  }
+
+  if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
+                                               || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
+  {
+    /* Empty the FRLVL fifo */
+    if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, Timeout, Tickstart) != HAL_OK)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+      return HAL_TIMEOUT;
+    }
+  }
+  return HAL_OK;
+}
+
+/**
+  * @brief  Handle the check of the RXTX or TX transaction complete.
+  * @param  hspi SPI handle
+  * @param  Timeout Timeout duration
+  * @param  Tickstart tick start value
+  * @retval HAL status
+  */
+static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
+{
+  /* Control if the TX fifo is empty */
+  if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FTLVL, SPI_FTLVL_EMPTY, Timeout, Tickstart) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+    return HAL_TIMEOUT;
+  }
+
+  /* Control the BSY flag */
+  if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+    return HAL_TIMEOUT;
+  }
+
+  /* Control if the RX fifo is empty */
+  if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, Timeout, Tickstart) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+    return HAL_TIMEOUT;
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Handle the end of the RXTX transaction.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi)
+{
+  uint32_t tickstart;
+
+  /* Init tickstart for timeout management */
+  tickstart = HAL_GetTick();
+
+  /* Disable ERR interrupt */
+  __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
+
+  /* Check the end of the transaction */
+  if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+  }
+
+#if (USE_SPI_CRC != 0U)
+  /* Check if CRC error occurred */
+  if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+  {
+    hspi->State = HAL_SPI_STATE_READY;
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+    __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+    /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+    hspi->ErrorCallback(hspi);
+#else
+    HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+  }
+  else
+  {
+#endif /* USE_SPI_CRC */
+    if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+    {
+      if (hspi->State == HAL_SPI_STATE_BUSY_RX)
+      {
+        hspi->State = HAL_SPI_STATE_READY;
+        /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+        hspi->RxCpltCallback(hspi);
+#else
+        HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+      }
+      else
+      {
+        hspi->State = HAL_SPI_STATE_READY;
+        /* Call user TxRx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+        hspi->TxRxCpltCallback(hspi);
+#else
+        HAL_SPI_TxRxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+      }
+    }
+    else
+    {
+      hspi->State = HAL_SPI_STATE_READY;
+      /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+      hspi->ErrorCallback(hspi);
+#else
+      HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+    }
+#if (USE_SPI_CRC != 0U)
+  }
+#endif /* USE_SPI_CRC */
+}
+
+/**
+  * @brief  Handle the end of the RX transaction.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi)
+{
+  /* Disable RXNE and ERR interrupt */
+  __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
+
+  /* Check the end of the transaction */
+  if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+  }
+  hspi->State = HAL_SPI_STATE_READY;
+
+#if (USE_SPI_CRC != 0U)
+  /* Check if CRC error occurred */
+  if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
+    __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
+    /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+    hspi->ErrorCallback(hspi);
+#else
+    HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+  }
+  else
+  {
+#endif /* USE_SPI_CRC */
+    if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
+    {
+      /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+      hspi->RxCpltCallback(hspi);
+#else
+      HAL_SPI_RxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+    }
+    else
+    {
+      /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+      hspi->ErrorCallback(hspi);
+#else
+      HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+    }
+#if (USE_SPI_CRC != 0U)
+  }
+#endif /* USE_SPI_CRC */
+}
+
+/**
+  * @brief  Handle the end of the TX transaction.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi)
+{
+  uint32_t tickstart;
+
+  /* Init tickstart for timeout management*/
+  tickstart = HAL_GetTick();
+
+  /* Disable TXE and ERR interrupt */
+  __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
+
+  /* Check the end of the transaction */
+  if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
+  {
+    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
+  }
+
+  /* Clear overrun flag in 2 Lines communication mode because received is not read */
+  if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
+  {
+    __HAL_SPI_CLEAR_OVRFLAG(hspi);
+  }
+
+  hspi->State = HAL_SPI_STATE_READY;
+  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
+  {
+    /* Call user error callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+    hspi->ErrorCallback(hspi);
+#else
+    HAL_SPI_ErrorCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+  }
+  else
+  {
+    /* Call user Rx complete callback */
+#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
+    hspi->TxCpltCallback(hspi);
+#else
+    HAL_SPI_TxCpltCallback(hspi);
+#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
+  }
+}
+
+/**
+  * @brief  Handle abort a Rx transaction.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi)
+{
+  __IO uint32_t count;
+
+  /* Disable SPI Peripheral */
+  __HAL_SPI_DISABLE(hspi);
+
+  count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+
+  /* Disable RXNEIE interrupt */
+  CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXNEIE));
+
+  /* Check RXNEIE is disabled */
+  do
+  {
+    if (count == 0U)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+      break;
+    }
+    count--;
+  } while (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE));
+
+  /* Control the BSY flag */
+  if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Empty the FRLVL fifo */
+  if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                    HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  hspi->State = HAL_SPI_STATE_ABORT;
+}
+
+/**
+  * @brief  Handle abort a Tx or Rx/Tx transaction.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for SPI module.
+  * @retval None
+  */
+static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi)
+{
+  __IO uint32_t count;
+
+  count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
+
+  /* Disable TXEIE interrupt */
+  CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE));
+
+  /* Check TXEIE is disabled */
+  do
+  {
+    if (count == 0U)
+    {
+      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+      break;
+    }
+    count--;
+  } while (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE));
+
+  if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Disable SPI Peripheral */
+  __HAL_SPI_DISABLE(hspi);
+
+  /* Empty the FRLVL fifo */
+  if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                    HAL_GetTick()) != HAL_OK)
+  {
+    hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+  }
+
+  /* Check case of Full-Duplex Mode and disable directly RXNEIE interrupt */
+  if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
+  {
+    /* Disable RXNEIE interrupt */
+    CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXNEIE));
+
+    /* Check RXNEIE is disabled */
+    do
+    {
+      if (count == 0U)
+      {
+        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
+        break;
+      }
+      count--;
+    } while (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE));
+
+    /* Control the BSY flag */
+    if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
+    {
+      hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+    }
+
+    /* Empty the FRLVL fifo */
+    if (SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FRLVL, SPI_FRLVL_EMPTY, SPI_DEFAULT_TIMEOUT,
+                                      HAL_GetTick()) != HAL_OK)
+    {
+      hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
+    }
+  }
+  hspi->State = HAL_SPI_STATE_ABORT;
+}
+
+/**
+  * @}
+  */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi_ex.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi_ex.c
new file mode 100644
index 0000000..241ff98
--- /dev/null
+++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_spi_ex.c
@@ -0,0 +1,112 @@
+/**
+  ******************************************************************************
+  * @file    stm32l4xx_hal_spi_ex.c
+  * @author  MCD Application Team
+  * @brief   Extended SPI HAL module driver.
+  *          This file provides firmware functions to manage the following
+  *          SPI peripheral extended functionalities :
+  *           + IO operation functions
+  *
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.
+  *
+  * This software is licensed under terms that can be found in the LICENSE file
+  * in the root directory of this software component.
+  * If no LICENSE file comes with this software, it is provided AS-IS.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32l4xx_hal.h"
+
+/** @addtogroup STM32L4xx_HAL_Driver
+  * @{
+  */
+
+/** @defgroup SPIEx SPIEx
+  * @brief SPI Extended HAL module driver
+  * @{
+  */
+#ifdef HAL_SPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup SPIEx_Private_Constants SPIEx Private Constants
+  * @{
+  */
+#define SPI_FIFO_SIZE       4UL
+/**
+  * @}
+  */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SPIEx_Exported_Functions SPIEx Exported Functions
+  * @{
+  */
+
+/** @defgroup SPIEx_Exported_Functions_Group1 IO operation functions
+  *  @brief   Data transfers functions
+  *
+@verbatim
+  ==============================================================================
+                      ##### IO operation functions #####
+ ===============================================================================
+ [..]
+    This subsection provides a set of extended functions to manage the SPI
+    data transfers.
+
+    (#) Rx data flush function:
+        (++) HAL_SPIEx_FlushRxFifo()
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Flush the RX fifo.
+  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
+  *               the configuration information for the specified SPI module.
+  * @retval HAL status
+  */
+HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi)
+{
+  __IO uint32_t tmpreg;
+  uint8_t  count = 0U;
+  while ((hspi->Instance->SR & SPI_FLAG_FRLVL) !=  SPI_FRLVL_EMPTY)
+  {
+    count++;
+    tmpreg = hspi->Instance->DR;
+    UNUSED(tmpreg); /* To avoid GCC warning */
+    if (count == SPI_FIFO_SIZE)
+    {
+      return HAL_TIMEOUT;
+    }
+  }
+  return HAL_OK;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
diff --git a/ISKBoard.ioc b/ISKBoard.ioc
index d43f3be..02d3eb4 100644
--- a/ISKBoard.ioc
+++ b/ISKBoard.ioc
@@ -24,30 +24,34 @@
 Mcu.IP0=ADC1
 Mcu.IP1=NVIC
 Mcu.IP2=RCC
-Mcu.IP3=SYS
-Mcu.IP4=TIM1
-Mcu.IP5=TIM6
-Mcu.IP6=USART1
-Mcu.IPNb=7
+Mcu.IP3=SPI1
+Mcu.IP4=SYS
+Mcu.IP5=TIM1
+Mcu.IP6=TIM6
+Mcu.IP7=USART1
+Mcu.IPNb=8
 Mcu.Name=STM32L431R(B-C)Tx
 Mcu.Package=LQFP64
 Mcu.Pin0=PH0-OSC_IN (PH0)
 Mcu.Pin1=PH1-OSC_OUT (PH1)
-Mcu.Pin10=PA9
-Mcu.Pin11=PA10
-Mcu.Pin12=PA11
-Mcu.Pin13=PD2
-Mcu.Pin14=VP_SYS_VS_Systick
-Mcu.Pin15=VP_TIM6_VS_ClockSourceINT
-Mcu.Pin2=PB0
-Mcu.Pin3=PB1
-Mcu.Pin4=PB2
-Mcu.Pin5=PB12
-Mcu.Pin6=PB13
-Mcu.Pin7=PB14
-Mcu.Pin8=PC6
-Mcu.Pin9=PC9
-Mcu.PinsNb=16
+Mcu.Pin10=PB14
+Mcu.Pin11=PC6
+Mcu.Pin12=PC9
+Mcu.Pin13=PA9
+Mcu.Pin14=PA10
+Mcu.Pin15=PA11
+Mcu.Pin16=PD2
+Mcu.Pin17=VP_SYS_VS_Systick
+Mcu.Pin18=VP_TIM6_VS_ClockSourceINT
+Mcu.Pin2=PA5
+Mcu.Pin3=PA6
+Mcu.Pin4=PA7
+Mcu.Pin5=PB0
+Mcu.Pin6=PB1
+Mcu.Pin7=PB2
+Mcu.Pin8=PB12
+Mcu.Pin9=PB13
+Mcu.PinsNb=19
 Mcu.ThirdPartyNb=0
 Mcu.UserConstants=
 Mcu.UserName=STM32L431RCTx
@@ -72,6 +76,13 @@
 PA11.GPIO_PuPd=GPIO_PULLDOWN
 PA11.Locked=true
 PA11.Signal=S_TIM1_CH4
+PA5.Locked=true
+PA5.Mode=Full_Duplex_Master
+PA5.Signal=SPI1_SCK
+PA6.Mode=Full_Duplex_Master
+PA6.Signal=SPI1_MISO
+PA7.Mode=Full_Duplex_Master
+PA7.Signal=SPI1_MOSI
 PA9.Mode=Asynchronous
 PA9.Signal=USART1_TX
 PB0.GPIOParameters=GPIO_Label
@@ -206,6 +217,13 @@
 SH.GPXTI14.ConfNb=1
 SH.S_TIM1_CH4.0=TIM1_CH4,PWM Generation4 CH4
 SH.S_TIM1_CH4.ConfNb=1
+SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4
+SPI1.CalculateBaudRate=20.0 MBits/s
+SPI1.DataSize=SPI_DATASIZE_8BIT
+SPI1.Direction=SPI_DIRECTION_2LINES
+SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler
+SPI1.Mode=SPI_MODE_MASTER
+SPI1.VirtualType=VM_MASTER
 TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
 TIM1.IPParameters=Channel-PWM Generation4 CH4,Prescaler,Period,Pulse-PWM Generation4 CH4
 TIM1.Period=370-1

--
Gitblit v1.9.1