Browse Source

Merge pull request #3685 from armink/fix_spi

完善 SPI 框架及驱动相关功能
Bernard Xiong 5 years ago
parent
commit
d3c270412d

+ 12 - 3
bsp/stm32/libraries/HAL_Drivers/drv_spi.c

@@ -11,12 +11,13 @@
  * 2020-01-15     whj4674672   Porting for stm32h7xx
  */
 
+#include <rtthread.h>
+#include <rtdevice.h>
 #include "board.h"
 
 #ifdef RT_USING_SPI
 
 #if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) || defined(BSP_USING_SPI4) || defined(BSP_USING_SPI5) || defined(BSP_USING_SPI6)
-/* this driver can be disabled at menuconfig → RT-Thread Components → Device Drivers */
 
 #include "drv_spi.h"
 #include "drv_config.h"
@@ -278,7 +279,7 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
     SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
     struct stm32_hw_spi_cs *cs = device->parent.user_data;
 
-    if (message->cs_take)
+    if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS))
     {
         HAL_GPIO_WritePin(cs->GPIOx, cs->GPIO_Pin, GPIO_PIN_RESET);
     }
@@ -333,6 +334,12 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
             {
                 state = HAL_SPI_Transmit(spi_handle, (uint8_t *)send_buf, send_length, 1000);
             }
+
+            if (message->cs_release && (device->config.mode & RT_SPI_3WIRE))
+            {
+                /* release the CS by disable SPI when using 3 wires SPI */
+                __HAL_SPI_DISABLE(spi_handle);
+            }
         }
         else
         {
@@ -343,6 +350,8 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
             }
             else
             {
+                /* clear the old error flag */
+                __HAL_SPI_CLEAR_OVRFLAG(spi_handle);
                 state = HAL_SPI_Receive(spi_handle, (uint8_t *)recv_buf, send_length, 1000);
             }
         }
@@ -364,7 +373,7 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
         while (HAL_SPI_GetState(spi_handle) != HAL_SPI_STATE_READY);
     }
 
-    if (message->cs_release)
+    if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS))
     {
         HAL_GPIO_WritePin(cs->GPIOx, cs->GPIO_Pin, GPIO_PIN_SET);
     }

+ 14 - 12
components/drivers/include/drivers/spi.h

@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2020, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
  * 2012-11-23     Bernard      Add extern "C"
+ * 2020-06-13     armink       fix the 3 wires issue
  */
 
 #ifndef __SPI_H__
