mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2015-2016 Nuvoton
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16
elessair 0:f269e3021894 17 #include "dma_api.h"
elessair 0:f269e3021894 18 #include "string.h"
elessair 0:f269e3021894 19 #include "cmsis.h"
elessair 0:f269e3021894 20 #include "mbed_assert.h"
elessair 0:f269e3021894 21 #include "PeripheralNames.h"
elessair 0:f269e3021894 22 #include "nu_modutil.h"
elessair 0:f269e3021894 23 #include "nu_bitutil.h"
elessair 0:f269e3021894 24 #include "dma.h"
elessair 0:f269e3021894 25
elessair 0:f269e3021894 26 struct nu_dma_chn_s {
elessair 0:f269e3021894 27 void (*handler)(uint32_t, uint32_t);
elessair 0:f269e3021894 28 uint32_t id;
elessair 0:f269e3021894 29 uint32_t event;
elessair 0:f269e3021894 30 };
elessair 0:f269e3021894 31
elessair 0:f269e3021894 32 static int dma_inited = 0;
elessair 0:f269e3021894 33 static uint32_t dma_chn_mask = 0;
elessair 0:f269e3021894 34 static struct nu_dma_chn_s dma_chn_arr[PDMA_CH_MAX];
elessair 0:f269e3021894 35
elessair 0:f269e3021894 36 static void pdma_vec(void);
elessair 0:f269e3021894 37 static const struct nu_modinit_s dma_modinit = {DMA_0, PDMA_MODULE, 0, 0, PDMA_RST, PDMA_IRQn, (void *) pdma_vec};
elessair 0:f269e3021894 38
elessair 0:f269e3021894 39
elessair 0:f269e3021894 40 void dma_init(void)
elessair 0:f269e3021894 41 {
elessair 0:f269e3021894 42 if (dma_inited) {
elessair 0:f269e3021894 43 return;
elessair 0:f269e3021894 44 }
elessair 0:f269e3021894 45
elessair 0:f269e3021894 46 dma_inited = 1;
elessair 0:f269e3021894 47 dma_chn_mask = 0;
elessair 0:f269e3021894 48 memset(dma_chn_arr, 0x00, sizeof (dma_chn_arr));
elessair 0:f269e3021894 49
elessair 0:f269e3021894 50 // Reset this module
elessair 0:f269e3021894 51 SYS_ResetModule(dma_modinit.rsetidx);
elessair 0:f269e3021894 52
elessair 0:f269e3021894 53 // Enable IP clock
elessair 0:f269e3021894 54 CLK_EnableModuleClock(dma_modinit.clkidx);
elessair 0:f269e3021894 55
elessair 0:f269e3021894 56 PDMA_Open(0);
elessair 0:f269e3021894 57
elessair 0:f269e3021894 58 NVIC_SetVector(dma_modinit.irq_n, (uint32_t) dma_modinit.var);
elessair 0:f269e3021894 59 NVIC_EnableIRQ(dma_modinit.irq_n);
elessair 0:f269e3021894 60 }
elessair 0:f269e3021894 61
elessair 0:f269e3021894 62 int dma_channel_allocate(uint32_t capabilities)
elessair 0:f269e3021894 63 {
elessair 0:f269e3021894 64 if (! dma_inited) {
elessair 0:f269e3021894 65 dma_init();
elessair 0:f269e3021894 66 }
elessair 0:f269e3021894 67
elessair 0:f269e3021894 68 #if 1
elessair 0:f269e3021894 69 int i = nu_cto(dma_chn_mask);
elessair 0:f269e3021894 70 if (i != 32) {
elessair 0:f269e3021894 71 dma_chn_mask |= 1 << i;
elessair 0:f269e3021894 72 memset(dma_chn_arr + i, 0x00, sizeof (struct nu_dma_chn_s));
elessair 0:f269e3021894 73 return i;
elessair 0:f269e3021894 74 }
elessair 0:f269e3021894 75 #else
elessair 0:f269e3021894 76 int i;
elessair 0:f269e3021894 77
elessair 0:f269e3021894 78 for (i = 0; i < PDMA_CH_MAX; i ++) {
elessair 0:f269e3021894 79 if ((dma_chn_mask & (1 << i)) == 0) {
elessair 0:f269e3021894 80 // Channel available
elessair 0:f269e3021894 81 dma_chn_mask |= 1 << i;
elessair 0:f269e3021894 82 memset(dma_chn_arr + i, 0x00, sizeof (struct nu_dma_chn_s));
elessair 0:f269e3021894 83 return i;
elessair 0:f269e3021894 84 }
elessair 0:f269e3021894 85 }
elessair 0:f269e3021894 86 #endif
elessair 0:f269e3021894 87
elessair 0:f269e3021894 88 // No channel available
elessair 0:f269e3021894 89 return DMA_ERROR_OUT_OF_CHANNELS;
elessair 0:f269e3021894 90 }
elessair 0:f269e3021894 91
elessair 0:f269e3021894 92 int dma_channel_free(int channelid)
elessair 0:f269e3021894 93 {
elessair 0:f269e3021894 94 if (channelid != DMA_ERROR_OUT_OF_CHANNELS) {
elessair 0:f269e3021894 95 dma_chn_mask &= ~(1 << channelid);
elessair 0:f269e3021894 96 }
elessair 0:f269e3021894 97
elessair 0:f269e3021894 98 return 0;
elessair 0:f269e3021894 99 }
elessair 0:f269e3021894 100
elessair 0:f269e3021894 101 void dma_set_handler(int channelid, uint32_t handler, uint32_t id, uint32_t event)
elessair 0:f269e3021894 102 {
elessair 0:f269e3021894 103 MBED_ASSERT(dma_chn_mask & (1 << channelid));
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 dma_chn_arr[channelid].handler = (void (*)(uint32_t, uint32_t)) handler;
elessair 0:f269e3021894 106 dma_chn_arr[channelid].id = id;
elessair 0:f269e3021894 107 dma_chn_arr[channelid].event = event;
elessair 0:f269e3021894 108
elessair 0:f269e3021894 109 // Set interrupt vector if someone has removed it.
elessair 0:f269e3021894 110 NVIC_SetVector(dma_modinit.irq_n, (uint32_t) dma_modinit.var);
elessair 0:f269e3021894 111 NVIC_EnableIRQ(dma_modinit.irq_n);
elessair 0:f269e3021894 112 }
elessair 0:f269e3021894 113
elessair 0:f269e3021894 114 static void pdma_vec(void)
elessair 0:f269e3021894 115 {
elessair 0:f269e3021894 116 uint32_t intsts = PDMA_GET_INT_STATUS();
elessair 0:f269e3021894 117
elessair 0:f269e3021894 118 // Abort
elessair 0:f269e3021894 119 if (intsts & PDMA_INTSTS_ABTIF_Msk) {
elessair 0:f269e3021894 120 uint32_t abtsts = PDMA_GET_ABORT_STS();
elessair 0:f269e3021894 121 // Clear all Abort flags
elessair 0:f269e3021894 122 PDMA_CLR_ABORT_FLAG(abtsts);
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 while (abtsts) {
elessair 0:f269e3021894 125 int chn_id = nu_ctz(abtsts);
elessair 0:f269e3021894 126 if (dma_chn_mask & (1 << chn_id)) {
elessair 0:f269e3021894 127 struct nu_dma_chn_s *dma_chn = dma_chn_arr + chn_id;
elessair 0:f269e3021894 128 if (dma_chn->handler && (dma_chn->event & DMA_EVENT_ABORT)) {
elessair 0:f269e3021894 129 dma_chn->handler(dma_chn->id, DMA_EVENT_ABORT);
elessair 0:f269e3021894 130 }
elessair 0:f269e3021894 131 }
elessair 0:f269e3021894 132 abtsts &= ~(1 << chn_id);
elessair 0:f269e3021894 133 }
elessair 0:f269e3021894 134 }
elessair 0:f269e3021894 135
elessair 0:f269e3021894 136 // Transfer done
elessair 0:f269e3021894 137 if (intsts & PDMA_INTSTS_TDIF_Msk) {
elessair 0:f269e3021894 138 uint32_t tdsts = PDMA_GET_TD_STS();
elessair 0:f269e3021894 139 // Clear all transfer done flags
elessair 0:f269e3021894 140 PDMA_CLR_TD_FLAG(tdsts);
elessair 0:f269e3021894 141
elessair 0:f269e3021894 142 while (tdsts) {
elessair 0:f269e3021894 143 int chn_id = nu_ctz(tdsts);
elessair 0:f269e3021894 144 if (dma_chn_mask & (1 << chn_id)) {
elessair 0:f269e3021894 145 struct nu_dma_chn_s *dma_chn = dma_chn_arr + chn_id;
elessair 0:f269e3021894 146 if (dma_chn->handler && (dma_chn->event & DMA_EVENT_TRANSFER_DONE)) {
elessair 0:f269e3021894 147 dma_chn->handler(dma_chn->id, DMA_EVENT_TRANSFER_DONE);
elessair 0:f269e3021894 148 }
elessair 0:f269e3021894 149 }
elessair 0:f269e3021894 150 tdsts &= ~(1 << chn_id);
elessair 0:f269e3021894 151 }
elessair 0:f269e3021894 152 }
elessair 0:f269e3021894 153
elessair 0:f269e3021894 154 // Table empty
elessair 0:f269e3021894 155 if (intsts & PDMA_INTSTS_TEIF_Msk) {
elessair 0:f269e3021894 156 uint32_t scatsts = PDMA_GET_EMPTY_STS();
elessair 0:f269e3021894 157 // Clear all table empty flags
elessair 0:f269e3021894 158 PDMA_CLR_EMPTY_FLAG(scatsts);
elessair 0:f269e3021894 159 }
elessair 0:f269e3021894 160
elessair 0:f269e3021894 161 // Timeout
elessair 0:f269e3021894 162 uint32_t reqto = intsts & PDMA_INTSTS_REQTOFX_Msk;
elessair 0:f269e3021894 163 if (reqto) {
elessair 0:f269e3021894 164 // Clear all Timeout flags
elessair 0:f269e3021894 165 PDMA->INTSTS = reqto;
elessair 0:f269e3021894 166
elessair 0:f269e3021894 167 while (reqto) {
elessair 0:f269e3021894 168 int chn_id = nu_ctz(reqto) >> PDMA_INTSTS_REQTOFX_Pos;
elessair 0:f269e3021894 169 if (dma_chn_mask & (1 << chn_id)) {
elessair 0:f269e3021894 170 struct nu_dma_chn_s *dma_chn = dma_chn_arr + chn_id;
elessair 0:f269e3021894 171 if (dma_chn->handler && (dma_chn->event & DMA_EVENT_TIMEOUT)) {
elessair 0:f269e3021894 172 dma_chn->handler(dma_chn->id, DMA_EVENT_TIMEOUT);
elessair 0:f269e3021894 173 }
elessair 0:f269e3021894 174 }
elessair 0:f269e3021894 175 reqto &= ~(1 << (chn_id + PDMA_INTSTS_REQTOFX_Pos));
elessair 0:f269e3021894 176 }
elessair 0:f269e3021894 177 }
elessair 0:f269e3021894 178 }