mirror of https://github.com/ARMmbed/mbed-os.git
SiLabs Pearl: LDMA support for serial_api
LDMA support for serial HAL. Adds callback support for emlib LDMA code so that most of the old serial code can be reused. Note: Serial shows some signs of life on the bus, but DMA mode is completely untested.pull/1501/head
parent
e3e385e16d
commit
7be6799638
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include "dma_api_HAL.h"
|
||||
#include "em_device.h"
|
||||
#include "em_cmu.h"
|
||||
|
||||
#ifdef DMA_PRESENT
|
||||
|
|
|
|||
|
|
@ -33,7 +33,15 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include "dma_api.h"
|
||||
#include "em_device.h"
|
||||
|
||||
#ifdef DMA_PRESENT
|
||||
#include "em_dma.h"
|
||||
#endif
|
||||
|
||||
#ifdef LDMA_PRESENT
|
||||
#include "em_ldma.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -65,6 +73,8 @@ typedef struct {
|
|||
int dmaChannel;
|
||||
#ifndef LDMA_PRESENT
|
||||
DMA_CB_TypeDef dmaCallback;
|
||||
#else
|
||||
LDMA_Callback_t dmaCallback;
|
||||
#endif
|
||||
} DMA_OPTIONS_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -434,6 +434,13 @@ typedef struct
|
|||
uint8_t ldmaLoopCnt; /**< Counter for looped transfers. */
|
||||
} LDMA_TransferCfg_t;
|
||||
|
||||
typedef void (*LDMA_CBFunc_t)(unsigned int channel, bool primary, void *user);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LDMA_CBFunc_t cbFunc;
|
||||
void *userPtr;
|
||||
} LDMA_Callback_t;
|
||||
|
||||
/*******************************************************************************
|
||||
************************** STRUCT INITIALIZERS ****************************
|
||||
|
|
@ -1213,7 +1220,9 @@ void LDMA_DeInit( void );
|
|||
void LDMA_Init( LDMA_Init_t *init );
|
||||
void LDMA_StartTransfer( int ch,
|
||||
LDMA_TransferCfg_t *transfer,
|
||||
LDMA_Descriptor_t *descriptor );
|
||||
LDMA_Descriptor_t *descriptor,
|
||||
LDMA_CBFunc_t callback,
|
||||
void *userData );
|
||||
void LDMA_StopTransfer( int ch );
|
||||
bool LDMA_TransferDone( int ch );
|
||||
uint32_t LDMA_TransferRemainingCount( int ch );
|
||||
|
|
|
|||
|
|
@ -202,7 +202,13 @@
|
|||
@endverbatim
|
||||
* @{ *************************************************************************/
|
||||
|
||||
#if defined( LDMA_IRQ_HANDLER_TEMPLATE )
|
||||
typedef struct {
|
||||
LDMA_CBFunc_t callback;
|
||||
void *userdata;
|
||||
} LDMA_InternCallback_t;
|
||||
|
||||
static LDMA_InternCallback_t ldmaCallback[DMA_CHAN_COUNT];
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Template for an LDMA IRQ handler.
|
||||
|
|
@ -234,10 +240,13 @@ void LDMA_IRQHandler( void )
|
|||
LDMA->IFC = chmask;
|
||||
|
||||
/* Do more stuff here, execute callbacks etc. */
|
||||
if ( ldmaCallback[chnum].callback )
|
||||
{
|
||||
ldmaCallback[chnum].callback(chnum, false, ldmaCallback[chnum].userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
|
|
@ -308,7 +317,9 @@ void LDMA_Init( LDMA_Init_t *init )
|
|||
******************************************************************************/
|
||||
void LDMA_StartTransfer( int ch,
|
||||
LDMA_TransferCfg_t *transfer,
|
||||
LDMA_Descriptor_t *descriptor )
|
||||
LDMA_Descriptor_t *descriptor,
|
||||
LDMA_CBFunc_t cbFunc,
|
||||
void *userData )
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t chMask = 1 << ch;
|
||||
|
|
@ -335,6 +346,9 @@ void LDMA_StartTransfer( int ch,
|
|||
EFM_ASSERT( !( ( transfer->ldmaLoopCnt << _LDMA_CH_LOOP_LOOPCNT_SHIFT )
|
||||
& ~_LDMA_CH_LOOP_LOOPCNT_MASK ) );
|
||||
|
||||
ldmaCallback[ch].callback = cbFunc;
|
||||
ldmaCallback[ch].userdata = userData;
|
||||
|
||||
LDMA->CH[ ch ].REQSEL = transfer->ldmaReqSel;
|
||||
|
||||
LDMA->CH[ ch ].LOOP =
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ void serial_enable_pins(serial_t *obj, uint8_t enable);
|
|||
IRQn_Type serial_get_rx_irq_index(serial_t *obj);
|
||||
IRQn_Type serial_get_tx_irq_index(serial_t *obj);
|
||||
CMU_Clock_TypeDef serial_get_clock(serial_t *obj);
|
||||
static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx);
|
||||
|
||||
/* ISRs for RX and TX events */
|
||||
#ifdef UART0
|
||||
|
|
@ -964,6 +965,8 @@ static void serial_dmaTransferComplete(unsigned int channel, bool primary, void
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef LDMA_PRESENT
|
||||
|
||||
/******************************************
|
||||
* static void serial_setupDmaChannel(serial_t *obj, bool tx_nrx)
|
||||
*
|
||||
|
|
@ -1065,10 +1068,10 @@ static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx)
|
|||
|
||||
DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* LDMA_PRESENT */
|
||||
|
||||
/******************************************
|
||||
* static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState)
|
||||
*
|
||||
|
|
@ -1121,6 +1124,8 @@ static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState, s
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef LDMA_PRESENT
|
||||
|
||||
static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx)
|
||||
{
|
||||
DMA_CfgDescr_TypeDef channelConfig;
|
||||
|
|
@ -1183,6 +1188,55 @@ static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LDMA_PRESENT
|
||||
|
||||
static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx)
|
||||
{
|
||||
uint32_t dma_periph;
|
||||
obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
|
||||
|
||||
if( tx_nrx ) {
|
||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||
case USART_0: dma_periph = DMAREQ_USART0_TXBL; break;
|
||||
case USART_1: dma_periph = DMAREQ_USART1_TXBL; break;
|
||||
case LEUART_0: dma_periph = DMAREQ_LEUART0_TXBL; break;
|
||||
default:
|
||||
EFM_ASSERT(0);
|
||||
while(1);
|
||||
break;
|
||||
}
|
||||
|
||||
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
||||
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(buffer, dma_periph, length);
|
||||
LDMA_StartTransfer(obj->serial.dmaOptionsTX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete, cb);
|
||||
|
||||
} else {
|
||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||
case USART_0: dma_periph = DMAREQ_USART0_RXDATAV; break;
|
||||
case USART_1: dma_periph = DMAREQ_USART1_RXDATAV; break;
|
||||
case LEUART_0: dma_periph = DMAREQ_LEUART0_RXDATAV; break;
|
||||
default:
|
||||
EFM_ASSERT(0);
|
||||
while(1);
|
||||
break;
|
||||
}
|
||||
|
||||
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
||||
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE(dma_periph, buffer, length);
|
||||
LDMA_StartTransfer(obj->serial.dmaOptionsRX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete, cb);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LDMA_PRESENT */
|
||||
|
||||
/************************************************************************************
|
||||
* ASYNCHRONOUS HAL *
|
||||
************************************************************************************/
|
||||
|
|
@ -1463,7 +1517,11 @@ uint8_t serial_tx_active(serial_t *obj)
|
|||
return 1;
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel));
|
||||
#ifndef LDMA_PRESENT
|
||||
return DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
#else
|
||||
return !LDMA_TransferDone(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
#endif
|
||||
default:
|
||||
/* Check whether interrupt for serial TX is enabled */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
|
|
@ -1487,7 +1545,11 @@ uint8_t serial_rx_active(serial_t *obj)
|
|||
return 1;
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel));
|
||||
#ifndef LDMA_PRESENT
|
||||
return DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel);
|
||||
#else
|
||||
return !LDMA_TransferDone(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
#endif
|
||||
default:
|
||||
/* Check whether interrupt for serial TX is enabled */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
|
|
@ -1764,11 +1826,19 @@ void serial_tx_abort_asynch(serial_t *obj)
|
|||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* stop DMA transfer */
|
||||
#ifndef LDMA_PRESENT
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||
#else
|
||||
LDMA_StopTransfer(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
#endif
|
||||
break;
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* stop DMA transfer and release channel */
|
||||
#ifndef LDMA_PRESENT
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||
#else
|
||||
LDMA_StopTransfer(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
#endif
|
||||
dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
|
|
@ -1811,11 +1881,19 @@ void serial_rx_abort_asynch(serial_t *obj)
|
|||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* stop DMA transfer */
|
||||
#ifndef LDMA_PRESENT
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||
#else
|
||||
LDMA_StopTransfer(obj->serial.dmaOptionsRX.dmaChannel);
|
||||
#endif
|
||||
break;
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* stop DMA transfer and release channel */
|
||||
#ifndef LDMA_PRESENT
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||
#else
|
||||
LDMA_StopTransfer(obj->serial.dmaOptionsRX.dmaChannel);
|
||||
#endif
|
||||
dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
|
||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
|
|
|
|||
Loading…
Reference in New Issue