mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Revision:
549:99e4f6522a2d
Parent:
548:1abac31e188e
Child:
563:536c9fb088a0
--- 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. */