@@ -18,8 +19,6 @@
 extern "C"{
 #endif
 
-#define RT_SPI_CPHA     (1<<0)                             /* bit[0]:CPHA, clock phase */
-#define RT_SPI_CPOL     (1<<1)                             /* bit[1]:CPOL, clock polarity */
 /**
  * At CPOL=0 the base value of the clock is zero
  *  - For CPHA=0, data are captured on the clock's rising edge (low->high transition)
@@ -32,26 +31,29 @@ extern "C"{
  *  - For CPHA=1, data are captured on clock's rising edge and data are propagated
  *    on a falling edge.
  */
+#define RT_SPI_CPHA     (1<<0)                             /* bit[0]:CPHA, clock phase */
+#define RT_SPI_CPOL     (1<<1)                             /* bit[1]:CPOL, clock polarity */
+
 #define RT_SPI_LSB      (0<<2)                             /* bit[2]: 0-LSB */
 #define RT_SPI_MSB      (1<<2)                             /* bit[2]: 1-MSB */
 
 #define RT_SPI_MASTER   (0<<3)                             /* SPI master device */
 #define RT_SPI_SLAVE    (1<<3)                             /* SPI slave device */
 
+#define RT_SPI_CS_HIGH  (1<<4)                             /* Chipselect active high */
+#define RT_SPI_NO_CS    (1<<5)                             /* No chipselect */
+#define RT_SPI_3WIRE    (1<<6)                             /* SI/SO pin shared */
+#define RT_SPI_READY    (1<<7)                             /* Slave pulls low to pause */
+
+#define RT_SPI_MODE_MASK    (RT_SPI_CPHA | RT_SPI_CPOL | RT_SPI_MSB | RT_SPI_SLAVE | RT_SPI_CS_HIGH | RT_SPI_NO_CS | RT_SPI_3WIRE | RT_SPI_READY)
+
 #define RT_SPI_MODE_0       (0 | 0)                        /* CPOL = 0, CPHA = 0 */
 #define RT_SPI_MODE_1       (0 | RT_SPI_CPHA)              /* CPOL = 0, CPHA = 1 */
 #define RT_SPI_MODE_2       (RT_SPI_CPOL | 0)              /* CPOL = 1, CPHA = 0 */
 #define RT_SPI_MODE_3       (RT_SPI_CPOL | RT_SPI_CPHA)    /* CPOL = 1, CPHA = 1 */
 
-#define RT_SPI_MODE_MASK    (RT_SPI_CPHA | RT_SPI_CPOL | RT_SPI_MSB | RT_SPI_SLAVE)
-
-#define RT_SPI_BUS_MODE_SPI         (1<<0)       
-#define RT_SPI_BUS_MODE_QSPI        (1<<1)       
-
-#define RT_SPI_CS_HIGH  (1<<4)                             /* Chipselect active high */
-#define RT_SPI_NO_CS    (1<<5)                             /* No chipselect */
-#define RT_SPI_3WIRE    (1<<6)                             /* SI/SO pin shared */
-#define RT_SPI_READY    (1<<7)                             /* Slave pulls low to pause */
+#define RT_SPI_BUS_MODE_SPI         (1<<0)
+#define RT_SPI_BUS_MODE_QSPI        (1<<1)
 
 /**
  * SPI message structure

+ 12 - 0
components/drivers/spi/sfud/inc/sfud_cfg.h

@@ -38,6 +38,18 @@
 #define SFUD_DEBUG_MODE
 #endif
 
+#ifdef RT_DEBUG_SFUD
+#define DBG_LVL DBG_LOG
+#define SFUD_DEBUG(fmt, ...)  LOG_D("(%s:%ld) "fmt"", __FILE__, __LINE__, ##__VA_ARGS__)
+#else
+#define DBG_LVL DBG_INFO
+#endif /* RT_DEBUG_SFUD */
+
+#define DBG_TAG "SFUD"
+#include <rtdbg.h>
+extern void rt_kprintf(const char *fmt, ...);
+#define SFUD_INFO(...)        LOG_I(__VA_ARGS__)
+
 /**
  * Using probe flash JEDEC SFDP parameter.
  */

+ 1 - 1
components/drivers/spi/sfud/inc/sfud_flash_def.h

@@ -124,7 +124,7 @@ typedef struct {
     {"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81},      \
     {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \
     {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \
-    {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \
+    {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \
     {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                  \
     {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                  \
     {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \

+ 42 - 70
components/drivers/spi/spi_flash_sfud.c

@@ -15,12 +15,6 @@
 
 #ifdef RT_USING_SFUD
 
-#ifdef RT_DEBUG_SFUD
-#define DEBUG_TRACE         rt_kprintf("[SFUD] "); rt_kprintf
-#else
-#define DEBUG_TRACE(...)
-#endif /* RT_DEBUG_SFUD */
-
 #ifndef RT_SFUD_DEFAULT_SPI_CFG
 
 #ifndef RT_SFUD_SPI_MAX_HZ
@@ -34,7 +28,7 @@
     .data_width = 8,                             \
     .max_hz = RT_SFUD_SPI_MAX_HZ,                \
 }
-#endif
+#endif /* RT_SFUD_DEFAULT_SPI_CFG */
 
 #ifdef SFUD_USING_QSPI
 #define RT_SFUD_DEFAULT_QSPI_CFG                 \
@@ -44,11 +38,7 @@
     .ddr_mode = 0,                               \
     .qspi_dl_width = 4,                          \
 }
-#endif
-
-static char log_buf[RT_CONSOLEBUF_SIZE];
-
-void sfud_log_debug(const char *file, const long line, const char *format, ...);
+#endif /* SFUD_USING_QSPI */
 
 static rt_err_t rt_sfud_control(rt_device_t dev, int cmd, void *args) {
     RT_ASSERT(dev);
@@ -259,44 +249,6 @@ static void retry_delay_100us(void) {
     rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000);
 }
 
-/**
- * This function is print debug info.
- *
- * @param file the file which has call this function
- * @param line the line number which has call this function
- * @param format output format
- * @param ... args
- */
-void sfud_log_debug(const char *file, const long line, const char *format, ...) {
-    va_list args;
-
-    /* args point to the first variable parameter */
-    va_start(args, format);
-    rt_kprintf("[SFUD] (%s:%ld) ", file, line);
-    /* must use vprintf to print */
-    rt_vsnprintf(log_buf, sizeof(log_buf), format, args);
-    rt_kprintf("%s\n", log_buf);
-    va_end(args);
-}
-
-/**
- * This function is print routine info.
- *
- * @param format output format
- * @param ... args
- */
-void sfud_log_info(const char *format, ...) {
-    va_list args;
-
-    /* args point to the first variable parameter */
-    va_start(args, format);
-    rt_kprintf("[SFUD] ");
-    /* must use vprintf to print */
-    rt_vsnprintf(log_buf, sizeof(log_buf), format, args);
-    rt_kprintf("%s\n", log_buf);
-    va_end(args);
-}
-
 sfud_err sfud_spi_port_init(sfud_flash *flash) {
     sfud_err result = SFUD_SUCCESS;
 
@@ -311,7 +263,7 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
     flash->spi.unlock = spi_unlock;
     flash->spi.user_data = flash;
     if (RT_TICK_PER_SECOND < 1000) {
-        rt_kprintf("[SFUD] Warning: The OS tick(%d) is less than 1000. So the flash write will take more time.\n", RT_TICK_PER_SECOND);
+        LOG_W("[SFUD] Warning: The OS tick(%d) is less than 1000. So the flash write will take more time.", RT_TICK_PER_SECOND);
     }
     /* 100 microsecond delay */
     flash->retry.delay = retry_delay_100us;
@@ -334,23 +286,23 @@ const static struct rt_device_ops flash_device_ops =
 #endif
 
 /**
- * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
+ * Probe SPI flash by SFUD (Serial Flash Universal Driver) driver library and though SPI device by specified configuration.
  *
  * @param spi_flash_dev_name the name which will create SPI flash device
  * @param spi_dev_name using SPI device name
+ * @param spi_cfg SPI device configuration
+ * @param qspi_cfg QSPI device configuration
  *
  * @return probed SPI flash device, probe failed will return RT_NULL
  */
-rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name) {
+rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, const char *spi_dev_name,
+        struct rt_spi_configuration *spi_cfg, struct rt_qspi_configuration *qspi_cfg)
+{
     rt_spi_flash_device_t rtt_dev = RT_NULL;
     sfud_flash *sfud_dev = RT_NULL;
     char *spi_flash_dev_name_bak = RT_NULL, *spi_dev_name_bak = RT_NULL;
-    /* using default flash SPI configuration for initialize SPI Flash
-     * @note you also can change the SPI to other configuration after initialized finish */
-    struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG;
     extern sfud_err sfud_device_init(sfud_flash *flash);
 #ifdef SFUD_USING_QSPI
-    struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG;
     struct rt_qspi_device *qspi_dev = RT_NULL;
 #endif
 
@@ -380,7 +332,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
             /* RT-Thread SPI device initialize */
             rtt_dev->rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
             if (rtt_dev->rt_spi_device == RT_NULL || rtt_dev->rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
-                rt_kprintf("ERROR: SPI device %s not found!\n", spi_dev_name);
+                LOG_E("ERROR: SPI device %s not found!", spi_dev_name);
                 goto error;
             }
             sfud_dev->spi.name = spi_dev_name_bak;
@@ -389,12 +341,12 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
             /* set the qspi line number and configure the QSPI bus */
             if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
                 qspi_dev = (struct rt_qspi_device *)rtt_dev->rt_spi_device;
-                qspi_cfg.qspi_dl_width = qspi_dev->config.qspi_dl_width;
-                rt_qspi_configure(qspi_dev, &qspi_cfg);
+                qspi_cfg->qspi_dl_width = qspi_dev->config.qspi_dl_width;
+                rt_qspi_configure(qspi_dev, qspi_cfg);
             }
             else
 #endif
-                rt_spi_configure(rtt_dev->rt_spi_device, &cfg);
+                rt_spi_configure(rtt_dev->rt_spi_device, spi_cfg);
         }
         /* SFUD flash device initialize */
         {
@@ -406,7 +358,7 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
             sfud_dev->user_data = rtt_dev;
             /* initialize SFUD device */
             if (sfud_device_init(sfud_dev) != SFUD_SUCCESS) {
-                rt_kprintf("ERROR: SPI flash probe failed by SPI device %s.\n", spi_dev_name);
+                LOG_E("ERROR: SPI flash probe failed by SPI device %s.", spi_dev_name);
                 goto error;
             }
             /* when initialize success, then copy SFUD flash device's geometry to RT-Thread SPI flash device */
@@ -416,8 +368,8 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
 #ifdef SFUD_USING_QSPI
             /* reconfigure the QSPI bus for medium size */
             if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
-                qspi_cfg.medium_size = sfud_dev->chip.capacity;
-                rt_qspi_configure(qspi_dev, &qspi_cfg);
+                qspi_cfg->medium_size = sfud_dev->chip.capacity;
+                rt_qspi_configure(qspi_dev, qspi_cfg);
                 if(qspi_dev->enter_qspi_mode != RT_NULL)
                     qspi_dev->enter_qspi_mode(qspi_dev);
 
@@ -442,10 +394,10 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
 
         rt_device_register(&(rtt_dev->flash_device), spi_flash_dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
 
-        DEBUG_TRACE("Probe SPI flash %s by SPI device %s success.\n",spi_flash_dev_name, spi_dev_name);
+        LOG_I("Probe SPI flash %s by SPI device %s success.",spi_flash_dev_name, spi_dev_name);
         return rtt_dev;
     } else {
-        rt_kprintf("ERROR: Low memory.\n");
+        LOG_E("ERROR: Low memory.");
         goto error;
     }
 
@@ -463,6 +415,26 @@ error:
     return RT_NULL;
 }
 
