implement LPC1768 GPDMA API

Dependents:   LPC1768_DMA_implementation

Currently, only LPC1768 HAL level API have been implemented. You can also find the test code to test the m2p and m2m here http://mbed.org/users/steniu01/code/LPC1768_DMA_implementation/. The target is to implement the user side platform agnostic API to make it more easily to use DMA.

There are still quite a few things undone (list in priority order):

1. Implement user side API to provide platform agnostic user friendly API

2. Tidy up the codes and add more comments

3. Create more test cases

4. Fully test the codes using mbed sdk automated test suits

5. Implement LLI

Committer:
steniu01
Date:
Thu Aug 21 00:03:00 2014 +0000
Revision:
1:86b13bfcbe46
first workable version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
steniu01 1:86b13bfcbe46 1 #include "LPC1768_dma.h"
steniu01 1:86b13bfcbe46 2 /**
steniu01 1:86b13bfcbe46 3 * @brief Initializes the DMAy Channelx according to the specified parameters
steniu01 1:86b13bfcbe46 4 * in the DMA_InitStruct.
steniu01 1:86b13bfcbe46 5 * @param x can be 1 to 7 for DMA1 to select the DMA Channel.
steniu01 1:86b13bfcbe46 6 * @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure that contains
steniu01 1:86b13bfcbe46 7 * the configuration information for the specified DMA Channel.
steniu01 1:86b13bfcbe46 8 * @retval None
steniu01 1:86b13bfcbe46 9 */
steniu01 1:86b13bfcbe46 10 void DMA_init(LPC_GPDMACH_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
steniu01 1:86b13bfcbe46 11 {
steniu01 1:86b13bfcbe46 12 uint32_t tmpreg = 0;
steniu01 1:86b13bfcbe46 13
steniu01 1:86b13bfcbe46 14
steniu01 1:86b13bfcbe46 15 /* clear the pending interrupts on the channel to be used by writing to the DMACIntTCClear and DMACIntErrClear register. */
steniu01 1:86b13bfcbe46 16 if (DMAy_Channelx == LPC_GPDMACH0){
steniu01 1:86b13bfcbe46 17 /* Reset interrupt pending bits for DMA1 Channel1 */
steniu01 1:86b13bfcbe46 18 LPC_GPDMA->DMACIntTCClear = 1<<0;
steniu01 1:86b13bfcbe46 19 LPC_GPDMA->DMACIntErrClr = 1<<0;
steniu01 1:86b13bfcbe46 20 }
steniu01 1:86b13bfcbe46 21 else if (DMAy_Channelx == LPC_GPDMACH1){
steniu01 1:86b13bfcbe46 22 /* Reset interrupt pending bits for DMA1 Channel2 */
steniu01 1:86b13bfcbe46 23 LPC_GPDMA->DMACIntTCClear = 1<<1;
steniu01 1:86b13bfcbe46 24 LPC_GPDMA->DMACIntErrClr = 1<<1;
steniu01 1:86b13bfcbe46 25 }
steniu01 1:86b13bfcbe46 26 else if (DMAy_Channelx == LPC_GPDMACH2){
steniu01 1:86b13bfcbe46 27 /* Reset interrupt pending bits for DMA1 Channel3 */
steniu01 1:86b13bfcbe46 28 LPC_GPDMA->DMACIntTCClear = 1<<2;
steniu01 1:86b13bfcbe46 29 LPC_GPDMA->DMACIntErrClr = 1<<2;
steniu01 1:86b13bfcbe46 30 }
steniu01 1:86b13bfcbe46 31 else if (DMAy_Channelx == LPC_GPDMACH3){
steniu01 1:86b13bfcbe46 32 /* Reset interrupt pending bits for DMA1 Channel3 */
steniu01 1:86b13bfcbe46 33 LPC_GPDMA->DMACIntTCClear = 1<<3;
steniu01 1:86b13bfcbe46 34 LPC_GPDMA->DMACIntErrClr = 1<<3;
steniu01 1:86b13bfcbe46 35 }
steniu01 1:86b13bfcbe46 36 else if (DMAy_Channelx == LPC_GPDMACH4){
steniu01 1:86b13bfcbe46 37 /* Reset interrupt pending bits for DMA1 Channel4 */
steniu01 1:86b13bfcbe46 38 LPC_GPDMA->DMACIntTCClear = 1<<4;
steniu01 1:86b13bfcbe46 39 LPC_GPDMA->DMACIntErrClr = 1<<4;
steniu01 1:86b13bfcbe46 40 }
steniu01 1:86b13bfcbe46 41 else if (DMAy_Channelx == LPC_GPDMACH5){
steniu01 1:86b13bfcbe46 42 /* Reset interrupt pending bits for DMA1 Channel5 */
steniu01 1:86b13bfcbe46 43 LPC_GPDMA->DMACIntTCClear = 1<<5;
steniu01 1:86b13bfcbe46 44 LPC_GPDMA->DMACIntErrClr = 1<<5;
steniu01 1:86b13bfcbe46 45 }
steniu01 1:86b13bfcbe46 46 else if (DMAy_Channelx == LPC_GPDMACH6){
steniu01 1:86b13bfcbe46 47 /* Reset interrupt pending bits for DMA1 Channel6 */
steniu01 1:86b13bfcbe46 48 LPC_GPDMA->DMACIntTCClear = 1<<6;
steniu01 1:86b13bfcbe46 49 LPC_GPDMA->DMACIntErrClr = 1<<6;
steniu01 1:86b13bfcbe46 50 }
steniu01 1:86b13bfcbe46 51 else if (DMAy_Channelx == LPC_GPDMACH7) {
steniu01 1:86b13bfcbe46 52 /* Reset interrupt pending bits for DMA1 Channel7 */
steniu01 1:86b13bfcbe46 53 LPC_GPDMA->DMACIntTCClear = 1<<7;
steniu01 1:86b13bfcbe46 54 LPC_GPDMA->DMACIntErrClr = 1<<7;
steniu01 1:86b13bfcbe46 55 }
steniu01 1:86b13bfcbe46 56
steniu01 1:86b13bfcbe46 57
steniu01 1:86b13bfcbe46 58
steniu01 1:86b13bfcbe46 59 // tmpreg = DMAy_Channelx->DMACControl;
steniu01 1:86b13bfcbe46 60 //tmpreg &= CControl_CLEAR_MASK; //undo
steniu01 1:86b13bfcbe46 61
steniu01 1:86b13bfcbe46 62 DMAy_Channelx->DMACCSrcAddr = DMA_InitStruct->DMA_SrcAddr;
steniu01 1:86b13bfcbe46 63 DMAy_Channelx->DMACCDestAddr = DMA_InitStruct->DMA_DestAddr;
steniu01 1:86b13bfcbe46 64 //DMAy_Channelx->DMACCLLI = DMA_InitStruct->LLI->next; //undo
steniu01 1:86b13bfcbe46 65 DMAy_Channelx->DMACCControl |= (DMA_InitStruct->DMA_TransferSize<<DMA_CCxControl_TransferSize_Pos) |
steniu01 1:86b13bfcbe46 66 (DMA_InitStruct->DMA_SrcBurst<<DMA_CCxControl_SBSize_Pos) |
steniu01 1:86b13bfcbe46 67 (DMA_InitStruct->DMA_DestBurst<<DMA_CCxControl_DBSize_Pos) |
steniu01 1:86b13bfcbe46 68 (DMA_InitStruct->DMA_SrcWidth<<DMA_CCxControl_SWidth_Pos) |
steniu01 1:86b13bfcbe46 69 (DMA_InitStruct->DMA_DestWidth<<DMA_CCxControl_DWidth_Pos) |
steniu01 1:86b13bfcbe46 70 (DMA_InitStruct->DMA_SrcInc<<DMA_CCxControl_SI_Pos) |
steniu01 1:86b13bfcbe46 71 (DMA_InitStruct->DMA_DestInc<<DMA_CCxControl_DI_Pos) |
steniu01 1:86b13bfcbe46 72 (DMA_InitStruct->DMA_TermInt<<DMA_CCxControl_I_Pos );
steniu01 1:86b13bfcbe46 73
steniu01 1:86b13bfcbe46 74 DMAy_Channelx->DMACCConfig |= (DMA_InitStruct->DMA_SrcPeripheral<<DMA_CCxConfig_SrcPeripheral_Pos)|
steniu01 1:86b13bfcbe46 75 (DMA_InitStruct->DMA_DestPeripheral<<DMA_CCxConfig_DestPeripheral_Pos)|
steniu01 1:86b13bfcbe46 76 (DMA_InitStruct->DMA_TransferType<< DMA_CCxConfig_TransferType_Pos);
steniu01 1:86b13bfcbe46 77
steniu01 1:86b13bfcbe46 78 //DMAy_Channelx->DMACCConfig=;
steniu01 1:86b13bfcbe46 79
steniu01 1:86b13bfcbe46 80 }
steniu01 1:86b13bfcbe46 81
steniu01 1:86b13bfcbe46 82 /**
steniu01 1:86b13bfcbe46 83 * @brief Fills each DMA_InitStruct member with its default value.
steniu01 1:86b13bfcbe46 84 * @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure which will
steniu01 1:86b13bfcbe46 85 * be initialized.
steniu01 1:86b13bfcbe46 86 * @retval None
steniu01 1:86b13bfcbe46 87 */
steniu01 1:86b13bfcbe46 88 void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct)
steniu01 1:86b13bfcbe46 89 {
steniu01 1:86b13bfcbe46 90 /*-------------- Reset DMA init structure parameters values ------------------*/
steniu01 1:86b13bfcbe46 91
steniu01 1:86b13bfcbe46 92 DMA_InitStruct->DMA_DestAddr=0;
steniu01 1:86b13bfcbe46 93 DMA_InitStruct->DMA_SrcAddr=0;
steniu01 1:86b13bfcbe46 94 //DMA_InitStruct->LLI;//undo
steniu01 1:86b13bfcbe46 95 DMA_InitStruct->DMA_TransferSize=0;
steniu01 1:86b13bfcbe46 96 DMA_InitStruct->DMA_SrcBurst=0;
steniu01 1:86b13bfcbe46 97 DMA_InitStruct->DMA_DestBurst=0;
steniu01 1:86b13bfcbe46 98 DMA_InitStruct->DMA_SrcWidth=0;
steniu01 1:86b13bfcbe46 99 DMA_InitStruct->DMA_DestWidth=0;
steniu01 1:86b13bfcbe46 100 DMA_InitStruct->DMA_SrcInc=0;
steniu01 1:86b13bfcbe46 101 DMA_InitStruct->DMA_DestInc=0;
steniu01 1:86b13bfcbe46 102 DMA_InitStruct->DMA_TermInt=0;
steniu01 1:86b13bfcbe46 103
steniu01 1:86b13bfcbe46 104 DMA_InitStruct->DMA_SrcPeripheral=0;
steniu01 1:86b13bfcbe46 105 DMA_InitStruct->DMA_DestPeripheral=0;
steniu01 1:86b13bfcbe46 106 DMA_InitStruct->DMA_TransferType=M2M;
steniu01 1:86b13bfcbe46 107 }
steniu01 1:86b13bfcbe46 108
steniu01 1:86b13bfcbe46 109
steniu01 1:86b13bfcbe46 110
steniu01 1:86b13bfcbe46 111
steniu01 1:86b13bfcbe46 112 /**
steniu01 1:86b13bfcbe46 113 * @brief Enables or disables the specified DMAy Channelx.
steniu01 1:86b13bfcbe46 114 * @param x can be 1 to 7 for DMA1 to select the DMA Channel.
steniu01 1:86b13bfcbe46 115 * @param NewState: new state of the DMAy Channelx.
steniu01 1:86b13bfcbe46 116 * This parameter can be: ENABLE or DISABLE.
steniu01 1:86b13bfcbe46 117 * @retval None
steniu01 1:86b13bfcbe46 118 */
steniu01 1:86b13bfcbe46 119 void DMA_Cmd(LPC_GPDMACH_TypeDef* DMAy_Channelx, FunctionalState NewState)
steniu01 1:86b13bfcbe46 120 {
steniu01 1:86b13bfcbe46 121 /* Check the parameters */
steniu01 1:86b13bfcbe46 122 //assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));
steniu01 1:86b13bfcbe46 123 //assert_param(IS_DMA_CONTROL(cmd));
steniu01 1:86b13bfcbe46 124
steniu01 1:86b13bfcbe46 125 if (NewState != DISABLE)
steniu01 1:86b13bfcbe46 126 {
steniu01 1:86b13bfcbe46 127 /* Enable the selected DMAy Channelx */
steniu01 1:86b13bfcbe46 128 DMAy_Channelx->DMACCConfig |= 1ul<<DMA_CCxConfig_E_Pos;
steniu01 1:86b13bfcbe46 129 }
steniu01 1:86b13bfcbe46 130 else
steniu01 1:86b13bfcbe46 131 {
steniu01 1:86b13bfcbe46 132 /* Disable the selected DMAy Channelx */
steniu01 1:86b13bfcbe46 133 DMAy_Channelx->DMACCConfig &= (uint16_t)(~1ul<<DMA_CCxConfig_E_Pos);
steniu01 1:86b13bfcbe46 134 }
steniu01 1:86b13bfcbe46 135 }
steniu01 1:86b13bfcbe46 136
steniu01 1:86b13bfcbe46 137
steniu01 1:86b13bfcbe46 138
steniu01 1:86b13bfcbe46 139 /* mask and unmask selected Interrupt: err interrupt or counter interrupt*/
steniu01 1:86b13bfcbe46 140 void DMA_ITConfig (LPC_GPDMACH_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState)
steniu01 1:86b13bfcbe46 141 {
steniu01 1:86b13bfcbe46 142 if (NewState != DISABLE)
steniu01 1:86b13bfcbe46 143 {
steniu01 1:86b13bfcbe46 144 /*unmask the selected DMA interrupts*/
steniu01 1:86b13bfcbe46 145 if(DMA_IT == DMA_ITC )
steniu01 1:86b13bfcbe46 146 {
steniu01 1:86b13bfcbe46 147 DMAy_Channelx->DMACCConfig |= 1ul <<DMA_CCxConfig_ITC_Pos;
steniu01 1:86b13bfcbe46 148 DMAy_Channelx->DMACCControl |= 1ul <<DMA_CCxControl_I_Pos;
steniu01 1:86b13bfcbe46 149 }
steniu01 1:86b13bfcbe46 150 else if (DMA_IT == DMA_IE )
steniu01 1:86b13bfcbe46 151 {
steniu01 1:86b13bfcbe46 152 DMAy_Channelx->DMACCConfig |= 1ul<< DMA_CCxConfig_IE_Pos;
steniu01 1:86b13bfcbe46 153 }
steniu01 1:86b13bfcbe46 154
steniu01 1:86b13bfcbe46 155 }
steniu01 1:86b13bfcbe46 156 else
steniu01 1:86b13bfcbe46 157 {
steniu01 1:86b13bfcbe46 158 /*mask the selected DMA interrupts*/
steniu01 1:86b13bfcbe46 159 if(DMA_IT == DMA_ITC )
steniu01 1:86b13bfcbe46 160 {
steniu01 1:86b13bfcbe46 161 DMAy_Channelx->DMACCConfig &= ~(1ul <<DMA_CCxConfig_ITC_Pos);
steniu01 1:86b13bfcbe46 162 DMAy_Channelx->DMACCControl &= ~(1ul <<DMA_CCxControl_I_Pos);
steniu01 1:86b13bfcbe46 163 }
steniu01 1:86b13bfcbe46 164 else if (DMA_IT == DMA_IE)
steniu01 1:86b13bfcbe46 165 {
steniu01 1:86b13bfcbe46 166 DMAy_Channelx->DMACCConfig &= ~(1ul <<DMA_CCxConfig_IE_Pos);
steniu01 1:86b13bfcbe46 167 }
steniu01 1:86b13bfcbe46 168 }
steniu01 1:86b13bfcbe46 169 }
steniu01 1:86b13bfcbe46 170
steniu01 1:86b13bfcbe46 171 void DMA_ClearITPendingBit(LPC_GPDMACH_TypeDef* DMAy_Channelx, uint32_t DMA_IT)
steniu01 1:86b13bfcbe46 172 {
steniu01 1:86b13bfcbe46 173
steniu01 1:86b13bfcbe46 174 /* clear the pending interrupts on the channel to be used by writing to the DMACIntTCClear and DMACIntErrClear register. */
steniu01 1:86b13bfcbe46 175 if (DMAy_Channelx == LPC_GPDMACH0){
steniu01 1:86b13bfcbe46 176 /* Reset interrupt pending bits for DMA1 Channel1 */
steniu01 1:86b13bfcbe46 177 LPC_GPDMA->DMACIntTCClear = 1<<0;
steniu01 1:86b13bfcbe46 178 LPC_GPDMA->DMACIntErrClr = 1<<0;
steniu01 1:86b13bfcbe46 179 }
steniu01 1:86b13bfcbe46 180 else if (DMAy_Channelx == LPC_GPDMACH1){
steniu01 1:86b13bfcbe46 181 /* Reset interrupt pending bits for DMA1 Channel2 */
steniu01 1:86b13bfcbe46 182 LPC_GPDMA->DMACIntTCClear = 1<<1;
steniu01 1:86b13bfcbe46 183 LPC_GPDMA->DMACIntErrClr = 1<<1;
steniu01 1:86b13bfcbe46 184 }
steniu01 1:86b13bfcbe46 185 else if (DMAy_Channelx == LPC_GPDMACH2){
steniu01 1:86b13bfcbe46 186 /* Reset interrupt pending bits for DMA1 Channel3 */
steniu01 1:86b13bfcbe46 187 LPC_GPDMA->DMACIntTCClear = 1<<2;
steniu01 1:86b13bfcbe46 188 LPC_GPDMA->DMACIntErrClr = 1<<2;
steniu01 1:86b13bfcbe46 189 }
steniu01 1:86b13bfcbe46 190 else if (DMAy_Channelx== LPC_GPDMACH3){
steniu01 1:86b13bfcbe46 191 /* Reset interrupt pending bits for DMA1 Channel3 */
steniu01 1:86b13bfcbe46 192 LPC_GPDMA->DMACIntTCClear = 1<<3;
steniu01 1:86b13bfcbe46 193 LPC_GPDMA->DMACIntErrClr = 1<<3;
steniu01 1:86b13bfcbe46 194 }
steniu01 1:86b13bfcbe46 195 else if (DMAy_Channelx == LPC_GPDMACH4){
steniu01 1:86b13bfcbe46 196 /* Reset interrupt pending bits for DMA1 Channel4 */
steniu01 1:86b13bfcbe46 197 LPC_GPDMA->DMACIntTCClear = 1<<4;
steniu01 1:86b13bfcbe46 198 LPC_GPDMA->DMACIntErrClr = 1<<4;
steniu01 1:86b13bfcbe46 199 }
steniu01 1:86b13bfcbe46 200 else if (DMAy_Channelx == LPC_GPDMACH5){
steniu01 1:86b13bfcbe46 201 /* Reset interrupt pending bits for DMA1 Channel5 */
steniu01 1:86b13bfcbe46 202 LPC_GPDMA->DMACIntTCClear = 1<<5;
steniu01 1:86b13bfcbe46 203 LPC_GPDMA->DMACIntErrClr = 1<<5;
steniu01 1:86b13bfcbe46 204 }
steniu01 1:86b13bfcbe46 205 else if (DMAy_Channelx == LPC_GPDMACH6){
steniu01 1:86b13bfcbe46 206 /* Reset interrupt pending bits for DMA1 Channel6 */
steniu01 1:86b13bfcbe46 207 LPC_GPDMA->DMACIntTCClear = 1<<6;
steniu01 1:86b13bfcbe46 208 LPC_GPDMA->DMACIntErrClr = 1<<6;
steniu01 1:86b13bfcbe46 209 }
steniu01 1:86b13bfcbe46 210 else if (DMAy_Channelx == LPC_GPDMACH7) {
steniu01 1:86b13bfcbe46 211 /* Reset interrupt pending bits for DMA1 Channel7 */
steniu01 1:86b13bfcbe46 212 LPC_GPDMA->DMACIntTCClear = 1<<7;
steniu01 1:86b13bfcbe46 213 LPC_GPDMA->DMACIntErrClr = 1<<7;
steniu01 1:86b13bfcbe46 214 }
steniu01 1:86b13bfcbe46 215
steniu01 1:86b13bfcbe46 216 }
steniu01 1:86b13bfcbe46 217
steniu01 1:86b13bfcbe46 218 /*check which channels are free*/
steniu01 1:86b13bfcbe46 219 uint32_t DMA_EnabledChannels(void){
steniu01 1:86b13bfcbe46 220
steniu01 1:86b13bfcbe46 221 return (LPC_GPDMA->DMACEnbldChns & 0xff);
steniu01 1:86b13bfcbe46 222
steniu01 1:86b13bfcbe46 223 }
steniu01 1:86b13bfcbe46 224
steniu01 1:86b13bfcbe46 225 bool DMA_ChannelActive (LPC_GPDMACH_TypeDef* DMAy_Channelx){
steniu01 1:86b13bfcbe46 226 if( DMAy_Channelx->DMACCConfig && 1<<DMA_CCxConfig_A_Pos)
steniu01 1:86b13bfcbe46 227 return 1;
steniu01 1:86b13bfcbe46 228 else
steniu01 1:86b13bfcbe46 229 return 0;
steniu01 1:86b13bfcbe46 230 }