From 7800d7cc9bebfb7838ece5888ba1efe3531c3497 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 24 Oct 2018 19:58:41 -0700 Subject: [PATCH 01/14] merge is ugly but is confirmed working --- docs/developer-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/developer-guide.md b/docs/developer-guide.md index d6243b5b..ecf3e1ea 100644 --- a/docs/developer-guide.md +++ b/docs/developer-guide.md @@ -183,7 +183,6 @@ How to use these is shown in the following example. * Make sure the rebase finishes, fixing any conflicts that may arise ### 4. Merge new STM32CubeMX code to your feature branch -**TODO: Nobody has done this yet, these instructions are new. Please verify that this works as intended.** Simply merge the new state at `STM32CubeMX-end` into your feature branch. * `git checkout your-feature` * `git merge STM32CubeMX-end` From 4348698ee18e35935ef5cfc7fc96cd7e52815697 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Sun, 25 Nov 2018 19:07:35 -0800 Subject: [PATCH 02/14] cube: add SPI irqs and DMA --- Firmware/Board/v3/Inc/stm32f4xx_it.h | 3 ++ Firmware/Board/v3/Odrive.ioc | 27 ++++++++++++++- Firmware/Board/v3/Src/dma.c | 6 ++++ Firmware/Board/v3/Src/spi.c | 49 ++++++++++++++++++++++++++++ Firmware/Board/v3/Src/stm32f4xx_it.c | 45 +++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 1 deletion(-) diff --git a/Firmware/Board/v3/Inc/stm32f4xx_it.h b/Firmware/Board/v3/Inc/stm32f4xx_it.h index bed8a253..784a3333 100644 --- a/Firmware/Board/v3/Inc/stm32f4xx_it.h +++ b/Firmware/Board/v3/Inc/stm32f4xx_it.h @@ -54,8 +54,10 @@ void BusFault_Handler(void); void UsageFault_Handler(void); void DebugMon_Handler(void); void SysTick_Handler(void); +void DMA1_Stream0_IRQHandler(void); void DMA1_Stream2_IRQHandler(void); void DMA1_Stream4_IRQHandler(void); +void DMA1_Stream5_IRQHandler(void); void ADC_IRQHandler(void); void CAN1_TX_IRQHandler(void); void CAN1_RX0_IRQHandler(void); @@ -63,6 +65,7 @@ void CAN1_RX1_IRQHandler(void); void CAN1_SCE_IRQHandler(void); void TIM8_TRG_COM_TIM14_IRQHandler(void); void TIM5_IRQHandler(void); +void SPI3_IRQHandler(void); void UART4_IRQHandler(void); void OTG_FS_IRQHandler(void); diff --git a/Firmware/Board/v3/Odrive.ioc b/Firmware/Board/v3/Odrive.ioc index d18c5f86..ab299065 100644 --- a/Firmware/Board/v3/Odrive.ioc +++ b/Firmware/Board/v3/Odrive.ioc @@ -97,7 +97,29 @@ Dma.ADC1.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlign Dma.Request0=UART4_RX Dma.Request1=UART4_TX Dma.Request2=ADC1 -Dma.RequestsNb=3 +Dma.Request3=SPI3_TX +Dma.Request4=SPI3_RX +Dma.RequestsNb=5 +Dma.SPI3_RX.4.Direction=DMA_PERIPH_TO_MEMORY +Dma.SPI3_RX.4.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.SPI3_RX.4.Instance=DMA1_Stream0 +Dma.SPI3_RX.4.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.SPI3_RX.4.MemInc=DMA_MINC_ENABLE +Dma.SPI3_RX.4.Mode=DMA_NORMAL +Dma.SPI3_RX.4.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.SPI3_RX.4.PeriphInc=DMA_PINC_DISABLE +Dma.SPI3_RX.4.Priority=DMA_PRIORITY_MEDIUM +Dma.SPI3_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +Dma.SPI3_TX.3.Direction=DMA_MEMORY_TO_PERIPH +Dma.SPI3_TX.3.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.SPI3_TX.3.Instance=DMA1_Stream5 +Dma.SPI3_TX.3.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.SPI3_TX.3.MemInc=DMA_MINC_ENABLE +Dma.SPI3_TX.3.Mode=DMA_NORMAL +Dma.SPI3_TX.3.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.SPI3_TX.3.PeriphInc=DMA_PINC_DISABLE +Dma.SPI3_TX.3.Priority=DMA_PRIORITY_MEDIUM +Dma.SPI3_TX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode Dma.UART4_RX.0.Direction=DMA_PERIPH_TO_MEMORY Dma.UART4_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE Dma.UART4_RX.0.Instance=DMA1_Stream2 @@ -221,8 +243,10 @@ NVIC.CAN1_RX0_IRQn=true\:6\:0\:true\:false\:true\:true\:true NVIC.CAN1_RX1_IRQn=true\:6\:0\:true\:false\:true\:true\:true NVIC.CAN1_SCE_IRQn=true\:6\:0\:true\:false\:true\:true\:true NVIC.CAN1_TX_IRQn=true\:6\:0\:true\:false\:true\:true\:true +NVIC.DMA1_Stream0_IRQn=true\:5\:0\:false\:false\:true\:true\:false NVIC.DMA1_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:true NVIC.DMA1_Stream4_IRQn=true\:5\:0\:false\:false\:true\:true\:false +NVIC.DMA1_Stream5_IRQn=true\:5\:0\:false\:false\:true\:true\:false NVIC.DMA2_Stream0_IRQn=true\:5\:0\:false\:false\:false\:true\:false NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true @@ -231,6 +255,7 @@ NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:true NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true\:true NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:true NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SPI3_IRQn=true\:5\:0\:false\:false\:true\:true\:true NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:true NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:true\:true NVIC.TIM1_UP_TIM10_IRQn=true\:0\:0\:false\:false\:false\:false\:true diff --git a/Firmware/Board/v3/Src/dma.c b/Firmware/Board/v3/Src/dma.c index 55d5e034..753fa090 100644 --- a/Firmware/Board/v3/Src/dma.c +++ b/Firmware/Board/v3/Src/dma.c @@ -71,12 +71,18 @@ void MX_DMA_Init(void) __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA interrupt init */ + /* DMA1_Stream0_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); /* DMA1_Stream2_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); /* DMA1_Stream4_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); + /* DMA1_Stream5_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* DMA2_Stream0_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); diff --git a/Firmware/Board/v3/Src/spi.c b/Firmware/Board/v3/Src/spi.c index 87b2a018..d66515f9 100644 --- a/Firmware/Board/v3/Src/spi.c +++ b/Firmware/Board/v3/Src/spi.c @@ -51,12 +51,15 @@ #include "spi.h" #include "gpio.h" +#include "dma.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ SPI_HandleTypeDef hspi3; +DMA_HandleTypeDef hdma_spi3_tx; +DMA_HandleTypeDef hdma_spi3_rx; /* SPI3 init function */ void MX_SPI3_Init(void) @@ -105,6 +108,46 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + /* SPI3 DMA Init */ + /* SPI3_TX Init */ + hdma_spi3_tx.Instance = DMA1_Stream5; + hdma_spi3_tx.Init.Channel = DMA_CHANNEL_0; + hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_spi3_tx.Init.Mode = DMA_NORMAL; + hdma_spi3_tx.Init.Priority = DMA_PRIORITY_MEDIUM; + hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_spi3_tx) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi3_tx); + + /* SPI3_RX Init */ + hdma_spi3_rx.Instance = DMA1_Stream0; + hdma_spi3_rx.Init.Channel = DMA_CHANNEL_0; + hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_spi3_rx.Init.Mode = DMA_NORMAL; + hdma_spi3_rx.Init.Priority = DMA_PRIORITY_MEDIUM; + hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_spi3_rx) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + __HAL_LINKDMA(spiHandle,hdmarx,hdma_spi3_rx); + + /* SPI3 interrupt Init */ + HAL_NVIC_SetPriority(SPI3_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(SPI3_IRQn); /* USER CODE BEGIN SPI3_MspInit 1 */ /* USER CODE END SPI3_MspInit 1 */ @@ -129,6 +172,12 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12); + /* SPI3 DMA DeInit */ + HAL_DMA_DeInit(spiHandle->hdmatx); + HAL_DMA_DeInit(spiHandle->hdmarx); + + /* SPI3 interrupt Deinit */ + HAL_NVIC_DisableIRQ(SPI3_IRQn); /* USER CODE BEGIN SPI3_MspDeInit 1 */ /* USER CODE END SPI3_MspDeInit 1 */ diff --git a/Firmware/Board/v3/Src/stm32f4xx_it.c b/Firmware/Board/v3/Src/stm32f4xx_it.c index 8acc96ee..f0fe1d3e 100644 --- a/Firmware/Board/v3/Src/stm32f4xx_it.c +++ b/Firmware/Board/v3/Src/stm32f4xx_it.c @@ -63,6 +63,9 @@ extern ADC_HandleTypeDef hadc1; extern ADC_HandleTypeDef hadc2; extern ADC_HandleTypeDef hadc3; extern CAN_HandleTypeDef hcan1; +extern DMA_HandleTypeDef hdma_spi3_tx; +extern DMA_HandleTypeDef hdma_spi3_rx; +extern SPI_HandleTypeDef hspi3; extern TIM_HandleTypeDef htim5; extern TIM_HandleTypeDef htim8; extern DMA_HandleTypeDef hdma_uart4_rx; @@ -194,6 +197,20 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f4xx.s). */ /******************************************************************************/ +/** +* @brief This function handles DMA1 stream0 global interrupt. +*/ +void DMA1_Stream0_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */ + + /* USER CODE END DMA1_Stream0_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_spi3_rx); + /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */ + + /* USER CODE END DMA1_Stream0_IRQn 1 */ +} + /** * @brief This function handles DMA1 stream2 global interrupt. */ @@ -222,6 +239,20 @@ void DMA1_Stream4_IRQHandler(void) /* USER CODE END DMA1_Stream4_IRQn 1 */ } +/** +* @brief This function handles DMA1 stream5 global interrupt. +*/ +void DMA1_Stream5_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */ + + /* USER CODE END DMA1_Stream5_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_spi3_tx); + /* USER CODE BEGIN DMA1_Stream5_IRQn 1 */ + + /* USER CODE END DMA1_Stream5_IRQn 1 */ +} + /** * @brief This function handles ADC1, ADC2 and ADC3 global interrupts. */ @@ -336,6 +367,20 @@ void TIM5_IRQHandler(void) /* USER CODE END TIM5_IRQn 1 */ } +/** +* @brief This function handles SPI3 global interrupt. +*/ +void SPI3_IRQHandler(void) +{ + /* USER CODE BEGIN SPI3_IRQn 0 */ + + /* USER CODE END SPI3_IRQn 0 */ + HAL_SPI_IRQHandler(&hspi3); + /* USER CODE BEGIN SPI3_IRQn 1 */ + + /* USER CODE END SPI3_IRQn 1 */ +} + /** * @brief This function handles UART4 global interrupt. */ From c4aac84c72254496c3777865b13a9dbc5c9d4f8c Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:23:46 -0700 Subject: [PATCH 03/14] bake patch: display correct ODrive version in USB descriptor --- ...ect-ODrive-version-in-USB-descriptor.patch | 41 ------------------- Firmware/Board/v3/Src/usbd_desc.c | 8 ++-- 2 files changed, 5 insertions(+), 44 deletions(-) delete mode 100644 Firmware/Board/v3/0001-display-correct-ODrive-version-in-USB-descriptor.patch diff --git a/Firmware/Board/v3/0001-display-correct-ODrive-version-in-USB-descriptor.patch b/Firmware/Board/v3/0001-display-correct-ODrive-version-in-USB-descriptor.patch deleted file mode 100644 index 0b031242..00000000 --- a/Firmware/Board/v3/0001-display-correct-ODrive-version-in-USB-descriptor.patch +++ /dev/null @@ -1,41 +0,0 @@ -From b7ea3f500fbfc187a0a7112282ae6b1eee4555d0 Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Tue, 13 Mar 2018 20:05:07 -0700 -Subject: [PATCH] display correct ODrive version in USB descriptor - ---- - Firmware/Board/v3/Src/usbd_desc.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c -index 94dc49b..37b4302 100644 ---- a/Firmware/Board/v3/Src/usbd_desc.c -+++ b/Firmware/Board/v3/Src/usbd_desc.c -@@ -96,7 +96,9 @@ - #define USBD_LANGID_STRING 1033 - #define USBD_MANUFACTURER_STRING "ODrive Robotics" - #define USBD_PID_FS 0x0D32 --#define USBD_PRODUCT_STRING_FS "ODrive v3.3" -+#define USBD_PRODUCT_XSTR(s) USBD_PRODUCT_STR(s) -+#define USBD_PRODUCT_STR(s) #s -+#define USBD_PRODUCT_STRING_FS ODrive version HW_VERSION_MAJOR.HW_VERSION_MINOR - #define USBD_SERIALNUMBER_STRING_FS "000000000001" - #define USBD_CONFIGURATION_STRING_FS "CDC Config" - #define USBD_INTERFACE_STRING_FS "CDC Interface" -@@ -299,11 +301,11 @@ uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length - { - if(speed == 0) - { -- USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); -+ USBD_GetString((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length); - } - else - { -- USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); -+ USBD_GetString((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length); - } - return USBD_StrDesc; - } --- -2.16.2 - diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c index 2e139e50..973b0ae2 100644 --- a/Firmware/Board/v3/Src/usbd_desc.c +++ b/Firmware/Board/v3/Src/usbd_desc.c @@ -95,7 +95,9 @@ #define USBD_LANGID_STRING 1033 #define USBD_MANUFACTURER_STRING "ODrive Robotics" #define USBD_PID_FS 0x0D32 -#define USBD_PRODUCT_STRING_FS "ODrive v3.3" +#define USBD_PRODUCT_XSTR(s) USBD_PRODUCT_STR(s) +#define USBD_PRODUCT_STR(s) #s +#define USBD_PRODUCT_STRING_FS ODrive version HW_VERSION_MAJOR.HW_VERSION_MINOR #define USBD_SERIALNUMBER_STRING_FS "000000000001" #define USBD_CONFIGURATION_STRING_FS "CDC Config" #define USBD_INTERFACE_STRING_FS "CDC Interface" @@ -342,11 +344,11 @@ uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length { if(speed == 0) { - USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); + USBD_GetString((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length); } else { - USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); + USBD_GetString((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length); } return USBD_StrDesc; } From 1b95b2af9488728425a00a1f844efa5f9e1d6ca2 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:27:56 -0700 Subject: [PATCH 04/14] bake patch: expose correct serial number on USB --- ...-expose-correct-serial-number-on-USB.patch | 32 ------------------- Firmware/Board/v3/Src/usbd_desc.c | 9 +----- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 Firmware/Board/v3/0001-expose-correct-serial-number-on-USB.patch diff --git a/Firmware/Board/v3/0001-expose-correct-serial-number-on-USB.patch b/Firmware/Board/v3/0001-expose-correct-serial-number-on-USB.patch deleted file mode 100644 index b9fef648..00000000 --- a/Firmware/Board/v3/0001-expose-correct-serial-number-on-USB.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0867a92f742b312a0ebaafe94cade6f57be22170 Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Mon, 12 Mar 2018 23:49:32 -0700 -Subject: [PATCH] expose correct serial number on USB - ---- - Firmware/Board/v3/Src/usbd_desc.c | 9 +++++++++------- - 1 file changed, 1 insertions(+), 8 deletions(-) - -diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c -index b9c7bd0..94dc49b 100644 ---- a/Firmware/Board/v3/Src/usbd_desc.c -+++ b/Firmware/Board/v3/Src/usbd_desc.c -@@ -327,14 +327,7 @@ uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *l - */ - uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) - { -- if(speed == USBD_SPEED_HIGH) -- { -- USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); -- } -- else -- { -- USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); -- } -+ USBD_GetString ((uint8_t *)serial_number_str, USBD_StrDesc, length); - return USBD_StrDesc; - } - --- -2.16.2 - diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c index 973b0ae2..b0906144 100644 --- a/Firmware/Board/v3/Src/usbd_desc.c +++ b/Firmware/Board/v3/Src/usbd_desc.c @@ -373,14 +373,7 @@ uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *l */ uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - if(speed == USBD_SPEED_HIGH) - { - USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); - } - else - { - USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); - } + USBD_GetString ((uint8_t *)serial_number_str, USBD_StrDesc, length); return USBD_StrDesc; } From 6b441b134e91ed41113d1996827900d032f8ec5c Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:29:43 -0700 Subject: [PATCH 05/14] bake patch: fix return type of osSemaphoreWait --- ...1-fix-return-type-of-osSemaphoreWait.patch | 46 ------------------- .../FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c | 4 +- .../FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h | 4 +- 3 files changed, 4 insertions(+), 50 deletions(-) delete mode 100644 Firmware/Board/v3/0001-fix-return-type-of-osSemaphoreWait.patch diff --git a/Firmware/Board/v3/0001-fix-return-type-of-osSemaphoreWait.patch b/Firmware/Board/v3/0001-fix-return-type-of-osSemaphoreWait.patch deleted file mode 100644 index 53760fa1..00000000 --- a/Firmware/Board/v3/0001-fix-return-type-of-osSemaphoreWait.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 49353ccb7023c02c2bc6e3b6f14fac02a13fe599 Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Mon, 26 Feb 2018 14:55:17 -0800 -Subject: [PATCH] fix return type of osSemaphoreWait - ---- - .../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c | 6 +++--- - .../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c -index d0e0fd7..e764cbc 100644 ---- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c -+++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c -@@ -816,10 +816,10 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t - * @brief Wait until a Semaphore token becomes available - * @param semaphore_id semaphore object referenced with \ref osSemaphore. - * @param millisec timeout value or 0 in case of no time-out. --* @retval number of available tokens, or -1 in case of incorrect parameters. -+* @retval status code that indicates the execution status of the function. - * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. - */ --int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) -+osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) - { - TickType_t ticks; - portBASE_TYPE taskWoken = pdFALSE; -diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h -index 15e25b9..5223f8e 100644 ---- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h -+++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h -@@ -719,9 +719,9 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t - /// Wait until a Semaphore token becomes available. - /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. - /// \param[in] millisec timeout value or 0 in case of no time-out. --/// \return number of available tokens, or -1 in case of incorrect parameters. -+/// \return status code that indicates the execution status of the function. - /// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. --int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec); -+osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec); - - /// Release a Semaphore token. - /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. --- -2.16.1 - diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c index d0e0fd76..7828403b 100644 --- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c +++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c @@ -816,10 +816,10 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t * @brief Wait until a Semaphore token becomes available * @param semaphore_id semaphore object referenced with \ref osSemaphore. * @param millisec timeout value or 0 in case of no time-out. -* @retval number of available tokens, or -1 in case of incorrect parameters. +* @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. */ -int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) +osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) { TickType_t ticks; portBASE_TYPE taskWoken = pdFALSE; diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h index 15e25b96..09cdf273 100644 --- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h +++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h @@ -719,9 +719,9 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t /// Wait until a Semaphore token becomes available. /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. /// \param[in] millisec timeout value or 0 in case of no time-out. -/// \return number of available tokens, or -1 in case of incorrect parameters. +/// \return status code that indicates the execution status of the function. /// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. -int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec); +osStatus osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec); /// Release a Semaphore token. /// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. From 1a687e05376fd7a99c812d004d6a09332162f63e Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:31:41 -0700 Subject: [PATCH 06/14] bake patch: release sem_usb_tx in usb_cdc.c --- ...001-release-sem_usb_tx-in-usbd_cdc.c.patch | 35 ------------------- .../Class/CDC/Src/usbd_cdc.c | 5 +-- 2 files changed, 3 insertions(+), 37 deletions(-) delete mode 100644 Firmware/Board/v3/0001-release-sem_usb_tx-in-usbd_cdc.c.patch diff --git a/Firmware/Board/v3/0001-release-sem_usb_tx-in-usbd_cdc.c.patch b/Firmware/Board/v3/0001-release-sem_usb_tx-in-usbd_cdc.c.patch deleted file mode 100644 index b69370f5..00000000 --- a/Firmware/Board/v3/0001-release-sem_usb_tx-in-usbd_cdc.c.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 965f7f2c80e30d7a66dcac7abaa9bdc371d9ea51 Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Mon, 26 Feb 2018 14:53:52 -0800 -Subject: [PATCH] release sem_usb_tx in usbd_cdc.c - ---- - .../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Firmware/Board/v3.3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c -index b2ca5f1..6ae33e8 100644 ---- a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c -+++ b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c -@@ -62,7 +62,8 @@ - #include "usbd_cdc.h" - #include "usbd_desc.h" - #include "usbd_ctlreq.h" -- -+#include -+#include - - /** @addtogroup STM32_USB_DEVICE_LIBRARY - * @{ -@@ -669,7 +670,7 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) - { - - hcdc->TxState = 0; -- -+ osSemaphoreRelease(sem_usb_tx); - return USBD_OK; - } - else --- -2.16.1 - diff --git a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c index b2ca5f16..24465641 100644 --- a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +++ b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c @@ -62,7 +62,8 @@ #include "usbd_cdc.h" #include "usbd_desc.h" #include "usbd_ctlreq.h" - +#include +#include /** @addtogroup STM32_USB_DEVICE_LIBRARY * @{ @@ -669,7 +670,7 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) { hcdc->TxState = 0; - + osSemaphoreRelease(sem_usb_tx); return USBD_OK; } else From f606958bf2507f3715f672258a69dba2065273e9 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:43:04 -0700 Subject: [PATCH 07/14] bake patch: FreeRTOS constness fixes --- .../v3/0002-FreeRTOS-constness-fixes.patch | 64 ------------------- .../FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h | 8 +-- Firmware/Board/v3/Src/freertos.c | 4 +- 3 files changed, 6 insertions(+), 70 deletions(-) delete mode 100644 Firmware/Board/v3/0002-FreeRTOS-constness-fixes.patch diff --git a/Firmware/Board/v3/0002-FreeRTOS-constness-fixes.patch b/Firmware/Board/v3/0002-FreeRTOS-constness-fixes.patch deleted file mode 100644 index afe0326e..00000000 --- a/Firmware/Board/v3/0002-FreeRTOS-constness-fixes.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 510ead2b159e1d8116e5241066c54a7bf8b7bfbe Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Mon, 26 Mar 2018 15:29:44 -0700 -Subject: [PATCH] FreeRTOS constness fixes - - - make thread names const char * - - make thread argument non-const void* ---- - .../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h | 6 +++--- - Firmware/Board/v3/Src/freertos.c | 4 ++-- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h -index 09cdf27..754be24 100644 ---- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h -+++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h -@@ -270,11 +270,11 @@ typedef enum { - - /// Entry point of a thread. - /// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS. --typedef void (*os_pthread) (void const *argument); -+typedef void (*os_pthread) (void *argument); - - /// Entry point of a timer call back function. - /// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS. --typedef void (*os_ptimer) (void const *argument); -+typedef void (*os_ptimer) (void *argument); - - // >>> the following data type definitions may shall adapted towards a specific RTOS - -@@ -323,7 +323,7 @@ typedef StaticQueue_t osStaticMessageQDef_t; - /// Thread Definition structure contains startup information of a thread. - /// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS. - typedef struct os_thread_def { -- char *name; ///< Thread name -+ const char *name; ///< Thread name - os_pthread pthread; ///< start address of thread function - osPriority tpriority; ///< initial thread priority - uint32_t instances; ///< maximum number of instances of that thread function -diff --git a/Firmware/Board/v3/Src/freertos.c b/Firmware/Board/v3/Src/freertos.c -index 6eaea82..b247994 100644 ---- a/Firmware/Board/v3/Src/freertos.c -+++ b/Firmware/Board/v3/Src/freertos.c -@@ -75,7 +75,7 @@ uint8_t ucHeap[configTOTAL_HEAP_SIZE]; - /* USER CODE END Variables */ - - /* Function prototypes -------------------------------------------------------*/ --void StartDefaultTask(void const * argument); -+void StartDefaultTask(void * argument); - - extern void MX_USB_DEVICE_Init(void); - void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ -@@ -147,7 +147,7 @@ void MX_FREERTOS_Init(void) { - } - - /* StartDefaultTask function */ --void StartDefaultTask(void const * argument) -+void StartDefaultTask(void * argument) - { - /* init code for USB_DEVICE */ - MX_USB_DEVICE_Init(); --- -2.16.2 - diff --git a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h index 09cdf273..89a105dc 100644 --- a/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h +++ b/Firmware/Board/v3/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h @@ -26,7 +26,7 @@ * *---------------------------------------------------------------------------- * - * Portions Copyright © 2016 STMicroelectronics International N.V. All rights reserved. + * Portions Copyright ďż˝ 2016 STMicroelectronics International N.V. All rights reserved. * Portions Copyright (c) 2013 ARM LIMITED * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -270,11 +270,11 @@ typedef enum { /// Entry point of a thread. /// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS. -typedef void (*os_pthread) (void const *argument); +typedef void (*os_pthread) (void *argument); /// Entry point of a timer call back function. /// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS. -typedef void (*os_ptimer) (void const *argument); +typedef void (*os_ptimer) (void *argument); // >>> the following data type definitions may shall adapted towards a specific RTOS @@ -323,7 +323,7 @@ typedef StaticQueue_t osStaticMessageQDef_t; /// Thread Definition structure contains startup information of a thread. /// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS. typedef struct os_thread_def { - char *name; ///< Thread name + const char *name; ///< Thread name os_pthread pthread; ///< start address of thread function osPriority tpriority; ///< initial thread priority uint32_t instances; ///< maximum number of instances of that thread function diff --git a/Firmware/Board/v3/Src/freertos.c b/Firmware/Board/v3/Src/freertos.c index 0865d714..11154587 100644 --- a/Firmware/Board/v3/Src/freertos.c +++ b/Firmware/Board/v3/Src/freertos.c @@ -98,7 +98,7 @@ osThreadId defaultTaskHandle; /* USER CODE END FunctionPrototypes */ -void StartDefaultTask(void const * argument); +void StartDefaultTask(void * argument); extern void MX_USB_DEVICE_Init(void); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ @@ -214,7 +214,7 @@ void MX_FREERTOS_Init(void) { * @retval None */ /* USER CODE END Header_StartDefaultTask */ -void StartDefaultTask(void const * argument) +void StartDefaultTask(void * argument) { /* init code for USB_DEVICE */ MX_USB_DEVICE_Init(); From 8816a42aacfae92348e675e49422070ebe3b3c31 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:45:30 -0700 Subject: [PATCH 08/14] bake patch: disable IRQ for DMA2_Stream0 --- .../0003-disable-IRQ-for-DMA2_Stream0.patch | 33 ------------------- Firmware/Board/v3/Src/dma.c | 6 ++-- 2 files changed, 4 insertions(+), 35 deletions(-) delete mode 100644 Firmware/Board/v3/0003-disable-IRQ-for-DMA2_Stream0.patch diff --git a/Firmware/Board/v3/0003-disable-IRQ-for-DMA2_Stream0.patch b/Firmware/Board/v3/0003-disable-IRQ-for-DMA2_Stream0.patch deleted file mode 100644 index 282317d1..00000000 --- a/Firmware/Board/v3/0003-disable-IRQ-for-DMA2_Stream0.patch +++ /dev/null @@ -1,33 +0,0 @@ -From ab5ca860b3729d76a9c43c485776147ab69d2342 Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Mon, 26 Mar 2018 19:02:45 -0700 -Subject: [PATCH] disable IRQ for DMA2_Stream0 - -This DMA stream is used to read values from ADC1 -while ADC1 cycles through it's sequence of input -channels. No interrupts are required to make -this work. ---- - Firmware/Board/v3/Src/dma.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/Firmware/Board/v3/Src/dma.c b/Firmware/Board/v3/Src/dma.c -index 55d5e03..3de873a 100644 ---- a/Firmware/Board/v3/Src/dma.c -+++ b/Firmware/Board/v3/Src/dma.c -@@ -78,8 +78,10 @@ void MX_DMA_Init(void) - HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); - /* DMA2_Stream0_IRQn interrupt configuration */ -- HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0); -- HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); -+ // Dear STM, no we _don't_ want to fire an interrupt for this DMA -+ // (it's not possible to deselect this in CubeMX) -+ //HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0); -+ //HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); - - } - --- -2.16.2 - diff --git a/Firmware/Board/v3/Src/dma.c b/Firmware/Board/v3/Src/dma.c index 753fa090..813c735a 100644 --- a/Firmware/Board/v3/Src/dma.c +++ b/Firmware/Board/v3/Src/dma.c @@ -84,8 +84,10 @@ void MX_DMA_Init(void) HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* DMA2_Stream0_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); + // Dear STM, no we _don't_ want to fire an interrupt for this DMA + // (it's not possible to deselect this in CubeMX) + //HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0); + //HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); } From 2ca83c1d41949974dac58b87f8ebe22a8348a734 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 23 Oct 2018 23:57:44 -0700 Subject: [PATCH 09/14] bake patch: Add I2C files and settings --- .../v3/0002-Add-I2C-files-and-settings.patch | 6860 ----------------- .../Inc/stm32f4xx_hal_i2c.h | 649 ++ .../Inc/stm32f4xx_hal_i2c_ex.h | 137 + .../Src/stm32f4xx_hal_i2c.c | 5494 +++++++++++++ .../Src/stm32f4xx_hal_i2c_ex.c | 204 + Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h | 2 +- Firmware/Board/v3/Src/main.c | 2 +- 7 files changed, 6486 insertions(+), 6862 deletions(-) delete mode 100644 Firmware/Board/v3/0002-Add-I2C-files-and-settings.patch create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c diff --git a/Firmware/Board/v3/0002-Add-I2C-files-and-settings.patch b/Firmware/Board/v3/0002-Add-I2C-files-and-settings.patch deleted file mode 100644 index aae18bf4..00000000 --- a/Firmware/Board/v3/0002-Add-I2C-files-and-settings.patch +++ /dev/null @@ -1,6860 +0,0 @@ -From b45bdbbbfe3d084d069da99b98116991923f5eb6 Mon Sep 17 00:00:00 2001 -From: Samuel Sadok -Date: Thu, 26 Apr 2018 13:20:38 -0700 -Subject: [PATCH] Add I2C files and settings - ---- - .../Inc/stm32f4xx_hal_i2c.h | 649 ++ - .../Inc/stm32f4xx_hal_i2c_ex.h | 137 + - .../Src/stm32f4xx_hal_i2c.c | 5494 +++++++++++++++++ - .../Src/stm32f4xx_hal_i2c_ex.c | 204 + - Firmware/Board/v3/Inc/i2c.h | 91 + - Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h | 2 +- - Firmware/Board/v3/Odrive.ioc | 5 + - Firmware/Board/v3/Src/i2c.c | 198 + - Firmware/Board/v3/Src/main.c | 1 - - 11 files changed, 6811 insertions(+), 2 deletions(-) - create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h - create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h - create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c - create mode 100644 Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c - create mode 100644 Firmware/Board/v3/Inc/i2c.h - create mode 100644 Firmware/Board/v3/Src/i2c.c - -diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h -new file mode 100644 -index 0000000..5452a50 ---- /dev/null -+++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h -@@ -0,0 +1,649 @@ -+/** -+ ****************************************************************************** -+ * @file stm32f4xx_hal_i2c.h -+ * @author MCD Application Team -+ * @brief Header file of I2C HAL module. -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) 2017 STMicroelectronics