+/**
+ * Probe SPI flash by SFUD(Serial Flash Universal Driver) driver library and though SPI device.
+ *
+ * @param spi_flash_dev_name the name which will create SPI flash device
+ * @param spi_dev_name using SPI device name
+ *
+ * @return probed SPI flash device, probe failed will return RT_NULL
+ */
+rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name)
+{
+    struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG;
+#ifndef SFUD_USING_QSPI
+    return rt_sfud_flash_probe_ex(spi_flash_dev_name, spi_dev_name, &cfg, RT_NULL);
+#else
+    struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG;
+
+    return rt_sfud_flash_probe_ex(spi_flash_dev_name, spi_dev_name, &cfg, &qspi_cfg);
+#endif
+}
+
 /**
  * Delete SPI flash device
  *
@@ -496,7 +468,7 @@ sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name)
 
     rt_spi_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);
     if (rt_spi_device == RT_NULL || rt_spi_device->parent.type != RT_Device_Class_SPIDevice) {
-        rt_kprintf("ERROR: SPI device %s not found!\n", spi_dev_name);
+        LOG_E("ERROR: SPI device %s not found!", spi_dev_name);
         goto __error;
     }
 
@@ -505,7 +477,7 @@ sfud_flash_t rt_sfud_flash_find(const char *spi_dev_name)
         sfud_dev = (sfud_flash_t) (rtt_dev->user_data);
         return sfud_dev;
     } else {
-        rt_kprintf("ERROR: SFUD flash device not found!\n");
+        LOG_E("ERROR: SFUD flash device not found!");
         goto __error;
     }
 
@@ -520,7 +492,7 @@ sfud_flash_t rt_sfud_flash_find_by_dev_name(const char *flash_dev_name)
 
     rtt_dev = (rt_spi_flash_device_t) rt_device_find(flash_dev_name);
     if (rtt_dev == RT_NULL || rtt_dev->flash_device.type != RT_Device_Class_Block) {
-        rt_kprintf("ERROR: Flash device %s not found!\n", flash_dev_name);
+        LOG_E("ERROR: Flash device %s not found!", flash_dev_name);
         goto __error;
     }
 
@@ -528,7 +500,7 @@ sfud_flash_t rt_sfud_flash_find_by_dev_name(const char *flash_dev_name)
         sfud_dev = (sfud_flash_t) (rtt_dev->user_data);
         return sfud_dev;
     } else {
-        rt_kprintf("ERROR: SFUD flash device not found!\n");
+        LOG_E("ERROR: SFUD flash device not found!");
         goto __error;
     }
 

+ 13 - 0
components/drivers/spi/spi_flash_sfud.h

@@ -26,6 +26,19 @@
  */
 rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const char *spi_dev_name);
 
+/**
+ * Probe SPI flash by SFUD (Serial Flash Universal Driver) driver library and though SPI device by specified configuration.
+ *
+ * @param spi_flash_dev_name the name which will create SPI flash device
+ * @param spi_dev_name using SPI device name
+ * @param spi_cfg SPI device configuration
+ * @param qspi_cfg QSPI device configuration
+ *
+ * @return probed SPI flash device, probe failed will return RT_NULL
+ */
+rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, const char *spi_dev_name,
+        struct rt_spi_configuration *spi_cfg, struct rt_qspi_configuration *qspi_cfg);
+
 /**
  * Delete SPI flash device
  *