Skip to content

Commit ddca955

Browse files
committed
Merge branch 'marcuschangarm-master'
2 parents 88d158e + fc6ffc5 commit ddca955

File tree

1 file changed

+29
-1
lines changed
  • libraries/mbed/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32

1 file changed

+29
-1
lines changed

libraries/mbed/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,24 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, void* txdata, int tx_leng
767767
DMA_CfgDescr_TypeDef rxDescrCfg;
768768
DMA_CfgDescr_TypeDef txDescrCfg;
769769

770+
/* Split up transfers if the tx length is larger than what the DMA supports. */
771+
const int DMA_MAX_TRANSFER = (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT);
772+
773+
if (tx_length > DMA_MAX_TRANSFER) {
774+
uint32_t max_length = DMA_MAX_TRANSFER;
775+
776+
/* Make sure only an even amount of bytes are transferred
777+
if the width is larger than 8 bits. */
778+
if (obj->spi.bits > 8) {
779+
max_length = DMA_MAX_TRANSFER - (DMA_MAX_TRANSFER & 0x01);
780+
}
781+
782+
/* Update length for current transfer. */
783+
tx_length = max_length;
784+
}
785+
770786
/* Save amount of TX done by DMA */
771-
obj->tx_buff.pos = tx_length;
787+
obj->tx_buff.pos += tx_length;
772788

773789
if(obj->spi.bits != 9) {
774790
/* Only activate RX DMA if a receive buffer is specified */
@@ -966,6 +982,18 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
966982
if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
967983
/* DMA implementation */
968984

985+
/* If there is still data in the TX buffer, setup a new transfer. */
986+
if (obj->tx_buff.pos < obj->tx_buff.length) {
987+
/* Find position and remaining length without modifying tx_buff. */
988+
void* tx_pointer = obj->tx_buff.buffer + obj->tx_buff.pos;
989+
uint32_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
990+
991+
/* Begin transfer. Rely on spi_activate_dma to split up the transfer further. */
992+
spi_activate_dma(obj, obj->rx_buff.buffer, tx_pointer, tx_length, obj->rx_buff.length);
993+
994+
return 0;
995+
}
996+
969997
/* If there is an RX transfer ongoing, wait for it to finish */
970998
if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
971999
/* Check if we need to kick off TX transfer again to force more incoming data. */

0 commit comments

Comments
 (0)