mbed

Fork of mbed-dev by mbed official

Revision:
174:e131a1973e81
Parent:
171:19eb464bc2be
Child:
180:b0033dcd6934
--- a/targets/TARGET_STM/stm_spi_api.c	Thu Aug 31 17:27:04 2017 +0100
+++ b/targets/TARGET_STM/stm_spi_api.c	Fri Sep 15 14:59:18 2017 +0100
@@ -63,6 +63,9 @@
 #   define DEBUG_PRINTF(...) {}
 #endif
 
+/* Consider 10ms as the default timeout for sending/receving 1 byte */
+#define TIMEOUT_1_BYTE 10
+
 void init_spi(spi_t *obj)
 {
     struct spi_s *spiobj = SPI_S(obj);
@@ -75,7 +78,14 @@
         error("Cannot initialize SPI");
     }
 
-    __HAL_SPI_ENABLE(handle);
+    /* In case of standard 4 wires SPI,PI can be kept enabled all time
+     * and SCK will only be generated during the write operations. But in case
+     * of 3 wires, it should be only enabled during rd/wr unitary operations,
+     * which is handled inside STM32 HAL layer.
+     */
+    if (handle->Init.Direction  == SPI_DIRECTION_2LINES) {
+        __HAL_SPI_ENABLE(handle);
+    }
 }
 
 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
@@ -156,7 +166,13 @@
     handle->Instance = SPI_INST(obj);
     handle->Init.Mode              = SPI_MODE_MASTER;
     handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
-    handle->Init.Direction         = SPI_DIRECTION_2LINES;
+
+    if (miso != NC) {
+        handle->Init.Direction     = SPI_DIRECTION_2LINES;
+    } else {
+       handle->Init.Direction      = SPI_DIRECTION_1LINE;
+    }
+
     handle->Init.CLKPhase          = SPI_PHASE_1EDGE;
     handle->Init.CLKPolarity       = SPI_POLARITY_LOW;
     handle->Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE;
@@ -353,6 +369,10 @@
     struct spi_s *spiobj = SPI_S(obj);
     SPI_HandleTypeDef *handle = &(spiobj->handle);
 
+    if (handle->Init.Direction == SPI_DIRECTION_1LINE) {
+        return HAL_SPI_Transmit(handle, (uint8_t*)&value, 1, TIMEOUT_1_BYTE);
+    }
+
 #if defined(LL_SPI_RX_FIFO_TH_HALF)
     /*  Configure the default data size */
     if (handle->Init.DataSize == SPI_DATASIZE_16BIT) {
@@ -390,13 +410,31 @@
 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
                            char *rx_buffer, int rx_length, char write_fill)
 {
+    struct spi_s *spiobj = SPI_S(obj);
+    SPI_HandleTypeDef *handle = &(spiobj->handle);
     int total = (tx_length > rx_length) ? tx_length : rx_length;
-
-    for (int i = 0; i < total; i++) {
-        char out = (i < tx_length) ? tx_buffer[i] : write_fill;
-        char in = spi_master_write(obj, out);
-        if (i < rx_length) {
-            rx_buffer[i] = in;
+    int i = 0;
+    if (handle->Init.Direction == SPI_DIRECTION_2LINES) {
+        for (i = 0; i < total; i++) {
+            char out = (i < tx_length) ? tx_buffer[i] : write_fill;
+            char in = spi_master_write(obj, out);
+            if (i < rx_length) {
+                rx_buffer[i] = in;
+            }
+        }
+    } else {
+        /* In case of 1 WIRE only, first handle TX, then Rx */
+        if (tx_length != 0) {
+            if (HAL_OK != HAL_SPI_Transmit(handle, (uint8_t*)tx_buffer, tx_length, tx_length*TIMEOUT_1_BYTE)) {
+                /*  report an error */
+                total = 0;
+            }
+        }
+        if (rx_length != 0) {
+            if (HAL_OK != HAL_SPI_Receive(handle, (uint8_t*)rx_buffer, rx_length, rx_length*TIMEOUT_1_BYTE)) {
+                /*  report an error */
+                total = 0;
+            }
         }
     }
 
@@ -410,17 +448,13 @@
 
 int spi_slave_read(spi_t *obj)
 {
-    SPI_TypeDef *spi = SPI_INST(obj);
     struct spi_s *spiobj = SPI_S(obj);
     SPI_HandleTypeDef *handle = &(spiobj->handle);
     while (!ssp_readable(obj));
-    if (handle->Init.DataSize == SPI_DATASIZE_8BIT) {
-        // Force 8-bit access to the data register
-        uint8_t *p_spi_dr = 0;
-        p_spi_dr = (uint8_t *) & (spi->DR);
-        return (int)(*p_spi_dr);
+    if (handle->Init.DataSize == SPI_DATASIZE_16BIT) {
+        return LL_SPI_ReceiveData16(SPI_INST(obj));
     } else {
-        return (int)spi->DR;
+        return LL_SPI_ReceiveData8(SPI_INST(obj));
     }
 }