Răsfoiți Sursa

Fix SPI DMA timeout units and free temporary buffers

wdfk-prog 1 lună în urmă
părinte
comite
b0e55a46a1
1 a modificat fișierele cu 22 adăugiri și 8 ștergeri
  1. 22 8
      bsp/stm32/libraries/HAL_Drivers/drivers/drv_spi.c

+ 22 - 8
bsp/stm32/libraries/HAL_Drivers/drivers/drv_spi.c

@@ -287,7 +287,7 @@ static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configur
 
 static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
 {
-    #define DMA_TRANS_MIN_LEN  10 /* only buffer length >= DMA_TRANS_MIN_LEN will use DMA mode */
+#define DMA_TRANS_MIN_LEN  10 /* only buffer length >= DMA_TRANS_MIN_LEN will use DMA mode */
 
     HAL_StatusTypeDef state = HAL_OK;
     rt_size_t message_length, already_send_length;
@@ -301,6 +301,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
 
     struct stm32_spi *spi_drv =  rt_container_of(device->bus, struct stm32_spi, spi_bus);
     SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
+
     rt_uint64_t total_byte_ms = (rt_uint64_t)message->length * 1000;
     rt_uint32_t speed_bytes_per_sec = spi_drv->cfg->usage_freq / 8;
     if (speed_bytes_per_sec == 0)
@@ -383,7 +384,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
                 {
                     state = HAL_ERROR;
                     LOG_E("malloc aligned_send_buf failed!");
-                    break;
+                    goto transfer_cleanup;
                 }
                 rt_memcpy(aligned_send_buf, send_buf, send_length);
                 dma_send_buf = aligned_send_buf;
@@ -396,7 +397,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
                 {
                     state = HAL_ERROR;
                     LOG_E("malloc aligned_recv_buf failed!");
-                    break;
+                    goto transfer_cleanup;
                 }
                 dma_recv_buf = aligned_recv_buf;
             }
@@ -462,7 +463,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
             LOG_E("SPI transfer error: %d", state);
             message->length = 0;
             spi_handle->State = HAL_SPI_STATE_READY;
-            break;
+            goto transfer_cleanup;
         }
         else
         {
@@ -476,7 +477,8 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
             {
                 state = HAL_ERROR;
                 LOG_E("wait for DMA interrupt overtime!");
-                break;
+                HAL_SPI_DMAStop(spi_handle);
+                goto transfer_cleanup;
             }
         }
         else
@@ -497,16 +499,27 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
             }
         }
 
-        if (state == HAL_OK && aligned_recv_buf != RT_NULL)
+transfer_cleanup:
+        /* Post-transfer processing */
+        if (state == HAL_OK)
         {
+            if (aligned_recv_buf != RT_NULL)
+            {
 #if defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32F7)
-            rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, aligned_recv_buf, send_length);
+                rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, aligned_recv_buf, send_length);
 #endif
-            rt_memcpy(recv_buf, aligned_recv_buf, send_length);
+                rt_memcpy(recv_buf, aligned_recv_buf, send_length);
+            }
         }
 
+        // Free any temporary buffers that were allocated
         if (aligned_send_buf) rt_free_align(aligned_send_buf);
         if (aligned_recv_buf) rt_free_align(aligned_recv_buf);
+
+        if (state != HAL_OK)
+        {
+            break;
+        }
     }
 
     if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE))
@@ -532,6 +545,7 @@ static rt_err_t spi_configure(struct rt_spi_device *device,
 
     struct stm32_spi *spi_drv =  rt_container_of(device->bus, struct stm32_spi, spi_bus);
     spi_drv->cfg = configuration;
+
     return stm32_spi_init(spi_drv, configuration);
 }