git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16403 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
a593b93b19
commit
353daeaa12
|
@ -19,11 +19,11 @@
|
|||
* @brief GPDMA helper driver code.
|
||||
*
|
||||
* @addtogroup STM32_GPDMA
|
||||
* @details GPDMA sharing helper driver. In the STM32 the DMA channels are a
|
||||
* shared resource, this driver allows to allocate and free DMA
|
||||
* @details GPDMA sharing helper driver. In the STM32 the GPDMA channels are a
|
||||
* shared resource, this driver allows to allocate and free GPDMA
|
||||
* channels at runtime in order to allow all the other device
|
||||
* drivers to coordinate the access to the resource.
|
||||
* @note The DMA ISR handlers are all declared into this module because
|
||||
* @note The GPDMA ISR handlers are all declared into this module because
|
||||
* sharing, the various device drivers can associate a callback to
|
||||
* ISRs when allocating channels.
|
||||
* @{
|
||||
|
@ -106,7 +106,7 @@ const stm32_gpdma_channel_t __stm32_gpdma_channels[STM32_GPDMA_CHANNELS] = {
|
|||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Global DMA-related data structures.
|
||||
* @brief Global GPDMA-related data structures.
|
||||
*/
|
||||
static struct {
|
||||
/**
|
||||
|
@ -114,15 +114,15 @@ static struct {
|
|||
*/
|
||||
uint32_t allocated_mask;
|
||||
/**
|
||||
* @brief DMA IRQ redirectors.
|
||||
* @brief GPDMA IRQ redirectors.
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* @brief DMA callback function.
|
||||
* @brief GPDMA callback function.
|
||||
*/
|
||||
stm32_gpdmaisr_t func;
|
||||
/**
|
||||
* @brief DMA callback parameter.
|
||||
* @brief GPDMA callback parameter.
|
||||
*/
|
||||
void *param;
|
||||
} channels[STM32_GPDMA_CHANNELS];
|
||||
|
@ -141,7 +141,7 @@ static struct {
|
|||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief STM32 DMA helper initialization.
|
||||
* @brief STM32 GPDMA helper initialization.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
|
@ -158,13 +158,13 @@ void dmaInit(void) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a DMA channel.
|
||||
* @details The channel is allocated and, if required, the DMA clock enabled.
|
||||
* @brief Allocates a GPDMA channel.
|
||||
* @details The channel is allocated and, if required, the GPDMA clock enabled.
|
||||
* The function also enables the IRQ vector associated to the channel
|
||||
* and initializes its priority.
|
||||
*
|
||||
* @param[in] cmask channels mask where to search for an available chennel
|
||||
* @param[in] irqprio IRQ priority for the DMA channel
|
||||
* @param[in] irqprio IRQ priority for the GPDMA channel
|
||||
* @param[in] func handling function pointer, can be @p NULL
|
||||
* @param[in] param a parameter to be passed to the handling function
|
||||
* @return Pointer to the allocated @p stm32_dma_channel_t
|
||||
|
@ -192,12 +192,12 @@ const stm32_gpdma_channel_t *gpdmaChannelAllocI(uint32_t cmask,
|
|||
/* Channel found.*/
|
||||
const stm32_gpdma_channel_t *dmachp = STM32_GPDMA_CHANNEL(i);
|
||||
|
||||
/* Installs the DMA handler.*/
|
||||
/* Installs the GPDMA handler.*/
|
||||
gpdma.channels[i].func = func;
|
||||
gpdma.channels[i].param = param;
|
||||
gpdma.allocated_mask |= mask;
|
||||
|
||||
/* Enabling DMA clocks required by the current channels set.*/
|
||||
/* Enabling GPDMA clocks required by the current channels set.*/
|
||||
if ((STM32_GPDMA1_MASK_ANY & mask) != 0U) {
|
||||
rccEnableGPDMA1(true);
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ const stm32_gpdma_channel_t *gpdmaChannelAllocI(uint32_t cmask,
|
|||
}
|
||||
|
||||
/* Putting the channel in a known state.*/
|
||||
gpdmaStreamDisable(dmachp);
|
||||
gpdmaChannelDisable(dmachp);
|
||||
dmachp->channel->CCR = 0U;
|
||||
|
||||
return dmachp;
|
||||
|
@ -226,13 +226,13 @@ const stm32_gpdma_channel_t *gpdmaChannelAllocI(uint32_t cmask,
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a DMA channel.
|
||||
* @details The channel is allocated and, if required, the DMA clock enabled.
|
||||
* @brief Allocates a GPDMA channel.
|
||||
* @details The channel is allocated and, if required, the GPDMA clock enabled.
|
||||
* The function also enables the IRQ vector associated to the channel
|
||||
* and initializes its priority.
|
||||
*
|
||||
* @param[in] cmask channels mask where to search for an available chennel
|
||||
* @param[in] irqprio IRQ priority for the DMA channel
|
||||
* @param[in] irqprio IRQ priority for the GPDMA channel
|
||||
* @param[in] func handling function pointer, can be @p NULL
|
||||
* @param[in] param a parameter to be passed to the handling function
|
||||
* @return Pointer to the allocated @p stm32_dma_channel_t
|
||||
|
@ -255,8 +255,8 @@ const stm32_gpdma_channel_t *gpdmaChannelAlloc(uint32_t cmask,
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a DMA channel.
|
||||
* @details The channel is freed and, if required, the DMA clock disabled.
|
||||
* @brief Releases a GPDMA channel.
|
||||
* @details The channel is freed and, if required, the GPDMA clock disabled.
|
||||
* Trying to release a unallocated channel is an illegal operation
|
||||
* and is trapped if assertions are enabled.
|
||||
*
|
||||
|
@ -279,7 +279,7 @@ void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp) {
|
|||
/* Disables the associated IRQ vector if it is no more in use.*/
|
||||
nvicDisableVector(dmachp->vector);
|
||||
|
||||
/* Removes the DMA handler.*/
|
||||
/* Removes the GPDMA handler.*/
|
||||
gpdma.channels[selfindex].func = NULL;
|
||||
gpdma.channels[selfindex].param = NULL;
|
||||
|
||||
|
@ -295,8 +295,8 @@ void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a DMA channel.
|
||||
* @details The channel is freed and, if required, the DMA clock disabled.
|
||||
* @brief Releases a GPDMA channel.
|
||||
* @details The channel is freed and, if required, the GPDMA clock disabled.
|
||||
* Trying to release a unallocated channel is an illegal operation
|
||||
* and is trapped if assertions are enabled.
|
||||
*
|
||||
|
@ -307,12 +307,74 @@ void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp) {
|
|||
void gpdmaChannelFree(const stm32_gpdma_channel_t *dmachp) {
|
||||
|
||||
osalSysLock();
|
||||
gpdmaStreamFreeI(dmachp);
|
||||
gpdmaChannelFreeI(dmachp);
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Serves a DMA IRQ.
|
||||
* @brief GPDMA channel suspend.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAlloc().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmastp pointer to a @p stm32_gpdma_channel_t structure
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void gpdmaChannelSuspend(const stm32_gpdma_channel_t *dmastp) {
|
||||
|
||||
osalDbgAssert((dmastp->channel->CCR & STM32_GPDMA_CCR_EN) != 0U,
|
||||
"not enabled");
|
||||
|
||||
dmastp->channel->CCR |= STM32_GPDMA_CCR_SUSP;
|
||||
while ((dmastp->channel->CSR & STM32_GPDMA_CSR_SUSPF) != 0U) {
|
||||
/* Wait completion.*/
|
||||
}
|
||||
dmastp->channel->CFCR = STM32_GPDMA_CFCR_SUSPF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPDMA channel disable.
|
||||
* @details The function disables the specified channel and then clears any
|
||||
* pending interrupt.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @note Interrupts enabling flags are set to zero after this call, see
|
||||
* bug 3607518.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAlloc().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmastp pointer to a @p stm32_gpdma_channel_t structure
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void gpdmaChannelDisable(const stm32_gpdma_channel_t *dmastp) {
|
||||
|
||||
/* Suspending channel, note, we don't know if it is still active at this
|
||||
point because the EN bit can be reset in HW.*/
|
||||
dmastp->channel->CCR |= STM32_GPDMA_CCR_SUSP;
|
||||
|
||||
/* If the channel was actually active.*/
|
||||
if ((dmastp->channel->CCR & STM32_GPDMA_CCR_EN) != 0U) {
|
||||
|
||||
/* Waiting for completion if suspend operation then resetting the
|
||||
completion flag.*/
|
||||
while ((dmastp->channel->CSR & STM32_GPDMA_CSR_SUSPF) != 0U) {
|
||||
/* Wait completion.*/
|
||||
}
|
||||
dmastp->channel->CFCR = STM32_GPDMA_CFCR_SUSPF;
|
||||
}
|
||||
|
||||
/* Now resetting the channel.*/
|
||||
dmastp->channel->CCR |= STM32_GPDMA_CCR_RESET;
|
||||
dmastp->channel->CCR = 0U;
|
||||
|
||||
/* Clearing all interrupts.*/
|
||||
dmastp->channel->CFCR = STM32_GPDMA_CFCR_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serves a GPDMA IRQ.
|
||||
*
|
||||
* @param[in] dmachp pointer to a @p stm32_gpdma_channel_t structure
|
||||
*
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file GPDMAv1/stm32_gpdma.h
|
||||
* @file DMAv1/stm32_gpdma.h
|
||||
* @brief GPDMA helper driver header.
|
||||
*
|
||||
* @addtogroup STM32_GPDMA
|
||||
|
@ -32,7 +32,7 @@
|
|||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name GPDMA registers helpers
|
||||
* @name DMA registers helpers
|
||||
* @{
|
||||
*/
|
||||
#define STM32_GPDMA_CLBAR_LBA_POS DMA_CLBAR_LBA_Pos
|
||||
|
@ -46,6 +46,10 @@
|
|||
#define STM32_GPDMA_CFCR_DTEF DMA_CFCR_DTEF
|
||||
#define STM32_GPDMA_CFCR_HTF DMA_CFCR_HTF
|
||||
#define STM32_GPDMA_CFCR_TCF DMA_CFCR_TCF
|
||||
#define STM32_GPDMA_CFCR_ALL (DMA_CFCR_TOF | DMA_CFCR_SUSPF | \
|
||||
DMA_CFCR_USEF | DMA_CFCR_ULEF | \
|
||||
DMA_CFCR_DTEF | DMA_CFCR_HTF | \
|
||||
DMA_CFCR_TCF)
|
||||
|
||||
#define STM32_GPDMA_CSR_FIFOL_POS DMA_CSR_FIFOL_Pos
|
||||
#define STM32_GPDMA_CSR_FIFOL_MASK (0x7FU << STM32_GPDMA_CSR_FIFOL_POS)
|
||||
|
@ -63,21 +67,21 @@
|
|||
DMA_CSR_DTEF | DMA_CSR_HTF | \
|
||||
DMA_CSR_TCF)
|
||||
|
||||
#define STM32_GPDMA_CR_PRIO_POS DMA_CCR_PRIO_Pos
|
||||
#define STM32_GPDMA_CR_PRIO_MASK (3U << STM32_GPDMA_CR_PRIO_POS)
|
||||
#define STM32_GPDMA_CR_PRIO(n) ((n) << STM32_GPDMA_CR_PRIO_POS)
|
||||
#define STM32_GPDMA_CR_LAP DMA_CCR_LAP
|
||||
#define STM32_GPDMA_CR_LSM DMA_CCR_LSM
|
||||
#define STM32_GPDMA_CR_TOIE DMA_CCR_TOIE
|
||||
#define STM32_GPDMA_CR_SUSPIE DMA_CCR_SUSPIE
|
||||
#define STM32_GPDMA_CR_USEIE DMA_CCR_USEIE
|
||||
#define STM32_GPDMA_CR_ULEIE DMA_CCR_ULEIE
|
||||
#define STM32_GPDMA_CR_DTEIE DMA_CCR_DTEIE
|
||||
#define STM32_GPDMA_CR_HTIE DMA_CCR_HTIE
|
||||
#define STM32_GPDMA_CR_TCIE DMA_CCR_TCIE
|
||||
#define STM32_GPDMA_CR_SUSP DMA_CCR_SUSP
|
||||
#define STM32_GPDMA_CR_RESET DMA_CCR_RESET
|
||||
#define STM32_GPDMA_CR_EN DMA_CCR_EN
|
||||
#define STM32_GPDMA_CCR_PRIO_POS DMA_CCR_PRIO_Pos
|
||||
#define STM32_GPDMA_CCR_PRIO_MASK (3U << STM32_GPDMA_CR_PRIO_POS)
|
||||
#define STM32_GPDMA_CCR_PRIO(n) ((n) << STM32_GPDMA_CR_PRIO_POS)
|
||||
#define STM32_GPDMA_CCR_LAP DMA_CCR_LAP
|
||||
#define STM32_GPDMA_CCR_LSM DMA_CCR_LSM
|
||||
#define STM32_GPDMA_CCR_TOIE DMA_CCR_TOIE
|
||||
#define STM32_GPDMA_CCR_SUSPIE DMA_CCR_SUSPIE
|
||||
#define STM32_GPDMA_CCR_USEIE DMA_CCR_USEIE
|
||||
#define STM32_GPDMA_CCR_ULEIE DMA_CCR_ULEIE
|
||||
#define STM32_GPDMA_CCR_DTEIE DMA_CCR_DTEIE
|
||||
#define STM32_GPDMA_CCR_HTIE DMA_CCR_HTIE
|
||||
#define STM32_GPDMA_CCR_TCIE DMA_CCR_TCIE
|
||||
#define STM32_GPDMA_CCR_SUSP DMA_CCR_SUSP
|
||||
#define STM32_GPDMA_CCR_RESET DMA_CCR_RESET
|
||||
#define STM32_GPDMA_CCR_EN DMA_CCR_EN
|
||||
|
||||
#define STM32_GPDMA_CTR1_DSEC DMA_CTR1_DSEC
|
||||
#define STM32_GPDMA_CTR1_DAP DMA_CTR1_DAP
|
||||
|
@ -143,6 +147,31 @@
|
|||
#define STM32_GPDMA_CBR1_BNDT_MASK (3U << STM32_GPDMA_CBR1_BNDT_POS)
|
||||
#define STM32_GPDMA_CBR1_BNDT(n) ((n) << STM32_GPDMA_CBR1_BNDT_POS)
|
||||
|
||||
#define STM32_GPDMA_CTR3_DAO_POS DMA_CTR3_DAO_Pos
|
||||
#define STM32_GPDMA_CTR3_DAO_MASK (0x1FFFU << STM32_GPDMA_CTR3_DAO_POS)
|
||||
#define STM32_GPDMA_CTR3_DAO(n) ((n) << STM32_GPDMA_CTR3_DAO_POS)
|
||||
#define STM32_GPDMA_CTR3_SAO_POS DMA_CTR3_SAO_Pos
|
||||
#define STM32_GPDMA_CTR3_SAO_MASK (0x1FFFU << STM32_GPDMA_CTR3_SAO_POS)
|
||||
#define STM32_GPDMA_CTR3_SAO(n) ((n) << STM32_GPDMA_CTR3_SAO_POS)
|
||||
|
||||
#define STM32_GPDMA_CBR2_BRDAO_POS DMA_CBR2_BRDAO_Pos
|
||||
#define STM32_GPDMA_CBR2_BRDAO_MASK (0xFFFFU << STM32_GPDMA_CBR2_BRDAO_POS)
|
||||
#define STM32_GPDMA_CBR2_BRDAO(n) ((n) << STM32_GPDMA_CBR2_BRDAO_POS)
|
||||
#define STM32_GPDMA_CBR2_BRSAO_POS DMA_CBR2_BRSAO_Pos
|
||||
#define STM32_GPDMA_CBR2_BRSAO_MASK (0xFFFFU << STM32_GPDMA_CBR2_BRSAO_POS)
|
||||
#define STM32_GPDMA_CBR2_BRSAO(n) ((n) << STM32_GPDMA_CBR2_BRSAO_POS)
|
||||
|
||||
#define STM32_GPDMA_CLLR_UT1 DMA_CLLR_UT1
|
||||
#define STM32_GPDMA_CLLR_UT2 DMA_CLLR_UT2
|
||||
#define STM32_GPDMA_CLLR_UB1 DMA_CLLR_UB1
|
||||
#define STM32_GPDMA_CLLR_USA DMA_CLLR_USA
|
||||
#define STM32_GPDMA_CLLR_UDA DMA_CLLR_UDA
|
||||
#define STM32_GPDMA_CLLR_UT3 DMA_CLLR_UT3
|
||||
#define STM32_GPDMA_CLLR_UB2 DMA_CLLR_UB2
|
||||
#define STM32_GPDMA_CLLR_ULL DMA_CLLR_ULL
|
||||
#define STM32_GPDMA_CLLR_LA_POS DMA_CLLR_LA_Pos
|
||||
#define STM32_GPDMA_CLLR_LA_MASK (0xFFFCU << STM32_GPDMA_CLLR_LA_POS)
|
||||
#define STM32_GPDMA_CLLR_LA(n) ((n) << STM32_GPDMA_CLLR_LA_POS)
|
||||
/** @< */
|
||||
|
||||
/**
|
||||
|
@ -156,7 +185,7 @@
|
|||
|
||||
/**
|
||||
* @brief Checks if a GPDMA priority is within the valid range.
|
||||
* @param[in] prio GPDMA priority
|
||||
* @param[in] prio DMA priority
|
||||
*
|
||||
* @retval The check result.
|
||||
* @retval false invalid GPDMA priority.
|
||||
|
@ -187,7 +216,7 @@
|
|||
(1U << STM32_GPDMA_CHANNEL_ID(dma, ch))
|
||||
|
||||
/**
|
||||
* @name GPDMA channels identifiers
|
||||
* @name DMA channels identifiers
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
|
@ -315,12 +344,12 @@
|
|||
* @brief Type of a GPDMA callback.
|
||||
*
|
||||
* @param[in] p parameter for the registered function
|
||||
* @param[in] v content of the CxSR register
|
||||
* @param[in] csr content of the CxSR register
|
||||
*/
|
||||
typedef void (*stm32_gpdmaisr_t)(void *p, uint32_t csr);
|
||||
|
||||
/**
|
||||
* @brief STM32 DMA channel descriptor structure.
|
||||
* @brief STM32 GPDMA channel descriptor structure.
|
||||
*/
|
||||
typedef struct {
|
||||
DMA_Channel_TypeDef *channel; /**< @brief Associated channel. */
|
||||
|
@ -336,7 +365,7 @@ typedef struct {
|
|||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Associates a peripheral data register to a DMA channel.
|
||||
* @brief Associates a peripheral data register to a GPDMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAlloc().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
|
@ -351,7 +380,7 @@ typedef struct {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Associates a memory destination to a DMA channel.
|
||||
* @brief Associates a memory destination to a GPDMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAlloc().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
|
@ -409,7 +438,7 @@ typedef struct {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable.
|
||||
* @brief GPDMA channel enable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAlloc().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
|
@ -423,7 +452,7 @@ typedef struct {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable.
|
||||
* @brief GPDMA channel disable.
|
||||
* @details The function disables the specified channel and then clears any
|
||||
* pending interrupt.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
|
@ -436,14 +465,14 @@ typedef struct {
|
|||
*
|
||||
* @special
|
||||
*/
|
||||
#define gpdmaStreamDisable(dmastp) { \
|
||||
#define ______gpdmaStreamDisable(dmastp) { \
|
||||
(dmastp)->channel->CCR &= ~(STM32_GPDMA_CR_TCIE | STM32_GPDMA_CR_HTIE | \
|
||||
STM32_GPDMA_CR_TEIE | STM32_GPDMA_CR_EN); \
|
||||
dmaStreamClearInterrupt(dmastp); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA channel interrupt sources clear.
|
||||
* @brief GPDMA channel interrupt sources clear.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAlloc().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
|
@ -485,7 +514,7 @@ typedef struct {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Polled wait for DMA transfer end.
|
||||
* @brief Polled wait for GPDMA transfer end.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAlloc().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
*
|
||||
|
@ -520,6 +549,8 @@ extern "C" {
|
|||
void *param);
|
||||
void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp);
|
||||
void gpdmaChannelFree(const stm32_gpdma_channel_t *dmachp);
|
||||
void gpdmaChannelSuspend(const stm32_gpdma_channel_t *dmastp);
|
||||
void gpdmaChannelDisable(const stm32_gpdma_channel_t *dmastp);
|
||||
void gpdmaServeInterrupt(const stm32_gpdma_channel_t *dmachp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -518,7 +518,7 @@
|
|||
*
|
||||
* @api
|
||||
*/
|
||||
#define rccDisableGPDMA1() rccDisableGPAHB1(RCC_AHB1ENR_GPDMA1EN)
|
||||
#define rccDisableGPDMA1() rccDisableAHB1(RCC_AHB1ENR_GPDMA1EN)
|
||||
|
||||
/**
|
||||
* @brief Resets the GPDMA1 peripheral.
|
||||
|
|
Loading…
Reference in New Issue