mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 187:0387e8f68319 1 /* mbed Microcontroller Library
AnnaBridge 187:0387e8f68319 2 * Copyright (c) 2015-2016 Nuvoton
AnnaBridge 187:0387e8f68319 3 *
AnnaBridge 187:0387e8f68319 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 187:0387e8f68319 5 * you may not use this file except in compliance with the License.
AnnaBridge 187:0387e8f68319 6 * You may obtain a copy of the License at
AnnaBridge 187:0387e8f68319 7 *
AnnaBridge 187:0387e8f68319 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 187:0387e8f68319 9 *
AnnaBridge 187:0387e8f68319 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 187:0387e8f68319 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 187:0387e8f68319 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 187:0387e8f68319 13 * See the License for the specific language governing permissions and
AnnaBridge 187:0387e8f68319 14 * limitations under the License.
AnnaBridge 187:0387e8f68319 15 */
AnnaBridge 187:0387e8f68319 16
AnnaBridge 187:0387e8f68319 17 #include "dma_api.h"
AnnaBridge 187:0387e8f68319 18 #include "string.h"
AnnaBridge 187:0387e8f68319 19 #include "cmsis.h"
AnnaBridge 187:0387e8f68319 20 #include "mbed_assert.h"
AnnaBridge 187:0387e8f68319 21 #include "mbed_error.h"
AnnaBridge 187:0387e8f68319 22 #include "PeripheralNames.h"
AnnaBridge 187:0387e8f68319 23 #include "nu_modutil.h"
AnnaBridge 187:0387e8f68319 24 #include "nu_bitutil.h"
AnnaBridge 187:0387e8f68319 25 #include "dma.h"
AnnaBridge 187:0387e8f68319 26 #include "partition_M2351.h"
AnnaBridge 187:0387e8f68319 27
AnnaBridge 187:0387e8f68319 28 #define NU_PDMA_CH_MAX PDMA_CH_MAX /* Specify maximum channels of PDMA */
AnnaBridge 187:0387e8f68319 29 #define NU_PDMA_CH_Pos 0 /* Specify first channel number of PDMA */
AnnaBridge 187:0387e8f68319 30 #define NU_PDMA_CH_Msk (((1 << NU_PDMA_CH_MAX) - 1) << NU_PDMA_CH_Pos)
AnnaBridge 187:0387e8f68319 31
AnnaBridge 187:0387e8f68319 32 struct nu_dma_chn_s {
AnnaBridge 187:0387e8f68319 33 void (*handler)(uint32_t, uint32_t);
AnnaBridge 187:0387e8f68319 34 uint32_t id;
AnnaBridge 187:0387e8f68319 35 uint32_t event;
AnnaBridge 187:0387e8f68319 36 };
AnnaBridge 187:0387e8f68319 37
AnnaBridge 187:0387e8f68319 38 /* Partition policy of PDMAs
AnnaBridge 187:0387e8f68319 39 *
AnnaBridge 187:0387e8f68319 40 * To support DMA for secure/non-secure peripherals simultaneously, we have the following
AnnaBridge 187:0387e8f68319 41 * partition policy:
AnnaBridge 187:0387e8f68319 42 *
AnnaBridge 187:0387e8f68319 43 * 1. PDMA0 is hard-wired to secure and PDMA1 is configured to non-secure.
AnnaBridge 187:0387e8f68319 44 * 2. In secure domain, only PDMA0 is accessible and shall be used for secure peripheral.
AnnaBridge 187:0387e8f68319 45 * 3. In non-secure domain, only PDMA1 is accessible and shall be used for non-secure peripheral.
AnnaBridge 187:0387e8f68319 46 */
AnnaBridge 187:0387e8f68319 47 #if (! defined(SCU_INIT_PNSSET0_VAL)) || (! (SCU_INIT_PNSSET0_VAL & (1 << 24)))
AnnaBridge 187:0387e8f68319 48 #error("PDMA1 must be configured to non-secure for non-secure peripherals.")
AnnaBridge 187:0387e8f68319 49 #endif
AnnaBridge 187:0387e8f68319 50
AnnaBridge 187:0387e8f68319 51 static int dma_inited = 0;
AnnaBridge 187:0387e8f68319 52 static uint32_t dma_chn_mask = 0;
AnnaBridge 187:0387e8f68319 53 static struct nu_dma_chn_s dma_chn_arr[NU_PDMA_CH_MAX];
AnnaBridge 187:0387e8f68319 54
AnnaBridge 187:0387e8f68319 55 static void pdma_vec(void);
AnnaBridge 187:0387e8f68319 56 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L)
AnnaBridge 187:0387e8f68319 57 static const struct nu_modinit_s dma_modinit = {DMA_0, PDMA0_MODULE, 0, 0, PDMA0_RST, PDMA0_IRQn, (void *) pdma_vec};
AnnaBridge 187:0387e8f68319 58 #else
AnnaBridge 187:0387e8f68319 59 static const struct nu_modinit_s dma_modinit = {DMA_1, PDMA1_MODULE, 0, 0, PDMA1_RST, PDMA1_IRQn, (void *) pdma_vec};
AnnaBridge 187:0387e8f68319 60 #endif
AnnaBridge 187:0387e8f68319 61
AnnaBridge 187:0387e8f68319 62 void dma_init(void)
AnnaBridge 187:0387e8f68319 63 {
AnnaBridge 187:0387e8f68319 64 if (dma_inited) {
AnnaBridge 187:0387e8f68319 65 return;
AnnaBridge 187:0387e8f68319 66 }
AnnaBridge 187:0387e8f68319 67
AnnaBridge 187:0387e8f68319 68 dma_inited = 1;
AnnaBridge 187:0387e8f68319 69 dma_chn_mask = ~NU_PDMA_CH_Msk;
AnnaBridge 187:0387e8f68319 70 memset(dma_chn_arr, 0x00, sizeof (dma_chn_arr));
AnnaBridge 187:0387e8f68319 71
AnnaBridge 187:0387e8f68319 72 /* Reset module
AnnaBridge 187:0387e8f68319 73 *
AnnaBridge 187:0387e8f68319 74 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 75 */
AnnaBridge 187:0387e8f68319 76 SYS_ResetModule_S(dma_modinit.rsetidx);
AnnaBridge 187:0387e8f68319 77
AnnaBridge 187:0387e8f68319 78 /* Enable IP clock
AnnaBridge 187:0387e8f68319 79 *
AnnaBridge 187:0387e8f68319 80 * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
AnnaBridge 187:0387e8f68319 81 */
AnnaBridge 187:0387e8f68319 82 CLK_EnableModuleClock_S(dma_modinit.clkidx);
AnnaBridge 187:0387e8f68319 83
AnnaBridge 187:0387e8f68319 84 /* Check security state of PDMA0/1 match the partition policy above. */
AnnaBridge 187:0387e8f68319 85 PDMA_T *pdma_base = dma_modbase();
AnnaBridge 187:0387e8f68319 86 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L)
AnnaBridge 187:0387e8f68319 87 if (((uint32_t) pdma_base) != PDMA0_BASE) {
AnnaBridge 187:0387e8f68319 88 error("In secure domain, only PDMA0 is accessible and shall be used for secure peripheral");
AnnaBridge 187:0387e8f68319 89 }
AnnaBridge 187:0387e8f68319 90 #else
AnnaBridge 187:0387e8f68319 91 if (((uint32_t) pdma_base) != (PDMA1_BASE + NS_OFFSET)) {
AnnaBridge 187:0387e8f68319 92 error("In non-secure domain, only PDMA1 is accessible and shall be used for non-secure peripheral");
AnnaBridge 187:0387e8f68319 93 }
AnnaBridge 187:0387e8f68319 94 #endif
AnnaBridge 187:0387e8f68319 95
AnnaBridge 187:0387e8f68319 96 PDMA_Open(pdma_base, 0);
AnnaBridge 187:0387e8f68319 97
AnnaBridge 187:0387e8f68319 98 NVIC_SetVector(dma_modinit.irq_n, (uint32_t) dma_modinit.var);
AnnaBridge 187:0387e8f68319 99 NVIC_EnableIRQ(dma_modinit.irq_n);
AnnaBridge 187:0387e8f68319 100 }
AnnaBridge 187:0387e8f68319 101
AnnaBridge 187:0387e8f68319 102 int dma_channel_allocate(uint32_t capabilities)
AnnaBridge 187:0387e8f68319 103 {
AnnaBridge 187:0387e8f68319 104 if (! dma_inited) {
AnnaBridge 187:0387e8f68319 105 dma_init();
AnnaBridge 187:0387e8f68319 106 }
AnnaBridge 187:0387e8f68319 107
AnnaBridge 187:0387e8f68319 108 int i = nu_cto(dma_chn_mask);
AnnaBridge 187:0387e8f68319 109 if (i != 32) {
AnnaBridge 187:0387e8f68319 110 dma_chn_mask |= 1 << i;
AnnaBridge 187:0387e8f68319 111 memset(dma_chn_arr + i - NU_PDMA_CH_Pos, 0x00, sizeof (struct nu_dma_chn_s));
AnnaBridge 187:0387e8f68319 112 return i;
AnnaBridge 187:0387e8f68319 113 }
AnnaBridge 187:0387e8f68319 114
AnnaBridge 187:0387e8f68319 115 // No channel available
AnnaBridge 187:0387e8f68319 116 return DMA_ERROR_OUT_OF_CHANNELS;
AnnaBridge 187:0387e8f68319 117 }
AnnaBridge 187:0387e8f68319 118
AnnaBridge 187:0387e8f68319 119 int dma_channel_free(int channelid)
AnnaBridge 187:0387e8f68319 120 {
AnnaBridge 187:0387e8f68319 121 if (channelid != DMA_ERROR_OUT_OF_CHANNELS) {
AnnaBridge 187:0387e8f68319 122 dma_chn_mask &= ~(1 << channelid);
AnnaBridge 187:0387e8f68319 123 }
AnnaBridge 187:0387e8f68319 124
AnnaBridge 187:0387e8f68319 125 return 0;
AnnaBridge 187:0387e8f68319 126 }
AnnaBridge 187:0387e8f68319 127
AnnaBridge 187:0387e8f68319 128 void dma_set_handler(int channelid, uint32_t handler, uint32_t id, uint32_t event)
AnnaBridge 187:0387e8f68319 129 {
AnnaBridge 187:0387e8f68319 130 MBED_ASSERT(dma_chn_mask & (1 << channelid));
AnnaBridge 187:0387e8f68319 131
AnnaBridge 187:0387e8f68319 132 dma_chn_arr[channelid - NU_PDMA_CH_Pos].handler = (void (*)(uint32_t, uint32_t)) handler;
AnnaBridge 187:0387e8f68319 133 dma_chn_arr[channelid - NU_PDMA_CH_Pos].id = id;
AnnaBridge 187:0387e8f68319 134 dma_chn_arr[channelid - NU_PDMA_CH_Pos].event = event;
AnnaBridge 187:0387e8f68319 135
AnnaBridge 187:0387e8f68319 136 // Set interrupt vector if someone has removed it.
AnnaBridge 187:0387e8f68319 137 NVIC_SetVector(dma_modinit.irq_n, (uint32_t) dma_modinit.var);
AnnaBridge 187:0387e8f68319 138 NVIC_EnableIRQ(dma_modinit.irq_n);
AnnaBridge 187:0387e8f68319 139 }
AnnaBridge 187:0387e8f68319 140
AnnaBridge 187:0387e8f68319 141 PDMA_T *dma_modbase(void)
AnnaBridge 187:0387e8f68319 142 {
AnnaBridge 187:0387e8f68319 143 return (PDMA_T *) NU_MODBASE(dma_modinit.modname);
AnnaBridge 187:0387e8f68319 144 }
AnnaBridge 187:0387e8f68319 145
AnnaBridge 187:0387e8f68319 146 static void pdma_vec(void)
AnnaBridge 187:0387e8f68319 147 {
AnnaBridge 187:0387e8f68319 148 PDMA_T *pdma_base = (PDMA_T *) NU_MODBASE(dma_modinit.modname);
AnnaBridge 187:0387e8f68319 149
AnnaBridge 187:0387e8f68319 150 uint32_t intsts = PDMA_GET_INT_STATUS(pdma_base);
AnnaBridge 187:0387e8f68319 151
AnnaBridge 187:0387e8f68319 152 // Abort
AnnaBridge 187:0387e8f68319 153 if (intsts & PDMA_INTSTS_ABTIF_Msk) {
AnnaBridge 187:0387e8f68319 154 uint32_t abtsts = PDMA_GET_ABORT_STS(pdma_base);
AnnaBridge 187:0387e8f68319 155 // Clear all Abort flags
AnnaBridge 187:0387e8f68319 156 PDMA_CLR_ABORT_FLAG(pdma_base, abtsts);
AnnaBridge 187:0387e8f68319 157
AnnaBridge 187:0387e8f68319 158 while (abtsts) {
AnnaBridge 187:0387e8f68319 159 int chn_id = nu_ctz(abtsts) - PDMA_ABTSTS_ABTIF0_Pos + NU_PDMA_CH_Pos;
AnnaBridge 187:0387e8f68319 160 if (dma_chn_mask & (1 << chn_id)) {
AnnaBridge 187:0387e8f68319 161 struct nu_dma_chn_s *dma_chn = dma_chn_arr + chn_id - NU_PDMA_CH_Pos;
AnnaBridge 187:0387e8f68319 162 if (dma_chn->handler && (dma_chn->event & DMA_EVENT_ABORT)) {
AnnaBridge 187:0387e8f68319 163 dma_chn->handler(dma_chn->id, DMA_EVENT_ABORT);
AnnaBridge 187:0387e8f68319 164 }
AnnaBridge 187:0387e8f68319 165 }
AnnaBridge 187:0387e8f68319 166 abtsts &= ~(1 << (chn_id - NU_PDMA_CH_Pos + PDMA_ABTSTS_ABTIF0_Pos));
AnnaBridge 187:0387e8f68319 167 }
AnnaBridge 187:0387e8f68319 168 }
AnnaBridge 187:0387e8f68319 169
AnnaBridge 187:0387e8f68319 170 // Transfer done
AnnaBridge 187:0387e8f68319 171 if (intsts & PDMA_INTSTS_TDIF_Msk) {
AnnaBridge 187:0387e8f68319 172 uint32_t tdsts = PDMA_GET_TD_STS(pdma_base);
AnnaBridge 187:0387e8f68319 173 // Clear all transfer done flags
AnnaBridge 187:0387e8f68319 174 PDMA_CLR_TD_FLAG(pdma_base, tdsts);
AnnaBridge 187:0387e8f68319 175
AnnaBridge 187:0387e8f68319 176 while (tdsts) {
AnnaBridge 187:0387e8f68319 177 int chn_id = nu_ctz(tdsts) - PDMA_TDSTS_TDIF0_Pos + NU_PDMA_CH_Pos;
AnnaBridge 187:0387e8f68319 178 if (dma_chn_mask & (1 << chn_id)) {
AnnaBridge 187:0387e8f68319 179 struct nu_dma_chn_s *dma_chn = dma_chn_arr + chn_id - NU_PDMA_CH_Pos;
AnnaBridge 187:0387e8f68319 180 if (dma_chn->handler && (dma_chn->event & DMA_EVENT_TRANSFER_DONE)) {
AnnaBridge 187:0387e8f68319 181 dma_chn->handler(dma_chn->id, DMA_EVENT_TRANSFER_DONE);
AnnaBridge 187:0387e8f68319 182 }
AnnaBridge 187:0387e8f68319 183 }
AnnaBridge 187:0387e8f68319 184 tdsts &= ~(1 << (chn_id - NU_PDMA_CH_Pos + PDMA_TDSTS_TDIF0_Pos));
AnnaBridge 187:0387e8f68319 185 }
AnnaBridge 187:0387e8f68319 186 }
AnnaBridge 187:0387e8f68319 187
AnnaBridge 187:0387e8f68319 188 // Timeout
AnnaBridge 187:0387e8f68319 189 uint32_t reqto = intsts & (PDMA_INTSTS_REQTOF0_Msk | PDMA_INTSTS_REQTOF1_Msk);
AnnaBridge 187:0387e8f68319 190 if (reqto) {
AnnaBridge 187:0387e8f68319 191 // Clear all Timeout flags
AnnaBridge 187:0387e8f68319 192 pdma_base->INTSTS = reqto;
AnnaBridge 187:0387e8f68319 193
AnnaBridge 187:0387e8f68319 194 while (reqto) {
AnnaBridge 187:0387e8f68319 195 int chn_id = nu_ctz(reqto) - PDMA_INTSTS_REQTOF0_Pos + NU_PDMA_CH_Pos;
AnnaBridge 187:0387e8f68319 196 if (dma_chn_mask & (1 << chn_id)) {
AnnaBridge 187:0387e8f68319 197 struct nu_dma_chn_s *dma_chn = dma_chn_arr + chn_id - NU_PDMA_CH_Pos;
AnnaBridge 187:0387e8f68319 198 if (dma_chn->handler && (dma_chn->event & DMA_EVENT_TIMEOUT)) {
AnnaBridge 187:0387e8f68319 199 dma_chn->handler(dma_chn->id, DMA_EVENT_TIMEOUT);
AnnaBridge 187:0387e8f68319 200 }
AnnaBridge 187:0387e8f68319 201 }
AnnaBridge 187:0387e8f68319 202 reqto &= ~(1 << (chn_id - NU_PDMA_CH_Pos + PDMA_INTSTS_REQTOF0_Pos));
AnnaBridge 187:0387e8f68319 203 }
AnnaBridge 187:0387e8f68319 204 }
AnnaBridge 187:0387e8f68319 205 }