WXK
2024-09-18 05e2e954bd127de378a9d1dfbb0ed95d725aad63
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/********************************************************* * 
@file        : dmac.c 
@brief      :dmac driver source file in IP library 
@author     :zhongfeng
@version    :v1.0 
@date         :19/08/15
Copyright (C) 2019 Panchip Technology Corp. All rights reserved. 
***********************************************************/
#include "PanSeries.h"
#include "pan_dmac.h"
 
static uint8_t g_DmacChannels = 0;
 
/*
  * @brief       :enable dma
  * @param in  :where dma is the base address of dma peripheral
  * @retval    :none
*/
void DMAC_Init(DMA_T * dma)
{
    DMAC_DeInit(dma);
    /*dma enable*/
    dma->DMA_CFG_REG_L = 0x1;
}
/*
  * @brief       :disable dma & mask all dma interrupt
  * @param in  :where dma is the base address of dma peripheral
  * @retval    :none
*/
void DMAC_DeInit(DMA_T * dma)
{
    /*disable dma*/
    dma->DMA_CFG_REG_L = 0x0;
    /*mask interrupt*/
    dma->MSK_TFR_L = 0xff00ul;
    dma->MSK_BLOCK_L = 0xff00ul;
    dma->MSK_DSTTRAN_L = 0xff00ul;
    dma->MSK_ERR_L = 0xff00ul;
    dma->MSK_SRCTRAN_L = 0xff00ul;
}
/*
  * @brief       :clear interrupt mask to make sure intterupt enable
  * @param in  :where dma is the base address of dma peripheral
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2
  * @param in  :where FlgIdx is interrupt type,It could be:
  *                  DMAC_FLAG_INDEX_TFR    
  *                  DMAC_FLAG_INDEX_BLK    
  *                  DMAC_FLAG_INDEX_SRCTFR 
  *                  DMAC_FLAG_INDEX_DSTTFR 
  *                  DMAC_FLAG_INDEX_ERR    
  * @retval    :none
*/
void DMAC_ClrIntFlagMsk(DMA_T* dma, uint32_t ChIdx, uint32_t FlgIdx)
{
    /*choose the interrupt mask sequence*/
    uint32_t mask = DMAC_ChannelMask(ChIdx);
    /*write enable*/
    mask |= mask << 8;
    /*Clear specified interrupt mask*/
    ((__IO uint32_t*)(&(dma)->MSK_TFR_L))[FlgIdx] |= mask;
}
/*
  * @brief       :mask interrupt,interrupt is useless
  * @param in  :where dma is the base address of dma peripheral
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2
  * @param in  :where FlgIdx is interrupt type,It could be:
  *                  DMAC_FLAG_INDEX_TFR    
  *                  DMAC_FLAG_INDEX_BLK    
  *                  DMAC_FLAG_INDEX_SRCTFR 
  *                  DMAC_FLAG_INDEX_DSTTFR 
  *                  DMAC_FLAG_INDEX_ERR    
  * @retval    :none
*/
void DMAC_SetIntFlagMsk(DMA_T* dma, uint32_t ChIdx, uint32_t FlgIdx)
{
    /*choose the interrupt mask sequence*/
    uint32_t msk = DMAC_ChannelMask(ChIdx);
    uint32_t reg = ((__IO uint32_t*)(&(dma)->MSK_TFR_L))[FlgIdx] & (~msk);
    /*set specified interrupt mask,Operable when the write enable operation*/
    ((__IO uint32_t*)(&(dma)->MSK_TFR_L))[FlgIdx] = reg | (msk << 8);
}
/*
  * @brief       :set dma channel config,include control register and config register
  * @param in  :where dma is the base address of dma peripheral
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2
  * @param in  :where Config is the config of dma channel:    
  * @retval    :none
*/
void DMAC_SetChannelConfig(DMA_T * dma,uint32_t ChIdx,DMAC_ChannelConfigTypeDef *Config)
{
    __DMAC_ChannelConfigTypeDef* cfg = (__DMAC_ChannelConfigTypeDef*)Config;
    dma->CH[ChIdx].CTL_L = cfg->CTL_L;
    dma->CH[ChIdx].CTL_H = cfg->CTL_H;
    dma->CH[ChIdx].CFG_L = cfg->CFG_L;
    dma->CH[ChIdx].CFG_H = cfg->CFG_H;
}
/*
  * @brief       :get dma channel config,include control register and config register
  * @param in  :where dma is the base address of dma peripheral
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2
  * @param in  :where Config is the config of dma channel:    
  * @retval    :none
*/
void DMAC_GetChannelConfig(DMA_T * dma,uint32_t ChIdx,DMAC_ChannelConfigTypeDef *Config)
{
    __DMAC_ChannelConfigTypeDef* cfg = (__DMAC_ChannelConfigTypeDef*)Config;
    cfg->CTL_L = dma->CH[ChIdx].CTL_L;
    cfg->CTL_H = dma->CH[ChIdx].CTL_H;
    cfg->CFG_L = dma->CH[ChIdx].CFG_L;
    cfg->CFG_H = dma->CH[ChIdx].CFG_H;    
}
/*
  * @brief       :start dma channel to transmit
  * @param in  :where dma is the base address of dma peripheral
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2
  * @param in  :where Src is the address of source data:    
  * @param in  :where Dst is the address of destination data:      
  * @param in  :where Len is the block size number:      
  * @retval    :none
*/
void DMAC_StartChannel(DMA_T * dma,uint32_t ChIdx,void* Src,void* Dst,uint32_t Len)
{
    /*set the source address of dma transfer*/
    if(Src) dma->CH[ChIdx].SAR_L = (uint32_t)Src;
    /*set the destination address of dma transfer*/
    if(Dst) dma->CH[ChIdx].DAR_L = (uint32_t)Dst;
    /*set the number of block size, block_size = data_len / DataWidth*/
    if(Len) dma->CH[ChIdx].CTL_H = (dma->CH[ChIdx].CTL_H & (~0xffful)) | Len;
    /*DMA channel enable,start to transfer*/
    dma->CH_EN_REG_L |= (0x101ul << ChIdx);
}
/*
  * @brief       :stop dma channel
  * @param in  :where dma is the base address of dma peripheral
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2  
  * @retval    :none
*/
void DMAC_StopChannel(DMA_T * dma,uint32_t ChIdx)
{
    dma->CH_EN_REG_L = (dma->CH_EN_REG_L & (~(0x1ul << ChIdx))) | (0x100ul << ChIdx);
}
/*
  * @brief       :Acquire dma free channel
  * @param in  :where dma is the base address of dma peripheral      
  * @retval    :none
*/
uint32_t DMAC_AcquireChannel(DMA_T * dma)
{
    uint32_t idx;
    uint8_t msk;
    for(idx = 0, msk = 0x1; idx < DMAC_CHANNEL_NUMBER; idx++, msk <<= 1){
        if(!(g_DmacChannels & msk)){
            g_DmacChannels |= msk;
            return idx;
        }
    }
    return DMA_INVLID_CHANNEL;
}
/*
  * @brief       :release dma channel
  * @param in  :where dma is the base address of dma peripheral   
  * @param in  :where ChIdx is the dma channel number.It could be 0,1,2  
  * @retval    :none
*/
void DMAC_ReleaseChannel(DMA_T * dma, uint32_t ChIdx)
{
    g_DmacChannels &= ~(1ul << ChIdx);
}
 
bool DMAC_IsAllChannelReleased(DMA_T *dma)
{
    return (g_DmacChannels == 0);
}
 
/*-------------------------------------------------------*/