-+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. Neither the name of STMicroelectronics nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ****************************************************************************** -+ */ -+ -+/* Define to prevent recursive inclusion -------------------------------------*/ -+#ifndef __STM32F4xx_HAL_I2C_H -+#define __STM32F4xx_HAL_I2C_H -+ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+ -+/* Includes ------------------------------------------------------------------*/ -+#include "stm32f4xx_hal_def.h" -+ -+/** @addtogroup STM32F4xx_HAL_Driver -+ * @{ -+ */ -+ -+/** @addtogroup I2C -+ * @{ -+ */ -+ -+/* Exported types ------------------------------------------------------------*/ -+/** @defgroup I2C_Exported_Types I2C Exported Types -+ * @{ -+ */ -+ -+/** -+ * @brief I2C Configuration Structure definition -+ */ -+typedef struct -+{ -+ uint32_t ClockSpeed; /*!< Specifies the clock frequency. -+ This parameter must be set to a value lower than 400kHz */ -+ -+ uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle. -+ This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ -+ -+ uint32_t OwnAddress1; /*!< Specifies the first device own address. -+ This parameter can be a 7-bit or 10-bit address. */ -+ -+ uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. -+ This parameter can be a value of @ref I2C_addressing_mode */ -+ -+ uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. -+ This parameter can be a value of @ref I2C_dual_addressing_mode */ -+ -+ uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected -+ This parameter can be a 7-bit address. */ -+ -+ uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. -+ This parameter can be a value of @ref I2C_general_call_addressing_mode */ -+ -+ uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. -+ This parameter can be a value of @ref I2C_nostretch_mode */ -+ -+}I2C_InitTypeDef; -+ -+/** -+ * @brief HAL State structure definition -+ * @note HAL I2C State value coding follow below described bitmap : -+ * b7-b6 Error information -+ * 00 : No Error -+ * 01 : Abort (Abort user request on going) -+ * 10 : Timeout -+ * 11 : Error -+ * b5 IP initilisation status -+ * 0 : Reset (IP not initialized) -+ * 1 : Init done (IP initialized and ready to use. HAL I2C Init function called) -+ * b4 (not used) -+ * x : Should be set to 0 -+ * b3 -+ * 0 : Ready or Busy (No Listen mode ongoing) -+ * 1 : Listen (IP in Address Listen Mode) -+ * b2 Intrinsic process state -+ * 0 : Ready -+ * 1 : Busy (IP busy with some configuration or internal operations) -+ * b1 Rx state -+ * 0 : Ready (no Rx operation ongoing) -+ * 1 : Busy (Rx operation ongoing) -+ * b0 Tx state -+ * 0 : Ready (no Tx operation ongoing) -+ * 1 : Busy (Tx operation ongoing) -+ */ -+typedef enum -+{ -+ HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ -+ HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ -+ HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ -+ HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ -+ HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ -+ HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ -+ HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission -+ process is ongoing */ -+ HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception -+ process is ongoing */ -+ HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ -+ HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ -+ HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ -+ -+}HAL_I2C_StateTypeDef; -+ -+/** -+ * @brief HAL Mode structure definition -+ * @note HAL I2C Mode value coding follow below described bitmap : -+ * b7 (not used) -+ * x : Should be set to 0 -+ * b6 -+ * 0 : None -+ * 1 : Memory (HAL I2C communication is in Memory Mode) -+ * b5 -+ * 0 : None -+ * 1 : Slave (HAL I2C communication is in Slave Mode) -+ * b4 -+ * 0 : None -+ * 1 : Master (HAL I2C communication is in Master Mode) -+ * b3-b2-b1-b0 (not used) -+ * xxxx : Should be set to 0000 -+ */ -+typedef enum -+{ -+ HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ -+ HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ -+ HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ -+ HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ -+ -+}HAL_I2C_ModeTypeDef; -+ -+/** -+ * @brief I2C handle Structure definition -+ */ -+typedef struct -+{ -+ I2C_TypeDef *Instance; /*!< I2C registers base address */ -+ -+ I2C_InitTypeDef Init; /*!< I2C communication parameters */ -+ -+ uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ -+ -+ uint16_t XferSize; /*!< I2C transfer size */ -+ -+ __IO uint16_t XferCount; /*!< I2C transfer counter */ -+ -+ __IO uint32_t XferOptions; /*!< I2C transfer options */ -+ -+ __IO uint32_t PreviousState; /*!< I2C communication Previous state and mode -+ context for internal usage */ -+ -+ DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ -+ -+ DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ -+ -+ HAL_LockTypeDef Lock; /*!< I2C locking object */ -+ -+ __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ -+ -+ __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ -+ -+ __IO uint32_t ErrorCode; /*!< I2C Error code */ -+ -+ __IO uint32_t Devaddress; /*!< I2C Target device address */ -+ -+ __IO uint32_t Memaddress; /*!< I2C Target memory address */ -+ -+ __IO uint32_t MemaddSize; /*!< I2C Target memory address size */ -+ -+ __IO uint32_t EventCount; /*!< I2C Event counter */ -+ -+}I2C_HandleTypeDef; -+ -+/** -+ * @} -+ */ -+ -+/* Exported constants --------------------------------------------------------*/ -+/** @defgroup I2C_Exported_Constants I2C Exported Constants -+ * @{ -+ */ -+ -+/** @defgroup I2C_Error_Code I2C Error Code -+ * @brief I2C Error Code -+ * @{ -+ */ -+#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */ -+#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */ -+#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */ -+#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */ -+#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */ -+#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */ -+#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */ -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_duty_cycle_in_fast_mode I2C duty cycle in fast mode -+ * @{ -+ */ -+#define I2C_DUTYCYCLE_2 0x00000000U -+#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_addressing_mode I2C addressing mode -+ * @{ -+ */ -+#define I2C_ADDRESSINGMODE_7BIT 0x00004000U -+#define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U) -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_dual_addressing_mode I2C dual addressing mode -+ * @{ -+ */ -+#define I2C_DUALADDRESS_DISABLE 0x00000000U -+#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_general_call_addressing_mode I2C general call addressing mode -+ * @{ -+ */ -+#define I2C_GENERALCALL_DISABLE 0x00000000U -+#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_nostretch_mode I2C nostretch mode -+ * @{ -+ */ -+#define I2C_NOSTRETCH_DISABLE 0x00000000U -+#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_Memory_Address_Size I2C Memory Address Size -+ * @{ -+ */ -+#define I2C_MEMADD_SIZE_8BIT 0x00000001U -+#define I2C_MEMADD_SIZE_16BIT 0x00000010U -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_XferDirection_definition I2C XferDirection definition -+ * @{ -+ */ -+#define I2C_DIRECTION_RECEIVE 0x00000000U -+#define I2C_DIRECTION_TRANSMIT 0x00000001U -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_XferOptions_definition I2C XferOptions definition -+ * @{ -+ */ -+#define I2C_FIRST_FRAME 0x00000001U -+#define I2C_NEXT_FRAME 0x00000002U -+#define I2C_FIRST_AND_LAST_FRAME 0x00000004U -+#define I2C_LAST_FRAME 0x00000008U -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition -+ * @{ -+ */ -+#define I2C_IT_BUF I2C_CR2_ITBUFEN -+#define I2C_IT_EVT I2C_CR2_ITEVTEN -+#define I2C_IT_ERR I2C_CR2_ITERREN -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_Flag_definition I2C Flag definition -+ * @{ -+ */ -+#define I2C_FLAG_SMBALERT 0x00018000U -+#define I2C_FLAG_TIMEOUT 0x00014000U -+#define I2C_FLAG_PECERR 0x00011000U -+#define I2C_FLAG_OVR 0x00010800U -+#define I2C_FLAG_AF 0x00010400U -+#define I2C_FLAG_ARLO 0x00010200U -+#define I2C_FLAG_BERR 0x00010100U -+#define I2C_FLAG_TXE 0x00010080U -+#define I2C_FLAG_RXNE 0x00010040U -+#define I2C_FLAG_STOPF 0x00010010U -+#define I2C_FLAG_ADD10 0x00010008U -+#define I2C_FLAG_BTF 0x00010004U -+#define I2C_FLAG_ADDR 0x00010002U -+#define I2C_FLAG_SB 0x00010001U -+#define I2C_FLAG_DUALF 0x00100080U -+#define I2C_FLAG_SMBHOST 0x00100040U -+#define I2C_FLAG_SMBDEFAULT 0x00100020U -+#define I2C_FLAG_GENCALL 0x00100010U -+#define I2C_FLAG_TRA 0x00100004U -+#define I2C_FLAG_BUSY 0x00100002U -+#define I2C_FLAG_MSL 0x00100001U -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/* Exported macro ------------------------------------------------------------*/ -+/** @defgroup I2C_Exported_Macros I2C Exported Macros -+ * @{ -+ */ -+ -+/** @brief Reset I2C handle state -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @retval None -+ */ -+#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET) -+ -+/** @brief Enable or disable the specified I2C interrupts. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @param __INTERRUPT__ specifies the interrupt source to enable or disable. -+ * This parameter can be one of the following values: -+ * @arg I2C_IT_BUF: Buffer interrupt enable -+ * @arg I2C_IT_EVT: Event interrupt enable -+ * @arg I2C_IT_ERR: Error interrupt enable -+ * @retval None -+ */ -+#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 |= (__INTERRUPT__)) -+#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 &= (~(__INTERRUPT__))) -+ -+/** @brief Checks if the specified I2C interrupt source is enabled or disabled. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @param __INTERRUPT__ specifies the I2C interrupt source to check. -+ * This parameter can be one of the following values: -+ * @arg I2C_IT_BUF: Buffer interrupt enable -+ * @arg I2C_IT_EVT: Event interrupt enable -+ * @arg I2C_IT_ERR: Error interrupt enable -+ * @retval The new state of __INTERRUPT__ (TRUE or FALSE). -+ */ -+#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) -+ -+/** @brief Checks whether the specified I2C flag is set or not. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @param __FLAG__ specifies the flag to check. -+ * This parameter can be one of the following values: -+ * @arg I2C_FLAG_SMBALERT: SMBus Alert flag -+ * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag -+ * @arg I2C_FLAG_PECERR: PEC error in reception flag -+ * @arg I2C_FLAG_OVR: Overrun/Underrun flag -+ * @arg I2C_FLAG_AF: Acknowledge failure flag -+ * @arg I2C_FLAG_ARLO: Arbitration lost flag -+ * @arg I2C_FLAG_BERR: Bus error flag -+ * @arg I2C_FLAG_TXE: Data register empty flag -+ * @arg I2C_FLAG_RXNE: Data register not empty flag -+ * @arg I2C_FLAG_STOPF: Stop detection flag -+ * @arg I2C_FLAG_ADD10: 10-bit header sent flag -+ * @arg I2C_FLAG_BTF: Byte transfer finished flag -+ * @arg I2C_FLAG_ADDR: Address sent flag -+ * Address matched flag -+ * @arg I2C_FLAG_SB: Start bit flag -+ * @arg I2C_FLAG_DUALF: Dual flag -+ * @arg I2C_FLAG_SMBHOST: SMBus host header -+ * @arg I2C_FLAG_SMBDEFAULT: SMBus default header -+ * @arg I2C_FLAG_GENCALL: General call header flag -+ * @arg I2C_FLAG_TRA: Transmitter/Receiver flag -+ * @arg I2C_FLAG_BUSY: Bus busy flag -+ * @arg I2C_FLAG_MSL: Master/Slave flag -+ * @retval The new state of __FLAG__ (TRUE or FALSE). -+ */ -+#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U)?((((__HANDLE__)->Instance->SR1) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)): \ -+ ((((__HANDLE__)->Instance->SR2) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK))) -+ -+/** @brief Clears the I2C pending flags which are cleared by writing 0 in a specific bit. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @param __FLAG__ specifies the flag to clear. -+ * This parameter can be any combination of the following values: -+ * @arg I2C_FLAG_SMBALERT: SMBus Alert flag -+ * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag -+ * @arg I2C_FLAG_PECERR: PEC error in reception flag -+ * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) -+ * @arg I2C_FLAG_AF: Acknowledge failure flag -+ * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) -+ * @arg I2C_FLAG_BERR: Bus error flag -+ * @retval None -+ */ -+#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__) & I2C_FLAG_MASK)) -+ -+/** @brief Clears the I2C ADDR pending flag. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @retval None -+ */ -+#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ -+ do{ \ -+ __IO uint32_t tmpreg = 0x00U; \ -+ tmpreg = (__HANDLE__)->Instance->SR1; \ -+ tmpreg = (__HANDLE__)->Instance->SR2; \ -+ UNUSED(tmpreg); \ -+ } while(0) -+ -+/** @brief Clears the I2C STOPF pending flag. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. -+ * @retval None -+ */ -+#define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \ -+ do{ \ -+ __IO uint32_t tmpreg = 0x00U; \ -+ tmpreg = (__HANDLE__)->Instance->SR1; \ -+ (__HANDLE__)->Instance->CR1 |= I2C_CR1_PE; \ -+ UNUSED(tmpreg); \ -+ } while(0) -+ -+/** @brief Enable the I2C peripheral. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral. -+ * @retval None -+ */ -+#define __HAL_I2C_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= I2C_CR1_PE) -+ -+/** @brief Disable the I2C peripheral. -+ * @param __HANDLE__ specifies the I2C Handle. -+ * This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral. -+ * @retval None -+ */ -+#define __HAL_I2C_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~I2C_CR1_PE) -+ -+/** -+ * @} -+ */ -+ -+/* Include I2C HAL Extension module */ -+#include "stm32f4xx_hal_i2c_ex.h" -+ -+/* Exported functions --------------------------------------------------------*/ -+/** @addtogroup I2C_Exported_Functions -+ * @{ -+ */ -+ -+/** @addtogroup I2C_Exported_Functions_Group1 -+ * @{ -+ */ -+/* Initialization/de-initialization functions **********************************/ -+HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); -+HAL_StatusTypeDef HAL_I2C_DeInit (I2C_HandleTypeDef *hi2c); -+void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c); -+/** -+ * @} -+ */ -+ -+/** @addtogroup I2C_Exported_Functions_Group2 -+ * @{ -+ */ -+/* I/O operation functions *****************************************************/ -+/******* Blocking mode: Polling */ -+HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); -+HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); -+HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); -+HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); -+HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); -+HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); -+HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); -+ -+/******* Non-Blocking mode: Interrupt */ -+HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); -+ -+HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -+HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -+HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -+HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); -+HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress); -+HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c); -+HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c); -+ -+/******* Non-Blocking mode: DMA */ -+HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); -+HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); -+ -+/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ -+void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); -+void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c); -+void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c); -+/** -+ * @} -+ */ -+ -+/** @addtogroup I2C_Exported_Functions_Group3 -+ * @{ -+ */ -+/* Peripheral State, Mode and Errors functions *********************************/ -+HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c); -+HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c); -+uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c); -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+/* Private types -------------------------------------------------------------*/ -+/* Private variables ---------------------------------------------------------*/ -+/* Private constants ---------------------------------------------------------*/ -+/** @defgroup I2C_Private_Constants I2C Private Constants -+ * @{ -+ */ -+#define I2C_FLAG_MASK 0x0000FFFFU -+/** -+ * @} -+ */ -+ -+/* Private macros ------------------------------------------------------------*/ -+/** @defgroup I2C_Private_Macros I2C Private Macros -+ * @{ -+ */ -+ -+#define I2C_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U) -+#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U)) -+#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) (((((__PCLK__)/((__SPEED__) << 1U)) & I2C_CCR_CCR) < 4U)? 4U:((__PCLK__) / ((__SPEED__) << 1U))) -+#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? ((__PCLK__) / ((__SPEED__) * 3U)) : (((__PCLK__) / ((__SPEED__) * 25U)) | I2C_DUTYCYCLE_16_9)) -+#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__SPEED__) <= 100000U)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) : \ -+ ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U)? 1U : \ -+ ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS)) -+ -+#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0))) -+#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0)) -+ -+#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) -+#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0))) -+#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1)))) -+ -+#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0xFF00)) >> 8))) -+#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) -+ -+/** @defgroup I2C_IS_RTC_Definitions I2C Private macros to check input parameters -+ * @{ -+ */ -+#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DUTYCYCLE_2) || \ -+ ((CYCLE) == I2C_DUTYCYCLE_16_9)) -+#define IS_I2C_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || \ -+ ((ADDRESS) == I2C_ADDRESSINGMODE_10BIT)) -+#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \ -+ ((ADDRESS) == I2C_DUALADDRESS_ENABLE)) -+#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || \ -+ ((CALL) == I2C_GENERALCALL_ENABLE)) -+#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || \ -+ ((STRETCH) == I2C_NOSTRETCH_ENABLE)) -+#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || \ -+ ((SIZE) == I2C_MEMADD_SIZE_16BIT)) -+#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) > 0U) && ((SPEED) <= 400000U)) -+#define IS_I2C_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & 0xFFFFFC00U) == 0U) -+#define IS_I2C_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & 0xFFFFFF01U) == 0U) -+#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || \ -+ ((REQUEST) == I2C_NEXT_FRAME) || \ -+ ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || \ -+ ((REQUEST) == I2C_LAST_FRAME)) -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/* Private functions ---------------------------------------------------------*/ -+/** @defgroup I2C_Private_Functions I2C Private Functions -+ * @{ -+ */ -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+ -+#endif /* __STM32F4xx_HAL_I2C_H */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h -new file mode 100644 -index 0000000..ff47d5c ---- /dev/null -+++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h -@@ -0,0 +1,137 @@ -+/** -+ ****************************************************************************** -+ * @file stm32f4xx_hal_i2c_ex.h -+ * @author MCD Application Team -+ * @brief Header file of I2C HAL Extension module. -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) 2017 STMicroelectronics

-+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. Neither the name of STMicroelectronics nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ****************************************************************************** -+ */ -+ -+/* Define to prevent recursive inclusion -------------------------------------*/ -+#ifndef __STM32F4xx_HAL_I2C_EX_H -+#define __STM32F4xx_HAL_I2C_EX_H -+ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+ -+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ -+ defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) ||\ -+ defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) -+/* Includes ------------------------------------------------------------------*/ -+#include "stm32f4xx_hal_def.h" -+ -+/** @addtogroup STM32F4xx_HAL_Driver -+ * @{ -+ */ -+ -+/** @addtogroup I2CEx -+ * @{ -+ */ -+ -+/* Exported types ------------------------------------------------------------*/ -+/* Exported constants --------------------------------------------------------*/ -+/** @defgroup I2CEx_Exported_Constants I2C Exported Constants -+ * @{ -+ */ -+ -+/** @defgroup I2CEx_Analog_Filter I2C Analog Filter -+ * @{ -+ */ -+#define I2C_ANALOGFILTER_ENABLE 0x00000000U -+#define I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/* Exported macro ------------------------------------------------------------*/ -+/* Exported functions --------------------------------------------------------*/ -+/** @addtogroup I2CEx_Exported_Functions -+ * @{ -+ */ -+ -+/** @addtogroup I2CEx_Exported_Functions_Group1 -+ * @{ -+ */ -+/* Peripheral Control functions ************************************************/ -+HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); -+HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+/* Private types -------------------------------------------------------------*/ -+/* Private variables ---------------------------------------------------------*/ -+/* Private constants ---------------------------------------------------------*/ -+/** @defgroup I2CEx_Private_Constants I2C Private Constants -+ * @{ -+ */ -+ -+/** -+ * @} -+ */ -+ -+/* Private macros ------------------------------------------------------------*/ -+/** @defgroup I2CEx_Private_Macros I2C Private Macros -+ * @{ -+ */ -+#define IS_I2C_ANALOG_FILTER(FILTER) (((FILTER) == I2C_ANALOGFILTER_ENABLE) || \ -+ ((FILTER) == I2C_ANALOGFILTER_DISABLE)) -+#define IS_I2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+#endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F401xC ||\ -+ STM32F401xE || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx ||\ -+ STM32F413xx || STM32F423xx */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __STM32F4xx_HAL_I2C_EX_H */ -+ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c -new file mode 100644 -index 0000000..da18520 ---- /dev/null -+++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c -@@ -0,0 +1,5494 @@ -+/** -+ ****************************************************************************** -+ * @file stm32f4xx_hal_i2c.c -+ * @author MCD Application Team -+ * @brief I2C HAL module driver. -+ * This file provides firmware functions to manage the following -+ * functionalities of the Inter Integrated Circuit (I2C) peripheral: -+ * + Initialization and de-initialization functions -+ * + IO operation functions -+ * + Peripheral State, Mode and Error functions -+ * -+ @verbatim -+ ============================================================================== -+ ##### How to use this driver ##### -+ ============================================================================== -+ [..] -+ The I2C HAL driver can be used as follows: -+ -+ (#) Declare a I2C_HandleTypeDef handle structure, for example: -+ I2C_HandleTypeDef hi2c; -+ -+ (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API: -+ (##) Enable the I2Cx interface clock -+ (##) I2C pins configuration -+ (+++) Enable the clock for the I2C GPIOs -+ (+++) Configure I2C pins as alternate function open-drain -+ (##) NVIC configuration if you need to use interrupt process -+ (+++) Configure the I2Cx interrupt priority -+ (+++) Enable the NVIC I2C IRQ Channel -+ (##) DMA Configuration if you need to use DMA process -+ (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive stream -+ (+++) Enable the DMAx interface clock using -+ (+++) Configure the DMA handle parameters -+ (+++) Configure the DMA Tx or Rx Stream -+ (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle -+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on -+ the DMA Tx or Rx Stream -+ -+ (#) Configure the Communication Speed, Duty cycle, Addressing mode, Own Address1, -+ Dual Addressing mode, Own Address2, General call and Nostretch mode in the hi2c Init structure. -+ -+ (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware -+ (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API. -+ -+ (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady() -+ -+ (#) For I2C IO and IO MEM operations, three operation modes are available within this driver : -+ -+ *** Polling mode IO operation *** -+ ================================= -+ [..] -+ (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit() -+ (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive() -+ (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit() -+ (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive() -+ -+ *** Polling mode IO MEM operation *** -+ ===================================== -+ [..] -+ (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write() -+ (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read() -+ -+ -+ *** Interrupt mode IO operation *** -+ =================================== -+ [..] -+ (+) Transmit in master mode an amount of data in non blocking mode using HAL_I2C_Master_Transmit_IT() -+ (+) At transmission end of transfer HAL_I2C_MasterTxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback -+ (+) Receive in master mode an amount of data in non blocking mode using HAL_I2C_Master_Receive_IT() -+ (+) At reception end of transfer HAL_I2C_MasterRxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback -+ (+) Transmit in slave mode an amount of data in non blocking mode using HAL_I2C_Slave_Transmit_IT() -+ (+) At transmission end of transfer HAL_I2C_SlaveTxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback -+ (+) Receive in slave mode an amount of data in non blocking mode using HAL_I2C_Slave_Receive_IT() -+ (+) At reception end of transfer HAL_I2C_SlaveRxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback -+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can -+ add his own code by customization of function pointer HAL_I2C_ErrorCallback -+ (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() -+ (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() -+ -+ *** Interrupt mode IO sequential operation *** -+ ============================================== -+ [..] -+ (@) These interfaces allow to manage a sequential transfer with a repeated start condition -+ when a direction change during transfer -+ [..] -+ (+) A specific option field manage the different steps of a sequential transfer -+ (+) Option field values are defined through @ref I2C_XFEROPTIONS and are listed below: -+ (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode -+ (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address -+ and data to transfer without a final stop condition -+ (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address -+ and with new data to transfer if the direction change or manage only the new data to transfer -+ if no direction change and without a final stop condition in both cases -+ (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address -+ and with new data to transfer if the direction change or manage only the new data to transfer -+ if no direction change and with a final stop condition in both cases -+ -+ (+) Differents sequential I2C interfaces are listed below: -+ (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Transmit_IT() -+ (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() -+ (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Receive_IT() -+ (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() -+ (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() -+ (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() -+ (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT() -+ (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can -+ add his own code to check the Address Match Code and the transmission direction request by master (Write/Read). -+ (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_ListenCpltCallback() -+ (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Transmit_IT() -+ (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() -+ (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Receive_IT() -+ (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() -+ (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can -+ add his own code by customization of function pointer HAL_I2C_ErrorCallback() -+ (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() -+ (++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() -+ -+ *** Interrupt mode IO MEM operation *** -+ ======================================= -+ [..] -+ (+) Write an amount of data in no-blocking mode with Interrupt to a specific memory address using -+ HAL_I2C_Mem_Write_IT() -+ (+) At MEM end of write transfer HAL_I2C_MemTxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback -+ (+) Read an amount of data in no-blocking mode with Interrupt from a specific memory address using -+ HAL_I2C_Mem_Read_IT() -+ (+) At MEM end of read transfer HAL_I2C_MemRxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback -+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can -+ add his own code by customization of function pointer HAL_I2C_ErrorCallback -+ -+ *** DMA mode IO operation *** -+ ============================== -+ [..] -+ (+) Transmit in master mode an amount of data in non blocking mode (DMA) using -+ HAL_I2C_Master_Transmit_DMA() -+ (+) At transmission end of transfer HAL_I2C_MasterTxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback -+ (+) Receive in master mode an amount of data in non blocking mode (DMA) using -+ HAL_I2C_Master_Receive_DMA() -+ (+) At reception end of transfer HAL_I2C_MasterRxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback -+ (+) Transmit in slave mode an amount of data in non blocking mode (DMA) using -+ HAL_I2C_Slave_Transmit_DMA() -+ (+) At transmission end of transfer HAL_I2C_SlaveTxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback -+ (+) Receive in slave mode an amount of data in non blocking mode (DMA) using -+ HAL_I2C_Slave_Receive_DMA() -+ (+) At reception end of transfer HAL_I2C_SlaveRxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback -+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can -+ add his own code by customization of function pointer HAL_I2C_ErrorCallback -+ (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() -+ (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can -+ add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() -+ -+ *** DMA mode IO MEM operation *** -+ ================================= -+ [..] -+ (+) Write an amount of data in no-blocking mode with DMA to a specific memory address using -+ HAL_I2C_Mem_Write_DMA() -+ (+) At MEM end of write transfer HAL_I2C_MemTxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback -+ (+) Read an amount of data in no-blocking mode with DMA from a specific memory address using -+ HAL_I2C_Mem_Read_DMA() -+ (+) At MEM end of read transfer HAL_I2C_MemRxCpltCallback is executed and user can -+ add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback -+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can -+ add his own code by customization of function pointer HAL_I2C_ErrorCallback -+ -+ -+ *** I2C HAL driver macros list *** -+ ================================== -+ [..] -+ Below the list of most used macros in I2C HAL driver. -+ -+ (+) __HAL_I2C_ENABLE: Enable the I2C peripheral -+ (+) __HAL_I2C_DISABLE: Disable the I2C peripheral -+ (+) __HAL_I2C_GET_FLAG : Checks whether the specified I2C flag is set or not -+ (+) __HAL_I2C_CLEAR_FLAG : Clear the specified I2C pending flag -+ (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt -+ (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt -+ -+ [..] -+ (@) You can refer to the I2C HAL driver header file for more useful macros -+ -+ -+ @endverbatim -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) 2017 STMicroelectronics

