mbed library sources

Fork of mbed-src by mbed official

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Tue May 26 09:00:08 2015 +0100
Parent:
548:1abac31e188e
Child:
550:787824fdf8f9
Commit message:
Synchronized with git revision ddca955901f48383d8554d19a650c2c88fe3409d

Full URL: https://github.com/mbedmicro/mbed/commit/ddca955901f48383d8554d19a650c2c88fe3409d/

Changed in this revision

targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c Show annotated file Show diff for this revision Revisions of this file
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c	Fri May 22 10:45:46 2015 +0100
+++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c	Tue May 26 09:00:08 2015 +0100
@@ -767,8 +767,24 @@
     DMA_CfgDescr_TypeDef rxDescrCfg;
     DMA_CfgDescr_TypeDef txDescrCfg;
 
+    /* Split up transfers if the tx length is larger than what the DMA supports. */
+    const int DMA_MAX_TRANSFER = (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT);
+
+    if (tx_length > DMA_MAX_TRANSFER) {
+        uint32_t max_length = DMA_MAX_TRANSFER;
+
+        /* Make sure only an even amount of bytes are transferred
+           if the width is larger than 8 bits. */
+        if (obj->spi.bits > 8) {
+            max_length = DMA_MAX_TRANSFER - (DMA_MAX_TRANSFER & 0x01);
+        }
+
+        /* Update length for current transfer. */
+        tx_length = max_length;
+    }
+
     /* Save amount of TX done by DMA */
-    obj->tx_buff.pos = tx_length;
+    obj->tx_buff.pos += tx_length;
 
     if(obj->spi.bits != 9) {
         /* Only activate RX DMA if a receive buffer is specified */
@@ -966,6 +982,18 @@
     if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
         /* DMA implementation */
 
+        /* If there is still data in the TX buffer, setup a new transfer. */
+        if (obj->tx_buff.pos < obj->tx_buff.length) {
+            /* Find position and remaining length without modifying tx_buff. */
+            void* tx_pointer = obj->tx_buff.buffer + obj->tx_buff.pos;
+            uint32_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
+
+            /* Begin transfer. Rely on spi_activate_dma to split up the transfer further. */
+            spi_activate_dma(obj, obj->rx_buff.buffer, tx_pointer, tx_length, obj->rx_buff.length);
+
+            return 0;
+        }
+
         /* If there is an RX transfer ongoing, wait for it to finish */
         if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
             /* Check if we need to kick off TX transfer again to force more incoming data. */