mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
378 lines
18 KiB
C
378 lines
18 KiB
C
/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
|
|
* Use, distribution and modification of this code is permitted under the
|
|
* terms stated in the Alif Semiconductor Software License Agreement
|
|
*
|
|
* You should have received a copy of the Alif Semiconductor Software
|
|
* License Agreement with this file. If not, please write to:
|
|
* contact@alifsemi.com, or visit: https://alifsemi.com/license
|
|
*
|
|
*/
|
|
/**************************************************************************//**
|
|
* @file dma.h
|
|
* @author Sudhir Sreedharan
|
|
* @email sudhir@alifsemi.com
|
|
* @version V1.0.0
|
|
* @date 11-08-2023
|
|
* @brief Low Level Header file for DMA
|
|
* @bug None.
|
|
* @Note None
|
|
******************************************************************************/
|
|
|
|
#ifndef DMA_H_
|
|
#define DMA_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief DMA_DMA_CHANNEL_RT_INFO_Type [DMA_CHANNEL_RT_INFO] ([0..7])
|
|
*/
|
|
typedef struct {
|
|
volatile const uint32_t DMA_CSR; /*!< (@ 0x00000000) Channel Status for DMA Channel (n) Register */
|
|
volatile const uint32_t DMA_CPC; /*!< (@ 0x00000004) Channel PC for DMA Channel (n) Register */
|
|
} DMA_DMA_CHANNEL_RT_INFO_Type; /*!< Size = 8 (0x8) */
|
|
|
|
|
|
/**
|
|
* @brief DMA_DMA_RT_CHANNEL_CFG_Type [DMA_RT_CHANNEL_CFG] ([0..7])
|
|
*/
|
|
typedef struct {
|
|
volatile const uint32_t DMA_SAR; /*!< (@ 0x00000000) Source Address for DMA Channel (n) Register */
|
|
volatile const uint32_t DMA_DAR; /*!< (@ 0x00000004) Destination Address for DMA Channel (n) Register */
|
|
volatile const uint32_t DMA_CCR; /*!< (@ 0x00000008) Channel Control for DMA Channel (n) Register */
|
|
volatile const uint32_t DMA_LC0; /*!< (@ 0x0000000C) Loop Counter 0 for DMA Channel (n) Register */
|
|
volatile const uint32_t DMA_LC1; /*!< (@ 0x00000010) Loop Counter 1 for DMA Channel (n) Register */
|
|
volatile const uint32_t RESERVED[3];
|
|
} DMA_DMA_RT_CHANNEL_CFG_Type; /*!< Size = 32 (0x20) */
|
|
|
|
|
|
/**
|
|
* @brief DMA (DMA)
|
|
*/
|
|
|
|
typedef struct { /*!< (@ 0x00000000) DMA Structure */
|
|
volatile const uint32_t DMA_DSR; /*!< (@ 0x00000000) DMA Manager Status Register */
|
|
volatile const uint32_t DMA_DPC; /*!< (@ 0x00000004) DMA Program Counter Register */
|
|
volatile const uint32_t RESERVED[6];
|
|
volatile uint32_t DMA_INTEN; /*!< (@ 0x00000020) Interrupt Enable Register */
|
|
volatile const uint32_t DMA_INT_EVENT_RIS; /*!< (@ 0x00000024) Event-Interrupt Raw Status Register */
|
|
volatile const uint32_t DMA_INTMIS; /*!< (@ 0x00000028) Interrupt Status Register */
|
|
volatile uint32_t DMA_INTCLR; /*!< (@ 0x0000002C) Interrupt Clear Register */
|
|
volatile const uint32_t DMA_FSRD; /*!< (@ 0x00000030) Fault Status DMA Manager Register */
|
|
volatile const uint32_t DMA_FSRC; /*!< (@ 0x00000034) Fault Status DMA Channel Register */
|
|
volatile const uint32_t DMA_FTRD; /*!< (@ 0x00000038) Fault Type DMA Manager Register */
|
|
volatile const uint32_t RESERVED1;
|
|
volatile const uint32_t DMA_FTR[8]; /*!< (@ 0x00000040) Fault Type for DMA Channel (n) Register */
|
|
volatile const uint32_t RESERVED2[40];
|
|
volatile DMA_DMA_CHANNEL_RT_INFO_Type DMA_CHANNEL_RT_INFO[8];/*!< (@ 0x00000100) [0..7] */
|
|
volatile const uint32_t RESERVED3[176];
|
|
volatile DMA_DMA_RT_CHANNEL_CFG_Type DMA_RT_CHANNEL_CFG[8];/*!< (@ 0x00000400) [0..7] */
|
|
volatile const uint32_t RESERVED4[512];
|
|
volatile const uint32_t DMA_DBGSTATUS; /*!< (@ 0x00000D00) Debug Status Register */
|
|
volatile uint32_t DMA_DBGCMD; /*!< (@ 0x00000D04) Debug Command Register */
|
|
volatile uint32_t DMA_DBGINST0; /*!< (@ 0x00000D08) Debug Instruction Register 0 */
|
|
volatile uint32_t DMA_DBGINST1; /*!< (@ 0x00000D0C) Debug Instruction Register 1 */
|
|
volatile const uint32_t RESERVED5[60];
|
|
volatile const uint32_t DMA_CR0; /*!< (@ 0x00000E00) Configuration Register 0 */
|
|
volatile const uint32_t DMA_CR1; /*!< (@ 0x00000E04) Configuration Register 1 */
|
|
volatile const uint32_t DMA_CR2; /*!< (@ 0x00000E08) Configuration Register 2 */
|
|
volatile const uint32_t DMA_CR3; /*!< (@ 0x00000E0C) Configuration Register 3 */
|
|
volatile const uint32_t DMA_CR4; /*!< (@ 0x00000E10) Configuration Register 4 */
|
|
volatile const uint32_t DMA_CRD; /*!< (@ 0x00000E14) DMA Configuration Register */
|
|
volatile const uint32_t RESERVED6[26];
|
|
volatile uint32_t DMA_WD; /*!< (@ 0x00000E80) Watchdog Register */
|
|
} DMA_Type; /*!< Size = 3716 (0xe84) */
|
|
|
|
/* Register fields and masks */
|
|
|
|
/* DMA DSR: Status of Manager thread */
|
|
#define DMA_DSR_DMA_STATUS_Pos 0U
|
|
#define DMA_DSR_DMA_STATUS_Msk (0xFUL << DMA_DSR_DMA_STATUS_Pos)
|
|
#define DMA_DSR_WAKEUP_EVENT_Pos 4U
|
|
#define DMA_DSR_WAKEUP_EVENT_Msk (0x1FUL << DMA_DSR_WAKEUP_EVENT_Pos)
|
|
#define DMA_DSR_DNS_Pos 9U
|
|
#define DMA_DSR_DNS_Msk (0x1UL << DMA_DSR_DNS_Pos)
|
|
|
|
/* DMA FSRD: Fault Status of Manager */
|
|
#define DMA_FSRD_FS_MGR_Pos 0U
|
|
#define DMA_FSRD_FS_MGR_Msk (0x1UL << DMA_FSRD_FS_MGR_Pos)
|
|
|
|
/* DMA FSRC: Fault Status of Channels */
|
|
#define DMA_FSRC_FAULT_STATUS_Pos 0U
|
|
#define DMA_FSRC_FAULT_STATUS_Msk (0xFFUL << DMA_FSRC_FAULT_STATUS_Pos)
|
|
|
|
/* DMA CSR: Channel Status */
|
|
#define DMA_CSR_CHANNEL_STATUS_Pos 0U
|
|
#define DMA_CSR_CHANNEL_STATUS_Msk (0xFUL << DMA_CSR_CHANNEL_STATUS_Pos)
|
|
#define DMA_CSR_WAKEUP_NUMBER_Pos 4U
|
|
#define DMA_CSR_WAKEUP_NUMBER_Msk (0x1FUL << DMA_CSR_WAKEUP_NUMBER_Pos)
|
|
#define DMA_CSR_DMAWFP_B_NS_Pos 14U
|
|
#define DMA_CSR_DMAWFP_B_NS_Msk (0x1UL << DMA_CSR_DMAWFP_B_NS_Pos)
|
|
#define DMA_CSR_DMAWFP_PERIPH_Pos 15U
|
|
#define DMA_CSR_DMAWFP_PERIPH_Msk (0x1UL << DMA_CSR_DMAWFP_PERIPH_Pos)
|
|
#define DMA_CSR_CNS_Pos 21U
|
|
#define DMA_CSR_CNS_Msk (0x1UL << DMA_CSR_CNS_Pos)
|
|
|
|
/* DMA DBGSTATUS: Debug Status */
|
|
#define DMA_DBGSTATUS_DBGSTATUS_Pos 0U
|
|
#define DMA_DBGSTATUS_DBGSTATUS_Msk (0x1UL << DMA_DBGSTATUS_DBGSTATUS_Pos)
|
|
|
|
/* DMA WD.IRQ.ONLY: Watchdog IRQ Only */
|
|
#define DMA_WD_IRQ_ONLY_Pos 0U
|
|
#define DMA_WD_IRQ_ONLY_Msk (0x1UL << DMA_WD_IRQ_ONLY_Pos)
|
|
|
|
#define DMA_MAX_CHANNELS 8 /*!< Max 8 channels supported */
|
|
#define DMA_MAX_PERIPH_REQ 32 /*!< Max 32 peripheral requests supported */
|
|
#define DMA_MAX_EVENTS 32 /*!< Max 32 events supported */
|
|
#define DMA_MAX_IRQ 32 /*!< Max 32 irqs supported */
|
|
#define DMA_MAX_BURST_LEN 16 /*!< Max 16 xfers are supported */
|
|
#define DMA_MAX_BURST_SIZE 8 /*!< Max 8bytes(DATA_WIDTH/8) */
|
|
#define DMA_MAX_BUFF_DEPTH 128 /*!< 32lines * 4bytes for each FIFO */
|
|
|
|
#define DMA_IRQ_ABORT_OFFSET 32 /*!< Abort irq offset */
|
|
|
|
/**
|
|
* enum DMA_THREAD
|
|
* DMA Thread: Manager and Channel Thread
|
|
*/
|
|
typedef enum _DMA_THREAD {
|
|
DMA_THREAD_MANAGER = 0, /*!< DMA Manager thread */
|
|
DMA_THREAD_CHANNEL, /*!< DMA Channel thread */
|
|
} DMA_THREAD;
|
|
|
|
/**
|
|
* enum DMA_THREAD_STATUS
|
|
* DMA Thread Status: Covers both Manager and Channel Thread Status.
|
|
*/
|
|
typedef enum _DMA_THREAD_STATUS {
|
|
DMA_THREAD_STATUS_STOPPED = 0, /*!< MGR/CHNL Thread is Stopped */
|
|
DMA_THREAD_STATUS_EXECUTING, /*!< MGR/CHNL Thread is executing */
|
|
DMA_THREAD_STATUS_CACHE_MISS, /*!< MGR/CHNL Cache miss occurred */
|
|
DMA_THREAD_STATUS_UPDATING_PC, /*!< MGR/CHNL Thread is updating the program counter */
|
|
DMA_THREAD_STATUS_WAITING_FOR_EVENT, /*!< MGR/CHNL Thread is waiting for an event */
|
|
DMA_THREAD_STATUS_AT_BARRIER, /*!< CHNL Thread is waiting at an barrier */
|
|
DMA_THREAD_STATUS_WAITING_FOR_PERIPHERAL = 7, /*!< CHNL Thread is waiting for a peripheral */
|
|
DMA_THREAD_STATUS_KILLING, /*!< CHNL Thread is at killing state */
|
|
DMA_THREAD_STATUS_COMPLETING, /*!< CHNL Thread is at completing state */
|
|
DMA_THREAD_STATUS_FAULTING_COMPLETING = 14, /*!< CHNL Thread is in faulting completing state */
|
|
DMA_THREAD_STATUS_FAULTING = 15, /*!< MGR/CHNL Thread is in Faulting State */
|
|
} DMA_THREAD_STATUS;
|
|
|
|
/* Fault Type DMA Manager Register */
|
|
typedef union _dma_ftrd_t {
|
|
uint32_t ftrd;
|
|
struct {
|
|
uint32_t undef_instr : 1; /*!< Undefined Instruction */
|
|
uint32_t operand_invalid : 1; /*!< Invalid arguments passed */
|
|
uint32_t RESERVED1 : 2; /*!< Reserved */
|
|
uint32_t dmago_err : 1; /*!< Security aspect while executing DMAGO */
|
|
uint32_t mgr_evnt_err : 1; /*!< security aspect while executing DMAWFE or DMASEV */
|
|
uint32_t RESERVED2 : 10; /*!< Reserved */
|
|
uint32_t instr_fetch_err : 1; /*!< Instr fetch error on AXI */
|
|
uint32_t RESERVED3 : 13; /*!< Reserved */
|
|
uint32_t dbg_instr : 1; /*!< Instr read from system or debug interface */
|
|
} ftrd_b;
|
|
} dma_ftrd_t;
|
|
|
|
/* Fault Type DMA Channel Register */
|
|
typedef union _dma_ftr {
|
|
uint32_t ftr;
|
|
struct {
|
|
uint32_t undef_instr : 1; /*!< Undefined Instruction */
|
|
uint32_t operand_invalid : 1; /*!< Invalid arguments passed */
|
|
uint32_t reserved1 : 3; /*!< Reserved */
|
|
uint32_t ch_evnt_err : 1; /*!< security aspect while executing DMAWFE or DMASEV */
|
|
uint32_t ch_periph_err : 1; /*!< security aspect while executing DMAWFP/DMALDP/DMASTP/DMAFLUSHP */
|
|
uint32_t ch_rdwr_err : 1; /*!< security aspect while programming CCRn */
|
|
uint32_t reserved2 : 4; /*!< Reserved */
|
|
uint32_t mfifo_err : 1; /*!< mfifo prevented channel from executing DMALD/DMAST */
|
|
uint32_t no_st_data : 1; /*!< mfifo didn't contain data to perform DMAST */
|
|
uint32_t reserved3 : 2; /*!< Reserved */
|
|
uint32_t instr_fetch_err : 1; /*!< AXI response on inst fetch */
|
|
uint32_t data_write_err : 1; /*!< AXI response on data write */
|
|
uint32_t data_read_err : 1; /*!< AXI response on data read */
|
|
uint32_t reserved4 : 11; /*!< Reserved */
|
|
uint32_t dbg_instr : 1; /*!< Instr read from system or debug interface */
|
|
uint32_t lockup_err : 1; /*!< channel lockedup due to resource starvation */
|
|
} ftr_b;
|
|
} dma_ftr;
|
|
|
|
/* DMA Instruction0 Register */
|
|
typedef union _dma_dbginst0_t {
|
|
uint32_t dbginst0;
|
|
struct {
|
|
uint32_t dbg_thrd : 1; /*!< Debug Manager/Channel Thread */
|
|
uint32_t reserved1 : 7; /*!< Reserved */
|
|
uint32_t chn_num : 3; /*!< Channel number */
|
|
uint32_t reserved2 : 5; /*!< Reserved */
|
|
uint32_t ins_byte0 : 8; /*!< Instruction byte 0 */
|
|
uint32_t ins_byte1 : 8; /*!< Instruction byte 1 */
|
|
} dbginst0_b;
|
|
} dma_dbginst0_t;
|
|
|
|
/* DMA Instruction1 Register */
|
|
typedef union _dma_dbginst1_t {
|
|
uint32_t dbginst1;
|
|
struct {
|
|
uint32_t ins_byte2 : 8; /*!< Instruction byte 2 */
|
|
uint32_t ins_byte3 : 8; /*!< Instruction byte 3 */
|
|
uint32_t ins_byte4 : 8; /*!< Instruction byte 4 */
|
|
uint32_t ins_byte5 : 8; /*!< Instruction byte 5 */
|
|
} dbginst1_b;
|
|
} dma_dbginst1_t;
|
|
|
|
/**
|
|
\fn void dma_enable_interrupt(DMA_Type *dma,
|
|
uint8_t event_irq_select_index)
|
|
\brief Enable the interrupt for the requested interrupt line
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] event_irq_select_index Index of the interrupt to be enabled
|
|
*/
|
|
static inline void dma_enable_interrupt(DMA_Type *dma,
|
|
uint8_t event_irq_select_index)
|
|
{
|
|
dma->DMA_INTEN |= (1U << event_irq_select_index);
|
|
}
|
|
|
|
/**
|
|
\fn void dma_disable_interrupt(DMA_Type *dma,
|
|
uint8_t event_irq_select_index)
|
|
\brief Disable the interrupt for the requested interrupt line
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] event_irq_select_index Index of the interrupt to be disabled
|
|
*/
|
|
static inline void dma_disable_interrupt(DMA_Type *dma,
|
|
uint8_t event_irq_select_index)
|
|
{
|
|
dma->DMA_INTEN &= ~(1U << event_irq_select_index);
|
|
}
|
|
|
|
/**
|
|
\fn void dma_clear_interrupt(DMA_Type *dma, uint8_t irq_clr_index)
|
|
\brief Clear the interrupt for the requested interrupt line
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] irq_clr_index Index of the interrupt to be cleared
|
|
*/
|
|
static inline void dma_clear_interrupt(DMA_Type *dma, uint8_t irq_clr_index)
|
|
{
|
|
dma->DMA_INTCLR = (1U << irq_clr_index);
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_manager_is_nonsecure(DMA_Type *dma)
|
|
\brief Get Security status of the Manager thread
|
|
\param[in] dma Pointer to DMA register map
|
|
\return bool True if Non-Secure
|
|
*/
|
|
static inline bool dma_manager_is_nonsecure(DMA_Type *dma)
|
|
{
|
|
return (dma->DMA_DSR & DMA_DSR_DNS_Msk);
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_manager_is_faulting(DMA_Type *dma)
|
|
\brief Get fault status of the Manager thread
|
|
\param[in] dma Pointer to DMA register map
|
|
\return bool True if Manager thread is faulting
|
|
*/
|
|
static inline bool dma_manager_is_faulting(DMA_Type *dma)
|
|
{
|
|
return (dma->DMA_FSRD & DMA_FSRD_FS_MGR_Msk);
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_get_channel_fault_status(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
\brief Get Fault status of the requested channel
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] channel_num Channel Number
|
|
\return bool True if channel is faulted
|
|
*/
|
|
static inline bool dma_get_channel_fault_status(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
{
|
|
return (dma->DMA_FSRC & (1 << channel_num));
|
|
}
|
|
|
|
/**
|
|
\fn DMA_THREAD_STATUS dma_get_channel_status(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
\brief Get Current status of the Channel
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] channel_num Channel Number
|
|
\return DMA_THREAD_STATUS channel status
|
|
*/
|
|
static inline DMA_THREAD_STATUS dma_get_channel_status(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
{
|
|
return (DMA_THREAD_STATUS)(dma->DMA_CHANNEL_RT_INFO[channel_num].DMA_CSR
|
|
& DMA_CSR_CHANNEL_STATUS_Msk);
|
|
}
|
|
|
|
/**
|
|
\fn uint32_t dma_get_channel_src_addr(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
\brief Get Source Address of the Channel
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] channel_num Channel Number
|
|
\return uint32_t Current Source Address
|
|
*/
|
|
static inline uint32_t dma_get_channel_src_addr(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
{
|
|
return dma->DMA_RT_CHANNEL_CFG[channel_num].DMA_SAR;
|
|
}
|
|
|
|
/**
|
|
\fn uint32_t dma_get_channel_dest_addr(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
\brief Get Destination Address of the Channel
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] channel_num Channel Number
|
|
\return uint32_t Current Destination Address
|
|
*/
|
|
static inline uint32_t dma_get_channel_dest_addr(DMA_Type *dma,
|
|
uint8_t channel_num)
|
|
{
|
|
return dma->DMA_RT_CHANNEL_CFG[channel_num].DMA_DAR;
|
|
}
|
|
|
|
/**
|
|
\fn bool dma_debug_is_busy(DMA_Type *dma)
|
|
\brief Get Debug Status of DMAC
|
|
\param[in] dma Pointer to DMA register map
|
|
\return bool True if DMAC is busy in executing debug CMDS
|
|
*/
|
|
static inline bool dma_debug_is_busy(DMA_Type *dma)
|
|
{
|
|
return (dma->DMA_DBGSTATUS & DMA_DBGSTATUS_DBGSTATUS_Msk);
|
|
}
|
|
|
|
/**
|
|
\fn void dma_execute(DMA_Type *dma,
|
|
uint32_t dbginst0,
|
|
uint32_t dbginst1)
|
|
\brief Execute command in DBGINST register
|
|
\param[in] dma Pointer to DMA register map
|
|
\param[in] dbginst0 DBGINST0
|
|
\param[in] dbginst1 DBGINST1
|
|
\return void
|
|
*/
|
|
static inline void dma_execute(DMA_Type *dma,
|
|
uint32_t dbginst0,
|
|
uint32_t dbginst1)
|
|
{
|
|
dma->DMA_DBGINST0 = dbginst0;
|
|
dma->DMA_DBGINST1 = dbginst1;
|
|
dma->DMA_DBGCMD = 0;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* DMA_H_ */
|