-+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. Neither the name of STMicroelectronics nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ****************************************************************************** -+ */ -+ -+/* Includes ------------------------------------------------------------------*/ -+#include "stm32f4xx_hal.h" -+ -+/** @addtogroup STM32F4xx_HAL_Driver -+ * @{ -+ */ -+ -+/** @defgroup I2C I2C -+ * @brief I2C HAL module driver -+ * @{ -+ */ -+ -+#ifdef HAL_I2C_MODULE_ENABLED -+ -+/* Private typedef -----------------------------------------------------------*/ -+/* Private define ------------------------------------------------------------*/ -+/** @addtogroup I2C_Private_Define -+ * @{ -+ */ -+#define I2C_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */ -+#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */ -+#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */ -+ -+/* Private define for @ref PreviousState usage */ -+#define I2C_STATE_MSK ((uint32_t)((HAL_I2C_STATE_BUSY_TX | HAL_I2C_STATE_BUSY_RX) & (~(uint32_t)HAL_I2C_STATE_READY))) /*!< Mask State define, keep only RX and TX bits */ -+#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ -+#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ -+#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ -+#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ -+#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ -+ -+/** -+ * @} -+ */ -+ -+/* Private macro -------------------------------------------------------------*/ -+/* Private variables ---------------------------------------------------------*/ -+/* Private function prototypes -----------------------------------------------*/ -+/** @addtogroup I2C_Private_Functions -+ * @{ -+ */ -+/* Private functions to handle DMA transfer */ -+static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma); -+static void I2C_DMAError(DMA_HandleTypeDef *hdma); -+static void I2C_DMAAbort(DMA_HandleTypeDef *hdma); -+ -+static void I2C_ITError(I2C_HandleTypeDef *hi2c); -+ -+static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); -+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c); -+ -+/* Private functions for I2C transfer IRQ handler */ -+static HAL_StatusTypeDef I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_Master_SB(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_Master_ADD10(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_Master_ADDR(I2C_HandleTypeDef *hi2c); -+ -+static HAL_StatusTypeDef I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_SlaveTransmit_BTF(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_SlaveReceive_BTF(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_Slave_ADDR(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c); -+static HAL_StatusTypeDef I2C_Slave_AF(I2C_HandleTypeDef *hi2c); -+/** -+ * @} -+ */ -+ -+/* Exported functions --------------------------------------------------------*/ -+/** @defgroup I2C_Exported_Functions I2C Exported Functions -+ * @{ -+ */ -+ -+/** @defgroup I2C_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 I2Cx peripheral: -+ -+ (+) User must Implement HAL_I2C_MspInit() function in which he configures -+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC). -+ -+ (+) Call the function HAL_I2C_Init() to configure the selected device with -+ the selected configuration: -+ (++) Communication Speed -+ (++) Duty cycle -+ (++) Addressing mode -+ (++) Own Address 1 -+ (++) Dual Addressing mode -+ (++) Own Address 2 -+ (++) General call mode -+ (++) Nostretch mode -+ -+ (+) Call the function HAL_I2C_DeInit() to restore the default configuration -+ of the selected I2Cx peripheral. -+ -+@endverbatim -+ * @{ -+ */ -+ -+/** -+ * @brief Initializes the I2C according to the specified parameters -+ * in the I2C_InitTypeDef and create the associated handle. -+ * @param hi2c pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) -+{ -+ uint32_t freqrange = 0U; -+ uint32_t pclk1 = 0U; -+ -+ /* Check the I2C handle allocation */ -+ if(hi2c == NULL) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); -+ assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed)); -+ assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle)); -+ assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); -+ assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); -+ assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); -+ assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); -+ assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); -+ assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); -+ -+ if(hi2c->State == HAL_I2C_STATE_RESET) -+ { -+ /* Allocate lock resource and initialize it */ -+ hi2c->Lock = HAL_UNLOCKED; -+ /* Init the low level hardware : GPIO, CLOCK, NVIC */ -+ HAL_I2C_MspInit(hi2c); -+ } -+ -+ hi2c->State = HAL_I2C_STATE_BUSY; -+ -+ /* Disable the selected I2C peripheral */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* Get PCLK1 frequency */ -+ pclk1 = HAL_RCC_GetPCLK1Freq(); -+ -+ /* Calculate frequency range */ -+ freqrange = I2C_FREQRANGE(pclk1); -+ -+ /*---------------------------- I2Cx CR2 Configuration ----------------------*/ -+ /* Configure I2Cx: Frequency range */ -+ hi2c->Instance->CR2 = freqrange; -+ -+ /*---------------------------- I2Cx TRISE Configuration --------------------*/ -+ /* Configure I2Cx: Rise Time */ -+ hi2c->Instance->TRISE = I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed); -+ -+ /*---------------------------- I2Cx CCR Configuration ----------------------*/ -+ /* Configure I2Cx: Speed */ -+ hi2c->Instance->CCR = I2C_SPEED(pclk1, hi2c->Init.ClockSpeed, hi2c->Init.DutyCycle); -+ -+ /*---------------------------- I2Cx CR1 Configuration ----------------------*/ -+ /* Configure I2Cx: Generalcall and NoStretch mode */ -+ hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode); -+ -+ /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ -+ /* Configure I2Cx: Own Address1 and addressing mode */ -+ hi2c->Instance->OAR1 = (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1); -+ -+ /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ -+ /* Configure I2Cx: Dual mode and Own Address2 */ -+ hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2); -+ -+ /* Enable the selected I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief DeInitializes the I2C peripheral. -+ * @param hi2c pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) -+{ -+ /* Check the I2C handle allocation */ -+ if(hi2c == NULL) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); -+ -+ hi2c->State = HAL_I2C_STATE_BUSY; -+ -+ /* Disable the I2C Peripheral Clock */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ -+ HAL_I2C_MspDeInit(hi2c); -+ -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ hi2c->State = HAL_I2C_STATE_RESET; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Release Lock */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief I2C MSP Init. -+ * @param hi2c pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval None -+ */ -+ __weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ /* NOTE : This function Should not be modified, when the callback is needed, -+ the HAL_I2C_MspInit could be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief I2C MSP DeInit -+ * @param hi2c pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval None -+ */ -+ __weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ /* NOTE : This function Should not be modified, when the callback is needed, -+ the HAL_I2C_MspDeInit could be implemented in the user file -+ */ -+} -+ -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_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 I2C data -+ transfers. -+ -+ (#) There are two modes of transfer: -+ (++) Blocking mode : The communication is performed in the polling mode. -+ The 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 functions return the status of the transfer startup. -+ The end of the data processing will be indicated through the -+ dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when -+ using DMA mode. -+ -+ (#) Blocking mode functions are : -+ (++) HAL_I2C_Master_Transmit() -+ (++) HAL_I2C_Master_Receive() -+ (++) HAL_I2C_Slave_Transmit() -+ (++) HAL_I2C_Slave_Receive() -+ (++) HAL_I2C_Mem_Write() -+ (++) HAL_I2C_Mem_Read() -+ (++) HAL_I2C_IsDeviceReady() -+ -+ (#) No-Blocking mode functions with Interrupt are : -+ (++) HAL_I2C_Master_Transmit_IT() -+ (++) HAL_I2C_Master_Receive_IT() -+ (++) HAL_I2C_Slave_Transmit_IT() -+ (++) HAL_I2C_Slave_Receive_IT() -+ (++) HAL_I2C_Master_Sequential_Transmit_IT() -+ (++) HAL_I2C_Master_Sequential_Receive_IT() -+ (++) HAL_I2C_Slave_Sequential_Transmit_IT() -+ (++) HAL_I2C_Slave_Sequential_Receive_IT() -+ (++) HAL_I2C_Mem_Write_IT() -+ (++) HAL_I2C_Mem_Read_IT() -+ -+ (#) No-Blocking mode functions with DMA are : -+ (++) HAL_I2C_Master_Transmit_DMA() -+ (++) HAL_I2C_Master_Receive_DMA() -+ (++) HAL_I2C_Slave_Transmit_DMA() -+ (++) HAL_I2C_Slave_Receive_DMA() -+ (++) HAL_I2C_Mem_Write_DMA() -+ (++) HAL_I2C_Mem_Read_DMA() -+ -+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: -+ (++) HAL_I2C_MemTxCpltCallback() -+ (++) HAL_I2C_MemRxCpltCallback() -+ (++) HAL_I2C_MasterTxCpltCallback() -+ (++) HAL_I2C_MasterRxCpltCallback() -+ (++) HAL_I2C_SlaveTxCpltCallback() -+ (++) HAL_I2C_SlaveRxCpltCallback() -+ (++) HAL_I2C_ErrorCallback() -+ (++) HAL_I2C_AbortCpltCallback() -+ -+@endverbatim -+ * @{ -+ */ -+ -+/** -+ * @brief Transmits in master mode an amount of data in blocking mode. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_BUSY; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Send Slave Address */ -+ if(I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ while(hi2c->XferSize > 0U) -+ { -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ hi2c->XferSize--; -+ -+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ hi2c->XferSize--; -+ } -+ -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ } -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Receives in master mode an amount of data in blocking mode. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_BUSY; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Send Slave Address */ -+ if(I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ if(hi2c->XferSize == 0U) -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ else if(hi2c->XferSize == 1U) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ else if(hi2c->XferSize == 2U) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Enable Pos */ -+ hi2c->Instance->CR1 |= I2C_CR1_POS; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ else -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ -+ while(hi2c->XferSize > 0U) -+ { -+ if(hi2c->XferSize <= 3U) -+ { -+ /* One byte */ -+ if(hi2c->XferSize == 1U) -+ { -+ /* Wait until RXNE flag is set */ -+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) -+ { -+ return HAL_TIMEOUT; -+ } -+ else -+ { -+ return HAL_ERROR; -+ } -+ } -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ /* Two bytes */ -+ else if(hi2c->XferSize == 2U) -+ { -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ /* 3 Last bytes */ -+ else -+ { -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ } -+ else -+ { -+ /* Wait until RXNE flag is set */ -+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) -+ { -+ return HAL_TIMEOUT; -+ } -+ else -+ { -+ return HAL_ERROR; -+ } -+ } -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ } -+ } -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Transmits in slave mode an amount of data in blocking mode. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* If 10bit addressing mode is selected */ -+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) -+ { -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ -+ while(hi2c->XferSize > 0U) -+ { -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ /* Disable Address Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ hi2c->XferSize--; -+ -+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ hi2c->XferSize--; -+ } -+ } -+ -+ /* Wait until AF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_AF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Clear AF flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ -+ /* Disable Address Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Receive in slave mode an amount of data in blocking mode -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ if((pData == NULL) || (Size == 0)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ while(hi2c->XferSize > 0U) -+ { -+ /* Wait until RXNE flag is set */ -+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ /* Disable Address Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) -+ { -+ return HAL_TIMEOUT; -+ } -+ else -+ { -+ return HAL_ERROR; -+ } -+ } -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (Size != 0U)) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ } -+ -+ /* Wait until STOP flag is set */ -+ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ /* Disable Address Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear STOP flag */ -+ __HAL_I2C_CLEAR_STOPFLAG(hi2c); -+ -+ /* Disable Address Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ hi2c->Devaddress = DevAddress; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ hi2c->Devaddress = DevAddress; -+ -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Sequential transmit in master mode an amount of data in non-blocking mode with Interrupt -+ * @note This interface allow to manage repeated start condition when a direction change during transfer -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) -+{ -+ __IO uint32_t Prev_State = 0x00U; -+ __IO uint32_t count = 0x00U; -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Check Busy Flag only if FIRST call of Master interface */ -+ if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = XferOptions; -+ hi2c->XferSize = hi2c->XferCount; -+ hi2c->Devaddress = DevAddress; -+ -+ Prev_State = hi2c->PreviousState; -+ -+ /* Generate Start */ -+ if((Prev_State == I2C_STATE_MASTER_BUSY_RX) || (Prev_State == I2C_STATE_NONE)) -+ { -+ /* Generate Start condition if first transfer */ -+ if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) -+ { -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ else -+ { -+ /* Generate ReStart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ } -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Sequential receive in master mode an amount of data in non-blocking mode with Interrupt -+ * @note This interface allow to manage repeated start condition when a direction change during transfer -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) -+{ -+ __IO uint32_t count = 0U; -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Check Busy Flag only if FIRST call of Master interface */ -+ if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = XferOptions; -+ hi2c->XferSize = hi2c->XferCount; -+ hi2c->Devaddress = DevAddress; -+ -+ if((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) || (hi2c->PreviousState == I2C_STATE_NONE)) -+ { -+ /* Generate Start condition if first transfer */ -+ if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_NO_OPTION_FRAME)) -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ else if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate ReStart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ } -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferSize = Size; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Sequential transmit in slave mode an amount of data in no-blocking mode with Interrupt -+ * @note This interface allow to manage repeated start condition when a direction change during transfer -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) -+{ -+ /* Check the parameters */ -+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); -+ -+ if(hi2c->State == HAL_I2C_STATE_LISTEN) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = XferOptions; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Sequential receive in slave mode an amount of data in non-blocking mode with Interrupt -+ * @note This interface allow to manage repeated start condition when a direction change during transfer -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) -+{ -+ /* Check the parameters */ -+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); -+ -+ if(hi2c->State == HAL_I2C_STATE_LISTEN) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = XferOptions; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Enable the Address listen mode with Interrupt. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c) -+{ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ hi2c->State = HAL_I2C_STATE_LISTEN; -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Enable EVT and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Disable the Address listen mode with Interrupt. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of tmp to prevent undefined behavior of volatile usage */ -+ uint32_t tmp; -+ -+ /* Disable Address listen mode only if a transfer is not ongoing */ -+ if(hi2c->State == HAL_I2C_STATE_LISTEN) -+ { -+ tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK; -+ hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode); -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Disable Address Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Disable EVT and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Transmit in master mode an amount of data in non-blocking mode with DMA -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ hi2c->Devaddress = DevAddress; -+ -+ if(hi2c->XferSize > 0U) -+ { -+ /* Set the I2C DMA transfer complete callback */ -+ hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; -+ -+ /* Set the DMA error callback */ -+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError; -+ -+ /* Set the unused DMA callbacks to NULL */ -+ hi2c->hdmatx->XferHalfCpltCallback = NULL; -+ hi2c->hdmatx->XferM1CpltCallback = NULL; -+ hi2c->hdmatx->XferM1HalfCpltCallback = NULL; -+ hi2c->hdmatx->XferAbortCallback = NULL; -+ -+ /* Enable the DMA Stream */ -+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); -+ -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ /* Enable DMA Request */ -+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN; -+ } -+ else -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ } -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Receive in master mode an amount of data in non-blocking mode with DMA -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MASTER; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ hi2c->Devaddress = DevAddress; -+ -+ if(hi2c->XferSize > 0U) -+ { -+ /* Set the I2C DMA transfer complete callback */ -+ hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; -+ -+ /* Set the DMA error callback */ -+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError; -+ -+ /* Set the unused DMA callbacks to NULL */ -+ hi2c->hdmarx->XferHalfCpltCallback = NULL; -+ hi2c->hdmarx->XferM1CpltCallback = NULL; -+ hi2c->hdmarx->XferM1HalfCpltCallback = NULL; -+ hi2c->hdmarx->XferAbortCallback = NULL; -+ -+ /* Enable the DMA Stream */ -+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); -+ -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ /* Enable DMA Request */ -+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN; -+ } -+ else -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ } -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Abort a master I2C process communication with Interrupt. -+ * @note This abort can be called only if state is ready -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(DevAddress); -+ -+ /* Abort Master transfer during Receive or Transmit process */ -+ if(hi2c->Mode == HAL_I2C_MODE_MASTER) -+ { -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_ABORT; -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ hi2c->XferCount = 0U; -+ -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Call the corresponding callback to inform upper layer of End of Transfer */ -+ I2C_ITError(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ /* Wrong usage of abort function */ -+ /* This function should be used only in case of abort monitored by master device */ -+ return HAL_ERROR; -+ } -+} -+ -+/** -+ * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Set the I2C DMA transfer complete callback */ -+ hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; -+ -+ /* Set the DMA error callback */ -+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError; -+ -+ /* Set the unused DMA callbacks to NULL */ -+ hi2c->hdmatx->XferHalfCpltCallback = NULL; -+ hi2c->hdmatx->XferM1CpltCallback = NULL; -+ hi2c->hdmatx->XferM1HalfCpltCallback = NULL; -+ hi2c->hdmatx->XferAbortCallback = NULL; -+ -+ /* Enable the DMA Stream */ -+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ /* Enable EVT and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ /* Enable DMA Request */ -+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN; -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Receive in slave mode an amount of data in non-blocking mode with DMA -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ if((pData == NULL) || (Size == 0U)) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_SLAVE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Set the I2C DMA transfer complete callback */ -+ hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; -+ -+ /* Set the DMA error callback */ -+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError; -+ -+ /* Set the unused DMA callbacks to NULL */ -+ hi2c->hdmarx->XferHalfCpltCallback = NULL; -+ hi2c->hdmarx->XferM1CpltCallback = NULL; -+ hi2c->hdmarx->XferM1HalfCpltCallback = NULL; -+ hi2c->hdmarx->XferAbortCallback = NULL; -+ -+ /* Enable the DMA Stream */ -+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); -+ -+ /* Enable Address Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ /* Enable EVT and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ /* Enable DMA Request */ -+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN; -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+/** -+ * @brief Write an amount of data in blocking mode to a specific memory address -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_BUSY; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MEM; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Send Slave Address and Memory Address */ -+ if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ while(hi2c->XferSize > 0U) -+ { -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ } -+ -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Read an amount of data in blocking mode from a specific memory address -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_BUSY; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MEM; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ /* Send Slave Address and Memory Address */ -+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ if(hi2c->XferSize == 0U) -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ else if(hi2c->XferSize == 1U) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ else if(hi2c->XferSize == 2U) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Enable Pos */ -+ hi2c->Instance->CR1 |= I2C_CR1_POS; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ else -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ -+ while(hi2c->XferSize > 0U) -+ { -+ if(hi2c->XferSize <= 3U) -+ { -+ /* One byte */ -+ if(hi2c->XferSize== 1U) -+ { -+ /* Wait until RXNE flag is set */ -+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) -+ { -+ return HAL_TIMEOUT; -+ } -+ else -+ { -+ return HAL_ERROR; -+ } -+ } -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ /* Two bytes */ -+ else if(hi2c->XferSize == 2U) -+ { -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ /* 3 Last bytes */ -+ else -+ { -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ /* Wait until BTF flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ } -+ else -+ { -+ /* Wait until RXNE flag is set */ -+ if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) -+ { -+ return HAL_TIMEOUT; -+ } -+ else -+ { -+ return HAL_ERROR; -+ } -+ } -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferSize--; -+ hi2c->XferCount--; -+ } -+ } -+ } -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MEM; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferSize = Size; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->Devaddress = DevAddress; -+ hi2c->Memaddress = MemAddress; -+ hi2c->MemaddSize = MemAddSize; -+ hi2c->EventCount = 0U; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MEM; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferSize = Size; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->Devaddress = DevAddress; -+ hi2c->Memaddress = MemAddress; -+ hi2c->MemaddSize = MemAddSize; -+ hi2c->EventCount = 0U; -+ -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ if(hi2c->XferSize > 0U) -+ { -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ -+ /* Enable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ } -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be sent -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) -+{ -+ __IO uint32_t count = 0U; -+ -+ uint32_t tickstart = 0x00U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_MEM; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferSize = Size; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ -+ if(hi2c->XferSize > 0U) -+ { -+ /* Set the I2C DMA transfer complete callback */ -+ hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; -+ -+ /* Set the DMA error callback */ -+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError; -+ -+ /* Set the unused DMA callbacks to NULL */ -+ hi2c->hdmatx->XferHalfCpltCallback = NULL; -+ hi2c->hdmatx->XferM1CpltCallback = NULL; -+ hi2c->hdmatx->XferM1HalfCpltCallback = NULL; -+ hi2c->hdmatx->XferAbortCallback = NULL; -+ -+ /* Enable the DMA Stream */ -+ HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); -+ -+ /* Send Slave Address and Memory Address */ -+ if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ /* Enable ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); -+ -+ /* Enable DMA Request */ -+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN; -+ } -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param pData Pointer to data buffer -+ * @param Size Amount of data to be read -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) -+{ -+ uint32_t tickstart = 0x00U; -+ __IO uint32_t count = 0U; -+ -+ /* Init tickstart for timeout management*/ -+ tickstart = HAL_GetTick(); -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); -+ do -+ { -+ if(count-- == 0U) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY_RX; -+ hi2c->Mode = HAL_I2C_MODE_MEM; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Prepare transfer parameters */ -+ hi2c->pBuffPtr = pData; -+ hi2c->XferCount = Size; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->XferSize = hi2c->XferCount; -+ -+ if(hi2c->XferSize > 0U) -+ { -+ /* Set the I2C DMA transfer complete callback */ -+ hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; -+ -+ /* Set the DMA error callback */ -+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError; -+ -+ /* Set the unused DMA callbacks to NULL */ -+ hi2c->hdmarx->XferHalfCpltCallback = NULL; -+ hi2c->hdmarx->XferM1CpltCallback = NULL; -+ hi2c->hdmarx->XferM1HalfCpltCallback = NULL; -+ hi2c->hdmarx->XferAbortCallback = NULL; -+ -+ /* Enable the DMA Stream */ -+ HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); -+ -+ /* Send Slave Address and Memory Address */ -+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ if(Size == 1U) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ } -+ else -+ { -+ /* Enable Last DMA bit */ -+ hi2c->Instance->CR2 |= I2C_CR2_LAST; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ /* Note : The I2C interrupts must be enabled after unlocking current process -+ to avoid the risk of I2C interrupt handle execution before current -+ process unlock */ -+ /* Enable ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); -+ -+ /* Enable DMA Request */ -+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN; -+ } -+ else -+ { -+ /* Send Slave Address and Memory Address */ -+ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_ERROR; -+ } -+ else -+ { -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ } -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Checks if target device is ready for communication. -+ * @note This function is used with Memory devices -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param DevAddress Target device address -+ * @param Trials Number of trials -+ * @param Timeout Timeout duration -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) -+{ -+ uint32_t tickstart = 0U, tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, I2C_Trials = 1U; -+ -+ /* Get tick */ -+ tickstart = HAL_GetTick(); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_BUSY; -+ } -+ -+ /* Process Locked */ -+ __HAL_LOCK(hi2c); -+ -+ /* Check if the I2C is already enabled */ -+ if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) -+ { -+ /* Enable I2C peripheral */ -+ __HAL_I2C_ENABLE(hi2c); -+ } -+ -+ /* Disable Pos */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ hi2c->State = HAL_I2C_STATE_BUSY; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ -+ do -+ { -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); -+ -+ /* Wait until ADDR or AF flag are set */ -+ /* Get tick */ -+ tickstart = HAL_GetTick(); -+ -+ tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); -+ tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); -+ tmp3 = hi2c->State; -+ while((tmp1 == RESET) && (tmp2 == RESET) && (tmp3 != HAL_I2C_STATE_TIMEOUT)) -+ { -+ if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) -+ { -+ hi2c->State = HAL_I2C_STATE_TIMEOUT; -+ } -+ tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); -+ tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); -+ tmp3 = hi2c->State; -+ } -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ /* Check if the ADDR flag has been set */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Clear ADDR Flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_OK; -+ } -+ else -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Clear AF Flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ -+ /* Wait until BUSY flag is reset */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ }while(I2C_Trials++ < Trials); -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief This function handles I2C event interrupt request. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) -+{ -+ uint32_t sr2itflags = READ_REG(hi2c->Instance->SR2); -+ uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); -+ uint32_t itsources = READ_REG(hi2c->Instance->CR2); -+ -+ uint32_t CurrentMode = hi2c->Mode; -+ -+ /* Master or Memory mode selected */ -+ if((CurrentMode == HAL_I2C_MODE_MASTER) || (CurrentMode == HAL_I2C_MODE_MEM)) -+ { -+ /* SB Set ----------------------------------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_SB) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_Master_SB(hi2c); -+ } -+ /* ADD10 Set -------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_ADD10) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_Master_ADD10(hi2c); -+ } -+ /* ADDR Set --------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_Master_ADDR(hi2c); -+ } -+ -+ /* I2C in mode Transmitter -----------------------------------------------*/ -+ if((sr2itflags & I2C_FLAG_TRA) != RESET) -+ { -+ /* TXE set and BTF reset -----------------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_TXE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) -+ { -+ I2C_MasterTransmit_TXE(hi2c); -+ } -+ /* BTF set -------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_MasterTransmit_BTF(hi2c); -+ } -+ } -+ /* I2C in mode Receiver --------------------------------------------------*/ -+ else -+ { -+ /* RXNE set and BTF reset -----------------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) -+ { -+ I2C_MasterReceive_RXNE(hi2c); -+ } -+ /* BTF set -------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_MasterReceive_BTF(hi2c); -+ } -+ } -+ } -+ /* Slave mode selected */ -+ else -+ { -+ /* ADDR set --------------------------------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_Slave_ADDR(hi2c); -+ } -+ /* STOPF set --------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_STOPF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_Slave_STOPF(hi2c); -+ } -+ /* I2C in mode Transmitter -----------------------------------------------*/ -+ else if((sr2itflags & I2C_FLAG_TRA) != RESET) -+ { -+ /* TXE set and BTF reset -----------------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_TXE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) -+ { -+ I2C_SlaveTransmit_TXE(hi2c); -+ } -+ /* BTF set -------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_SlaveTransmit_BTF(hi2c); -+ } -+ } -+ /* I2C in mode Receiver --------------------------------------------------*/ -+ else -+ { -+ /* RXNE set and BTF reset ----------------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) -+ { -+ I2C_SlaveReceive_RXNE(hi2c); -+ } -+ /* BTF set -------------------------------------------------------------*/ -+ else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) -+ { -+ I2C_SlaveReceive_BTF(hi2c); -+ } -+ } -+ } -+} -+ -+/** -+ * @brief This function handles I2C error interrupt request. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c) -+{ -+ uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, tmp4 = 0U; -+ uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); -+ uint32_t itsources = READ_REG(hi2c->Instance->CR2); -+ -+ /* I2C Bus error interrupt occurred ----------------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_BERR) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; -+ -+ /* Clear BERR flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); -+ } -+ -+ /* I2C Arbitration Loss error interrupt occurred ---------------------------*/ -+ if(((sr1itflags & I2C_FLAG_ARLO) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; -+ -+ /* Clear ARLO flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); -+ } -+ -+ /* I2C Acknowledge failure error interrupt occurred ------------------------*/ -+ if(((sr1itflags & I2C_FLAG_AF) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) -+ { -+ tmp1 = hi2c->Mode; -+ tmp2 = hi2c->XferCount; -+ tmp3 = hi2c->State; -+ tmp4 = hi2c->PreviousState; -+ if((tmp1 == HAL_I2C_MODE_SLAVE) && (tmp2 == 0U) && \ -+ ((tmp3 == HAL_I2C_STATE_BUSY_TX) || (tmp3 == HAL_I2C_STATE_BUSY_TX_LISTEN) || \ -+ ((tmp3 == HAL_I2C_STATE_LISTEN) && (tmp4 == I2C_STATE_SLAVE_BUSY_TX)))) -+ { -+ I2C_Slave_AF(hi2c); -+ } -+ else -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF; -+ -+ /* Do not generate a STOP in case of Slave receive non acknowledge during transfer (mean not at the end of transfer) */ -+ if(hi2c->Mode == HAL_I2C_MODE_MASTER) -+ { -+ /* Generate Stop */ -+ SET_BIT(hi2c->Instance->CR1,I2C_CR1_STOP); -+ } -+ -+ /* Clear AF flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ } -+ } -+ -+ /* I2C Over-Run/Under-Run interrupt occurred -------------------------------*/ -+ if(((sr1itflags & I2C_FLAG_OVR) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; -+ /* Clear OVR flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); -+ } -+ -+ /* Call the Error Callback in case of Error detected -----------------------*/ -+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE) -+ { -+ I2C_ITError(hi2c); -+ } -+} -+ -+/** -+ * @brief Master Tx Transfer completed callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_MasterTxCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief Master Rx Transfer completed callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_MasterRxCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** @brief Slave Tx Transfer completed callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_SlaveTxCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief Slave Rx Transfer completed callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_SlaveRxCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief Slave Address Match callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XferOptions_definition -+ * @param AddrMatchCode Address Match Code -+ * @retval None -+ */ -+__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ UNUSED(TransferDirection); -+ UNUSED(AddrMatchCode); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_AddrCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief Listen Complete callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_ListenCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief Memory Tx Transfer completed callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_MemTxCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief Memory Rx Transfer completed callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_MemRxCpltCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief I2C error callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_ErrorCallback can be implemented in the user file -+ */ -+} -+ -+/** -+ * @brief I2C abort callback. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval None -+ */ -+__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) -+{ -+ /* Prevent unused argument(s) compilation warning */ -+ UNUSED(hi2c); -+ -+ /* NOTE : This function should not be modified, when the callback is needed, -+ the HAL_I2C_AbortCpltCallback could be implemented in the user file -+ */ -+} -+ -+/** -+ * @} -+ */ -+ -+/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions -+ * @brief Peripheral State and Errors functions -+ * -+@verbatim -+ =============================================================================== -+ ##### Peripheral State, Mode and Error functions ##### -+ =============================================================================== -+ [..] -+ This subsection permits to get in run-time the status of the peripheral -+ and the data flow. -+ -+@endverbatim -+ * @{ -+ */ -+ -+/** -+ * @brief Return the I2C handle state. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval HAL state -+ */ -+HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c) -+{ -+ /* Return I2C handle state */ -+ return hi2c->State; -+} -+ -+/** -+ * @brief Return the I2C Master, Slave, Memory or no mode. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL mode -+ */ -+HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c) -+{ -+ return hi2c->Mode; -+} -+ -+/** -+ * @brief Return the I2C error code -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval I2C Error Code -+ */ -+uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) -+{ -+ return hi2c->ErrorCode; -+} -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @brief Handle TXE flag for Master -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ uint32_t CurrentMode = hi2c->Mode; -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ -+ if((hi2c->XferSize == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX)) -+ { -+ /* Call TxCpltCallback() directly if no stop mode is set */ -+ if((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) -+ { -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ HAL_I2C_MasterTxCpltCallback(hi2c); -+ } -+ else /* Generate Stop condition then Call TxCpltCallback() */ -+ { -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ HAL_I2C_MemTxCpltCallback(hi2c); -+ } -+ else -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ HAL_I2C_MasterTxCpltCallback(hi2c); -+ } -+ } -+ } -+ else if((CurrentState == HAL_I2C_STATE_BUSY_TX) || \ -+ ((CurrentMode == HAL_I2C_MODE_MEM) && (CurrentState == HAL_I2C_STATE_BUSY_RX))) -+ { -+ if(hi2c->XferCount == 0U) -+ { -+ /* Disable BUF interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); -+ } -+ else -+ { -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ if(hi2c->EventCount == 0) -+ { -+ /* If Memory address size is 8Bit */ -+ if(hi2c->MemaddSize == I2C_MEMADD_SIZE_8BIT) -+ { -+ /* Send Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); -+ -+ hi2c->EventCount += 2; -+ } -+ /* If Memory address size is 16Bit */ -+ else -+ { -+ /* Send MSB of Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_MSB(hi2c->Memaddress); -+ -+ hi2c->EventCount++; -+ } -+ } -+ else if(hi2c->EventCount == 1) -+ { -+ /* Send LSB of Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); -+ -+ hi2c->EventCount++; -+ } -+ else if(hi2c->EventCount == 2) -+ { -+ if(hi2c->State == HAL_I2C_STATE_BUSY_RX) -+ { -+ /* Generate Restart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ else if(hi2c->State == HAL_I2C_STATE_BUSY_TX) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ } -+ } -+ } -+ else -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle BTF flag for Master transmitter -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ -+ if(hi2c->State == HAL_I2C_STATE_BUSY_TX) -+ { -+ if(hi2c->XferCount != 0U) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ } -+ else -+ { -+ /* Call TxCpltCallback() directly if no stop mode is set */ -+ if((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) -+ { -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ HAL_I2C_MasterTxCpltCallback(hi2c); -+ } -+ else /* Generate Stop condition then Call TxCpltCallback() */ -+ { -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_MemTxCpltCallback(hi2c); -+ } -+ else -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_MasterTxCpltCallback(hi2c); -+ } -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle RXNE flag for Master -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c) -+{ -+ if(hi2c->State == HAL_I2C_STATE_BUSY_RX) -+ { -+ uint32_t tmp = 0U; -+ -+ tmp = hi2c->XferCount; -+ if(tmp > 3U) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ -+ if(hi2c->XferCount == 3) -+ { -+ /* Disable BUF interrupt, this help to treat correctly the last 4 bytes -+ on BTF subroutine */ -+ /* Disable BUF interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); -+ } -+ } -+ else if((tmp == 1U) || (tmp == 0U)) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ HAL_I2C_MemRxCpltCallback(hi2c); -+ } -+ else -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ HAL_I2C_MasterRxCpltCallback(hi2c); -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle BTF flag for Master receiver -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ -+ if(hi2c->XferCount == 4U) -+ { -+ /* Disable BUF interrupt, this help to treat correctly the last 2 bytes -+ on BTF subroutine if there is a reception delay between N-1 and N byte */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ } -+ else if(hi2c->XferCount == 3U) -+ { -+ /* Disable BUF interrupt, this help to treat correctly the last 2 bytes -+ on BTF subroutine if there is a reception delay between N-1 and N byte */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ } -+ else if(hi2c->XferCount == 2U) -+ { -+ /* Prepare next transfer or stop current transfer */ -+ if((CurrentXferOptions == I2C_NEXT_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME)) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Generate ReStart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ else -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ -+ /* Disable EVT and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_MemRxCpltCallback(hi2c); -+ } -+ else -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_MasterRxCpltCallback(hi2c); -+ } -+ } -+ else -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle SB flag for Master -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_Master_SB(I2C_HandleTypeDef *hi2c) -+{ -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ if(hi2c->EventCount == 0U) -+ { -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); -+ } -+ else -+ { -+ hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); -+ } -+ } -+ else -+ { -+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) -+ { -+ /* Send slave 7 Bits address */ -+ if(hi2c->State == HAL_I2C_STATE_BUSY_TX) -+ { -+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); -+ } -+ else -+ { -+ hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); -+ } -+ } -+ else -+ { -+ if(hi2c->EventCount == 0U) -+ { -+ /* Send header of slave address */ -+ hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(hi2c->Devaddress); -+ } -+ else if(hi2c->EventCount == 1U) -+ { -+ /* Send header of slave address */ -+ hi2c->Instance->DR = I2C_10BIT_HEADER_READ(hi2c->Devaddress); -+ } -+ } -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle ADD10 flag for Master -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_Master_ADD10(I2C_HandleTypeDef *hi2c) -+{ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_10BIT_ADDRESS(hi2c->Devaddress); -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle ADDR flag for Master -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_Master_ADDR(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentMode = hi2c->Mode; -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ uint32_t Prev_State = hi2c->PreviousState; -+ -+ if(hi2c->State == HAL_I2C_STATE_BUSY_RX) -+ { -+ if((hi2c->EventCount == 0U) && (CurrentMode == HAL_I2C_MODE_MEM)) -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ else if((hi2c->EventCount == 0U) && (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)) -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Restart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ hi2c->EventCount++; -+ } -+ else -+ { -+ if(hi2c->XferCount == 0U) -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ else if(hi2c->XferCount == 1U) -+ { -+ if(CurrentXferOptions == I2C_NO_OPTION_FRAME) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ else -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ } -+ /* Prepare next transfer or stop current transfer */ -+ else if((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) \ -+ && (Prev_State != I2C_STATE_MASTER_BUSY_RX)) -+ { -+ if(hi2c->XferOptions != I2C_NEXT_FRAME) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ } -+ else -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ else -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ } -+ } -+ else if(hi2c->XferCount == 2U) -+ { -+ if(hi2c->XferOptions != I2C_NEXT_FRAME) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Enable Pos */ -+ hi2c->Instance->CR1 |= I2C_CR1_POS; -+ } -+ else -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ } -+ -+ if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) -+ { -+ /* Enable Last DMA bit */ -+ hi2c->Instance->CR2 |= I2C_CR2_LAST; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ else -+ { -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) -+ { -+ /* Enable Last DMA bit */ -+ hi2c->Instance->CR2 |= I2C_CR2_LAST; -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ -+ /* Reset Event counter */ -+ hi2c->EventCount = 0U; -+ } -+ } -+ else -+ { -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle TXE flag for Slave -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ -+ if(hi2c->XferCount != 0U) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ -+ if((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN)) -+ { -+ /* Last Byte is received, disable Interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); -+ -+ /* Set state at HAL_I2C_STATE_LISTEN */ -+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; -+ hi2c->State = HAL_I2C_STATE_LISTEN; -+ -+ /* Call the Tx complete callback to inform upper layer of the end of receive process */ -+ HAL_I2C_SlaveTxCpltCallback(hi2c); -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle BTF flag for Slave transmitter -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_SlaveTransmit_BTF(I2C_HandleTypeDef *hi2c) -+{ -+ if(hi2c->XferCount != 0U) -+ { -+ /* Write data to DR */ -+ hi2c->Instance->DR = (*hi2c->pBuffPtr++); -+ hi2c->XferCount--; -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle RXNE flag for Slave -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ -+ if(hi2c->XferCount != 0U) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ -+ if((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) -+ { -+ /* Last Byte is received, disable Interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); -+ -+ /* Set state at HAL_I2C_STATE_LISTEN */ -+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX; -+ hi2c->State = HAL_I2C_STATE_LISTEN; -+ -+ /* Call the Rx complete callback to inform upper layer of the end of receive process */ -+ HAL_I2C_SlaveRxCpltCallback(hi2c); -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle BTF flag for Slave receiver -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_SlaveReceive_BTF(I2C_HandleTypeDef *hi2c) -+{ -+ if(hi2c->XferCount != 0U) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle ADD flag for Slave -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_Slave_ADDR(I2C_HandleTypeDef *hi2c) -+{ -+ uint8_t TransferDirection = I2C_DIRECTION_RECEIVE; -+ uint16_t SlaveAddrCode = 0U; -+ -+ /* Transfer Direction requested by Master */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TRA) == RESET) -+ { -+ TransferDirection = I2C_DIRECTION_TRANSMIT; -+ } -+ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_DUALF) == RESET) -+ { -+ SlaveAddrCode = hi2c->Init.OwnAddress1; -+ } -+ else -+ { -+ SlaveAddrCode = hi2c->Init.OwnAddress2; -+ } -+ -+ /* Call Slave Addr callback */ -+ HAL_I2C_AddrCallback(hi2c, TransferDirection, SlaveAddrCode); -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Handle STOPF flag for Slave -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Clear STOPF flag */ -+ __HAL_I2C_CLEAR_STOPFLAG(hi2c); -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* If a DMA is ongoing, Update handle size context */ -+ if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) -+ { -+ if((hi2c->State == HAL_I2C_STATE_BUSY_RX) || (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)) -+ { -+ hi2c->XferCount = __HAL_DMA_GET_COUNTER(hi2c->hdmarx); -+ } -+ else -+ { -+ hi2c->XferCount = __HAL_DMA_GET_COUNTER(hi2c->hdmatx); -+ } -+ } -+ -+ /* All data are not transferred, so set error code accordingly */ -+ if(hi2c->XferCount != 0U) -+ { -+ /* Store Last receive data if any */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ } -+ -+ /* Store Last receive data if any */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ hi2c->XferCount--; -+ } -+ -+ /* Set ErrorCode corresponding to a Non-Acknowledge */ -+ //hi2c->ErrorCode |= HAL_I2C_ERROR_AF; -+ } -+ -+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE) -+ { -+ /* Call the corresponding callback to inform upper layer of End of Transfer */ -+ I2C_ITError(hi2c); -+ } -+ else -+ { -+ if((CurrentState == HAL_I2C_STATE_LISTEN ) || (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN) || \ -+ (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN)) -+ { -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ -+ HAL_I2C_ListenCpltCallback(hi2c); -+ } -+ else -+ { -+ if((hi2c->PreviousState == I2C_STATE_SLAVE_BUSY_RX) || (CurrentState == HAL_I2C_STATE_BUSY_RX)) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_SlaveRxCpltCallback(hi2c); -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_Slave_AF(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ -+ if(((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME)) && \ -+ (CurrentState == HAL_I2C_STATE_LISTEN)) -+ { -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Clear AF flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ -+ HAL_I2C_ListenCpltCallback(hi2c); -+ } -+ else if(CurrentState == HAL_I2C_STATE_BUSY_TX) -+ { -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Disable EVT, BUF and ERR interrupt */ -+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); -+ -+ /* Clear AF flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ HAL_I2C_SlaveTxCpltCallback(hi2c); -+ } -+ else -+ { -+ /* Clear AF flag only */ -+ /* State Listen, but XferOptions == FIRST or NEXT */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief I2C interrupts error process -+ * @param hi2c I2C handle. -+ * @retval None -+ */ -+static void I2C_ITError(I2C_HandleTypeDef *hi2c) -+{ -+ /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ -+ if((CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN) || (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) -+ { -+ /* keep HAL_I2C_STATE_LISTEN */ -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_LISTEN; -+ } -+ else -+ { -+ /* If state is an abort treatment on going, don't change state */ -+ /* This change will be do later */ -+ if((hi2c->State != HAL_I2C_STATE_ABORT) && ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) != I2C_CR2_DMAEN)) -+ { -+ hi2c->State = HAL_I2C_STATE_READY; -+ } -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ } -+ -+ /* Disable Pos bit in I2C CR1 when error occurred in Master/Mem Receive IT Process */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_POS; -+ -+ /* Abort DMA transfer */ -+ if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) -+ { -+ hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; -+ -+ if(hi2c->hdmatx->State != HAL_DMA_STATE_READY) -+ { -+ /* Set the DMA Abort callback : -+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ -+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; -+ -+ if(HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) -+ { -+ /* Disable I2C peripheral to prevent dummy data in buffer */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ /* Call Directly XferAbortCallback function in case of error */ -+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); -+ } -+ } -+ else -+ { -+ /* Set the DMA Abort callback : -+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ -+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; -+ -+ if(HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) -+ { -+ /* Store Last receive data if any */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ } -+ -+ /* Disable I2C peripheral to prevent dummy data in buffer */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */ -+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); -+ } -+ } -+ } -+ else if(hi2c->State == HAL_I2C_STATE_ABORT) -+ { -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Store Last receive data if any */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ } -+ -+ /* Disable I2C peripheral to prevent dummy data in buffer */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* Call the corresponding callback to inform upper layer of End of Transfer */ -+ HAL_I2C_AbortCpltCallback(hi2c); -+ } -+ else -+ { -+ /* Store Last receive data if any */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) -+ { -+ /* Read data from DR */ -+ (*hi2c->pBuffPtr++) = hi2c->Instance->DR; -+ } -+ -+ /* Call user error callback */ -+ HAL_I2C_ErrorCallback(hi2c); -+ } -+ /* STOP Flag is not set after a NACK reception */ -+ /* So may inform upper layer that listen phase is stopped */ -+ /* during NACK error treatment */ -+ if((hi2c->State == HAL_I2C_STATE_LISTEN) && ((hi2c->ErrorCode & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF)) -+ { -+ hi2c->XferOptions = I2C_NO_OPTION_FRAME; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ -+ HAL_I2C_ListenCpltCallback(hi2c); -+ } -+} -+ -+/** -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) -+{ -+ /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ -+ /* Generate Start condition if first transfer */ -+ if((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) -+ { -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ else if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) -+ { -+ /* Generate ReStart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) -+ { -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); -+ } -+ else -+ { -+ /* Send header of slave address */ -+ hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); -+ -+ /* Wait until ADD10 flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); -+ } -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Master sends target device address for read request. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param DevAddress Target device address The device 7 bits address value -+ * in datasheet must be shifted to the left before calling the interface -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) -+{ -+ /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentXferOptions = hi2c->XferOptions; -+ -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start condition if first transfer */ -+ if((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) -+ { -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ else if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) -+ { -+ /* Generate ReStart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ } -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) -+ { -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); -+ } -+ else -+ { -+ /* Send header of slave address */ -+ hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); -+ -+ /* Wait until ADD10 flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Generate Restart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Send header of slave address */ -+ hi2c->Instance->DR = I2C_10BIT_HEADER_READ(DevAddress); -+ } -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Master sends target device address followed by internal memory address for write request. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) -+{ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* If Memory address size is 8Bit */ -+ if(MemAddSize == I2C_MEMADD_SIZE_8BIT) -+ { -+ /* Send Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); -+ } -+ /* If Memory address size is 16Bit */ -+ else -+ { -+ /* Send MSB of Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); -+ -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Send LSB of Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief Master sends target device address followed by internal memory address for read request. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param DevAddress Target device address -+ * @param MemAddress Internal memory address -+ * @param MemAddSize Size of internal memory address -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) -+{ -+ /* Enable Acknowledge */ -+ hi2c->Instance->CR1 |= I2C_CR1_ACK; -+ -+ /* Generate Start */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Clear ADDR flag */ -+ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); -+ -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* If Memory address size is 8Bit */ -+ if(MemAddSize == I2C_MEMADD_SIZE_8BIT) -+ { -+ /* Send Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); -+ } -+ /* If Memory address size is 16Bit */ -+ else -+ { -+ /* Send MSB of Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); -+ -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Send LSB of Memory Address */ -+ hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); -+ } -+ -+ /* Wait until TXE flag is set */ -+ if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ /* Generate Restart */ -+ hi2c->Instance->CR1 |= I2C_CR1_START; -+ -+ /* Wait until SB flag is set */ -+ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) -+ { -+ return HAL_TIMEOUT; -+ } -+ -+ /* Send slave address */ -+ hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); -+ -+ /* Wait until ADDR flag is set */ -+ if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) -+ { -+ if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) -+ { -+ return HAL_ERROR; -+ } -+ else -+ { -+ return HAL_TIMEOUT; -+ } -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief DMA I2C process complete callback. -+ * @param hdma DMA handle -+ * @retval None -+ */ -+static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma) -+{ -+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; -+ -+ /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ -+ uint32_t CurrentState = hi2c->State; -+ uint32_t CurrentMode = hi2c->Mode; -+ -+ if((CurrentState == HAL_I2C_STATE_BUSY_TX) || ((CurrentState == HAL_I2C_STATE_BUSY_RX) && (CurrentMode == HAL_I2C_MODE_SLAVE))) -+ { -+ /* Disable DMA Request */ -+ hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; -+ -+ hi2c->XferCount = 0U; -+ -+ /* Enable EVT and ERR interrupt */ -+ __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); -+ } -+ else -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Disable Last DMA */ -+ hi2c->Instance->CR2 &= ~I2C_CR2_LAST; -+ -+ /* Disable DMA Request */ -+ hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; -+ -+ hi2c->XferCount = 0U; -+ -+ /* Check if Errors has been detected during transfer */ -+ if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE) -+ { -+ HAL_I2C_ErrorCallback(hi2c); -+ } -+ else -+ { -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ if(hi2c->Mode == HAL_I2C_MODE_MEM) -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_MemRxCpltCallback(hi2c); -+ } -+ else -+ { -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ HAL_I2C_MasterRxCpltCallback(hi2c); -+ } -+ } -+ } -+} -+ -+/** -+ * @brief DMA I2C communication error callback. -+ * @param hdma DMA handle -+ * @retval None -+ */ -+static void I2C_DMAError(DMA_HandleTypeDef *hdma) -+{ -+ I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; -+ -+ /* Ignore DMA FIFO error */ -+ if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) -+ { -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ hi2c->XferCount = 0U; -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; -+ -+ HAL_I2C_ErrorCallback(hi2c); -+ } -+} -+ -+/** -+ * @brief DMA I2C communication abort callback -+ * (To be called at end of DMA Abort procedure). -+ * @param hdma DMA handle. -+ * @retval None -+ */ -+static void I2C_DMAAbort(DMA_HandleTypeDef *hdma) -+{ -+ I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; -+ -+ /* Disable Acknowledge */ -+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; -+ -+ hi2c->XferCount = 0U; -+ -+ /* Reset XferAbortCallback */ -+ hi2c->hdmatx->XferAbortCallback = NULL; -+ hi2c->hdmarx->XferAbortCallback = NULL; -+ -+ /* Check if come from abort from user */ -+ if(hi2c->State == HAL_I2C_STATE_ABORT) -+ { -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ -+ /* Disable I2C peripheral to prevent dummy data in buffer */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* Call the corresponding callback to inform upper layer of End of Transfer */ -+ HAL_I2C_AbortCpltCallback(hi2c); -+ } -+ else -+ { -+ hi2c->State = HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Disable I2C peripheral to prevent dummy data in buffer */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* Call the corresponding callback to inform upper layer of End of Transfer */ -+ HAL_I2C_ErrorCallback(hi2c); -+ } -+} -+ -+/** -+ * @brief This function handles I2C Communication Timeout. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param Flag specifies the I2C flag to check. -+ * @param Status The new Flag status (SET or RESET). -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) -+{ -+ /* Wait until flag is set */ -+ while((__HAL_I2C_GET_FLAG(hi2c, Flag) ? SET : RESET) == Status) -+ { -+ /* Check for the Timeout */ -+ if(Timeout != HAL_MAX_DELAY) -+ { -+ if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ hi2c->Mode = HAL_I2C_MODE_NONE; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ } -+ -+ return HAL_OK; -+} -+ -+/** -+ * @brief This function handles I2C Communication Timeout for Master addressing phase. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for I2C module -+ * @param Flag specifies the I2C flag to check. -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) -+{ -+ while(__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) -+ { -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) -+ { -+ /* Generate Stop */ -+ hi2c->Instance->CR1 |= I2C_CR1_STOP; -+ -+ /* Clear AF Flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ -+ hi2c->ErrorCode = HAL_I2C_ERROR_AF; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_ERROR; -+ } -+ -+ /* Check for the Timeout */ -+ if(Timeout != HAL_MAX_DELAY) -+ { -+ if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) -+ { -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief This function handles I2C Communication Timeout for specific usage of TXE flag. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) -+{ -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) -+ { -+ /* Check if a NACK is detected */ -+ if(I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Check for the Timeout */ -+ if(Timeout != HAL_MAX_DELAY) -+ { -+ if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief This function handles I2C Communication Timeout for specific usage of BTF flag. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) -+{ -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) -+ { -+ /* Check if a NACK is detected */ -+ if(I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Check for the Timeout */ -+ if(Timeout != HAL_MAX_DELAY) -+ { -+ if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief This function handles I2C Communication Timeout for specific usage of STOP flag. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) -+{ -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) -+ { -+ /* Check if a NACK is detected */ -+ if(I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) -+ { -+ return HAL_ERROR; -+ } -+ -+ /* Check for the Timeout */ -+ if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @param Timeout Timeout duration -+ * @param Tickstart Tick start value -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) -+{ -+ -+ while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) -+ { -+ /* Check if a STOPF is detected */ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) -+ { -+ /* Clear STOP Flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); -+ -+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_ERROR; -+ } -+ -+ /* Check for the Timeout */ -+ if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) -+ { -+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_TIMEOUT; -+ } -+ } -+ return HAL_OK; -+} -+ -+/** -+ * @brief This function handles Acknowledge failed detection during an I2C Communication. -+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2C. -+ * @retval HAL status -+ */ -+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) -+{ -+ if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) -+ { -+ /* Clear NACKF Flag */ -+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); -+ -+ hi2c->ErrorCode = HAL_I2C_ERROR_AF; -+ hi2c->PreviousState = I2C_STATE_NONE; -+ hi2c->State= HAL_I2C_STATE_READY; -+ -+ /* Process Unlocked */ -+ __HAL_UNLOCK(hi2c); -+ -+ return HAL_ERROR; -+ } -+ return HAL_OK; -+} -+/** -+ * @} -+ */ -+ -+#endif /* HAL_I2C_MODULE_ENABLED */ -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c -new file mode 100644 -index 0000000..de8f160 ---- /dev/null -+++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c -@@ -0,0 +1,204 @@ -+/** -+ ****************************************************************************** -+ * @file stm32f4xx_hal_i2c_ex.c -+ * @author MCD Application Team -+ * @brief I2C Extension HAL module driver. -+ * This file provides firmware functions to manage the following -+ * functionalities of I2C extension peripheral: -+ * + Extension features functions -+ * -+ @verbatim -+ ============================================================================== -+ ##### I2C peripheral extension features ##### -+ ============================================================================== -+ -+ [..] Comparing to other previous devices, the I2C interface for STM32F427xx/437xx/ -+ 429xx/439xx devices contains the following additional features : -+ -+ (+) Possibility to disable or enable Analog Noise Filter -+ (+) Use of a configured Digital Noise Filter -+ -+ ##### How to use this driver ##### -+ ============================================================================== -+ [..] This driver provides functions to configure Noise Filter -+ (#) Configure I2C Analog noise filter using the function HAL_I2C_AnalogFilter_Config() -+ (#) Configure I2C Digital noise filter using the function HAL_I2C_DigitalFilter_Config() -+ -+ @endverbatim -+ ****************************************************************************** -+ * @attention -+ * -+ *

