Skip to content

Commit a9f0fdb

Browse files
jhokajarstevew817
authored andcommitted
SiLabs Pearl: SPI
When doing a large transfer over the LDMA it is required to wait TX to be completed before transferring the next part of the data. Added a loop, to wait until TXC flag is set in function USART_STATUS_TXC. + minor code cleanup and EM1 sleep is allowed again. Second, the TX interrupt was not cleared after processing, causing it to stay in an infinite loop.
1 parent a7ef4ca commit a9f0fdb

File tree

1 file changed

+8
-3
lines changed
  • libraries/mbed/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32

1 file changed

+8
-3
lines changed

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
static uint16_t fill_word = SPI_FILL_WORD;
5252

53-
#define SPI_LEAST_ACTIVE_SLEEPMODE EM0
53+
#define SPI_LEAST_ACTIVE_SLEEPMODE EM1
5454
#define USE_UINT16_BUFFER
5555

5656
static inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj)
@@ -125,7 +125,6 @@ void spi_preinit(spi_t *obj, PinName mosi, PinName miso, PinName clk, PinName cs
125125
{
126126
obj->spi.spi = serial_uart_allocate(UART_TYPE_USART);
127127
MBED_ASSERT(obj->spi.spi);
128-
SPIName spi_cs = (SPIName) pinmap_peripheral(cs, PinMap_SPI_CS);
129128
if (cs != NC) { /* Slave mode */
130129
obj->spi.master = false;
131130
} else {
@@ -1173,6 +1172,8 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
11731172
void* tx_pointer = (char*)obj->tx_buff.buffer + obj->tx_buff.pos;
11741173
uint32_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
11751174

1175+
/* Wait previous transmit to complete */
1176+
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
11761177
/* Begin transfer. Rely on spi_activate_dma to split up the transfer further. */
11771178
spi_activate_dma(obj, obj->rx_buff.buffer, tx_pointer, tx_length, obj->rx_buff.length);
11781179

@@ -1347,9 +1348,13 @@ void spi_abort_asynch(spi_t *obj)
13471348
// Determine whether we're running DMA or interrupt
13481349
if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
13491350
// Cancel the DMA transfers
1351+
#ifdef LDMA_PRESENT
1352+
LDMA_StopTransfer(obj->spi.dmaOptionsTX.dmaChannel);
1353+
LDMA_StopTransfer(obj->spi.dmaOptionsRX.dmaChannel);
1354+
#else
13501355
DMA_ChannelEnable(obj->spi.dmaOptionsTX.dmaChannel, false);
13511356
DMA_ChannelEnable(obj->spi.dmaOptionsRX.dmaChannel, false);
1352-
1357+
#endif
13531358
/* Release the dma channels if they were opportunistically allocated */
13541359
if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
13551360
dma_channel_free(obj->spi.dmaOptionsTX.dmaChannel);

0 commit comments

Comments
 (0)