From 8fa88b0b7d247133af2642b61c04abbbdeb61bc6 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Fri, 16 Apr 2021 07:49:24 +0000 Subject: [PATCH] RP2040 DMA-related code. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14197 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/common/ext/RP/RP2040/rp2040.h | 34 +++++---- os/hal/ports/RP/LLD/DMAv1/rp_dma.c | 5 +- os/hal/ports/RP/LLD/DMAv1/rp_dma.h | 109 +++++++++++++++++++++++++++++ os/hal/ports/RP/RP2040/hal_lld.h | 1 + os/hal/ports/RP/RP2040/platform.mk | 1 + 5 files changed, 135 insertions(+), 15 deletions(-) diff --git a/os/common/ext/RP/RP2040/rp2040.h b/os/common/ext/RP/RP2040/rp2040.h index 938630953..cb8d4c7bf 100644 --- a/os/common/ext/RP/RP2040/rp2040.h +++ b/os/common/ext/RP/RP2040/rp2040.h @@ -85,13 +85,21 @@ typedef enum { * @{ */ typedef struct { - struct { - __IO uint32_t READ_ADDR; - __IO uint32_t WRITE_ADDR; - __IO uint32_t TRANS_COUNT; - __IO uint32_t CTRL_TRIG; - __I uint32_t resvd10[12]; - } CH[12]; + __IO uint32_t READ_ADDR; + __IO uint32_t WRITE_ADDR; + __IO uint32_t TRANS_COUNT; + __IO uint32_t CTRL_TRIG; + __I uint32_t resvd10[12]; +} DMA_Channel_Typedef; + +typedef struct { + __I uint32_t CTDREQ; + __I uint32_t TCR; + __I uint32_t resvd8[56]; +} DMA_Debug_Typedef; + +typedef struct { + DMA_Channel_Typedef CH[12]; __I uint32_t resvd300[64]; __IO uint32_t INTR; struct { @@ -107,11 +115,7 @@ typedef struct { __IO uint32_t CHAN_ABORT; __I uint32_t N_CHANNELS; __I uint32_t resvd44C[237]; - struct { - __I uint32_t CTDREQ; - __I uint32_t TCR; - __I uint32_t resvd8[56]; - } CH_DBG[12]; + DMA_Debug_Typedef CH_DBG[12]; } DMA_TypeDef; typedef struct { @@ -430,6 +434,9 @@ typedef struct { #define __IOPORT_BASE 0xD0000000U #define __DMA_BASE (__APBPERIPH_BASE + 0x00000000U) +#define __DMA_XOR_BASE (__APBPERIPH_BASE + 0x00001000U) +#define __DMA_SET_BASE (__APBPERIPH_BASE + 0x00002000U) +#define __DMA_CLR_BASE (__APBPERIPH_BASE + 0x00003000U) #define __RESETS_BASE (__APBPERIPH_BASE + 0x0000C000U) #define __IOUSER0_BASE (__APBPERIPH_BASE + 0x00014000U) #define __IOQSPI_BASE (__APBPERIPH_BASE + 0x00018000U) @@ -463,6 +470,9 @@ typedef struct { * @{ */ #define DMA ((DMA_TypeDef *) __DMA_BASE) +#define DMA_XOR ((DMA_TypeDef *) __DMA_XOR_BASE) +#define DMA_SET ((DMA_TypeDef *) __DMA_SET_BASE) +#define DMA_CLR ((DMA_TypeDef *) __DMA_CLR_BASE) #define IO_BANK0 ((IOUSER_TypeDef *) __IOUSER0_BASE) #define IO_QSPI ((IOUSER_TypeDef *) __IOQSPI_BASE) #define PADS_BANK0 ((PADS_TypeDef *) __PADSUSER0_BASE) diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c index e30d340dd..aa8d8d34f 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.c +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.c @@ -101,9 +101,8 @@ const rp_dma_channel_t *dmaChannelAllocI(uint32_t id, * @api */ const rp_dma_channel_t *dmaChannelAlloc(uint32_t id, - uint32_t priority, - rp_dmaisr_t func, - void *param) { + rp_dmaisr_t func, + void *param) { } /** diff --git a/os/hal/ports/RP/LLD/DMAv1/rp_dma.h b/os/hal/ports/RP/LLD/DMAv1/rp_dma.h index 28403628a..e7d32a35f 100644 --- a/os/hal/ports/RP/LLD/DMAv1/rp_dma.h +++ b/os/hal/ports/RP/LLD/DMAv1/rp_dma.h @@ -78,6 +78,9 @@ typedef void (*rp_dmaisr_t)(void *p, uint32_t flags); */ typedef struct { DMA_TypeDef *dma; /**< @brief Associated DMA. */ + DMA_Channel_Typedef *channel; /**< @brief Associated DMA channel. */ + uint32_t chnidx; /**< @brief Index to self in array. */ + uint32_t chnmask; /**< @brief Channel bit mask. */ } rp_dma_channel_t; /*===========================================================================*/ @@ -115,6 +118,112 @@ extern "C" { } #endif +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Setup of the source DMA pointer. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + * @param[in] addr value to be written in the @p READ_ADDR register + * + * @special + */ +__STATIC_INLINE void dmaChannelSetSource(const rp_dma_channel_t *dmachp, + uint32_t addr) { + + dmachp->channel->READ_ADDR = addr; +} + +/** + * @brief Setup of the destination DMA pointer. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + * @param[in] addr value to be written in the @p WRITE_ADDR register + * + * @special + */ +__STATIC_INLINE void dmaChannelSetDestination(const rp_dma_channel_t *dmachp, + uint32_t addr) { + + dmachp->channel->WRITE_ADDR = addr; +} + +/** + * @brief Setup of the DMA transfer counter. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + * @param[in] n value to be written in the @p TRANS_COUNT register + * + * @special + */ +__STATIC_INLINE void dmaChannelSetCounter(const rp_dma_channel_t *dmachp, + uint32_t n) { + + dmachp->channel->TRANS_COUNT = n; +} + +/** + * @brief Setup of the DMA transfer mode without linking. + * @note The link field is enforced to "self" meaning no linking. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + * @param[in] mode value to be written in the @p CTRL_TRIG register + * except link field + * + * @special + */ +__STATIC_INLINE void dmaChannelSetMode(const rp_dma_channel_t *dmachp, + uint32_t mode) { + + dmachp->channel->CTRL_TRIG = (mode & ~DMA_CTRL_TRIG_CHAIN_TO_Msk) | + DMA_CTRL_TRIG_CHAIN_TO(dmachp->chnidx); +} + +/** + * @brief Enables a DMA channel. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + + * + * @special + */ +__STATIC_INLINE void dmaChannelEnable(const rp_dma_channel_t *dmachp) { + + dmachp->channel->CTRL_TRIG |= DMA_CTRL_TRIG_EN; +} + +/** + * @brief Disables a DMA channel aborting the current transfer. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + + * + * @special + */ +__STATIC_INLINE void dmaChannelDisable(const rp_dma_channel_t *dmachp) { + + dmachp->dma->CHAN_ABORT |= dmachp->chnmask; + while ((dmachp->dma->CHAN_ABORT & dmachp->chnmask) != 0U) { + } +} + +/** + * @brief Returns the channel busy state. + * + * @param[in] dmachp pointer to a rp_dma_channel_t structure + * @return The channel busy state. + * @retval false if the channel is not busy. + * @retval true if the channel is busy. + * + * @special + */ +__STATIC_INLINE bool dmaChannelIsBusy(const rp_dma_channel_t *dmachp) { + + return (bool)((dmachp->channel->CTRL_TRIG & DMA_CTRL_TRIG_BUSY) != 0U); +} + #endif /* RP_DMA_H */ /** @} */ diff --git a/os/hal/ports/RP/RP2040/hal_lld.h b/os/hal/ports/RP/RP2040/hal_lld.h index 093092fff..0626d3600 100644 --- a/os/hal/ports/RP/RP2040/hal_lld.h +++ b/os/hal/ports/RP/RP2040/hal_lld.h @@ -153,6 +153,7 @@ typedef enum clock_index clock_index_t; #include "cache.h" #include "rp_isr.h" #include "rp_fifo.h" +#include "rp_dma.h" #ifdef __cplusplus extern "C" { diff --git a/os/hal/ports/RP/RP2040/platform.mk b/os/hal/ports/RP/RP2040/platform.mk index f5000556d..693575e1d 100644 --- a/os/hal/ports/RP/RP2040/platform.mk +++ b/os/hal/ports/RP/RP2040/platform.mk @@ -25,6 +25,7 @@ else endif # Drivers compatible with the platform. +include $(CHIBIOS)/os/hal/ports/RP/LLD/DMAv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/GPIOv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/TIMERv1/driver.mk include $(CHIBIOS)/os/hal/ports/RP/LLD/UARTv1/driver.mk