© COPYRIGHT(c) 2017 STMicroelectronics

-+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. Neither the name of STMicroelectronics nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ****************************************************************************** -+ */ -+ -+/* Includes ------------------------------------------------------------------*/ -+#include "stm32f4xx_hal.h" -+ -+/** @addtogroup STM32F4xx_HAL_Driver -+ * @{ -+ */ -+ -+/** @defgroup I2CEx I2CEx -+ * @brief I2C HAL module driver -+ * @{ -+ */ -+ -+#ifdef HAL_I2C_MODULE_ENABLED -+ -+#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ -+ defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) ||\ -+ defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) -+/* Private typedef -----------------------------------------------------------*/ -+/* Private define ------------------------------------------------------------*/ -+/* Private macro -------------------------------------------------------------*/ -+/* Private variables ---------------------------------------------------------*/ -+/* Private function prototypes -----------------------------------------------*/ -+/* Exported functions --------------------------------------------------------*/ -+/** @defgroup I2CEx_Exported_Functions I2C Exported Functions -+ * @{ -+ */ -+ -+ -+/** @defgroup I2CEx_Exported_Functions_Group1 Extension features functions -+ * @brief Extension features functions -+ * -+@verbatim -+ =============================================================================== -+ ##### Extension features functions ##### -+ =============================================================================== -+ [..] This section provides functions allowing to: -+ (+) Configure Noise Filters -+ -+@endverbatim -+ * @{ -+ */ -+ -+/** -+ * @brief Configures I2C Analog noise filter. -+ * @param hi2c pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2Cx peripheral. -+ * @param AnalogFilter new state of the Analog filter. -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) -+{ -+ /* Check the parameters */ -+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); -+ assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ hi2c->State = HAL_I2C_STATE_BUSY; -+ -+ /* Disable the selected I2C peripheral */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* Reset I2Cx ANOFF bit */ -+ hi2c->Instance->FLTR &= ~(I2C_FLTR_ANOFF); -+ -+ /* Disable the analog filter */ -+ hi2c->Instance->FLTR |= AnalogFilter; -+ -+ __HAL_I2C_ENABLE(hi2c); -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @brief Configures I2C Digital noise filter. -+ * @param hi2c pointer to a I2C_HandleTypeDef structure that contains -+ * the configuration information for the specified I2Cx peripheral. -+ * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F. -+ * @retval HAL status -+ */ -+HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) -+{ -+ uint16_t tmpreg = 0; -+ -+ /* Check the parameters */ -+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); -+ assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); -+ -+ if(hi2c->State == HAL_I2C_STATE_READY) -+ { -+ hi2c->State = HAL_I2C_STATE_BUSY; -+ -+ /* Disable the selected I2C peripheral */ -+ __HAL_I2C_DISABLE(hi2c); -+ -+ /* Get the old register value */ -+ tmpreg = hi2c->Instance->FLTR; -+ -+ /* Reset I2Cx DNF bit [3:0] */ -+ tmpreg &= ~(I2C_FLTR_DNF); -+ -+ /* Set I2Cx DNF coefficient */ -+ tmpreg |= DigitalFilter; -+ -+ /* Store the new register value */ -+ hi2c->Instance->FLTR = tmpreg; -+ -+ __HAL_I2C_ENABLE(hi2c); -+ -+ hi2c->State = HAL_I2C_STATE_READY; -+ -+ return HAL_OK; -+ } -+ else -+ { -+ return HAL_BUSY; -+ } -+} -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+#endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F401xC ||\ -+ STM32F401xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx ||\ -+ STM32F423xx */ -+ -+#endif /* HAL_I2C_MODULE_ENABLED */ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -diff --git a/Firmware/Board/v3/Inc/i2c.h b/Firmware/Board/v3/Inc/i2c.h -new file mode 100644 -index 0000000..f449b88 ---- /dev/null -+++ b/Firmware/Board/v3/Inc/i2c.h -@@ -0,0 +1,91 @@ -+/** -+ ****************************************************************************** -+ * File Name : I2C.h -+ * Description : This file provides code for the configuration -+ * of the I2C instances. -+ ****************************************************************************** -+ * This notice applies to any and all portions of this file -+ * that are not between comment pairs USER CODE BEGIN and -+ * USER CODE END. Other portions of this file, whether -+ * inserted by the user or by software development tools -+ * are owned by their respective copyright owners. -+ * -+ * Copyright (c) 2018 STMicroelectronics International N.V. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted, provided that the following conditions are met: -+ * -+ * 1. Redistribution of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. Neither the name of STMicroelectronics nor the names of other -+ * contributors to this software may be used to endorse or promote products -+ * derived from this software without specific written permission. -+ * 4. This software, including modifications and/or derivative works of this -+ * software, must execute solely and exclusively on microcontroller or -+ * microprocessor devices manufactured by or for STMicroelectronics. -+ * 5. Redistribution and use of this software other than as permitted under -+ * this license is void and will automatically terminate your rights under -+ * this license. -+ * -+ * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY -+ * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT -+ * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ****************************************************************************** -+ */ -+/* Define to prevent recursive inclusion -------------------------------------*/ -+#ifndef __i2c_H -+#define __i2c_H -+#ifdef __cplusplus -+ extern "C" { -+#endif -+ -+/* Includes ------------------------------------------------------------------*/ -+#include "stm32f4xx_hal.h" -+#include "main.h" -+ -+/* USER CODE BEGIN Includes */ -+ -+/* USER CODE END Includes */ -+ -+extern I2C_HandleTypeDef hi2c1; -+ -+/* USER CODE BEGIN Private defines */ -+ -+/* USER CODE END Private defines */ -+ -+extern void _Error_Handler(char *, int); -+ -+void MX_I2C1_Init(uint8_t addr); -+ -+/* USER CODE BEGIN Prototypes */ -+ -+/* USER CODE END Prototypes */ -+ -+#ifdef __cplusplus -+} -+#endif -+#endif /*__ i2c_H */ -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -diff --git a/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h b/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h -index d0f48f5..b3ef59a 100644 ---- a/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h -+++ b/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h -@@ -65,7 +65,7 @@ - /* #define HAL_SRAM_MODULE_ENABLED */ - /* #define HAL_SDRAM_MODULE_ENABLED */ - /* #define HAL_HASH_MODULE_ENABLED */ --/* #define HAL_I2C_MODULE_ENABLED */ -+#define HAL_I2C_MODULE_ENABLED - /* #define HAL_I2S_MODULE_ENABLED */ - /* #define HAL_IWDG_MODULE_ENABLED */ - /* #define HAL_LTDC_MODULE_ENABLED */ -diff --git a/Firmware/Board/v3/Src/i2c.c b/Firmware/Board/v3/Src/i2c.c -new file mode 100644 -index 0000000..bae77f1 ---- /dev/null -+++ b/Firmware/Board/v3/Src/i2c.c -@@ -0,0 +1,198 @@ -+/** -+ ****************************************************************************** -+ * File Name : I2C.c -+ * Description : This file provides code for the configuration -+ * of the I2C instances. -+ ****************************************************************************** -+ * This notice applies to any and all portions of this file -+ * that are not between comment pairs USER CODE BEGIN and -+ * USER CODE END. Other portions of this file, whether -+ * inserted by the user or by software development tools -+ * are owned by their respective copyright owners. -+ * -+ * Copyright (c) 2018 STMicroelectronics International N.V. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted, provided that the following conditions are met: -+ * -+ * 1. Redistribution of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. Neither the name of STMicroelectronics nor the names of other -+ * contributors to this software may be used to endorse or promote products -+ * derived from this software without specific written permission. -+ * 4. This software, including modifications and/or derivative works of this -+ * software, must execute solely and exclusively on microcontroller or -+ * microprocessor devices manufactured by or for STMicroelectronics. -+ * 5. Redistribution and use of this software other than as permitted under -+ * this license is void and will automatically terminate your rights under -+ * this license. -+ * -+ * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY -+ * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT -+ * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ****************************************************************************** -+ */ -+ -+/* Includes ------------------------------------------------------------------*/ -+#include "i2c.h" -+ -+#include "gpio.h" -+#include "dma.h" -+ -+/* USER CODE BEGIN 0 */ -+ -+/* USER CODE END 0 */ -+ -+I2C_HandleTypeDef hi2c1; -+DMA_HandleTypeDef hdma_i2c1_rx; -+DMA_HandleTypeDef hdma_i2c1_tx; -+ -+/* I2C1 init function */ -+void MX_I2C1_Init(uint8_t addr) -+{ -+ -+ hi2c1.Instance = I2C1; -+ hi2c1.Init.ClockSpeed = 100000; -+ hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; -+ hi2c1.Init.OwnAddress1 = addr << 1; -+ hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; -+ hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; -+ hi2c1.Init.OwnAddress2 = 0; -+ hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; -+ hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; -+ if (HAL_I2C_Init(&hi2c1) != HAL_OK) -+ { -+ _Error_Handler(__FILE__, __LINE__); -+ } -+ -+} -+ -+void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) -+{ -+ -+ GPIO_InitTypeDef GPIO_InitStruct; -+ if(i2cHandle->Instance==I2C1) -+ { -+ /* USER CODE BEGIN I2C1_MspInit 0 */ -+ -+ /* USER CODE END I2C1_MspInit 0 */ -+ -+ /**I2C1 GPIO Configuration -+ PB8 ------> I2C1_SCL -+ PB9 ------> I2C1_SDA -+ */ -+ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; -+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; -+ GPIO_InitStruct.Pull = GPIO_PULLUP; -+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; -+ GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; -+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); -+ -+ /* I2C1 clock enable */ -+ __HAL_RCC_I2C1_CLK_ENABLE(); -+ -+ /* I2C1 DMA Init */ -+ /* I2C1_RX Init */ -+ hdma_i2c1_rx.Instance = DMA1_Stream0; -+ hdma_i2c1_rx.Init.Channel = DMA_CHANNEL_1; -+ hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; -+ hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE; -+ hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE; -+ hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; -+ hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; -+ hdma_i2c1_rx.Init.Mode = DMA_CIRCULAR; -+ hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_LOW; -+ hdma_i2c1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; -+ if (HAL_DMA_Init(&hdma_i2c1_rx) != HAL_OK) -+ { -+ _Error_Handler(__FILE__, __LINE__); -+ } -+ -+ __HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c1_rx); -+ -+ /* I2C1_TX Init */ -+ hdma_i2c1_tx.Instance = DMA1_Stream6; -+ hdma_i2c1_tx.Init.Channel = DMA_CHANNEL_1; -+ hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; -+ hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE; -+ hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE; -+ hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; -+ hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; -+ hdma_i2c1_tx.Init.Mode = DMA_NORMAL; -+ hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_LOW; -+ hdma_i2c1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; -+ if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK) -+ { -+ _Error_Handler(__FILE__, __LINE__); -+ } -+ -+ __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c1_tx); -+ -+ /* I2C1 interrupt Init */ -+ HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0); -+ HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); -+ HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0); -+ HAL_NVIC_EnableIRQ(I2C1_ER_IRQn); -+ /* USER CODE BEGIN I2C1_MspInit 1 */ -+ -+ /* USER CODE END I2C1_MspInit 1 */ -+ } -+} -+ -+void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) -+{ -+ -+ if(i2cHandle->Instance==I2C1) -+ { -+ /* USER CODE BEGIN I2C1_MspDeInit 0 */ -+ -+ /* USER CODE END I2C1_MspDeInit 0 */ -+ /* Peripheral clock disable */ -+ __HAL_RCC_I2C1_CLK_DISABLE(); -+ -+ /**I2C1 GPIO Configuration -+ PB8 ------> I2C1_SCL -+ PB9 ------> I2C1_SDA -+ */ -+ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); -+ -+ /* I2C1 DMA DeInit */ -+ HAL_DMA_DeInit(i2cHandle->hdmarx); -+ HAL_DMA_DeInit(i2cHandle->hdmatx); -+ -+ /* I2C1 interrupt Deinit */ -+ HAL_NVIC_DisableIRQ(I2C1_EV_IRQn); -+ HAL_NVIC_DisableIRQ(I2C1_ER_IRQn); -+ /* USER CODE BEGIN I2C1_MspDeInit 1 */ -+ -+ /* USER CODE END I2C1_MspDeInit 1 */ -+ } -+} -+ -+/* USER CODE BEGIN 1 */ -+ -+/* USER CODE END 1 */ -+ -+/** -+ * @} -+ */ -+ -+/** -+ * @} -+ */ -+ -+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -diff --git a/Firmware/Board/v3/Src/main.c b/Firmware/Board/v3/Src/main.c -index 987e0bd..efaeef1 100644 ---- a/Firmware/Board/v3/Src/main.c -+++ b/Firmware/Board/v3/Src/main.c -@@ -187,7 +187,6 @@ int main(void) - MX_ADC3_Init(); - MX_TIM2_Init(); - MX_UART4_Init(); -- MX_CAN1_Init(); - /* USER CODE BEGIN 2 */ - - //Required to use OC4 for ADC triggering. --- -2.17.0 - diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h new file mode 100644 index 00000000..5452a507 --- /dev/null +++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h @@ -0,0 +1,649 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c.h + * @author MCD Application Team + * @brief Header file of I2C HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_I2C_H +#define __STM32F4xx_HAL_I2C_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup I2C_Exported_Types I2C Exported Types + * @{ + */ + +/** + * @brief I2C Configuration Structure definition + */ +typedef struct +{ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + + uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref I2C_addressing_mode */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref I2C_dual_addressing_mode */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref I2C_general_call_addressing_mode */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref I2C_nostretch_mode */ + +}I2C_InitTypeDef; + +/** + * @brief HAL State structure definition + * @note HAL I2C State value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : Abort (Abort user request on going) + * 10 : Timeout + * 11 : Error + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP initialized and ready to use. HAL I2C Init function called) + * b4 (not used) + * x : Should be set to 0 + * b3 + * 0 : Ready or Busy (No Listen mode ongoing) + * 1 : Listen (IP in Address Listen Mode) + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP busy with some configuration or internal operations) + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + */ +typedef enum +{ + HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ + +}HAL_I2C_StateTypeDef; + +/** + * @brief HAL Mode structure definition + * @note HAL I2C Mode value coding follow below described bitmap : + * b7 (not used) + * x : Should be set to 0 + * b6 + * 0 : None + * 1 : Memory (HAL I2C communication is in Memory Mode) + * b5 + * 0 : None + * 1 : Slave (HAL I2C communication is in Slave Mode) + * b4 + * 0 : None + * 1 : Master (HAL I2C communication is in Master Mode) + * b3-b2-b1-b0 (not used) + * xxxx : Should be set to 0000 + */ +typedef enum +{ + HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ + HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ + HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ + HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ + +}HAL_I2C_ModeTypeDef; + +/** + * @brief I2C handle Structure definition + */ +typedef struct +{ + I2C_TypeDef *Instance; /*!< I2C registers base address */ + + I2C_InitTypeDef Init; /*!< I2C communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ + + uint16_t XferSize; /*!< I2C transfer size */ + + __IO uint16_t XferCount; /*!< I2C transfer counter */ + + __IO uint32_t XferOptions; /*!< I2C transfer options */ + + __IO uint32_t PreviousState; /*!< I2C communication Previous state and mode + context for internal usage */ + + DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ + + HAL_LockTypeDef Lock; /*!< I2C locking object */ + + __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ + + __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ + + __IO uint32_t ErrorCode; /*!< I2C Error code */ + + __IO uint32_t Devaddress; /*!< I2C Target device address */ + + __IO uint32_t Memaddress; /*!< I2C Target memory address */ + + __IO uint32_t MemaddSize; /*!< I2C Target memory address size */ + + __IO uint32_t EventCount; /*!< I2C Event counter */ + +}I2C_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2C_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2C_Error_Code I2C Error Code + * @brief I2C Error Code + * @{ + */ +#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */ +#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */ +#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */ +#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */ +#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */ +/** + * @} + */ + +/** @defgroup I2C_duty_cycle_in_fast_mode I2C duty cycle in fast mode + * @{ + */ +#define I2C_DUTYCYCLE_2 0x00000000U +#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY +/** + * @} + */ + +/** @defgroup I2C_addressing_mode I2C addressing mode + * @{ + */ +#define I2C_ADDRESSINGMODE_7BIT 0x00004000U +#define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U) +/** + * @} + */ + +/** @defgroup I2C_dual_addressing_mode I2C dual addressing mode + * @{ + */ +#define I2C_DUALADDRESS_DISABLE 0x00000000U +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL +/** + * @} + */ + +/** @defgroup I2C_general_call_addressing_mode I2C general call addressing mode + * @{ + */ +#define I2C_GENERALCALL_DISABLE 0x00000000U +#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC +/** + * @} + */ + +/** @defgroup I2C_nostretch_mode I2C nostretch mode + * @{ + */ +#define I2C_NOSTRETCH_DISABLE 0x00000000U +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup I2C_Memory_Address_Size I2C Memory Address Size + * @{ + */ +#define I2C_MEMADD_SIZE_8BIT 0x00000001U +#define I2C_MEMADD_SIZE_16BIT 0x00000010U +/** + * @} + */ + +/** @defgroup I2C_XferDirection_definition I2C XferDirection definition + * @{ + */ +#define I2C_DIRECTION_RECEIVE 0x00000000U +#define I2C_DIRECTION_TRANSMIT 0x00000001U +/** + * @} + */ + +/** @defgroup I2C_XferOptions_definition I2C XferOptions definition + * @{ + */ +#define I2C_FIRST_FRAME 0x00000001U +#define I2C_NEXT_FRAME 0x00000002U +#define I2C_FIRST_AND_LAST_FRAME 0x00000004U +#define I2C_LAST_FRAME 0x00000008U +/** + * @} + */ + +/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition + * @{ + */ +#define I2C_IT_BUF I2C_CR2_ITBUFEN +#define I2C_IT_EVT I2C_CR2_ITEVTEN +#define I2C_IT_ERR I2C_CR2_ITERREN +/** + * @} + */ + +/** @defgroup I2C_Flag_definition I2C Flag definition + * @{ + */ +#define I2C_FLAG_SMBALERT 0x00018000U +#define I2C_FLAG_TIMEOUT 0x00014000U +#define I2C_FLAG_PECERR 0x00011000U +#define I2C_FLAG_OVR 0x00010800U +#define I2C_FLAG_AF 0x00010400U +#define I2C_FLAG_ARLO 0x00010200U +#define I2C_FLAG_BERR 0x00010100U +#define I2C_FLAG_TXE 0x00010080U +#define I2C_FLAG_RXNE 0x00010040U +#define I2C_FLAG_STOPF 0x00010010U +#define I2C_FLAG_ADD10 0x00010008U +#define I2C_FLAG_BTF 0x00010004U +#define I2C_FLAG_ADDR 0x00010002U +#define I2C_FLAG_SB 0x00010001U +#define I2C_FLAG_DUALF 0x00100080U +#define I2C_FLAG_SMBHOST 0x00100040U +#define I2C_FLAG_SMBDEFAULT 0x00100020U +#define I2C_FLAG_GENCALL 0x00100010U +#define I2C_FLAG_TRA 0x00100004U +#define I2C_FLAG_BUSY 0x00100002U +#define I2C_FLAG_MSL 0x00100001U +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup I2C_Exported_Macros I2C Exported Macros + * @{ + */ + +/** @brief Reset I2C handle state + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET) + +/** @brief Enable or disable the specified I2C interrupts. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg I2C_IT_BUF: Buffer interrupt enable + * @arg I2C_IT_EVT: Event interrupt enable + * @arg I2C_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 |= (__INTERRUPT__)) +#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 &= (~(__INTERRUPT__))) + +/** @brief Checks if the specified I2C interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @param __INTERRUPT__ specifies the I2C interrupt source to check. + * This parameter can be one of the following values: + * @arg I2C_IT_BUF: Buffer interrupt enable + * @arg I2C_IT_EVT: Event interrupt enable + * @arg I2C_IT_ERR: Error interrupt enable + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks whether the specified I2C flag is set or not. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_SMBALERT: SMBus Alert flag + * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR: PEC error in reception flag + * @arg I2C_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag + * @arg I2C_FLAG_BERR: Bus error flag + * @arg I2C_FLAG_TXE: Data register empty flag + * @arg I2C_FLAG_RXNE: Data register not empty flag + * @arg I2C_FLAG_STOPF: Stop detection flag + * @arg I2C_FLAG_ADD10: 10-bit header sent flag + * @arg I2C_FLAG_BTF: Byte transfer finished flag + * @arg I2C_FLAG_ADDR: Address sent flag + * Address matched flag + * @arg I2C_FLAG_SB: Start bit flag + * @arg I2C_FLAG_DUALF: Dual flag + * @arg I2C_FLAG_SMBHOST: SMBus host header + * @arg I2C_FLAG_SMBDEFAULT: SMBus default header + * @arg I2C_FLAG_GENCALL: General call header flag + * @arg I2C_FLAG_TRA: Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY: Bus busy flag + * @arg I2C_FLAG_MSL: Master/Slave flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U)?((((__HANDLE__)->Instance->SR1) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)): \ + ((((__HANDLE__)->Instance->SR2) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK))) + +/** @brief Clears the I2C pending flags which are cleared by writing 0 in a specific bit. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg I2C_FLAG_SMBALERT: SMBus Alert flag + * @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR: PEC error in reception flag + * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BERR: Bus error flag + * @retval None + */ +#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__) & I2C_FLAG_MASK)) + +/** @brief Clears the I2C ADDR pending flag. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + tmpreg = (__HANDLE__)->Instance->SR2; \ + UNUSED(tmpreg); \ + } while(0) + +/** @brief Clears the I2C STOPF pending flag. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + (__HANDLE__)->Instance->CR1 |= I2C_CR1_PE; \ + UNUSED(tmpreg); \ + } while(0) + +/** @brief Enable the I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= I2C_CR1_PE) + +/** @brief Disable the I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~I2C_CR1_PE) + +/** + * @} + */ + +/* Include I2C HAL Extension module */ +#include "stm32f4xx_hal_i2c_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2C_Exported_Functions + * @{ + */ + +/** @addtogroup I2C_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DeInit (I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions *****************************************************/ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); + +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress); +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c); + +/******* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State, Mode and Errors functions *********************************/ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c); +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c); +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c); + +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Constants I2C Private Constants + * @{ + */ +#define I2C_FLAG_MASK 0x0000FFFFU +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2C_Private_Macros I2C Private Macros + * @{ + */ + +#define I2C_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U) +#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U)) +#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) (((((__PCLK__)/((__SPEED__) << 1U)) & I2C_CCR_CCR) < 4U)? 4U:((__PCLK__) / ((__SPEED__) << 1U))) +#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? ((__PCLK__) / ((__SPEED__) * 3U)) : (((__PCLK__) / ((__SPEED__) * 25U)) | I2C_DUTYCYCLE_16_9)) +#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__SPEED__) <= 100000U)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) : \ + ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U)? 1U : \ + ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS)) + +#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0))) +#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0)) + +#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) +#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0))) +#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1)))) + +#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0xFF00)) >> 8))) +#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) + +/** @defgroup I2C_IS_RTC_Definitions I2C Private macros to check input parameters + * @{ + */ +#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DUTYCYCLE_2) || \ + ((CYCLE) == I2C_DUTYCYCLE_16_9)) +#define IS_I2C_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || \ + ((ADDRESS) == I2C_ADDRESSINGMODE_10BIT)) +#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == I2C_DUALADDRESS_ENABLE)) +#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || \ + ((CALL) == I2C_GENERALCALL_ENABLE)) +#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || \ + ((STRETCH) == I2C_NOSTRETCH_ENABLE)) +#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || \ + ((SIZE) == I2C_MEMADD_SIZE_16BIT)) +#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) > 0U) && ((SPEED) <= 400000U)) +#define IS_I2C_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & 0xFFFFFC00U) == 0U) +#define IS_I2C_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & 0xFFFFFF01U) == 0U) +#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || \ + ((REQUEST) == I2C_NEXT_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || \ + ((REQUEST) == I2C_LAST_FRAME)) +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32F4xx_HAL_I2C_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h new file mode 100644 index 00000000..ff47d5cc --- /dev/null +++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h @@ -0,0 +1,137 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c_ex.h + * @author MCD Application Team + * @brief Header file of I2C HAL Extension module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_I2C_EX_H +#define __STM32F4xx_HAL_I2C_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2CEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2CEx_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2CEx_Analog_Filter I2C Analog Filter + * @{ + */ +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2CEx_Exported_Functions + * @{ + */ + +/** @addtogroup I2CEx_Exported_Functions_Group1 + * @{ + */ +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Constants I2C Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Macros I2C Private Macros + * @{ + */ +#define IS_I2C_ANALOG_FILTER(FILTER) (((FILTER) == I2C_ANALOGFILTER_ENABLE) || \ + ((FILTER) == I2C_ANALOGFILTER_DISABLE)) +#define IS_I2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F401xC ||\ + STM32F401xE || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx ||\ + STM32F413xx || STM32F423xx */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_I2C_EX_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c new file mode 100644 index 00000000..da185200 --- /dev/null +++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c @@ -0,0 +1,5494 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c.c + * @author MCD Application Team + * @brief I2C HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Inter Integrated Circuit (I2C) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State, Mode and Error functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The I2C HAL driver can be used as follows: + + (#) Declare a I2C_HandleTypeDef handle structure, for example: + I2C_HandleTypeDef hi2c; + + (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API: + (##) Enable the I2Cx interface clock + (##) I2C pins configuration + (+++) Enable the clock for the I2C GPIOs + (+++) Configure I2C pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the I2Cx interrupt priority + (+++) Enable the NVIC I2C IRQ Channel + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive stream + (+++) Enable the DMAx interface clock using + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx Stream + (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on + the DMA Tx or Rx Stream + + (#) Configure the Communication Speed, Duty cycle, Addressing mode, Own Address1, + Dual Addressing mode, Own Address2, General call and Nostretch mode in the hi2c Init structure. + + (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware + (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API. + + (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady() + + (#) For I2C IO and IO MEM operations, three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit() + (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive() + (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit() + (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive() + + *** Polling mode IO MEM operation *** + ===================================== + [..] + (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write() + (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read() + + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Transmit in master mode an amount of data in non blocking mode using HAL_I2C_Master_Transmit_IT() + (+) At transmission end of transfer HAL_I2C_MasterTxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback + (+) Receive in master mode an amount of data in non blocking mode using HAL_I2C_Master_Receive_IT() + (+) At reception end of transfer HAL_I2C_MasterRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback + (+) Transmit in slave mode an amount of data in non blocking mode using HAL_I2C_Slave_Transmit_IT() + (+) At transmission end of transfer HAL_I2C_SlaveTxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback + (+) Receive in slave mode an amount of data in non blocking mode using HAL_I2C_Slave_Receive_IT() + (+) At reception end of transfer HAL_I2C_SlaveRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + + *** Interrupt mode IO sequential operation *** + ============================================== + [..] + (@) These interfaces allow to manage a sequential transfer with a repeated start condition + when a direction change during transfer + [..] + (+) A specific option field manage the different steps of a sequential transfer + (+) Option field values are defined through @ref I2C_XFEROPTIONS and are listed below: + (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode + (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition + (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and without a final stop condition in both cases + (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and with a final stop condition in both cases + + (+) Differents sequential I2C interfaces are listed below: + (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Transmit_IT() + (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Receive_IT() + (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT() + (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can + add his own code to check the Address Match Code and the transmission direction request by master (Write/Read). + (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_ListenCpltCallback() + (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Transmit_IT() + (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Receive_IT() + (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + + *** Interrupt mode IO MEM operation *** + ======================================= + [..] + (+) Write an amount of data in no-blocking mode with Interrupt to a specific memory address using + HAL_I2C_Mem_Write_IT() + (+) At MEM end of write transfer HAL_I2C_MemTxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback + (+) Read an amount of data in no-blocking mode with Interrupt from a specific memory address using + HAL_I2C_Mem_Read_IT() + (+) At MEM end of read transfer HAL_I2C_MemRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Transmit in master mode an amount of data in non blocking mode (DMA) using + HAL_I2C_Master_Transmit_DMA() + (+) At transmission end of transfer HAL_I2C_MasterTxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback + (+) Receive in master mode an amount of data in non blocking mode (DMA) using + HAL_I2C_Master_Receive_DMA() + (+) At reception end of transfer HAL_I2C_MasterRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback + (+) Transmit in slave mode an amount of data in non blocking mode (DMA) using + HAL_I2C_Slave_Transmit_DMA() + (+) At transmission end of transfer HAL_I2C_SlaveTxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback + (+) Receive in slave mode an amount of data in non blocking mode (DMA) using + HAL_I2C_Slave_Receive_DMA() + (+) At reception end of transfer HAL_I2C_SlaveRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + + *** DMA mode IO MEM operation *** + ================================= + [..] + (+) Write an amount of data in no-blocking mode with DMA to a specific memory address using + HAL_I2C_Mem_Write_DMA() + (+) At MEM end of write transfer HAL_I2C_MemTxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback + (+) Read an amount of data in no-blocking mode with DMA from a specific memory address using + HAL_I2C_Mem_Read_DMA() + (+) At MEM end of read transfer HAL_I2C_MemRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback + + + *** I2C HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in I2C HAL driver. + + (+) __HAL_I2C_ENABLE: Enable the I2C peripheral + (+) __HAL_I2C_DISABLE: Disable the I2C peripheral + (+) __HAL_I2C_GET_FLAG : Checks whether the specified I2C flag is set or not + (+) __HAL_I2C_CLEAR_FLAG : Clear the specified I2C pending flag + (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt + (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt + + [..] + (@) You can refer to the I2C HAL driver header file for more useful macros + + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2C I2C + * @brief I2C HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup I2C_Private_Define + * @{ + */ +#define I2C_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */ +#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */ +#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */ + +/* Private define for @ref PreviousState usage */ +#define I2C_STATE_MSK ((uint32_t)((HAL_I2C_STATE_BUSY_TX | HAL_I2C_STATE_BUSY_RX) & (~(uint32_t)HAL_I2C_STATE_READY))) /*!< Mask State define, keep only RX and TX bits */ +#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ +#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup I2C_Private_Functions + * @{ + */ +/* Private functions to handle DMA transfer */ +static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMAError(DMA_HandleTypeDef *hdma); +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma); + +static void I2C_ITError(I2C_HandleTypeDef *hi2c); + +static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c); + +/* Private functions for I2C transfer IRQ handler */ +static HAL_StatusTypeDef I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_Master_SB(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_Master_ADD10(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_Master_ADDR(I2C_HandleTypeDef *hi2c); + +static HAL_StatusTypeDef I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_SlaveTransmit_BTF(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_SlaveReceive_BTF(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_Slave_ADDR(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_Slave_AF(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup I2C_Exported_Functions I2C Exported Functions + * @{ + */ + +/** @defgroup I2C_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 I2Cx peripheral: + + (+) User must Implement HAL_I2C_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC). + + (+) Call the function HAL_I2C_Init() to configure the selected device with + the selected configuration: + (++) Communication Speed + (++) Duty cycle + (++) Addressing mode + (++) Own Address 1 + (++) Dual Addressing mode + (++) Own Address 2 + (++) General call mode + (++) Nostretch mode + + (+) Call the function HAL_I2C_DeInit() to restore the default configuration + of the selected I2Cx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the I2C according to the specified parameters + * in the I2C_InitTypeDef and create the associated handle. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) +{ + uint32_t freqrange = 0U; + uint32_t pclk1 = 0U; + + /* Check the I2C handle allocation */ + if(hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed)); + assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle)); + assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); + assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); + assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); + assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); + assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); + assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); + + if(hi2c->State == HAL_I2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2c->Lock = HAL_UNLOCKED; + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_I2C_MspInit(hi2c); + } + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get PCLK1 frequency */ + pclk1 = HAL_RCC_GetPCLK1Freq(); + + /* Calculate frequency range */ + freqrange = I2C_FREQRANGE(pclk1); + + /*---------------------------- I2Cx CR2 Configuration ----------------------*/ + /* Configure I2Cx: Frequency range */ + hi2c->Instance->CR2 = freqrange; + + /*---------------------------- I2Cx TRISE Configuration --------------------*/ + /* Configure I2Cx: Rise Time */ + hi2c->Instance->TRISE = I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed); + + /*---------------------------- I2Cx CCR Configuration ----------------------*/ + /* Configure I2Cx: Speed */ + hi2c->Instance->CCR = I2C_SPEED(pclk1, hi2c->Init.ClockSpeed, hi2c->Init.DutyCycle); + + /*---------------------------- I2Cx CR1 Configuration ----------------------*/ + /* Configure I2Cx: Generalcall and NoStretch mode */ + hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode); + + /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ + /* Configure I2Cx: Own Address1 and addressing mode */ + hi2c->Instance->OAR1 = (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1); + + /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ + /* Configure I2Cx: Dual mode and Own Address2 */ + hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2); + + /* Enable the selected I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + return HAL_OK; +} + +/** + * @brief DeInitializes the I2C peripheral. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if(hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the I2C Peripheral Clock */ + __HAL_I2C_DISABLE(hi2c); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_I2C_MspDeInit(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_RESET; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief I2C MSP Init. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ + __weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2C_MspInit could be implemented in the user file + */ +} + +/** + * @brief I2C MSP DeInit + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ + __weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2C_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_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 I2C data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The 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 functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_I2C_Master_Transmit() + (++) HAL_I2C_Master_Receive() + (++) HAL_I2C_Slave_Transmit() + (++) HAL_I2C_Slave_Receive() + (++) HAL_I2C_Mem_Write() + (++) HAL_I2C_Mem_Read() + (++) HAL_I2C_IsDeviceReady() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_I2C_Master_Transmit_IT() + (++) HAL_I2C_Master_Receive_IT() + (++) HAL_I2C_Slave_Transmit_IT() + (++) HAL_I2C_Slave_Receive_IT() + (++) HAL_I2C_Master_Sequential_Transmit_IT() + (++) HAL_I2C_Master_Sequential_Receive_IT() + (++) HAL_I2C_Slave_Sequential_Transmit_IT() + (++) HAL_I2C_Slave_Sequential_Receive_IT() + (++) HAL_I2C_Mem_Write_IT() + (++) HAL_I2C_Mem_Read_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_I2C_Master_Transmit_DMA() + (++) HAL_I2C_Master_Receive_DMA() + (++) HAL_I2C_Slave_Transmit_DMA() + (++) HAL_I2C_Slave_Receive_DMA() + (++) HAL_I2C_Mem_Write_DMA() + (++) HAL_I2C_Mem_Read_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_I2C_MemTxCpltCallback() + (++) HAL_I2C_MemRxCpltCallback() + (++) HAL_I2C_MasterTxCpltCallback() + (++) HAL_I2C_MasterRxCpltCallback() + (++) HAL_I2C_SlaveTxCpltCallback() + (++) HAL_I2C_SlaveRxCpltCallback() + (++) HAL_I2C_ErrorCallback() + (++) HAL_I2C_AbortCpltCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Send Slave Address */ + if(I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + while(hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + + if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + } + + /* Wait until BTF flag is set */ + if(I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + } + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Send Slave Address */ + if(I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + if(hi2c->XferSize == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + else if(hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + else if(hi2c->XferSize == 2U) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Enable Pos */ + hi2c->Instance->CR1 |= I2C_CR1_POS; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while(hi2c->XferSize > 0U) + { + if(hi2c->XferSize <= 3U) + { + /* One byte */ + if(hi2c->XferSize == 1U) + { + /* Wait until RXNE flag is set */ + if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + /* Two bytes */ + else if(hi2c->XferSize == 2U) + { + /* Wait until BTF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + /* 3 Last bytes */ + else + { + /* Wait until BTF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + /* Wait until BTF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + } + else + { + /* Wait until RXNE flag is set */ + if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + } + } + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmits in slave mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* If 10bit addressing mode is selected */ + if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + /* Wait until ADDR flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while(hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + + if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + } + } + + /* Wait until AF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_AF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Disable Address Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in blocking mode + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + if((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + while(hi2c->XferSize > 0U) + { + /* Wait until RXNE flag is set */ + if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (Size != 0U)) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + } + + /* Wait until STOP flag is set */ + if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_STOPFLAG(hi2c); + + /* Disable Address Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + hi2c->Devaddress = DevAddress; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + hi2c->Devaddress = DevAddress; + + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t Prev_State = 0x00U; + __IO uint32_t count = 0x00U; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferSize = hi2c->XferCount; + hi2c->Devaddress = DevAddress; + + Prev_State = hi2c->PreviousState; + + /* Generate Start */ + if((Prev_State == I2C_STATE_MASTER_BUSY_RX) || (Prev_State == I2C_STATE_NONE)) + { + /* Generate Start condition if first transfer */ + if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + else + { + /* Generate ReStart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t count = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferSize = hi2c->XferCount; + hi2c->Devaddress = DevAddress; + + if((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) || (hi2c->PreviousState == I2C_STATE_NONE)) + { + /* Generate Start condition if first transfer */ + if((XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_NO_OPTION_FRAME)) + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + else if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate ReStart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferSize = Size; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in slave mode an amount of data in no-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if(hi2c->State == HAL_I2C_STATE_LISTEN) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferSize = hi2c->XferCount; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in slave mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if(hi2c->State == HAL_I2C_STATE_LISTEN) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferSize = hi2c->XferCount; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c) +{ + if(hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp; + + /* Disable Address listen mode only if a transfer is not ongoing */ + if(hi2c->State == HAL_I2C_STATE_LISTEN) + { + tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK; + hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode); + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Disable Address Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Disable EVT and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + hi2c->Devaddress = DevAddress; + + if(hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferM1CpltCallback = NULL; + hi2c->hdmatx->XferM1HalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + } + else + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + hi2c->Devaddress = DevAddress; + + if(hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferM1CpltCallback = NULL; + hi2c->hdmarx->XferM1HalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + } + else + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master I2C process communication with Interrupt. + * @note This abort can be called only if state is ready + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(DevAddress); + + /* Abort Master transfer during Receive or Transmit process */ + if(hi2c->Mode == HAL_I2C_MODE_MASTER) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_ABORT; + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + hi2c->XferCount = 0U; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c); + + return HAL_OK; + } + else + { + /* Wrong usage of abort function */ + /* This function should be used only in case of abort monitored by master device */ + return HAL_ERROR; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferM1CpltCallback = NULL; + hi2c->hdmatx->XferM1HalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if(hi2c->State == HAL_I2C_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferM1CpltCallback = NULL; + hi2c->hdmarx->XferM1HalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + + /* Enable Address Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in blocking mode to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Send Slave Address and Memory Address */ + if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + while(hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferSize--; + hi2c->XferCount--; + + if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferSize--; + hi2c->XferCount--; + } + } + + /* Wait until BTF flag is set */ + if(I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in blocking mode from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + /* Send Slave Address and Memory Address */ + if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + if(hi2c->XferSize == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + else if(hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + else if(hi2c->XferSize == 2U) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Enable Pos */ + hi2c->Instance->CR1 |= I2C_CR1_POS; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while(hi2c->XferSize > 0U) + { + if(hi2c->XferSize <= 3U) + { + /* One byte */ + if(hi2c->XferSize== 1U) + { + /* Wait until RXNE flag is set */ + if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + /* Two bytes */ + else if(hi2c->XferSize == 2U) + { + /* Wait until BTF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + /* 3 Last bytes */ + else + { + /* Wait until BTF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + /* Wait until BTF flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + } + else + { + /* Wait until RXNE flag is set */ + if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferSize--; + hi2c->XferCount--; + } + } + } + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferSize = Size; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + hi2c->Memaddress = MemAddress; + hi2c->MemaddSize = MemAddSize; + hi2c->EventCount = 0U; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferSize = Size; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + hi2c->Memaddress = MemAddress; + hi2c->MemaddSize = MemAddSize; + hi2c->EventCount = 0U; + + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + if(hi2c->XferSize > 0U) + { + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + uint32_t tickstart = 0x00U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferSize = Size; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + if(hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferM1CpltCallback = NULL; + hi2c->hdmatx->XferM1HalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + + /* Send Slave Address and Memory Address */ + if(I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0x00U; + __IO uint32_t count = 0U; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock /25U /1000U); + do + { + if(count-- == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferSize = hi2c->XferCount; + + if(hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferM1CpltCallback = NULL; + hi2c->hdmarx->XferM1HalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + + /* Send Slave Address and Memory Address */ + if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + if(Size == 1U) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + } + else + { + /* Enable Last DMA bit */ + hi2c->Instance->CR2 |= I2C_CR2_LAST; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + } + else + { + /* Send Slave Address and Memory Address */ + if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) +{ + uint32_t tickstart = 0U, tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, I2C_Trials = 1U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + hi2c->State = HAL_I2C_STATE_BUSY; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + do + { + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR or AF flag are set */ + /* Get tick */ + tickstart = HAL_GetTick(); + + tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); + tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); + tmp3 = hi2c->State; + while((tmp1 == RESET) && (tmp2 == RESET) && (tmp3 != HAL_I2C_STATE_TIMEOUT)) + { + if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hi2c->State = HAL_I2C_STATE_TIMEOUT; + } + tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); + tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); + tmp3 = hi2c->State; + } + + hi2c->State = HAL_I2C_STATE_READY; + + /* Check if the ADDR flag has been set */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Clear ADDR Flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Clear AF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Wait until BUSY flag is reset */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + } + }while(I2C_Trials++ < Trials); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief This function handles I2C event interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + uint32_t sr2itflags = READ_REG(hi2c->Instance->SR2); + uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); + uint32_t itsources = READ_REG(hi2c->Instance->CR2); + + uint32_t CurrentMode = hi2c->Mode; + + /* Master or Memory mode selected */ + if((CurrentMode == HAL_I2C_MODE_MASTER) || (CurrentMode == HAL_I2C_MODE_MEM)) + { + /* SB Set ----------------------------------------------------------------*/ + if(((sr1itflags & I2C_FLAG_SB) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_Master_SB(hi2c); + } + /* ADD10 Set -------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_ADD10) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_Master_ADD10(hi2c); + } + /* ADDR Set --------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_Master_ADDR(hi2c); + } + + /* I2C in mode Transmitter -----------------------------------------------*/ + if((sr2itflags & I2C_FLAG_TRA) != RESET) + { + /* TXE set and BTF reset -----------------------------------------------*/ + if(((sr1itflags & I2C_FLAG_TXE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) + { + I2C_MasterTransmit_TXE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_MasterTransmit_BTF(hi2c); + } + } + /* I2C in mode Receiver --------------------------------------------------*/ + else + { + /* RXNE set and BTF reset -----------------------------------------------*/ + if(((sr1itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) + { + I2C_MasterReceive_RXNE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_MasterReceive_BTF(hi2c); + } + } + } + /* Slave mode selected */ + else + { + /* ADDR set --------------------------------------------------------------*/ + if(((sr1itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_Slave_ADDR(hi2c); + } + /* STOPF set --------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_STOPF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_Slave_STOPF(hi2c); + } + /* I2C in mode Transmitter -----------------------------------------------*/ + else if((sr2itflags & I2C_FLAG_TRA) != RESET) + { + /* TXE set and BTF reset -----------------------------------------------*/ + if(((sr1itflags & I2C_FLAG_TXE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) + { + I2C_SlaveTransmit_TXE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_SlaveTransmit_BTF(hi2c); + } + } + /* I2C in mode Receiver --------------------------------------------------*/ + else + { + /* RXNE set and BTF reset ----------------------------------------------*/ + if(((sr1itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_BUF) != RESET) && ((sr1itflags & I2C_FLAG_BTF) == RESET)) + { + I2C_SlaveReceive_RXNE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if(((sr1itflags & I2C_FLAG_BTF) != RESET) && ((itsources & I2C_IT_EVT) != RESET)) + { + I2C_SlaveReceive_BTF(hi2c); + } + } + } +} + +/** + * @brief This function handles I2C error interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, tmp4 = 0U; + uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); + uint32_t itsources = READ_REG(hi2c->Instance->CR2); + + /* I2C Bus error interrupt occurred ----------------------------------------*/ + if(((sr1itflags & I2C_FLAG_BERR) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); + } + + /* I2C Arbitration Loss error interrupt occurred ---------------------------*/ + if(((sr1itflags & I2C_FLAG_ARLO) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); + } + + /* I2C Acknowledge failure error interrupt occurred ------------------------*/ + if(((sr1itflags & I2C_FLAG_AF) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) + { + tmp1 = hi2c->Mode; + tmp2 = hi2c->XferCount; + tmp3 = hi2c->State; + tmp4 = hi2c->PreviousState; + if((tmp1 == HAL_I2C_MODE_SLAVE) && (tmp2 == 0U) && \ + ((tmp3 == HAL_I2C_STATE_BUSY_TX) || (tmp3 == HAL_I2C_STATE_BUSY_TX_LISTEN) || \ + ((tmp3 == HAL_I2C_STATE_LISTEN) && (tmp4 == I2C_STATE_SLAVE_BUSY_TX)))) + { + I2C_Slave_AF(hi2c); + } + else + { + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Do not generate a STOP in case of Slave receive non acknowledge during transfer (mean not at the end of transfer) */ + if(hi2c->Mode == HAL_I2C_MODE_MASTER) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1,I2C_CR1_STOP); + } + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } + } + + /* I2C Over-Run/Under-Run interrupt occurred -------------------------------*/ + if(((sr1itflags & I2C_FLAG_OVR) != RESET) && ((itsources & I2C_IT_ERR) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; + /* Clear OVR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); + } + + /* Call the Error Callback in case of Error detected -----------------------*/ + if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + I2C_ITError(hi2c); + } +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterTxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterRxCpltCallback can be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveTxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveRxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XferOptions_definition + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AddrCallback can be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ListenCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Memory Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemTxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Memory Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemRxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief I2C error callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ErrorCallback can be implemented in the user file + */ +} + +/** + * @brief I2C abort callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State, Mode and Error functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the I2C handle state. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL state + */ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c) +{ + /* Return I2C handle state */ + return hi2c->State; +} + +/** + * @brief Return the I2C Master, Slave, Memory or no mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL mode + */ +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c) +{ + return hi2c->Mode; +} + +/** + * @brief Return the I2C error code + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval I2C Error Code + */ +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) +{ + return hi2c->ErrorCode; +} + +/** + * @} + */ + +/** + * @brief Handle TXE flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + uint32_t CurrentMode = hi2c->Mode; + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if((hi2c->XferSize == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX)) + { + /* Call TxCpltCallback() directly if no stop mode is set */ + if((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) + { + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + + HAL_I2C_MasterTxCpltCallback(hi2c); + } + else /* Generate Stop condition then Call TxCpltCallback() */ + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + HAL_I2C_MemTxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + HAL_I2C_MasterTxCpltCallback(hi2c); + } + } + } + else if((CurrentState == HAL_I2C_STATE_BUSY_TX) || \ + ((CurrentMode == HAL_I2C_MODE_MEM) && (CurrentState == HAL_I2C_STATE_BUSY_RX))) + { + if(hi2c->XferCount == 0U) + { + /* Disable BUF interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + } + else + { + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + if(hi2c->EventCount == 0) + { + /* If Memory address size is 8Bit */ + if(hi2c->MemaddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); + + hi2c->EventCount += 2; + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_MSB(hi2c->Memaddress); + + hi2c->EventCount++; + } + } + else if(hi2c->EventCount == 1) + { + /* Send LSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); + + hi2c->EventCount++; + } + else if(hi2c->EventCount == 2) + { + if(hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + /* Generate Restart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + else if(hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + } + } + } + else + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + } + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Master transmitter + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if(hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + if(hi2c->XferCount != 0U) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + } + else + { + /* Call TxCpltCallback() directly if no stop mode is set */ + if((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) + { + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + + HAL_I2C_MasterTxCpltCallback(hi2c); + } + else /* Generate Stop condition then Call TxCpltCallback() */ + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_MemTxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_MasterTxCpltCallback(hi2c); + } + } + } + } + return HAL_OK; +} + +/** + * @brief Handle RXNE flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c) +{ + if(hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + uint32_t tmp = 0U; + + tmp = hi2c->XferCount; + if(tmp > 3U) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + + if(hi2c->XferCount == 3) + { + /* Disable BUF interrupt, this help to treat correctly the last 4 bytes + on BTF subroutine */ + /* Disable BUF interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + } + } + else if((tmp == 1U) || (tmp == 0U)) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + HAL_I2C_MemRxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + HAL_I2C_MasterRxCpltCallback(hi2c); + } + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Master receiver + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if(hi2c->XferCount == 4U) + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + } + else if(hi2c->XferCount == 3U) + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + } + else if(hi2c->XferCount == 2U) + { + /* Prepare next transfer or stop current transfer */ + if((CurrentXferOptions == I2C_NEXT_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME)) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Generate ReStart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + else + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + + /* Disable EVT and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_MemRxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_MasterRxCpltCallback(hi2c); + } + } + else + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + } + return HAL_OK; +} + +/** + * @brief Handle SB flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_SB(I2C_HandleTypeDef *hi2c) +{ + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + if(hi2c->EventCount == 0U) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); + } + else + { + hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); + } + } + else + { + if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave 7 Bits address */ + if(hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); + } + else + { + hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); + } + } + else + { + if(hi2c->EventCount == 0U) + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(hi2c->Devaddress); + } + else if(hi2c->EventCount == 1U) + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_READ(hi2c->Devaddress); + } + } + } + + return HAL_OK; +} + +/** + * @brief Handle ADD10 flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_ADD10(I2C_HandleTypeDef *hi2c) +{ + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(hi2c->Devaddress); + + return HAL_OK; +} + +/** + * @brief Handle ADDR flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_ADDR(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentMode = hi2c->Mode; + uint32_t CurrentXferOptions = hi2c->XferOptions; + uint32_t Prev_State = hi2c->PreviousState; + + if(hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + if((hi2c->EventCount == 0U) && (CurrentMode == HAL_I2C_MODE_MEM)) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else if((hi2c->EventCount == 0U) && (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Restart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + hi2c->EventCount++; + } + else + { + if(hi2c->XferCount == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + else if(hi2c->XferCount == 1U) + { + if(CurrentXferOptions == I2C_NO_OPTION_FRAME) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + } + /* Prepare next transfer or stop current transfer */ + else if((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) \ + && (Prev_State != I2C_STATE_MASTER_BUSY_RX)) + { + if(hi2c->XferOptions != I2C_NEXT_FRAME) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + } + else + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + } + } + else if(hi2c->XferCount == 2U) + { + if(hi2c->XferOptions != I2C_NEXT_FRAME) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Enable Pos */ + hi2c->Instance->CR1 |= I2C_CR1_POS; + } + else + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + } + + if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + /* Enable Last DMA bit */ + hi2c->Instance->CR2 |= I2C_CR2_LAST; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + /* Enable Last DMA bit */ + hi2c->Instance->CR2 |= I2C_CR2_LAST; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + /* Reset Event counter */ + hi2c->EventCount = 0U; + } + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + return HAL_OK; +} + +/** + * @brief Handle TXE flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + + if(hi2c->XferCount != 0U) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + + if((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN)) + { + /* Last Byte is received, disable Interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the Tx complete callback to inform upper layer of the end of receive process */ + HAL_I2C_SlaveTxCpltCallback(hi2c); + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Slave transmitter + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_SlaveTransmit_BTF(I2C_HandleTypeDef *hi2c) +{ + if(hi2c->XferCount != 0U) + { + /* Write data to DR */ + hi2c->Instance->DR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + } + return HAL_OK; +} + +/** + * @brief Handle RXNE flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + + if(hi2c->XferCount != 0U) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + + if((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + /* Last Byte is received, disable Interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the Rx complete callback to inform upper layer of the end of receive process */ + HAL_I2C_SlaveRxCpltCallback(hi2c); + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Slave receiver + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_SlaveReceive_BTF(I2C_HandleTypeDef *hi2c) +{ + if(hi2c->XferCount != 0U) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + } + return HAL_OK; +} + +/** + * @brief Handle ADD flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_ADDR(I2C_HandleTypeDef *hi2c) +{ + uint8_t TransferDirection = I2C_DIRECTION_RECEIVE; + uint16_t SlaveAddrCode = 0U; + + /* Transfer Direction requested by Master */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TRA) == RESET) + { + TransferDirection = I2C_DIRECTION_TRANSMIT; + } + + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_DUALF) == RESET) + { + SlaveAddrCode = hi2c->Init.OwnAddress1; + } + else + { + SlaveAddrCode = hi2c->Init.OwnAddress2; + } + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, TransferDirection, SlaveAddrCode); + + return HAL_OK; +} + +/** + * @brief Handle STOPF flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Clear STOPF flag */ + __HAL_I2C_CLEAR_STOPFLAG(hi2c); + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* If a DMA is ongoing, Update handle size context */ + if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + if((hi2c->State == HAL_I2C_STATE_BUSY_RX) || (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + hi2c->XferCount = __HAL_DMA_GET_COUNTER(hi2c->hdmarx); + } + else + { + hi2c->XferCount = __HAL_DMA_GET_COUNTER(hi2c->hdmatx); + } + } + + /* All data are not transferred, so set error code accordingly */ + if(hi2c->XferCount != 0U) + { + /* Store Last receive data if any */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + } + + /* Store Last receive data if any */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + hi2c->XferCount--; + } + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + //hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c); + } + else + { + if((CurrentState == HAL_I2C_STATE_LISTEN ) || (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN) || \ + (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN)) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); + } + else + { + if((hi2c->PreviousState == I2C_STATE_SLAVE_BUSY_RX) || (CurrentState == HAL_I2C_STATE_BUSY_RX)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_SlaveRxCpltCallback(hi2c); + } + } + } + return HAL_OK; +} + +/** + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_AF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if(((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME)) && \ + (CurrentState == HAL_I2C_STATE_LISTEN)) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); + } + else if(CurrentState == HAL_I2C_STATE_BUSY_TX) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + HAL_I2C_SlaveTxCpltCallback(hi2c); + } + else + { + /* Clear AF flag only */ + /* State Listen, but XferOptions == FIRST or NEXT */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } + + return HAL_OK; +} + +/** + * @brief I2C interrupts error process + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ITError(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + + if((CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN) || (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + /* keep HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_LISTEN; + } + else + { + /* If state is an abort treatment on going, don't change state */ + /* This change will be do later */ + if((hi2c->State != HAL_I2C_STATE_ABORT) && ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) != I2C_CR2_DMAEN)) + { + hi2c->State = HAL_I2C_STATE_READY; + } + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + } + + /* Disable Pos bit in I2C CR1 when error occurred in Master/Mem Receive IT Process */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + + /* Abort DMA transfer */ + if((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; + + if(hi2c->hdmatx->State != HAL_DMA_STATE_READY) + { + /* Set the DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + if(HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + else + { + /* Set the DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + if(HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Store Last receive data if any */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + } + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + } + else if(hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Store Last receive data if any */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + } + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_AbortCpltCallback(hi2c); + } + else + { + /* Store Last receive data if any */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->DR; + } + + /* Call user error callback */ + HAL_I2C_ErrorCallback(hi2c); + } + /* STOP Flag is not set after a NACK reception */ + /* So may inform upper layer that listen phase is stopped */ + /* during NACK error treatment */ + if((hi2c->State == HAL_I2C_STATE_LISTEN) && ((hi2c->ErrorCode & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF)) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); + } +} + +/** + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Generate Start condition if first transfer */ + if((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + else if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) + { + /* Generate ReStart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + } + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start condition if first transfer */ + if((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + else if(hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + /* Generate ReStart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + } + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if(hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Restart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_READ(DevAddress); + } + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for write request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* If Memory address size is 8Bit */ + if(MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send LSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + /* Enable Acknowledge */ + hi2c->Instance->CR1 |= I2C_CR1_ACK; + + /* Generate Start */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* If Memory address size is 8Bit */ + if(MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send LSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TXE flag is set */ + if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Generate Restart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + /* Wait until SB flag is set */ + if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); + + /* Wait until ADDR flag is set */ + if(I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @brief DMA I2C process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; + + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hi2c->State; + uint32_t CurrentMode = hi2c->Mode; + + if((CurrentState == HAL_I2C_STATE_BUSY_TX) || ((CurrentState == HAL_I2C_STATE_BUSY_RX) && (CurrentMode == HAL_I2C_MODE_SLAVE))) + { + /* Disable DMA Request */ + hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; + + hi2c->XferCount = 0U; + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + } + else + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Disable Last DMA */ + hi2c->Instance->CR2 &= ~I2C_CR2_LAST; + + /* Disable DMA Request */ + hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; + + hi2c->XferCount = 0U; + + /* Check if Errors has been detected during transfer */ + if(hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + HAL_I2C_ErrorCallback(hi2c); + } + else + { + hi2c->State = HAL_I2C_STATE_READY; + + if(hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_MemRxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + HAL_I2C_MasterRxCpltCallback(hi2c); + } + } + } +} + +/** + * @brief DMA I2C communication error callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAError(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; + + /* Ignore DMA FIFO error */ + if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + hi2c->XferCount = 0U; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + HAL_I2C_ErrorCallback(hi2c); + } +} + +/** + * @brief DMA I2C communication abort callback + * (To be called at end of DMA Abort procedure). + * @param hdma DMA handle. + * @retval None + */ +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef* hi2c = ( I2C_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + hi2c->XferCount = 0U; + + /* Reset XferAbortCallback */ + hi2c->hdmatx->XferAbortCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Check if come from abort from user */ + if(hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_AbortCpltCallback(hi2c); + } + else + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_ErrorCallback(hi2c); + } +} + +/** + * @brief This function handles I2C Communication Timeout. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param Flag specifies the I2C flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + /* Wait until flag is set */ + while((__HAL_I2C_GET_FLAG(hi2c, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + } + + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for Master addressing phase. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param Flag specifies the I2C flag to check. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) +{ + while(__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) + { + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Generate Stop */ + hi2c->Instance->CR1 |= I2C_CR1_STOP; + + /* Clear AF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->ErrorCode = HAL_I2C_ERROR_AF; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of TXE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + { + /* Check if a NACK is detected */ + if(I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of BTF flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) + { + /* Check if a NACK is detected */ + if(I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of STOP flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) + { + /* Check if a NACK is detected */ + if(I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + + while(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + { + /* Check if a STOPF is detected */ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + { + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief This function handles Acknowledge failed detection during an I2C Communication. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) +{ + if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Clear NACKF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->ErrorCode = HAL_I2C_ERROR_AF; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State= HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + return HAL_OK; +} +/** + * @} + */ + +#endif /* HAL_I2C_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c new file mode 100644 index 00000000..de8f1602 --- /dev/null +++ b/Firmware/Board/v3/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c @@ -0,0 +1,204 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c_ex.c + * @author MCD Application Team + * @brief I2C Extension HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of I2C extension peripheral: + * + Extension features functions + * + @verbatim + ============================================================================== + ##### I2C peripheral extension features ##### + ============================================================================== + + [..] Comparing to other previous devices, the I2C interface for STM32F427xx/437xx/ + 429xx/439xx devices contains the following additional features : + + (+) Possibility to disable or enable Analog Noise Filter + (+) Use of a configured Digital Noise Filter + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to configure Noise Filter + (#) Configure I2C Analog noise filter using the function HAL_I2C_AnalogFilter_Config() + (#) Configure I2C Digital noise filter using the function HAL_I2C_DigitalFilter_Config() + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2CEx I2CEx + * @brief I2C HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) ||\ + defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup I2CEx_Exported_Functions I2C Exported Functions + * @{ + */ + + +/** @defgroup I2CEx_Exported_Functions_Group1 Extension features functions + * @brief Extension features functions + * +@verbatim + =============================================================================== + ##### Extension features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Noise Filters + +@endverbatim + * @{ + */ + +/** + * @brief Configures I2C Analog noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param AnalogFilter new state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Reset I2Cx ANOFF bit */ + hi2c->Instance->FLTR &= ~(I2C_FLTR_ANOFF); + + /* Disable the analog filter */ + hi2c->Instance->FLTR |= AnalogFilter; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures I2C Digital noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); + + if(hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get the old register value */ + tmpreg = hi2c->Instance->FLTR; + + /* Reset I2Cx DNF bit [3:0] */ + tmpreg &= ~(I2C_FLTR_DNF); + + /* Set I2Cx DNF coefficient */ + tmpreg |= DigitalFilter; + + /* Store the new register value */ + hi2c->Instance->FLTR = tmpreg; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @} + */ + +/** + * @} + */ +#endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F401xC ||\ + STM32F401xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx ||\ + STM32F423xx */ + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h b/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h index e518489f..ed26bf39 100644 --- a/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h +++ b/Firmware/Board/v3/Inc/stm32f4xx_hal_conf.h @@ -65,7 +65,7 @@ /* #define HAL_SRAM_MODULE_ENABLED */ /* #define HAL_SDRAM_MODULE_ENABLED */ /* #define HAL_HASH_MODULE_ENABLED */ -/* #define HAL_I2C_MODULE_ENABLED */ +#define HAL_I2C_MODULE_ENABLED /* #define HAL_I2S_MODULE_ENABLED */ /* #define HAL_IWDG_MODULE_ENABLED */ /* #define HAL_LTDC_MODULE_ENABLED */ diff --git a/Firmware/Board/v3/Src/main.c b/Firmware/Board/v3/Src/main.c index e390af58..154c98af 100644 --- a/Firmware/Board/v3/Src/main.c +++ b/Firmware/Board/v3/Src/main.c @@ -180,7 +180,7 @@ int main(void) MX_DMA_Init(); MX_ADC1_Init(); MX_ADC2_Init(); - MX_CAN1_Init(); + // MX_CAN1_Init(); // CAN or I2C called in main.cpp instead MX_TIM1_Init(); MX_TIM8_Init(); MX_TIM3_Init(); From eea82a2e6ac41082065e270cd6ee107a98734000 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 24 Oct 2018 00:08:08 -0700 Subject: [PATCH 10/14] Cube: Notify OS that we are a composite device --- Firmware/Board/v3/Src/usbd_desc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Firmware/Board/v3/Src/usbd_desc.c b/Firmware/Board/v3/Src/usbd_desc.c index b0906144..d213f64a 100644 --- a/Firmware/Board/v3/Src/usbd_desc.c +++ b/Firmware/Board/v3/Src/usbd_desc.c @@ -97,7 +97,8 @@ #define USBD_PID_FS 0x0D32 #define USBD_PRODUCT_XSTR(s) USBD_PRODUCT_STR(s) #define USBD_PRODUCT_STR(s) #s -#define USBD_PRODUCT_STRING_FS ODrive version HW_VERSION_MAJOR.HW_VERSION_MINOR +#define USBD_PRODUCT_STRING_FS ODrive HW_VERSION_MAJOR.HW_VERSION_MINOR CDC Interface +#define NATIVE_STRING ODrive HW_VERSION_MAJOR.HW_VERSION_MINOR Native Interface #define USBD_SERIALNUMBER_STRING_FS "000000000001" #define USBD_CONFIGURATION_STRING_FS "CDC Config" #define USBD_INTERFACE_STRING_FS "CDC Interface" @@ -233,16 +234,17 @@ __ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = 0x00, /*bcdUSB */ #endif /* (USBD_LPM_ENABLED == 1) */ 0x02, - 0x02, /*bDeviceClass*/ + // Notify OS that this is a composite device + 0xEF, /*bDeviceClass*/ 0x02, /*bDeviceSubClass*/ - 0x00, /*bDeviceProtocol*/ + 0x01, /*bDeviceProtocol*/ USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ LOBYTE(USBD_VID), /*idVendor*/ HIBYTE(USBD_VID), /*idVendor*/ LOBYTE(USBD_PID_FS), /*idProduct*/ HIBYTE(USBD_PID_FS), /*idProduct*/ 0x00, /*bcdDevice rel. 2.00*/ - 0x02, + 0x03, /* bNumInterfaces */ USBD_IDX_MFC_STR, /*Index of manufacturer string*/ USBD_IDX_PRODUCT_STR, /*Index of product string*/ USBD_IDX_SERIAL_STR, /*Index of serial number string*/ From 492816961ae714786fd4b54146d5463e66f0f9d9 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 24 Oct 2018 00:51:04 -0700 Subject: [PATCH 11/14] cube: apply canges to USB --- Firmware/Board/v3/Inc/usbd_cdc_if.h | 2 +- Firmware/Board/v3/Inc/usbd_conf.h | 1 + Firmware/Board/v3/Inc/usbd_desc.h | 3 +- .../Class/CDC/Inc/usbd_cdc.h | 39 +- .../Class/CDC/Src/usbd_cdc.c | 562 +++++++++++------- .../Core/Inc/usbd_def.h | 4 +- Firmware/Board/v3/Src/usbd_cdc_if.c | 12 +- Firmware/Board/v3/Src/usbd_conf.c | 24 +- 8 files changed, 404 insertions(+), 243 deletions(-) diff --git a/Firmware/Board/v3/Inc/usbd_cdc_if.h b/Firmware/Board/v3/Inc/usbd_cdc_if.h index c15e8b91..ed1d6705 100644 --- a/Firmware/Board/v3/Inc/usbd_cdc_if.h +++ b/Firmware/Board/v3/Inc/usbd_cdc_if.h @@ -132,7 +132,7 @@ extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; * @{ */ -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len, uint8_t endpoint_pair); /* USER CODE BEGIN EXPORTED_FUNCTIONS */ /* USER CODE END EXPORTED_FUNCTIONS */ diff --git a/Firmware/Board/v3/Inc/usbd_conf.h b/Firmware/Board/v3/Inc/usbd_conf.h index bf276186..a897ba43 100644 --- a/Firmware/Board/v3/Inc/usbd_conf.h +++ b/Firmware/Board/v3/Inc/usbd_conf.h @@ -89,6 +89,7 @@ * @brief Defines for configuration of the Usb device. * @{ */ + #define MS_VendorCode 'P' /*---------- -----------*/ #define USBD_MAX_NUM_INTERFACES 1 diff --git a/Firmware/Board/v3/Inc/usbd_desc.h b/Firmware/Board/v3/Inc/usbd_desc.h index 18d1f34e..2a74de31 100644 --- a/Firmware/Board/v3/Inc/usbd_desc.h +++ b/Firmware/Board/v3/Inc/usbd_desc.h @@ -2,7 +2,7 @@ ****************************************************************************** * @file : usbd_desc.h * @version : v1.0_Cube - * @brief : Header for usbd_conf.c file. + * @brief : Header for usbd_desc.c file. ****************************************************************************** * This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and @@ -46,6 +46,7 @@ * ****************************************************************************** */ + /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USBD_DESC__H__ #define __USBD_DESC__H__ diff --git a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h index d937b2e8..c029e22a 100644 --- a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h +++ b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h @@ -52,13 +52,15 @@ #define CDC_IN_EP 0x81 /* EP1 for data IN */ #define CDC_OUT_EP 0x01 /* EP1 for data OUT */ #define CDC_CMD_EP 0x82 /* EP2 for CDC commands */ +#define ODRIVE_IN_EP 0x83 /* EP3 IN: ODrive device TX endpoint */ +#define ODRIVE_OUT_EP 0x03 /* EP3 OUT: ODrive device RX endpoint */ /* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ -#define CDC_DATA_HS_MAX_PACKET_SIZE 512 /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */ #define CDC_DATA_FS_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */ #define CDC_CMD_PACKET_SIZE 8 /* Control Endpoint Packet size */ -#define USB_CDC_CONFIG_DESC_SIZ 67 +#define USB_CDC_CONFIG_DESC_SIZ (67 + 39) #define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE #define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE @@ -103,23 +105,29 @@ typedef struct _USBD_CDC_Itf int8_t (* Init) (void); int8_t (* DeInit) (void); int8_t (* Control) (uint8_t, uint8_t * , uint16_t); - int8_t (* Receive) (uint8_t *, uint32_t *); + int8_t (* Receive) (uint8_t *, uint32_t *, uint8_t); }USBD_CDC_ItfTypeDef; +typedef struct +{ + uint8_t* Buffer; + uint32_t Length; + volatile uint8_t State; +} +USBD_CDC_EP_HandleTypeDef; typedef struct { uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */ uint8_t CmdOpCode; - uint8_t CmdLength; - uint8_t *RxBuffer; - uint8_t *TxBuffer; - uint32_t RxLength; - uint32_t TxLength; - - __IO uint32_t TxState; - __IO uint32_t RxState; + uint8_t CmdLength; + + USBD_CDC_EP_HandleTypeDef CDC_Tx; + USBD_CDC_EP_HandleTypeDef CDC_Rx; + + USBD_CDC_EP_HandleTypeDef ODRIVE_Tx; + USBD_CDC_EP_HandleTypeDef ODRIVE_Rx; } USBD_CDC_HandleTypeDef; @@ -151,14 +159,15 @@ uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, - uint16_t length); + uint16_t length, + uint8_t endpoint_pair); uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, - uint8_t *pbuff); + uint8_t *pbuff, uint8_t endpoint_pair); -uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev); +uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev, uint8_t endpoint_pair); -uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev); +uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev, uint8_t endpoint_pair); /** * @} */ diff --git a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c index 24465641..73313522 100644 --- a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +++ b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c @@ -132,6 +132,9 @@ static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length); uint8_t *USBD_CDC_GetDeviceQualifierDescriptor (uint16_t *length); +static uint8_t USBD_WinUSBComm_SetupVendor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +//static uint8_t * USBD_GetUsrStrDescriptor(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length); + /* USB Standard Device Descriptor */ __ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = { @@ -173,24 +176,37 @@ USBD_ClassTypeDef USBD_CDC = USBD_CDC_GetFSCfgDesc, USBD_CDC_GetOtherSpeedCfgDesc, USBD_CDC_GetDeviceQualifierDescriptor, + USBD_UsrStrDescriptor }; /* USB CDC device Configuration Descriptor */ -__ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +__ALIGN_BEGIN uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = { /*Configuration Descriptor*/ 0x09, /* bLength: Configuration Descriptor size */ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ 0x00, - 0x02, /* bNumInterfaces: 2 interface */ + 0x03, /* bNumInterfaces: 3 interfaces (2 for CDC, 1 custom) */ 0x01, /* bConfigurationValue: Configuration value */ 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ 0xC0, /* bmAttributes: self powered */ 0x32, /* MaxPower 0 mA */ + + /////////////////////////////////////////////////////////////////////////////// + + /* Interface Association Descriptor: CDC device (virtual com port) */ + 0x08, /* bLength: IAD size */ + 0x0B, /* bDescriptorType: Interface Association Descriptor */ + 0x00, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass: Communication Interface Class */ + 0x02, /* bFunctionSubClass: Abstract Control Model */ + 0x01, /* bFunctionProtocol: Common AT commands */ + 0x00, /* iFunction */ /*---------------------------------------------------------------------------*/ - + /*Interface Descriptor */ 0x09, /* bLength: Interface Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ @@ -202,7 +218,7 @@ __ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = 0x02, /* bInterfaceSubClass: Abstract Control Model */ 0x01, /* bInterfaceProtocol: Common AT commands */ 0x00, /* iInterface: */ - + /*Header Functional Descriptor*/ 0x05, /* bLength: Endpoint Descriptor size */ 0x24, /* bDescriptorType: CS_INTERFACE */ @@ -229,7 +245,7 @@ __ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = 0x06, /* bDescriptorSubtype: Union func desc */ 0x00, /* bMasterInterface: Communication class interface */ 0x01, /* bSlaveInterface0: Data Class Interface */ - + /*Endpoint 2 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ @@ -267,196 +283,52 @@ __ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = 0x02, /* bmAttributes: Bulk */ LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), - 0x00 /* bInterval: ignore for Bulk transfer */ -} ; + 0x00, /* bInterval: ignore for Bulk transfer */ + /////////////////////////////////////////////////////////////////////////////// + + /* Interface Association Descriptor: custom device */ + 0x08, /* bLength: IAD size */ + 0x0B, /* bDescriptorType: Interface Association Descriptor */ + 0x02, /* bFirstInterface */ + 0x01, /* bInterfaceCount */ + 0x00, /* bFunctionClass: */ + 0x00, /* bFunctionSubClass: */ + 0x00, /* bFunctionProtocol: */ + 0x06, /* iFunction */ -/* USB CDC device Configuration Descriptor */ -__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = -{ - /*Configuration Descriptor*/ - 0x09, /* bLength: Configuration Descriptor size */ - USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ - 0x00, - 0x02, /* bNumInterfaces: 2 interface */ - 0x01, /* bConfigurationValue: Configuration value */ - 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ - 0xC0, /* bmAttributes: self powered */ - 0x32, /* MaxPower 0 mA */ - - /*---------------------------------------------------------------------------*/ - - /*Interface Descriptor */ - 0x09, /* bLength: Interface Descriptor size */ - USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ - /* Interface descriptor type */ - 0x00, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x01, /* bNumEndpoints: One endpoints used */ - 0x02, /* bInterfaceClass: Communication Interface Class */ - 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x01, /* bInterfaceProtocol: Common AT commands */ - 0x00, /* iInterface: */ - - /*Header Functional Descriptor*/ - 0x05, /* bLength: Endpoint Descriptor size */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x00, /* bDescriptorSubtype: Header Func Desc */ - 0x10, /* bcdCDC: spec release number */ - 0x01, - - /*Call Management Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x01, /* bDescriptorSubtype: Call Management Func Desc */ - 0x00, /* bmCapabilities: D0+D1 */ - 0x01, /* bDataInterface: 1 */ - - /*ACM Functional Descriptor*/ - 0x04, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ - 0x02, /* bmCapabilities */ - - /*Union Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x06, /* bDescriptorSubtype: Union func desc */ - 0x00, /* bMasterInterface: Communication class interface */ - 0x01, /* bSlaveInterface0: Data Class Interface */ - - /*Endpoint 2 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - CDC_CMD_EP, /* bEndpointAddress */ - 0x03, /* bmAttributes: Interrupt */ - LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ - HIBYTE(CDC_CMD_PACKET_SIZE), - 0x10, /* bInterval: */ /*---------------------------------------------------------------------------*/ /*Data class interface descriptor*/ 0x09, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ - 0x01, /* bInterfaceNumber: Number of Interface */ + 0x02, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02, /* bNumEndpoints: Two endpoints used */ - 0x0A, /* bInterfaceClass: CDC */ - 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceClass: vendor specific */ + 0x01, /* bInterfaceSubClass: ODrive Communication */ 0x00, /* bInterfaceProtocol: */ 0x00, /* iInterface: */ /*Endpoint OUT Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - CDC_OUT_EP, /* bEndpointAddress */ + ODRIVE_OUT_EP, /* bEndpointAddress */ 0x02, /* bmAttributes: Bulk */ - LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ - HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), 0x00, /* bInterval: ignore for Bulk transfer */ /*Endpoint IN Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - CDC_IN_EP, /* bEndpointAddress */ + ODRIVE_IN_EP, /* bEndpointAddress */ 0x02, /* bmAttributes: Bulk */ - LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ - HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), - 0x00 /* bInterval: ignore for Bulk transfer */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ } ; -__ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = -{ - 0x09, /* bLength: Configuation Descriptor size */ - USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION, - USB_CDC_CONFIG_DESC_SIZ, - 0x00, - 0x02, /* bNumInterfaces: 2 interfaces */ - 0x01, /* bConfigurationValue: */ - 0x04, /* iConfiguration: */ - 0xC0, /* bmAttributes: */ - 0x32, /* MaxPower 100 mA */ - - /*Interface Descriptor */ - 0x09, /* bLength: Interface Descriptor size */ - USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ - /* Interface descriptor type */ - 0x00, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x01, /* bNumEndpoints: One endpoints used */ - 0x02, /* bInterfaceClass: Communication Interface Class */ - 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x01, /* bInterfaceProtocol: Common AT commands */ - 0x00, /* iInterface: */ - - /*Header Functional Descriptor*/ - 0x05, /* bLength: Endpoint Descriptor size */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x00, /* bDescriptorSubtype: Header Func Desc */ - 0x10, /* bcdCDC: spec release number */ - 0x01, - - /*Call Management Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x01, /* bDescriptorSubtype: Call Management Func Desc */ - 0x00, /* bmCapabilities: D0+D1 */ - 0x01, /* bDataInterface: 1 */ - - /*ACM Functional Descriptor*/ - 0x04, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ - 0x02, /* bmCapabilities */ - - /*Union Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x06, /* bDescriptorSubtype: Union func desc */ - 0x00, /* bMasterInterface: Communication class interface */ - 0x01, /* bSlaveInterface0: Data Class Interface */ - - /*Endpoint 2 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_DESC_TYPE_ENDPOINT , /* bDescriptorType: Endpoint */ - CDC_CMD_EP, /* bEndpointAddress */ - 0x03, /* bmAttributes: Interrupt */ - LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ - HIBYTE(CDC_CMD_PACKET_SIZE), - 0xFF, /* bInterval: */ - - /*---------------------------------------------------------------------------*/ - - /*Data class interface descriptor*/ - 0x09, /* bLength: Endpoint Descriptor size */ - USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ - 0x01, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x02, /* bNumEndpoints: Two endpoints used */ - 0x0A, /* bInterfaceClass: CDC */ - 0x00, /* bInterfaceSubClass: */ - 0x00, /* bInterfaceProtocol: */ - 0x00, /* iInterface: */ - - /*Endpoint OUT Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - CDC_OUT_EP, /* bEndpointAddress */ - 0x02, /* bmAttributes: Bulk */ - 0x40, /* wMaxPacketSize: */ - 0x00, - 0x00, /* bInterval: ignore for Bulk transfer */ - - /*Endpoint IN Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - CDC_IN_EP, /* bEndpointAddress */ - 0x02, /* bmAttributes: Bulk */ - 0x40, /* wMaxPacketSize: */ - 0x00, - 0x00 /* bInterval */ -}; /** * @} @@ -508,6 +380,19 @@ static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, USBD_EP_TYPE_BULK, CDC_DATA_FS_OUT_PACKET_SIZE); } + + /* Open ODrive IN endpoint */ + USBD_LL_OpenEP(pdev, + ODRIVE_IN_EP, + USBD_EP_TYPE_BULK, + pdev->dev_speed == USBD_SPEED_HIGH ? CDC_DATA_HS_IN_PACKET_SIZE : CDC_DATA_FS_IN_PACKET_SIZE); + + /* Open ODrive OUT endpoint */ + USBD_LL_OpenEP(pdev, + ODRIVE_OUT_EP, + USBD_EP_TYPE_BULK, + pdev->dev_speed == USBD_SPEED_HIGH ? CDC_DATA_HS_OUT_PACKET_SIZE : CDC_DATA_FS_OUT_PACKET_SIZE); + /* Open Command IN EP */ USBD_LL_OpenEP(pdev, CDC_CMD_EP, @@ -529,15 +414,17 @@ static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init(); /* Init Xfer states */ - hcdc->TxState =0; - hcdc->RxState =0; + hcdc->CDC_Tx.State =0; + hcdc->CDC_Rx.State =0; + hcdc->ODRIVE_Tx.State =0; + hcdc->ODRIVE_Rx.State =0; if(pdev->dev_speed == USBD_SPEED_HIGH ) { /* Prepare Out endpoint to receive next packet */ USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, - hcdc->RxBuffer, + hcdc->CDC_Rx.Buffer, CDC_DATA_HS_OUT_PACKET_SIZE); } else @@ -545,11 +432,15 @@ static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, /* Prepare Out endpoint to receive next packet */ USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, - hcdc->RxBuffer, + hcdc->CDC_Rx.Buffer, CDC_DATA_FS_OUT_PACKET_SIZE); } - + /* Prepare ODrive Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + ODRIVE_OUT_EP, + hcdc->ODRIVE_Rx.Buffer, + CDC_DATA_FS_OUT_PACKET_SIZE); } return ret; } @@ -566,17 +457,25 @@ static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev, { uint8_t ret = 0; - /* Open EP IN */ + /* Close EP IN */ USBD_LL_CloseEP(pdev, CDC_IN_EP); - /* Open EP OUT */ + /* Close EP OUT */ USBD_LL_CloseEP(pdev, CDC_OUT_EP); - /* Open Command IN EP */ + /* Close Command IN EP */ USBD_LL_CloseEP(pdev, CDC_CMD_EP); + + /* Close EP IN */ + USBD_LL_CloseEP(pdev, + ODRIVE_IN_EP); + + /* Close EP OUT */ + USBD_LL_CloseEP(pdev, + ODRIVE_OUT_EP); /* DeInit physical Interface components */ @@ -648,6 +547,9 @@ static uint8_t USBD_CDC_Setup (USBD_HandleTypeDef *pdev, case USB_REQ_SET_INTERFACE : break; } + + case USB_REQ_TYPE_VENDOR: + return USBD_WinUSBComm_SetupVendor(pdev, req); default: break; @@ -668,8 +570,12 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) if(pdev->pClassData != NULL) { - - hcdc->TxState = 0; + // NOTE: We would logically expect xx_IN_EP here, but we actually get the xx_OUT_EP + if (epnum == CDC_OUT_EP) + hcdc->CDC_Tx.State = 0; + if (epnum == ODRIVE_OUT_EP) + hcdc->ODRIVE_Tx.State = 0; + //Note: We could use independent semaphores for simoultainous USB transmission. osSemaphoreRelease(sem_usb_tx); return USBD_OK; } @@ -689,15 +595,24 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) static uint8_t USBD_CDC_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + USBD_CDC_EP_HandleTypeDef* hEP_Rx; + if (epnum == CDC_OUT_EP) { + hEP_Rx = &hcdc->CDC_Rx; + } else if (epnum == ODRIVE_OUT_EP) { + hEP_Rx = &hcdc->ODRIVE_Rx; + } else { + return USBD_FAIL; + } /* Get the received data length */ - hcdc->RxLength = USBD_LL_GetRxDataSize (pdev, epnum); + hEP_Rx->Length = USBD_LL_GetRxDataSize (pdev, epnum); /* USB data will be immediately processed, this allow next USB traffic being NAKed till the end of the application Xfer */ if(pdev->pClassData != NULL) { - ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hEP_Rx->Buffer, &hEP_Rx->Length, epnum); return USBD_OK; } @@ -740,8 +655,8 @@ static uint8_t USBD_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev) */ static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length) { - *length = sizeof (USBD_CDC_CfgFSDesc); - return USBD_CDC_CfgFSDesc; + *length = sizeof (USBD_CDC_CfgDesc); + return USBD_CDC_CfgDesc; } /** @@ -753,8 +668,8 @@ static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length) */ static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length) { - *length = sizeof (USBD_CDC_CfgHSDesc); - return USBD_CDC_CfgHSDesc; + *length = sizeof (USBD_CDC_CfgDesc); + return USBD_CDC_CfgDesc; } /** @@ -766,8 +681,8 @@ static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length) */ static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length) { - *length = sizeof (USBD_CDC_OtherSpeedCfgDesc); - return USBD_CDC_OtherSpeedCfgDesc; + *length = sizeof (USBD_CDC_CfgDesc); + return USBD_CDC_CfgDesc; } /** @@ -810,12 +725,22 @@ uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, */ uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, - uint16_t length) + uint16_t length, + uint8_t endpoint_pair) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; - hcdc->TxBuffer = pbuff; - hcdc->TxLength = length; + USBD_CDC_EP_HandleTypeDef* hEP_Tx; + if (endpoint_pair == CDC_OUT_EP) { + hEP_Tx = &hcdc->CDC_Tx; + } else if (endpoint_pair == ODRIVE_OUT_EP) { + hEP_Tx = &hcdc->ODRIVE_Tx; + } else { + return USBD_FAIL; + } + + hEP_Tx->Buffer = pbuff; + hEP_Tx->Length = length; return USBD_OK; } @@ -828,11 +753,20 @@ uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, * @retval status */ uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, - uint8_t *pbuff) + uint8_t *pbuff, uint8_t endpoint_pair) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + USBD_CDC_EP_HandleTypeDef* hEP_Rx; + if (endpoint_pair == CDC_OUT_EP) { + hEP_Rx = &hcdc->CDC_Rx; + } else if (endpoint_pair == ODRIVE_OUT_EP) { + hEP_Rx = &hcdc->ODRIVE_Rx; + } else { + return USBD_FAIL; + } - hcdc->RxBuffer = pbuff; + hEP_Rx->Buffer = pbuff; return USBD_OK; } @@ -844,23 +778,36 @@ uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, * @param epnum: endpoint number * @retval status */ -uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t endpoint_pair) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; if(pdev->pClassData != NULL) { - if(hcdc->TxState == 0) + // Select Endpoint + USBD_CDC_EP_HandleTypeDef* hEP_Tx; + uint8_t in_ep; + if (endpoint_pair == CDC_OUT_EP) { + hEP_Tx = &hcdc->CDC_Tx; + in_ep = CDC_IN_EP; + } else if (endpoint_pair == ODRIVE_OUT_EP) { + hEP_Tx = &hcdc->ODRIVE_Tx; + in_ep = ODRIVE_IN_EP; + } else { + return USBD_FAIL; + } + + if(hEP_Tx->State == 0) { /* Tx Transfer in progress */ - hcdc->TxState = 1; + hEP_Tx->State = 1; /* Transmit next packet */ USBD_LL_Transmit(pdev, - CDC_IN_EP, - hcdc->TxBuffer, - hcdc->TxLength); - + in_ep, + hEP_Tx->Buffer, + hEP_Tx->Length); + return USBD_OK; } else @@ -881,29 +828,32 @@ uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) * @param pdev: device instance * @retval status */ -uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev, uint8_t endpoint_pair) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; /* Suspend or Resume USB Out process */ if(pdev->pClassData != NULL) { - if(pdev->dev_speed == USBD_SPEED_HIGH ) - { - /* Prepare Out endpoint to receive next packet */ - USBD_LL_PrepareReceive(pdev, - CDC_OUT_EP, - hcdc->RxBuffer, - CDC_DATA_HS_OUT_PACKET_SIZE); - } - else - { - /* Prepare Out endpoint to receive next packet */ - USBD_LL_PrepareReceive(pdev, - CDC_OUT_EP, - hcdc->RxBuffer, - CDC_DATA_FS_OUT_PACKET_SIZE); + // Select Endpoint + USBD_CDC_EP_HandleTypeDef* hEP_Rx; + uint8_t out_ep; + if (endpoint_pair == CDC_OUT_EP) { + hEP_Rx = &hcdc->CDC_Rx; + out_ep = CDC_OUT_EP; + } else if (endpoint_pair == ODRIVE_OUT_EP) { + hEP_Rx = &hcdc->ODRIVE_Rx; + out_ep = ODRIVE_OUT_EP; + } else { + return USBD_FAIL; } + + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + out_ep, + hEP_Rx->Buffer, + pdev->dev_speed == USBD_SPEED_HIGH ? CDC_DATA_HS_OUT_PACKET_SIZE : CDC_DATA_FS_OUT_PACKET_SIZE); + return USBD_OK; } else @@ -911,6 +861,184 @@ uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) return USBD_FAIL; } } + + +/* WinUSB support ------------------------------------------------------------*/ +/* +* This section tells Windows that it should automatically load the WinUSB driver +* for the device (more specifically, interface 2 because it's a composite device). +* This allows for driverless communication with the device. +*/ + +#define NUM_INTERFACES 1 + +#if NUM_INTERFACES == 2 +#define USB_WINUSBCOMM_COMPAT_ID_OS_DESC_SIZ (16 + 24 + 24) +#else +#define USB_WINUSBCOMM_COMPAT_ID_OS_DESC_SIZ (16 + 24) +#endif + + +// This associates winusb driver with the device +__ALIGN_BEGIN uint8_t USBD_WinUSBComm_Extended_Compat_ID_OS_Desc[USB_WINUSBCOMM_COMPAT_ID_OS_DESC_SIZ] __ALIGN_END = +{ + // +-- Offset in descriptor + // | +-- Size + // v v + USB_WINUSBCOMM_COMPAT_ID_OS_DESC_SIZ, 0, 0, 0, // 0 dwLength 4 DWORD The length, in bytes, of the complete extended compat ID descriptor + 0x00, 0x01, // 4 bcdVersion 2 BCD The descriptor’s version number, in binary coded decimal (BCD) format + 0x04, 0x00, // 6 wIndex 2 WORD An index that identifies the particular OS feature descriptor + NUM_INTERFACES, // 8 bCount 1 BYTE The number of custom property sections + 0, 0, 0, 0, 0, 0, 0, // 9 RESERVED 7 BYTEs Reserved + // ===================== + // 16 + + // +-- Offset from function section start + // | +-- Size + // v v + 2, // 0 bFirstInterfaceNumber 1 BYTE The interface or function number + 0, // 1 RESERVED 1 BYTE Reserved + 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // 2 compatibleID 8 BYTEs The function’s compatible ID ("WINUSB") + 0, 0, 0, 0, 0, 0, 0, 0, // 10 subCompatibleID 8 BYTEs The function’s subcompatible ID + 0, 0, 0, 0, 0, 0, // 18 RESERVED 6 BYTEs Reserved + // ================================= + // 24 +#if NUM_INTERFACES == 2 + // +-- Offset from function section start + // | +-- Size + // v v + 2, // 0 bFirstInterfaceNumber 1 BYTE The interface or function number + 0, // 1 RESERVED 1 BYTE Reserved + 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // 2 compatibleID 8 BYTEs The function’s compatible ID ("WINUSB") + 0, 0, 0, 0, 0, 0, 0, 0, // 10 subCompatibleID 8 BYTEs The function’s subcompatible ID + 0, 0, 0, 0, 0, 0, // 18 RESERVED 6 BYTEs Reserved + // ================================= + // 24 +#endif +}; + + +// Properties are added to: +// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_xxxx&PID_xxxx\sssssssss\Device Parameters +// Use USBDeview or similar to uninstall + +__ALIGN_BEGIN uint8_t USBD_WinUSBComm_Extended_Properties_OS_Desc[0xB6] __ALIGN_END = +{ + 0xB6, 0x00, 0x00, 0x00, // 0 dwLength 4 DWORD The length, in bytes, of the complete extended properties descriptor + 0x00, 0x01, // 4 bcdVersion 2 BCD The descriptor’s version number, in binary coded decimal (BCD) format + 0x05, 0x00, // 6 wIndex 2 WORD The index for extended properties OS descriptors + 0x02, 0x00, // 8 wCount 2 WORD The number of custom property sections that follow the header section + // ==================== + // 10 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + 0x84, 0x00, 0x00, 0x00, // 0 dwSize 4 DWORD The size of this custom properties section + 0x01, 0x00, 0x00, 0x00, // 4 dwPropertyDataType 4 DWORD Property data format + 0x28, 0x00, // 8 wPropertyNameLength 2 DWORD Property name length + // ======================================== + // 10 + // 10 bPropertyName PNL WCHAR[] The property name + 'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, + 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, + 'U',0, 'I',0, 'D',0, 0,0, + // ======================================== + // 40 (0x28) + + 0x4E, 0x00, 0x00, 0x00, // 10 + PNL dwPropertyDataLength 4 DWORD Length of the buffer holding the property data + // ======================================== + // 4 + // 14 + PNL bPropertyData PDL Format-dependent Property data + '{',0, 'E',0, 'A',0, '0',0, 'B',0, 'D',0, '5',0, 'C',0, + '3',0, '-',0, '5',0, '0',0, 'F',0, '3',0, '-',0, '4',0, + '8',0, '8',0, '8',0, '-',0, '8',0, '4',0, 'B',0, '4',0, + '-',0, '7',0, '4',0, 'E',0, '5',0, '0',0, 'E',0, '1',0, + '6',0, '4',0, '9',0, 'D',0, 'B',0, '}',0, 0 ,0, + // ======================================== + // 78 (0x4E) +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + 0x3E, 0x00, 0x00, 0x00, // 0 dwSize 0x00000030 (62 bytes) + 0x01, 0x00, 0x00, 0x00, // 4 dwPropertyDataType 0x00000001 (Unicode string) + 0x0C, 0x00, // 8 wPropertyNameLength 0x000C (12 bytes) + // ======================================== + // 10 + 'L',0, 'a',0, 'b',0, 'e',0, 'l',0, 0,0, + // 10 bPropertyName “Label” + // ======================================== + // 12 + 0x24, 0x00, 0x00, 0x00, // 22 dwPropertyDataLength 0x00000016 (36 bytes) + // ======================================== + // 4 + 'O',0, 'D',0, 'r',0, 'i',0, 'v',0, 'e',0, 0,0 + // 26 bPropertyData “ODrive” + // ======================================== + // 14 + +}; + + + +static uint8_t USBD_WinUSBComm_GetMSExtendedCompatIDOSDescriptor (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + switch (req->wIndex) + { + case 0x04: + USBD_CtlSendData (pdev, USBD_WinUSBComm_Extended_Compat_ID_OS_Desc, req->wLength); + break; + default: + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + return USBD_OK; +} +static uint8_t USBD_WinUSBComm_GetMSExtendedPropertiesOSDescriptor (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + uint8_t byInterfaceIndex = (uint8_t)req->wValue; + if ( req->wIndex != 0x05 ) + { + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + switch ( byInterfaceIndex ) + { + case 0: +#if NUM_INTERFACES == 2 + case 1: +#endif + USBD_CtlSendData (pdev, USBD_WinUSBComm_Extended_Properties_OS_Desc, req->wLength); + break; + default: + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + return USBD_OK; +} +static uint8_t USBD_WinUSBComm_SetupVendorDevice(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_CtlError(pdev , req); + return USBD_FAIL; +} +static uint8_t USBD_WinUSBComm_SetupVendorInterface(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_CtlError(pdev , req); + // TODO: check if this is important + return USBD_FAIL; +} +static uint8_t USBD_WinUSBComm_SetupVendor(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + switch ( req->bmRequest & USB_REQ_RECIPIENT_MASK ) + { + case USB_REQ_RECIPIENT_DEVICE: + return ( MS_VendorCode == req->bRequest ) ? USBD_WinUSBComm_GetMSExtendedCompatIDOSDescriptor(pdev, req) : USBD_WinUSBComm_SetupVendorDevice(pdev, req); + case USB_REQ_RECIPIENT_INTERFACE: + return ( MS_VendorCode == req->bRequest ) ? USBD_WinUSBComm_GetMSExtendedPropertiesOSDescriptor(pdev, req) : USBD_WinUSBComm_SetupVendorInterface(pdev, req); + case USB_REQ_RECIPIENT_ENDPOINT: + // fall through + default: + break; + } + USBD_CtlError(pdev , req); + return USBD_FAIL; +} + /** * @} */ diff --git a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h index 8fbe81e4..f259b51d 100644 --- a/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h +++ b/Firmware/Board/v3/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h @@ -68,7 +68,9 @@ #define USBD_IDX_PRODUCT_STR 0x02 #define USBD_IDX_SERIAL_STR 0x03 #define USBD_IDX_CONFIG_STR 0x04 -#define USBD_IDX_INTERFACE_STR 0x05 +#define USBD_IDX_INTERFACE_STR 0x05 +#define USBD_IDX_ODRIVE_INTF_STR 0x06 +#define USBD_IDX_MICROSOFT_DESC_STR 0xEE #define USB_REQ_TYPE_STANDARD 0x00 #define USB_REQ_TYPE_CLASS 0x20 diff --git a/Firmware/Board/v3/Src/usbd_cdc_if.c b/Firmware/Board/v3/Src/usbd_cdc_if.c index fcc712a3..b8cb6e6c 100644 --- a/Firmware/Board/v3/Src/usbd_cdc_if.c +++ b/Firmware/Board/v3/Src/usbd_cdc_if.c @@ -117,10 +117,12 @@ /* Create buffer for reception and transmission */ /* It's up to user to redefine and/or remove those define */ /** Received data over USB are stored in this buffer */ -uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; +uint8_t CDCRxBufferFS[APP_RX_DATA_SIZE]; +uint8_t ODRIVERxBufferFS[APP_RX_DATA_SIZE]; /** Data to send over USB CDC are stored in this buffer */ -uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; +uint8_t CDCTxBufferFS[APP_TX_DATA_SIZE]; +uint8_t ODRIVETxBufferFS[APP_TX_DATA_SIZE]; /* USER CODE BEGIN PRIVATE_VARIABLES */ /* USER CODE END PRIVATE_VARIABLES */ @@ -151,7 +153,7 @@ extern USBD_HandleTypeDef hUsbDeviceFS; static int8_t CDC_Init_FS(void); static int8_t CDC_DeInit_FS(void); static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); -static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); +static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len, uint8_t endpoint_pair); /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ @@ -289,7 +291,7 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) * @param Len: Number of data received (in bytes) * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL */ -static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) +static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len, uint8_t endpoint_pair) { /* USER CODE BEGIN 6 */ usb_rx_process_packet(Buf, *Len, endpoint_pair); @@ -309,7 +311,7 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) * @param Len: Number of data to be sent (in bytes) * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY */ -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len, uint8_t endpoint_pair) { uint8_t result = USBD_OK; /* USER CODE BEGIN 7 */ diff --git a/Firmware/Board/v3/Src/usbd_conf.c b/Firmware/Board/v3/Src/usbd_conf.c index 7046dc96..2d66d4a1 100644 --- a/Firmware/Board/v3/Src/usbd_conf.c +++ b/Firmware/Board/v3/Src/usbd_conf.c @@ -66,7 +66,7 @@ /* USER CODE END PV */ - PCD_HandleTypeDef hpcd_USB_OTG_FS; +PCD_HandleTypeDef hpcd_USB_OTG_FS; void _Error_Handler(char * file, int line); /* External functions --------------------------------------------------------*/ @@ -154,6 +154,23 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) */ void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { + USBD_StatusTypeDef ret = USBD_OK; + USBD_HandleTypeDef *pdev = hpcd->pData; + USBD_SetupReqTypedef *req = &pdev->request; + USBD_ParseSetupRequest(req, (uint8_t *)hpcd->Setup); + if ( ( USB_REQ_TYPE_VENDOR == (req->bmRequest & USB_REQ_TYPE_MASK) ) && ( MS_VendorCode == req->bRequest ) ) + { + pdev->ep0_state = USBD_EP0_SETUP; + pdev->ep0_data_len = pdev->request.wLength; + + ret = pdev->pClass->Setup(pdev, req); + + if( (req->wLength == 0) && (ret == USBD_OK) ) + { + USBD_CtlSendStatus(pdev); + } + return; + } USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); } @@ -312,7 +329,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) pdev->pData = &hpcd_USB_OTG_FS; hpcd_USB_OTG_FS.Instance = USB_OTG_FS; - hpcd_USB_OTG_FS.Init.dev_endpoints = 4; + hpcd_USB_OTG_FS.Init.dev_endpoints = 6; hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL; hpcd_USB_OTG_FS.Init.dma_enable = DISABLE; hpcd_USB_OTG_FS.Init.ep0_mps = DEP0CTL_MPS_64; @@ -329,7 +346,8 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80); HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); - HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x40); // CDC IN endpoint + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x40); // ODrive IN endpoint } return USBD_OK; } From 5a4e1a4d598609ee7c39325e7f7dc7b7c229c101 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 24 Oct 2018 00:52:53 -0700 Subject: [PATCH 12/14] cube: can auto wake up --- Firmware/Board/v3/Src/can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Board/v3/Src/can.c b/Firmware/Board/v3/Src/can.c index 2171691a..fc7bf388 100644 --- a/Firmware/Board/v3/Src/can.c +++ b/Firmware/Board/v3/Src/can.c @@ -70,7 +70,7 @@ void MX_CAN1_Init(void) hcan1.Init.TimeSeg2 = CAN_BS2_5TQ; hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.AutoBusOff = DISABLE; - hcan1.Init.AutoWakeUp = DISABLE; + hcan1.Init.AutoWakeUp = ENABLE; hcan1.Init.AutoRetransmission = DISABLE; hcan1.Init.ReceiveFifoLocked = DISABLE; hcan1.Init.TransmitFifoPriority = DISABLE; From 5e5516b665c0d27e1271d5f1a29d0cfaf6054f99 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 24 Oct 2018 01:25:50 -0700 Subject: [PATCH 13/14] move configAPPLICATION_ALLOCATED_HEAP to FreeRTOSconfig.h --- Firmware/Board/v3/Inc/FreeRTOSConfig.h | 1 + Firmware/Board/v3/Inc/main.h | 1 - Firmware/Board/v3/Inc/prev_board_ver/main_V3_2.h | 1 - Firmware/Board/v3/Inc/prev_board_ver/main_V3_4.h | 1 - Firmware/Board/v3/Odrive.ioc | 2 +- 5 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Firmware/Board/v3/Inc/FreeRTOSConfig.h b/Firmware/Board/v3/Inc/FreeRTOSConfig.h index 90e233b3..715b0e67 100644 --- a/Firmware/Board/v3/Inc/FreeRTOSConfig.h +++ b/Firmware/Board/v3/Inc/FreeRTOSConfig.h @@ -167,6 +167,7 @@ standard names. */ /* USER CODE BEGIN Defines */ /* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ +#define configAPPLICATION_ALLOCATED_HEAP 1 // ucHeap allocated in freertos.c /* USER CODE END Defines */ #endif /* FREERTOS_CONFIG_H */ diff --git a/Firmware/Board/v3/Inc/main.h b/Firmware/Board/v3/Inc/main.h index 1e76830d..d41b19ee 100644 --- a/Firmware/Board/v3/Inc/main.h +++ b/Firmware/Board/v3/Inc/main.h @@ -72,7 +72,6 @@ #define TIM_APB1_CLOCK_HZ 84000000 #define TIM_APB1_PERIOD_CLOCKS 4096 #define TIM_APB1_DEADTIME_CLOCKS 40 -#define configAPPLICATION_ALLOCATED_HEAP 1 #define TIM_1_8_RCR 2 #define M0_nCS_Pin GPIO_PIN_13 diff --git a/Firmware/Board/v3/Inc/prev_board_ver/main_V3_2.h b/Firmware/Board/v3/Inc/prev_board_ver/main_V3_2.h index 567fe028..65f45efd 100644 --- a/Firmware/Board/v3/Inc/prev_board_ver/main_V3_2.h +++ b/Firmware/Board/v3/Inc/prev_board_ver/main_V3_2.h @@ -6,7 +6,6 @@ #define TIM_APB1_CLOCK_HZ 84000000 #define TIM_APB1_PERIOD_CLOCKS 4096 #define TIM_APB1_DEADTIME_CLOCKS 40 -#define configAPPLICATION_ALLOCATED_HEAP 1 #define TIM_1_8_RCR 2 #define M0_nCS_Pin GPIO_PIN_13 diff --git a/Firmware/Board/v3/Inc/prev_board_ver/main_V3_4.h b/Firmware/Board/v3/Inc/prev_board_ver/main_V3_4.h index 5695d700..64daaa4f 100644 --- a/Firmware/Board/v3/Inc/prev_board_ver/main_V3_4.h +++ b/Firmware/Board/v3/Inc/prev_board_ver/main_V3_4.h @@ -6,7 +6,6 @@ #define TIM_APB1_CLOCK_HZ 84000000 #define TIM_APB1_PERIOD_CLOCKS 4096 #define TIM_APB1_DEADTIME_CLOCKS 40 -#define configAPPLICATION_ALLOCATED_HEAP 1 #define TIM_1_8_RCR 2 #define M0_nCS_Pin GPIO_PIN_13 diff --git a/Firmware/Board/v3/Odrive.ioc b/Firmware/Board/v3/Odrive.ioc index ab299065..7a334af7 100644 --- a/Firmware/Board/v3/Odrive.ioc +++ b/Firmware/Board/v3/Odrive.ioc @@ -233,7 +233,7 @@ Mcu.Pin8=PC3 Mcu.Pin9=PA0-WKUP Mcu.PinsNb=57 Mcu.ThirdPartyNb=0 -Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,3500;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,40;configAPPLICATION_ALLOCATED_HEAP,1;TIM_1_8_RCR,2 +Mcu.UserConstants=TIM_1_8_CLOCK_HZ,168000000;TIM_1_8_PERIOD_CLOCKS,3500;TIM_1_8_DEADTIME_CLOCKS,20;TIM_APB1_CLOCK_HZ,84000000;TIM_APB1_PERIOD_CLOCKS,4096;TIM_APB1_DEADTIME_CLOCKS,40;TIM_1_8_RCR,2 Mcu.UserName=STM32F405RGTx MxCube.Version=4.27.0 MxDb.Version=DB.4.0.270 From 5559de4eca4c572380fd5c72ec094e6732c106d5 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 24 Oct 2018 01:32:54 -0700 Subject: [PATCH 14/14] cube: support user string --- Firmware/Board/v3/Inc/usbd_conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Board/v3/Inc/usbd_conf.h b/Firmware/Board/v3/Inc/usbd_conf.h index a897ba43..dbf800b3 100644 --- a/Firmware/Board/v3/Inc/usbd_conf.h +++ b/Firmware/Board/v3/Inc/usbd_conf.h @@ -98,7 +98,7 @@ /*---------- -----------*/ #define USBD_MAX_STR_DESC_SIZ 512 /*---------- -----------*/ -#define USBD_SUPPORT_USER_STRING 0 +#define USBD_SUPPORT_USER_STRING 1 /*---------- -----------*/ #define USBD_DEBUG_LEVEL 0 /*---------- -----------*/