Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
This example is known to work great on the following platforms:
- WISE-1530 WiFi Module using DB-1505 carrier board and external SD card reader.
Example Functionality
This example showcases the following device functionality:
- On timer button increment, simulate Pelion LWM2M button resource change
Use this example with Mbed CLI
1. Import the application into your desktop:
mbed import https://os.mbed.com/teams/Advantech/code/pelion-example-common cd pelion-example-common
2. Download your developer certificate from pelion portal
3. Compile the program
mbed compile -t <toolchain> -m <TARGET_BOARD>
(supported toolchains : GCC_ARM / ARM / IAR)
4. Copy the binary file pelion-example-common.bin to your mbed device.
drivers/storage/COMPONENT_NUSD/NuSDBlockDevice.cpp@0:43ff9e3bc244, 2019-03-12 (annotated)
- Committer:
- chuanga
- Date:
- Tue Mar 12 13:48:39 2019 +0800
- Revision:
- 0:43ff9e3bc244
copying sources from github repository
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| chuanga | 0:43ff9e3bc244 | 1 | /* mbed Microcontroller Library |
| chuanga | 0:43ff9e3bc244 | 2 | * Copyright (c) 2015-2016 Nuvoton |
| chuanga | 0:43ff9e3bc244 | 3 | * |
| chuanga | 0:43ff9e3bc244 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| chuanga | 0:43ff9e3bc244 | 5 | * you may not use this file except in compliance with the License. |
| chuanga | 0:43ff9e3bc244 | 6 | * You may obtain a copy of the License at |
| chuanga | 0:43ff9e3bc244 | 7 | * |
| chuanga | 0:43ff9e3bc244 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| chuanga | 0:43ff9e3bc244 | 9 | * |
| chuanga | 0:43ff9e3bc244 | 10 | * Unless required by applicable law or agreed to in writing, software |
| chuanga | 0:43ff9e3bc244 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| chuanga | 0:43ff9e3bc244 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| chuanga | 0:43ff9e3bc244 | 13 | * See the License for the specific language governing permissions and |
| chuanga | 0:43ff9e3bc244 | 14 | * limitations under the License. |
| chuanga | 0:43ff9e3bc244 | 15 | */ |
| chuanga | 0:43ff9e3bc244 | 16 | |
| chuanga | 0:43ff9e3bc244 | 17 | /* Nuvoton mbed enabled targets which support SD card of SD bus mode */ |
| chuanga | 0:43ff9e3bc244 | 18 | #if TARGET_NUVOTON |
| chuanga | 0:43ff9e3bc244 | 19 | |
| chuanga | 0:43ff9e3bc244 | 20 | #include "NuSDBlockDevice.h" |
| chuanga | 0:43ff9e3bc244 | 21 | #include "PeripheralPins.h" |
| chuanga | 0:43ff9e3bc244 | 22 | #include "mbed_debug.h" |
| chuanga | 0:43ff9e3bc244 | 23 | #include "nu_modutil.h" |
| chuanga | 0:43ff9e3bc244 | 24 | #include "mbed_critical.h" |
| chuanga | 0:43ff9e3bc244 | 25 | #include "mbed_toolchain.h" |
| chuanga | 0:43ff9e3bc244 | 26 | |
| chuanga | 0:43ff9e3bc244 | 27 | /* SD DMA compatible buffer if user buffer doesn't meet requirements |
| chuanga | 0:43ff9e3bc244 | 28 | * |
| chuanga | 0:43ff9e3bc244 | 29 | * SD DMA buffer location requires to be: |
| chuanga | 0:43ff9e3bc244 | 30 | * (1) Word-aligned |
| chuanga | 0:43ff9e3bc244 | 31 | * (2) Located in 0x2xxxxxxx/0x3xxxxxxx region. Check linker files to ensure global/static |
| chuanga | 0:43ff9e3bc244 | 32 | * variables are placed in this region. |
| chuanga | 0:43ff9e3bc244 | 33 | * |
| chuanga | 0:43ff9e3bc244 | 34 | * SD DMA buffer size DMA_BUF_SIZE must be a multiple of 512-byte block size. |
| chuanga | 0:43ff9e3bc244 | 35 | * Its value is estimated to trade memory footprint off against performance. |
| chuanga | 0:43ff9e3bc244 | 36 | * |
| chuanga | 0:43ff9e3bc244 | 37 | */ |
| chuanga | 0:43ff9e3bc244 | 38 | #define DMA_BUFF_SIZE 512 |
| chuanga | 0:43ff9e3bc244 | 39 | MBED_ALIGN(4) static uint8_t dma_buff[DMA_BUFF_SIZE]; |
| chuanga | 0:43ff9e3bc244 | 40 | |
| chuanga | 0:43ff9e3bc244 | 41 | /* Check if specified buffer is SD DMA-compatible */ |
| chuanga | 0:43ff9e3bc244 | 42 | static bool sd_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to); |
| chuanga | 0:43ff9e3bc244 | 43 | |
| chuanga | 0:43ff9e3bc244 | 44 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 45 | #define NU_SDH_DAT0 PF_5 |
| chuanga | 0:43ff9e3bc244 | 46 | #define NU_SDH_DAT1 PF_4 |
| chuanga | 0:43ff9e3bc244 | 47 | #define NU_SDH_DAT2 PF_3 |
| chuanga | 0:43ff9e3bc244 | 48 | #define NU_SDH_DAT3 PF_2 |
| chuanga | 0:43ff9e3bc244 | 49 | #define NU_SDH_CMD PF_7 |
| chuanga | 0:43ff9e3bc244 | 50 | #define NU_SDH_CLK PF_8 |
| chuanga | 0:43ff9e3bc244 | 51 | #define NU_SDH_CDn PF_6 |
| chuanga | 0:43ff9e3bc244 | 52 | |
| chuanga | 0:43ff9e3bc244 | 53 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 54 | #define NU_SDH_DAT0 PE_2 |
| chuanga | 0:43ff9e3bc244 | 55 | #define NU_SDH_DAT1 PE_3 |
| chuanga | 0:43ff9e3bc244 | 56 | #define NU_SDH_DAT2 PB_4 |
| chuanga | 0:43ff9e3bc244 | 57 | #define NU_SDH_DAT3 PB_5 |
| chuanga | 0:43ff9e3bc244 | 58 | #define NU_SDH_CMD PE_7 |
| chuanga | 0:43ff9e3bc244 | 59 | #define NU_SDH_CLK PE_6 |
| chuanga | 0:43ff9e3bc244 | 60 | #define NU_SDH_CDn PD_13 |
| chuanga | 0:43ff9e3bc244 | 61 | |
| chuanga | 0:43ff9e3bc244 | 62 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 63 | #define NU_SDH_DAT0 PE_2 |
| chuanga | 0:43ff9e3bc244 | 64 | #define NU_SDH_DAT1 PE_3 |
| chuanga | 0:43ff9e3bc244 | 65 | #define NU_SDH_DAT2 PE_4 |
| chuanga | 0:43ff9e3bc244 | 66 | #define NU_SDH_DAT3 PE_5 |
| chuanga | 0:43ff9e3bc244 | 67 | #define NU_SDH_CMD PE_7 |
| chuanga | 0:43ff9e3bc244 | 68 | #define NU_SDH_CLK PE_6 |
| chuanga | 0:43ff9e3bc244 | 69 | #define NU_SDH_CDn PD_13 |
| chuanga | 0:43ff9e3bc244 | 70 | |
| chuanga | 0:43ff9e3bc244 | 71 | #endif |
| chuanga | 0:43ff9e3bc244 | 72 | |
| chuanga | 0:43ff9e3bc244 | 73 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 74 | extern DISK_DATA_T SD_DiskInfo0; |
| chuanga | 0:43ff9e3bc244 | 75 | extern DISK_DATA_T SD_DiskInfo1; |
| chuanga | 0:43ff9e3bc244 | 76 | extern SD_INFO_T SD0,SD1; |
| chuanga | 0:43ff9e3bc244 | 77 | extern int sd0_ok,sd1_ok; |
| chuanga | 0:43ff9e3bc244 | 78 | |
| chuanga | 0:43ff9e3bc244 | 79 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 80 | extern int SDH_ok; |
| chuanga | 0:43ff9e3bc244 | 81 | extern SDH_INFO_T SD0, SD1; |
| chuanga | 0:43ff9e3bc244 | 82 | |
| chuanga | 0:43ff9e3bc244 | 83 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 84 | extern int SDH_ok; |
| chuanga | 0:43ff9e3bc244 | 85 | extern SDH_INFO_T SD0; |
| chuanga | 0:43ff9e3bc244 | 86 | |
| chuanga | 0:43ff9e3bc244 | 87 | #endif |
| chuanga | 0:43ff9e3bc244 | 88 | |
| chuanga | 0:43ff9e3bc244 | 89 | |
| chuanga | 0:43ff9e3bc244 | 90 | static const struct nu_modinit_s sdh_modinit_tab[] = { |
| chuanga | 0:43ff9e3bc244 | 91 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 92 | {SD_0_0, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, |
| chuanga | 0:43ff9e3bc244 | 93 | {SD_0_1, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, |
| chuanga | 0:43ff9e3bc244 | 94 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 95 | {SD_0, SDH0_MODULE, CLK_CLKSEL0_SDH0SEL_HCLK, CLK_CLKDIV0_SDH0(2), SDH0_RST, SDH0_IRQn, NULL}, |
| chuanga | 0:43ff9e3bc244 | 96 | {SD_1, SDH1_MODULE, CLK_CLKSEL0_SDH1SEL_HCLK, CLK_CLKDIV3_SDH1(2), SDH1_RST, SDH1_IRQn, NULL}, |
| chuanga | 0:43ff9e3bc244 | 97 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 98 | {SD_0, SDH0_MODULE, CLK_CLKSEL0_SDH0SEL_HCLK, CLK_CLKDIV0_SDH0(2), SDH0_RST, SDH0_IRQn, NULL}, |
| chuanga | 0:43ff9e3bc244 | 99 | #endif |
| chuanga | 0:43ff9e3bc244 | 100 | |
| chuanga | 0:43ff9e3bc244 | 101 | {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} |
| chuanga | 0:43ff9e3bc244 | 102 | }; |
| chuanga | 0:43ff9e3bc244 | 103 | |
| chuanga | 0:43ff9e3bc244 | 104 | |
| chuanga | 0:43ff9e3bc244 | 105 | |
| chuanga | 0:43ff9e3bc244 | 106 | #define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ |
| chuanga | 0:43ff9e3bc244 | 107 | #define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ |
| chuanga | 0:43ff9e3bc244 | 108 | #define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ |
| chuanga | 0:43ff9e3bc244 | 109 | #define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ |
| chuanga | 0:43ff9e3bc244 | 110 | #define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ |
| chuanga | 0:43ff9e3bc244 | 111 | #define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ |
| chuanga | 0:43ff9e3bc244 | 112 | |
| chuanga | 0:43ff9e3bc244 | 113 | |
| chuanga | 0:43ff9e3bc244 | 114 | NuSDBlockDevice::NuSDBlockDevice() : |
| chuanga | 0:43ff9e3bc244 | 115 | _sectors(0), |
| chuanga | 0:43ff9e3bc244 | 116 | _dbg(false), |
| chuanga | 0:43ff9e3bc244 | 117 | _sdh_modinit(NULL), |
| chuanga | 0:43ff9e3bc244 | 118 | _sdh((SDName) NC), |
| chuanga | 0:43ff9e3bc244 | 119 | _sdh_base(NULL), |
| chuanga | 0:43ff9e3bc244 | 120 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 121 | _sdh_port((uint32_t) -1), |
| chuanga | 0:43ff9e3bc244 | 122 | #endif |
| chuanga | 0:43ff9e3bc244 | 123 | _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq), |
| chuanga | 0:43ff9e3bc244 | 124 | _sd_dat0(NU_SDH_DAT0), |
| chuanga | 0:43ff9e3bc244 | 125 | _sd_dat1(NU_SDH_DAT1), |
| chuanga | 0:43ff9e3bc244 | 126 | _sd_dat2(NU_SDH_DAT2), |
| chuanga | 0:43ff9e3bc244 | 127 | _sd_dat3(NU_SDH_DAT3), |
| chuanga | 0:43ff9e3bc244 | 128 | _sd_cmd(NU_SDH_CMD), |
| chuanga | 0:43ff9e3bc244 | 129 | _sd_clk(NU_SDH_CLK), |
| chuanga | 0:43ff9e3bc244 | 130 | _sd_cdn(NU_SDH_CDn), |
| chuanga | 0:43ff9e3bc244 | 131 | _is_initialized(false), |
| chuanga | 0:43ff9e3bc244 | 132 | _init_ref_count(0) |
| chuanga | 0:43ff9e3bc244 | 133 | { |
| chuanga | 0:43ff9e3bc244 | 134 | } |
| chuanga | 0:43ff9e3bc244 | 135 | |
| chuanga | 0:43ff9e3bc244 | 136 | NuSDBlockDevice::NuSDBlockDevice(PinName sd_dat0, PinName sd_dat1, PinName sd_dat2, PinName sd_dat3, |
| chuanga | 0:43ff9e3bc244 | 137 | PinName sd_cmd, PinName sd_clk, PinName sd_cdn) : |
| chuanga | 0:43ff9e3bc244 | 138 | _sectors(0), |
| chuanga | 0:43ff9e3bc244 | 139 | _dbg(false), |
| chuanga | 0:43ff9e3bc244 | 140 | _sdh_modinit(NULL), |
| chuanga | 0:43ff9e3bc244 | 141 | _sdh((SDName) NC), |
| chuanga | 0:43ff9e3bc244 | 142 | _sdh_base(NULL), |
| chuanga | 0:43ff9e3bc244 | 143 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 144 | _sdh_port((uint32_t) -1), |
| chuanga | 0:43ff9e3bc244 | 145 | #endif |
| chuanga | 0:43ff9e3bc244 | 146 | _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq), |
| chuanga | 0:43ff9e3bc244 | 147 | _is_initialized(false), |
| chuanga | 0:43ff9e3bc244 | 148 | _init_ref_count(0) |
| chuanga | 0:43ff9e3bc244 | 149 | { |
| chuanga | 0:43ff9e3bc244 | 150 | _sd_dat0 = sd_dat0; |
| chuanga | 0:43ff9e3bc244 | 151 | _sd_dat1 = sd_dat1; |
| chuanga | 0:43ff9e3bc244 | 152 | _sd_dat2 = sd_dat2; |
| chuanga | 0:43ff9e3bc244 | 153 | _sd_dat3 = sd_dat3; |
| chuanga | 0:43ff9e3bc244 | 154 | _sd_cmd = sd_cmd; |
| chuanga | 0:43ff9e3bc244 | 155 | _sd_clk = sd_clk; |
| chuanga | 0:43ff9e3bc244 | 156 | _sd_cdn = sd_cdn; |
| chuanga | 0:43ff9e3bc244 | 157 | } |
| chuanga | 0:43ff9e3bc244 | 158 | |
| chuanga | 0:43ff9e3bc244 | 159 | NuSDBlockDevice::~NuSDBlockDevice() |
| chuanga | 0:43ff9e3bc244 | 160 | { |
| chuanga | 0:43ff9e3bc244 | 161 | if (_is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 162 | deinit(); |
| chuanga | 0:43ff9e3bc244 | 163 | } |
| chuanga | 0:43ff9e3bc244 | 164 | } |
| chuanga | 0:43ff9e3bc244 | 165 | |
| chuanga | 0:43ff9e3bc244 | 166 | int NuSDBlockDevice::init() |
| chuanga | 0:43ff9e3bc244 | 167 | { |
| chuanga | 0:43ff9e3bc244 | 168 | _lock.lock(); |
| chuanga | 0:43ff9e3bc244 | 169 | int err = BD_ERROR_OK; |
| chuanga | 0:43ff9e3bc244 | 170 | |
| chuanga | 0:43ff9e3bc244 | 171 | do { |
| chuanga | 0:43ff9e3bc244 | 172 | if (_is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 173 | _init_ref_count ++; |
| chuanga | 0:43ff9e3bc244 | 174 | break; |
| chuanga | 0:43ff9e3bc244 | 175 | } else { |
| chuanga | 0:43ff9e3bc244 | 176 | _init_ref_count = 0; |
| chuanga | 0:43ff9e3bc244 | 177 | } |
| chuanga | 0:43ff9e3bc244 | 178 | |
| chuanga | 0:43ff9e3bc244 | 179 | err = _init_sdh(); |
| chuanga | 0:43ff9e3bc244 | 180 | if (err != BD_ERROR_OK) { |
| chuanga | 0:43ff9e3bc244 | 181 | break; |
| chuanga | 0:43ff9e3bc244 | 182 | } |
| chuanga | 0:43ff9e3bc244 | 183 | |
| chuanga | 0:43ff9e3bc244 | 184 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 185 | SD_Open(_sdh_port | CardDetect_From_GPIO); |
| chuanga | 0:43ff9e3bc244 | 186 | SD_Probe(_sdh_port); |
| chuanga | 0:43ff9e3bc244 | 187 | |
| chuanga | 0:43ff9e3bc244 | 188 | switch (_sdh_port) { |
| chuanga | 0:43ff9e3bc244 | 189 | case SD_PORT0: |
| chuanga | 0:43ff9e3bc244 | 190 | _is_initialized = sd0_ok && (SD0.CardType != SD_TYPE_UNKNOWN); |
| chuanga | 0:43ff9e3bc244 | 191 | break; |
| chuanga | 0:43ff9e3bc244 | 192 | |
| chuanga | 0:43ff9e3bc244 | 193 | case SD_PORT1: |
| chuanga | 0:43ff9e3bc244 | 194 | _is_initialized = sd1_ok && (SD1.CardType != SD_TYPE_UNKNOWN); |
| chuanga | 0:43ff9e3bc244 | 195 | break; |
| chuanga | 0:43ff9e3bc244 | 196 | } |
| chuanga | 0:43ff9e3bc244 | 197 | |
| chuanga | 0:43ff9e3bc244 | 198 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 199 | MBED_ASSERT(_sdh_modinit != NULL); |
| chuanga | 0:43ff9e3bc244 | 200 | |
| chuanga | 0:43ff9e3bc244 | 201 | NVIC_SetVector(_sdh_modinit->irq_n, _sdh_irq_thunk.entry()); |
| chuanga | 0:43ff9e3bc244 | 202 | NVIC_EnableIRQ(_sdh_modinit->irq_n); |
| chuanga | 0:43ff9e3bc244 | 203 | |
| chuanga | 0:43ff9e3bc244 | 204 | SDH_Open(_sdh_base, CardDetect_From_GPIO); |
| chuanga | 0:43ff9e3bc244 | 205 | SDH_Probe(_sdh_base); |
| chuanga | 0:43ff9e3bc244 | 206 | |
| chuanga | 0:43ff9e3bc244 | 207 | switch (NU_MODINDEX(_sdh)) { |
| chuanga | 0:43ff9e3bc244 | 208 | case 0: |
| chuanga | 0:43ff9e3bc244 | 209 | _is_initialized = SDH_ok && (SD0.CardType != SDH_TYPE_UNKNOWN); |
| chuanga | 0:43ff9e3bc244 | 210 | break; |
| chuanga | 0:43ff9e3bc244 | 211 | |
| chuanga | 0:43ff9e3bc244 | 212 | case 1: |
| chuanga | 0:43ff9e3bc244 | 213 | _is_initialized = SDH_ok && (SD1.CardType != SDH_TYPE_UNKNOWN); |
| chuanga | 0:43ff9e3bc244 | 214 | break; |
| chuanga | 0:43ff9e3bc244 | 215 | } |
| chuanga | 0:43ff9e3bc244 | 216 | |
| chuanga | 0:43ff9e3bc244 | 217 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 218 | MBED_ASSERT(_sdh_modinit != NULL); |
| chuanga | 0:43ff9e3bc244 | 219 | |
| chuanga | 0:43ff9e3bc244 | 220 | NVIC_SetVector(_sdh_modinit->irq_n, _sdh_irq_thunk.entry()); |
| chuanga | 0:43ff9e3bc244 | 221 | NVIC_EnableIRQ(_sdh_modinit->irq_n); |
| chuanga | 0:43ff9e3bc244 | 222 | |
| chuanga | 0:43ff9e3bc244 | 223 | SDH_Open(_sdh_base, CardDetect_From_GPIO); |
| chuanga | 0:43ff9e3bc244 | 224 | SDH_Probe(_sdh_base); |
| chuanga | 0:43ff9e3bc244 | 225 | |
| chuanga | 0:43ff9e3bc244 | 226 | switch (NU_MODINDEX(_sdh)) { |
| chuanga | 0:43ff9e3bc244 | 227 | case 0: |
| chuanga | 0:43ff9e3bc244 | 228 | _is_initialized = SDH_ok && (SD0.CardType != SDH_TYPE_UNKNOWN); |
| chuanga | 0:43ff9e3bc244 | 229 | break; |
| chuanga | 0:43ff9e3bc244 | 230 | } |
| chuanga | 0:43ff9e3bc244 | 231 | #endif |
| chuanga | 0:43ff9e3bc244 | 232 | |
| chuanga | 0:43ff9e3bc244 | 233 | if (_is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 234 | _init_ref_count = 1; |
| chuanga | 0:43ff9e3bc244 | 235 | } else { |
| chuanga | 0:43ff9e3bc244 | 236 | debug_if(_dbg, "Fail to initialize card\n"); |
| chuanga | 0:43ff9e3bc244 | 237 | err = BD_ERROR_DEVICE_ERROR; |
| chuanga | 0:43ff9e3bc244 | 238 | } |
| chuanga | 0:43ff9e3bc244 | 239 | debug_if(_dbg, "init card = %d\n", _is_initialized); |
| chuanga | 0:43ff9e3bc244 | 240 | _sectors = _sd_sectors(); |
| chuanga | 0:43ff9e3bc244 | 241 | |
| chuanga | 0:43ff9e3bc244 | 242 | } while (0); |
| chuanga | 0:43ff9e3bc244 | 243 | |
| chuanga | 0:43ff9e3bc244 | 244 | _lock.unlock(); |
| chuanga | 0:43ff9e3bc244 | 245 | |
| chuanga | 0:43ff9e3bc244 | 246 | return err; |
| chuanga | 0:43ff9e3bc244 | 247 | } |
| chuanga | 0:43ff9e3bc244 | 248 | |
| chuanga | 0:43ff9e3bc244 | 249 | int NuSDBlockDevice::deinit() |
| chuanga | 0:43ff9e3bc244 | 250 | { |
| chuanga | 0:43ff9e3bc244 | 251 | _lock.lock(); |
| chuanga | 0:43ff9e3bc244 | 252 | int err = BD_ERROR_OK; |
| chuanga | 0:43ff9e3bc244 | 253 | |
| chuanga | 0:43ff9e3bc244 | 254 | do { |
| chuanga | 0:43ff9e3bc244 | 255 | if (_is_initialized && _init_ref_count > 1) { |
| chuanga | 0:43ff9e3bc244 | 256 | _init_ref_count --; |
| chuanga | 0:43ff9e3bc244 | 257 | break; |
| chuanga | 0:43ff9e3bc244 | 258 | } else if (! _is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 259 | _init_ref_count = 0; |
| chuanga | 0:43ff9e3bc244 | 260 | break; |
| chuanga | 0:43ff9e3bc244 | 261 | } |
| chuanga | 0:43ff9e3bc244 | 262 | |
| chuanga | 0:43ff9e3bc244 | 263 | if (_sdh_modinit) { |
| chuanga | 0:43ff9e3bc244 | 264 | #if defined(DOMAIN_NS) && DOMAIN_NS |
| chuanga | 0:43ff9e3bc244 | 265 | CLK_DisableModuleClock_S(_sdh_modinit->clkidx); |
| chuanga | 0:43ff9e3bc244 | 266 | #else |
| chuanga | 0:43ff9e3bc244 | 267 | CLK_DisableModuleClock(_sdh_modinit->clkidx); |
| chuanga | 0:43ff9e3bc244 | 268 | #endif |
| chuanga | 0:43ff9e3bc244 | 269 | } |
| chuanga | 0:43ff9e3bc244 | 270 | |
| chuanga | 0:43ff9e3bc244 | 271 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 272 | // TODO |
| chuanga | 0:43ff9e3bc244 | 273 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 274 | // TODO |
| chuanga | 0:43ff9e3bc244 | 275 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 276 | // TODO |
| chuanga | 0:43ff9e3bc244 | 277 | #endif |
| chuanga | 0:43ff9e3bc244 | 278 | |
| chuanga | 0:43ff9e3bc244 | 279 | _is_initialized = false; |
| chuanga | 0:43ff9e3bc244 | 280 | _init_ref_count = 0; |
| chuanga | 0:43ff9e3bc244 | 281 | } while (0); |
| chuanga | 0:43ff9e3bc244 | 282 | |
| chuanga | 0:43ff9e3bc244 | 283 | _lock.unlock(); |
| chuanga | 0:43ff9e3bc244 | 284 | |
| chuanga | 0:43ff9e3bc244 | 285 | return err; |
| chuanga | 0:43ff9e3bc244 | 286 | } |
| chuanga | 0:43ff9e3bc244 | 287 | |
| chuanga | 0:43ff9e3bc244 | 288 | int NuSDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) |
| chuanga | 0:43ff9e3bc244 | 289 | { |
| chuanga | 0:43ff9e3bc244 | 290 | if (! is_valid_program(addr, size)) { |
| chuanga | 0:43ff9e3bc244 | 291 | return SD_BLOCK_DEVICE_ERROR_PARAMETER; |
| chuanga | 0:43ff9e3bc244 | 292 | } |
| chuanga | 0:43ff9e3bc244 | 293 | |
| chuanga | 0:43ff9e3bc244 | 294 | _lock.lock(); |
| chuanga | 0:43ff9e3bc244 | 295 | int err = BD_ERROR_OK; |
| chuanga | 0:43ff9e3bc244 | 296 | |
| chuanga | 0:43ff9e3bc244 | 297 | do { |
| chuanga | 0:43ff9e3bc244 | 298 | if (! _is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 299 | err = SD_BLOCK_DEVICE_ERROR_NO_INIT; |
| chuanga | 0:43ff9e3bc244 | 300 | break; |
| chuanga | 0:43ff9e3bc244 | 301 | } |
| chuanga | 0:43ff9e3bc244 | 302 | |
| chuanga | 0:43ff9e3bc244 | 303 | /* Check if user buffer is SD DMA-compatible */ |
| chuanga | 0:43ff9e3bc244 | 304 | if (sd_dma_buff_compat(b, static_cast<size_t>(size), 512)) { |
| chuanga | 0:43ff9e3bc244 | 305 | /* User buffer is DMA-compatible. We can transfer directly. */ |
| chuanga | 0:43ff9e3bc244 | 306 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 307 | if (SD_Write(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { |
| chuanga | 0:43ff9e3bc244 | 308 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 309 | if (SDH_Write(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { |
| chuanga | 0:43ff9e3bc244 | 310 | #endif |
| chuanga | 0:43ff9e3bc244 | 311 | err = BD_ERROR_DEVICE_ERROR; |
| chuanga | 0:43ff9e3bc244 | 312 | } |
| chuanga | 0:43ff9e3bc244 | 313 | } else { |
| chuanga | 0:43ff9e3bc244 | 314 | /* User buffer is not SD DMA-compatible. We must transfer via DMA intermediate buffer. */ |
| chuanga | 0:43ff9e3bc244 | 315 | const uint8_t *b_pos = static_cast<const uint8_t *>(b); |
| chuanga | 0:43ff9e3bc244 | 316 | bd_addr_t addr_pos = addr; |
| chuanga | 0:43ff9e3bc244 | 317 | bd_size_t rmn = size; |
| chuanga | 0:43ff9e3bc244 | 318 | |
| chuanga | 0:43ff9e3bc244 | 319 | while (rmn) { |
| chuanga | 0:43ff9e3bc244 | 320 | size_t todo_size = (rmn >= DMA_BUFF_SIZE) ? DMA_BUFF_SIZE : static_cast<size_t>(rmn); |
| chuanga | 0:43ff9e3bc244 | 321 | memcpy(dma_buff, b_pos, todo_size); |
| chuanga | 0:43ff9e3bc244 | 322 | |
| chuanga | 0:43ff9e3bc244 | 323 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 324 | if (SD_Write(_sdh_port, const_cast<uint8_t*>(dma_buff), static_cast<uint32_t>(addr_pos / 512), static_cast<uint32_t>(todo_size / 512)) != 0) { |
| chuanga | 0:43ff9e3bc244 | 325 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 326 | if (SDH_Write(_sdh_base, const_cast<uint8_t*>(dma_buff), static_cast<uint32_t>(addr_pos / 512), static_cast<uint32_t>(todo_size / 512)) != 0) { |
| chuanga | 0:43ff9e3bc244 | 327 | #endif |
| chuanga | 0:43ff9e3bc244 | 328 | err = BD_ERROR_DEVICE_ERROR; |
| chuanga | 0:43ff9e3bc244 | 329 | break; |
| chuanga | 0:43ff9e3bc244 | 330 | } |
| chuanga | 0:43ff9e3bc244 | 331 | |
| chuanga | 0:43ff9e3bc244 | 332 | b_pos += todo_size; |
| chuanga | 0:43ff9e3bc244 | 333 | addr_pos += todo_size; |
| chuanga | 0:43ff9e3bc244 | 334 | rmn -= todo_size; |
| chuanga | 0:43ff9e3bc244 | 335 | } |
| chuanga | 0:43ff9e3bc244 | 336 | } |
| chuanga | 0:43ff9e3bc244 | 337 | } while (0); |
| chuanga | 0:43ff9e3bc244 | 338 | |
| chuanga | 0:43ff9e3bc244 | 339 | _lock.unlock(); |
| chuanga | 0:43ff9e3bc244 | 340 | |
| chuanga | 0:43ff9e3bc244 | 341 | return err; |
| chuanga | 0:43ff9e3bc244 | 342 | } |
| chuanga | 0:43ff9e3bc244 | 343 | |
| chuanga | 0:43ff9e3bc244 | 344 | int NuSDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) |
| chuanga | 0:43ff9e3bc244 | 345 | { |
| chuanga | 0:43ff9e3bc244 | 346 | if (! is_valid_read(addr, size)) { |
| chuanga | 0:43ff9e3bc244 | 347 | return SD_BLOCK_DEVICE_ERROR_PARAMETER; |
| chuanga | 0:43ff9e3bc244 | 348 | } |
| chuanga | 0:43ff9e3bc244 | 349 | |
| chuanga | 0:43ff9e3bc244 | 350 | _lock.lock(); |
| chuanga | 0:43ff9e3bc244 | 351 | int err = BD_ERROR_OK; |
| chuanga | 0:43ff9e3bc244 | 352 | |
| chuanga | 0:43ff9e3bc244 | 353 | do { |
| chuanga | 0:43ff9e3bc244 | 354 | if (! _is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 355 | err = SD_BLOCK_DEVICE_ERROR_NO_INIT; |
| chuanga | 0:43ff9e3bc244 | 356 | break; |
| chuanga | 0:43ff9e3bc244 | 357 | } |
| chuanga | 0:43ff9e3bc244 | 358 | |
| chuanga | 0:43ff9e3bc244 | 359 | /* Check if user buffer is SD DMA-compatible */ |
| chuanga | 0:43ff9e3bc244 | 360 | if (sd_dma_buff_compat(b, static_cast<size_t>(size), 512)) { |
| chuanga | 0:43ff9e3bc244 | 361 | /* User buffer is SD DMA-compatible. We can transfer directly. */ |
| chuanga | 0:43ff9e3bc244 | 362 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 363 | if (SD_Read(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { |
| chuanga | 0:43ff9e3bc244 | 364 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 365 | if (SDH_Read(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { |
| chuanga | 0:43ff9e3bc244 | 366 | #endif |
| chuanga | 0:43ff9e3bc244 | 367 | err = BD_ERROR_DEVICE_ERROR; |
| chuanga | 0:43ff9e3bc244 | 368 | } |
| chuanga | 0:43ff9e3bc244 | 369 | } else { |
| chuanga | 0:43ff9e3bc244 | 370 | /* User buffer is not SD DMA-compatible. We must transfer via DMA intermediate buffer. */ |
| chuanga | 0:43ff9e3bc244 | 371 | uint8_t *b_pos = static_cast<uint8_t *>(b); |
| chuanga | 0:43ff9e3bc244 | 372 | bd_addr_t addr_pos = addr; |
| chuanga | 0:43ff9e3bc244 | 373 | bd_size_t rmn = size; |
| chuanga | 0:43ff9e3bc244 | 374 | |
| chuanga | 0:43ff9e3bc244 | 375 | while (rmn) { |
| chuanga | 0:43ff9e3bc244 | 376 | size_t todo_size = (rmn >= DMA_BUFF_SIZE) ? DMA_BUFF_SIZE : static_cast<size_t>(rmn); |
| chuanga | 0:43ff9e3bc244 | 377 | |
| chuanga | 0:43ff9e3bc244 | 378 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 379 | if (SD_Read(_sdh_port, static_cast<uint8_t*>(dma_buff), static_cast<uint32_t>(addr_pos / 512), static_cast<uint32_t>(todo_size / 512)) != 0) { |
| chuanga | 0:43ff9e3bc244 | 380 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 381 | if (SDH_Read(_sdh_base, static_cast<uint8_t*>(dma_buff), static_cast<uint32_t>(addr_pos / 512), static_cast<uint32_t>(todo_size / 512)) != 0) { |
| chuanga | 0:43ff9e3bc244 | 382 | #endif |
| chuanga | 0:43ff9e3bc244 | 383 | err = BD_ERROR_DEVICE_ERROR; |
| chuanga | 0:43ff9e3bc244 | 384 | break; |
| chuanga | 0:43ff9e3bc244 | 385 | } |
| chuanga | 0:43ff9e3bc244 | 386 | |
| chuanga | 0:43ff9e3bc244 | 387 | memcpy(b_pos, dma_buff, todo_size); |
| chuanga | 0:43ff9e3bc244 | 388 | |
| chuanga | 0:43ff9e3bc244 | 389 | b_pos += todo_size; |
| chuanga | 0:43ff9e3bc244 | 390 | addr_pos += todo_size; |
| chuanga | 0:43ff9e3bc244 | 391 | rmn -= todo_size; |
| chuanga | 0:43ff9e3bc244 | 392 | } |
| chuanga | 0:43ff9e3bc244 | 393 | } |
| chuanga | 0:43ff9e3bc244 | 394 | } while (0); |
| chuanga | 0:43ff9e3bc244 | 395 | |
| chuanga | 0:43ff9e3bc244 | 396 | _lock.unlock(); |
| chuanga | 0:43ff9e3bc244 | 397 | |
| chuanga | 0:43ff9e3bc244 | 398 | return err; |
| chuanga | 0:43ff9e3bc244 | 399 | } |
| chuanga | 0:43ff9e3bc244 | 400 | |
| chuanga | 0:43ff9e3bc244 | 401 | int NuSDBlockDevice::erase(bd_addr_t addr, bd_size_t size) |
| chuanga | 0:43ff9e3bc244 | 402 | { |
| chuanga | 0:43ff9e3bc244 | 403 | if (! _is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 404 | return SD_BLOCK_DEVICE_ERROR_NO_INIT; |
| chuanga | 0:43ff9e3bc244 | 405 | } |
| chuanga | 0:43ff9e3bc244 | 406 | |
| chuanga | 0:43ff9e3bc244 | 407 | return BD_ERROR_OK; |
| chuanga | 0:43ff9e3bc244 | 408 | } |
| chuanga | 0:43ff9e3bc244 | 409 | |
| chuanga | 0:43ff9e3bc244 | 410 | bd_size_t NuSDBlockDevice::get_read_size() const |
| chuanga | 0:43ff9e3bc244 | 411 | { |
| chuanga | 0:43ff9e3bc244 | 412 | return 512; |
| chuanga | 0:43ff9e3bc244 | 413 | } |
| chuanga | 0:43ff9e3bc244 | 414 | |
| chuanga | 0:43ff9e3bc244 | 415 | bd_size_t NuSDBlockDevice::get_program_size() const |
| chuanga | 0:43ff9e3bc244 | 416 | { |
| chuanga | 0:43ff9e3bc244 | 417 | return 512; |
| chuanga | 0:43ff9e3bc244 | 418 | } |
| chuanga | 0:43ff9e3bc244 | 419 | |
| chuanga | 0:43ff9e3bc244 | 420 | bd_size_t NuSDBlockDevice::get_erase_size() const |
| chuanga | 0:43ff9e3bc244 | 421 | { |
| chuanga | 0:43ff9e3bc244 | 422 | return 512; |
| chuanga | 0:43ff9e3bc244 | 423 | } |
| chuanga | 0:43ff9e3bc244 | 424 | |
| chuanga | 0:43ff9e3bc244 | 425 | bd_size_t NuSDBlockDevice::get_erase_size(bd_addr_t addr) const |
| chuanga | 0:43ff9e3bc244 | 426 | { |
| chuanga | 0:43ff9e3bc244 | 427 | return 512; |
| chuanga | 0:43ff9e3bc244 | 428 | } |
| chuanga | 0:43ff9e3bc244 | 429 | |
| chuanga | 0:43ff9e3bc244 | 430 | bd_size_t NuSDBlockDevice::size() const |
| chuanga | 0:43ff9e3bc244 | 431 | { |
| chuanga | 0:43ff9e3bc244 | 432 | if (! _is_initialized) { |
| chuanga | 0:43ff9e3bc244 | 433 | return SD_BLOCK_DEVICE_ERROR_NO_INIT; |
| chuanga | 0:43ff9e3bc244 | 434 | } |
| chuanga | 0:43ff9e3bc244 | 435 | |
| chuanga | 0:43ff9e3bc244 | 436 | return 512 * _sectors; |
| chuanga | 0:43ff9e3bc244 | 437 | } |
| chuanga | 0:43ff9e3bc244 | 438 | |
| chuanga | 0:43ff9e3bc244 | 439 | void NuSDBlockDevice::debug(bool dbg) |
| chuanga | 0:43ff9e3bc244 | 440 | { |
| chuanga | 0:43ff9e3bc244 | 441 | _dbg = dbg; |
| chuanga | 0:43ff9e3bc244 | 442 | } |
| chuanga | 0:43ff9e3bc244 | 443 | |
| chuanga | 0:43ff9e3bc244 | 444 | int NuSDBlockDevice::_init_sdh() |
| chuanga | 0:43ff9e3bc244 | 445 | { |
| chuanga | 0:43ff9e3bc244 | 446 | debug_if(_dbg, "SD MPF Setting & Enable SD IP Clock\n"); |
| chuanga | 0:43ff9e3bc244 | 447 | |
| chuanga | 0:43ff9e3bc244 | 448 | // Check if all pins belong to the same SD module |
| chuanga | 0:43ff9e3bc244 | 449 | // Merge SD DAT0/1/2/3 |
| chuanga | 0:43ff9e3bc244 | 450 | uint32_t sd_dat0_mod = pinmap_peripheral(_sd_dat0, PinMap_SD_DAT0); |
| chuanga | 0:43ff9e3bc244 | 451 | uint32_t sd_dat1_mod = pinmap_peripheral(_sd_dat1, PinMap_SD_DAT1); |
| chuanga | 0:43ff9e3bc244 | 452 | uint32_t sd_dat2_mod = pinmap_peripheral(_sd_dat2, PinMap_SD_DAT2); |
| chuanga | 0:43ff9e3bc244 | 453 | uint32_t sd_dat3_mod = pinmap_peripheral(_sd_dat3, PinMap_SD_DAT3); |
| chuanga | 0:43ff9e3bc244 | 454 | uint32_t sd_dat01_mod = (SDName) pinmap_merge(sd_dat0_mod, sd_dat1_mod); |
| chuanga | 0:43ff9e3bc244 | 455 | uint32_t sd_dat23_mod = (SDName) pinmap_merge(sd_dat2_mod, sd_dat3_mod); |
| chuanga | 0:43ff9e3bc244 | 456 | uint32_t sd_dat0123_mod = (SDName) pinmap_merge(sd_dat01_mod, sd_dat23_mod); |
| chuanga | 0:43ff9e3bc244 | 457 | // Merge SD CMD/CLK/CDn |
| chuanga | 0:43ff9e3bc244 | 458 | uint32_t sd_cmd_mod = pinmap_peripheral(_sd_cmd, PinMap_SD_CMD); |
| chuanga | 0:43ff9e3bc244 | 459 | uint32_t sd_clk_mod = pinmap_peripheral(_sd_clk, PinMap_SD_CLK); |
| chuanga | 0:43ff9e3bc244 | 460 | uint32_t sd_cdn_mod = pinmap_peripheral(_sd_cdn, PinMap_SD_CD); |
| chuanga | 0:43ff9e3bc244 | 461 | uint32_t sd_cmdclk_mod = (SDName) pinmap_merge(sd_cmd_mod, sd_clk_mod); |
| chuanga | 0:43ff9e3bc244 | 462 | uint32_t sd_cmdclkcdn_mod = (SDName) pinmap_merge(sd_cmdclk_mod, sd_cdn_mod); |
| chuanga | 0:43ff9e3bc244 | 463 | // Merge SD DAT0/1/2/3 and SD CMD/CLK/CDn |
| chuanga | 0:43ff9e3bc244 | 464 | uint32_t sd_mod = (SDName) pinmap_merge(sd_dat0123_mod, sd_cmdclkcdn_mod); |
| chuanga | 0:43ff9e3bc244 | 465 | |
| chuanga | 0:43ff9e3bc244 | 466 | if (sd_mod == (uint32_t) NC) { |
| chuanga | 0:43ff9e3bc244 | 467 | debug("SD pinmap error\n"); |
| chuanga | 0:43ff9e3bc244 | 468 | return BD_ERROR_DEVICE_ERROR; |
| chuanga | 0:43ff9e3bc244 | 469 | } |
| chuanga | 0:43ff9e3bc244 | 470 | |
| chuanga | 0:43ff9e3bc244 | 471 | _sdh_modinit = get_modinit(sd_mod, sdh_modinit_tab); |
| chuanga | 0:43ff9e3bc244 | 472 | MBED_ASSERT(_sdh_modinit != NULL); |
| chuanga | 0:43ff9e3bc244 | 473 | MBED_ASSERT(_sdh_modinit->modname == sd_mod); |
| chuanga | 0:43ff9e3bc244 | 474 | |
| chuanga | 0:43ff9e3bc244 | 475 | |
| chuanga | 0:43ff9e3bc244 | 476 | // Configure SD multi-function pins |
| chuanga | 0:43ff9e3bc244 | 477 | pinmap_pinout(_sd_dat0, PinMap_SD_DAT0); |
| chuanga | 0:43ff9e3bc244 | 478 | pinmap_pinout(_sd_dat1, PinMap_SD_DAT1); |
| chuanga | 0:43ff9e3bc244 | 479 | pinmap_pinout(_sd_dat2, PinMap_SD_DAT2); |
| chuanga | 0:43ff9e3bc244 | 480 | pinmap_pinout(_sd_dat3, PinMap_SD_DAT3); |
| chuanga | 0:43ff9e3bc244 | 481 | pinmap_pinout(_sd_cmd, PinMap_SD_CMD); |
| chuanga | 0:43ff9e3bc244 | 482 | pinmap_pinout(_sd_clk, PinMap_SD_CLK); |
| chuanga | 0:43ff9e3bc244 | 483 | pinmap_pinout(_sd_cdn, PinMap_SD_CD); |
| chuanga | 0:43ff9e3bc244 | 484 | |
| chuanga | 0:43ff9e3bc244 | 485 | // Configure SD IP clock |
| chuanga | 0:43ff9e3bc244 | 486 | #if defined(DOMAIN_NS) && DOMAIN_NS |
| chuanga | 0:43ff9e3bc244 | 487 | SYS_UnlockReg_S(); |
| chuanga | 0:43ff9e3bc244 | 488 | #else |
| chuanga | 0:43ff9e3bc244 | 489 | SYS_UnlockReg(); |
| chuanga | 0:43ff9e3bc244 | 490 | #endif |
| chuanga | 0:43ff9e3bc244 | 491 | |
| chuanga | 0:43ff9e3bc244 | 492 | // Determine SDH port dependent on passed-in pins |
| chuanga | 0:43ff9e3bc244 | 493 | _sdh = (SDName) sd_mod; |
| chuanga | 0:43ff9e3bc244 | 494 | _sdh_base = (SDH_T *) NU_MODBASE(_sdh); |
| chuanga | 0:43ff9e3bc244 | 495 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 496 | switch (NU_MODSUBINDEX(_sdh)) { |
| chuanga | 0:43ff9e3bc244 | 497 | case 0: |
| chuanga | 0:43ff9e3bc244 | 498 | _sdh_port = SD_PORT0; |
| chuanga | 0:43ff9e3bc244 | 499 | break; |
| chuanga | 0:43ff9e3bc244 | 500 | |
| chuanga | 0:43ff9e3bc244 | 501 | case 1: |
| chuanga | 0:43ff9e3bc244 | 502 | _sdh_port = SD_PORT1; |
| chuanga | 0:43ff9e3bc244 | 503 | break; |
| chuanga | 0:43ff9e3bc244 | 504 | } |
| chuanga | 0:43ff9e3bc244 | 505 | #endif |
| chuanga | 0:43ff9e3bc244 | 506 | |
| chuanga | 0:43ff9e3bc244 | 507 | #if defined(DOMAIN_NS) && DOMAIN_NS |
| chuanga | 0:43ff9e3bc244 | 508 | SYS_ResetModule_S(_sdh_modinit->rsetidx); |
| chuanga | 0:43ff9e3bc244 | 509 | #else |
| chuanga | 0:43ff9e3bc244 | 510 | SYS_ResetModule(_sdh_modinit->rsetidx); |
| chuanga | 0:43ff9e3bc244 | 511 | #endif |
| chuanga | 0:43ff9e3bc244 | 512 | |
| chuanga | 0:43ff9e3bc244 | 513 | #if defined(DOMAIN_NS) && DOMAIN_NS |
| chuanga | 0:43ff9e3bc244 | 514 | CLK_SetModuleClock_S(_sdh_modinit->clkidx, _sdh_modinit->clksrc, _sdh_modinit->clkdiv); |
| chuanga | 0:43ff9e3bc244 | 515 | #else |
| chuanga | 0:43ff9e3bc244 | 516 | CLK_SetModuleClock(_sdh_modinit->clkidx, _sdh_modinit->clksrc, _sdh_modinit->clkdiv); |
| chuanga | 0:43ff9e3bc244 | 517 | #endif |
| chuanga | 0:43ff9e3bc244 | 518 | |
| chuanga | 0:43ff9e3bc244 | 519 | #if defined(DOMAIN_NS) && DOMAIN_NS |
| chuanga | 0:43ff9e3bc244 | 520 | CLK_EnableModuleClock_S(_sdh_modinit->clkidx); |
| chuanga | 0:43ff9e3bc244 | 521 | #else |
| chuanga | 0:43ff9e3bc244 | 522 | CLK_EnableModuleClock(_sdh_modinit->clkidx); |
| chuanga | 0:43ff9e3bc244 | 523 | #endif |
| chuanga | 0:43ff9e3bc244 | 524 | |
| chuanga | 0:43ff9e3bc244 | 525 | #if defined(DOMAIN_NS) && DOMAIN_NS |
| chuanga | 0:43ff9e3bc244 | 526 | SYS_LockReg_S(); |
| chuanga | 0:43ff9e3bc244 | 527 | #else |
| chuanga | 0:43ff9e3bc244 | 528 | SYS_LockReg(); |
| chuanga | 0:43ff9e3bc244 | 529 | #endif |
| chuanga | 0:43ff9e3bc244 | 530 | |
| chuanga | 0:43ff9e3bc244 | 531 | return BD_ERROR_OK; |
| chuanga | 0:43ff9e3bc244 | 532 | } |
| chuanga | 0:43ff9e3bc244 | 533 | |
| chuanga | 0:43ff9e3bc244 | 534 | uint32_t NuSDBlockDevice::_sd_sectors() |
| chuanga | 0:43ff9e3bc244 | 535 | { |
| chuanga | 0:43ff9e3bc244 | 536 | _lock.lock(); |
| chuanga | 0:43ff9e3bc244 | 537 | |
| chuanga | 0:43ff9e3bc244 | 538 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 539 | switch (_sdh_port) { |
| chuanga | 0:43ff9e3bc244 | 540 | case SD_PORT0: |
| chuanga | 0:43ff9e3bc244 | 541 | _sectors = SD_DiskInfo0.totalSectorN; |
| chuanga | 0:43ff9e3bc244 | 542 | break; |
| chuanga | 0:43ff9e3bc244 | 543 | case SD_PORT1: |
| chuanga | 0:43ff9e3bc244 | 544 | _sectors = SD_DiskInfo1.totalSectorN; |
| chuanga | 0:43ff9e3bc244 | 545 | break; |
| chuanga | 0:43ff9e3bc244 | 546 | } |
| chuanga | 0:43ff9e3bc244 | 547 | |
| chuanga | 0:43ff9e3bc244 | 548 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 549 | switch (NU_MODINDEX(_sdh)) { |
| chuanga | 0:43ff9e3bc244 | 550 | case 0: |
| chuanga | 0:43ff9e3bc244 | 551 | _sectors = SD0.totalSectorN; |
| chuanga | 0:43ff9e3bc244 | 552 | break; |
| chuanga | 0:43ff9e3bc244 | 553 | case 1: |
| chuanga | 0:43ff9e3bc244 | 554 | _sectors = SD1.totalSectorN; |
| chuanga | 0:43ff9e3bc244 | 555 | break; |
| chuanga | 0:43ff9e3bc244 | 556 | } |
| chuanga | 0:43ff9e3bc244 | 557 | |
| chuanga | 0:43ff9e3bc244 | 558 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 559 | switch (NU_MODINDEX(_sdh)) { |
| chuanga | 0:43ff9e3bc244 | 560 | case 0: |
| chuanga | 0:43ff9e3bc244 | 561 | _sectors = SD0.totalSectorN; |
| chuanga | 0:43ff9e3bc244 | 562 | break; |
| chuanga | 0:43ff9e3bc244 | 563 | } |
| chuanga | 0:43ff9e3bc244 | 564 | |
| chuanga | 0:43ff9e3bc244 | 565 | #endif |
| chuanga | 0:43ff9e3bc244 | 566 | |
| chuanga | 0:43ff9e3bc244 | 567 | _lock.unlock(); |
| chuanga | 0:43ff9e3bc244 | 568 | |
| chuanga | 0:43ff9e3bc244 | 569 | return _sectors; |
| chuanga | 0:43ff9e3bc244 | 570 | } |
| chuanga | 0:43ff9e3bc244 | 571 | |
| chuanga | 0:43ff9e3bc244 | 572 | void NuSDBlockDevice::_sdh_irq() |
| chuanga | 0:43ff9e3bc244 | 573 | { |
| chuanga | 0:43ff9e3bc244 | 574 | #if TARGET_NUMAKER_PFM_NUC472 |
| chuanga | 0:43ff9e3bc244 | 575 | // TODO: Support IRQ |
| chuanga | 0:43ff9e3bc244 | 576 | |
| chuanga | 0:43ff9e3bc244 | 577 | #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 |
| chuanga | 0:43ff9e3bc244 | 578 | // FMI data abort interrupt |
| chuanga | 0:43ff9e3bc244 | 579 | if (_sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 580 | _sdh_base->GINTSTS = SDH_GINTSTS_DTAIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 581 | /* ResetAllEngine() */ |
| chuanga | 0:43ff9e3bc244 | 582 | _sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; |
| chuanga | 0:43ff9e3bc244 | 583 | } |
| chuanga | 0:43ff9e3bc244 | 584 | |
| chuanga | 0:43ff9e3bc244 | 585 | //----- SD interrupt status |
| chuanga | 0:43ff9e3bc244 | 586 | if (_sdh_base->INTSTS & SDH_INTSTS_BLKDIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 587 | // block down |
| chuanga | 0:43ff9e3bc244 | 588 | extern uint8_t volatile _SDH_SDDataReady; |
| chuanga | 0:43ff9e3bc244 | 589 | _SDH_SDDataReady = TRUE; |
| chuanga | 0:43ff9e3bc244 | 590 | _sdh_base->INTSTS = SDH_INTSTS_BLKDIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 591 | } |
| chuanga | 0:43ff9e3bc244 | 592 | |
| chuanga | 0:43ff9e3bc244 | 593 | // NOTE: On M487, there are two SDH instances which each support port 0 and don't support port 1. |
| chuanga | 0:43ff9e3bc244 | 594 | // Port 0 (support): INTEN.CDIEN0, INTEN.CDSRC0, INTSTS.CDIF0, INTSTS.CDSTS0 |
| chuanga | 0:43ff9e3bc244 | 595 | // Port 1 (no support): INTEN.CDIEN1, INTEN.CDSRC1, INTSTS.CDIF1, INTSTS.CDSTS1 |
| chuanga | 0:43ff9e3bc244 | 596 | if (_sdh_base->INTSTS & SDH_INTSTS_CDIF_Msk) { // port 0 card detect |
| chuanga | 0:43ff9e3bc244 | 597 | _sdh_base->INTSTS = SDH_INTSTS_CDIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 598 | // TBD: Support PnP |
| chuanga | 0:43ff9e3bc244 | 599 | } |
| chuanga | 0:43ff9e3bc244 | 600 | |
| chuanga | 0:43ff9e3bc244 | 601 | // CRC error interrupt |
| chuanga | 0:43ff9e3bc244 | 602 | if (_sdh_base->INTSTS & SDH_INTSTS_CRCIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 603 | _sdh_base->INTSTS = SDH_INTSTS_CRCIF_Msk; // clear interrupt flag |
| chuanga | 0:43ff9e3bc244 | 604 | } |
| chuanga | 0:43ff9e3bc244 | 605 | |
| chuanga | 0:43ff9e3bc244 | 606 | if (_sdh_base->INTSTS & SDH_INTSTS_DITOIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 607 | _sdh_base->INTSTS = SDH_INTSTS_DITOIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 608 | } |
| chuanga | 0:43ff9e3bc244 | 609 | |
| chuanga | 0:43ff9e3bc244 | 610 | // Response in timeout interrupt |
| chuanga | 0:43ff9e3bc244 | 611 | if (_sdh_base->INTSTS & SDH_INTSTS_RTOIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 612 | _sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 613 | } |
| chuanga | 0:43ff9e3bc244 | 614 | |
| chuanga | 0:43ff9e3bc244 | 615 | #elif TARGET_NUMAKER_PFM_M2351 |
| chuanga | 0:43ff9e3bc244 | 616 | // FMI data abort interrupt |
| chuanga | 0:43ff9e3bc244 | 617 | if (_sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 618 | _sdh_base->GINTSTS = SDH_GINTSTS_DTAIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 619 | /* ResetAllEngine() */ |
| chuanga | 0:43ff9e3bc244 | 620 | _sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; |
| chuanga | 0:43ff9e3bc244 | 621 | } |
| chuanga | 0:43ff9e3bc244 | 622 | |
| chuanga | 0:43ff9e3bc244 | 623 | //----- SD interrupt status |
| chuanga | 0:43ff9e3bc244 | 624 | if (_sdh_base->INTSTS & SDH_INTSTS_BLKDIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 625 | // block down |
| chuanga | 0:43ff9e3bc244 | 626 | extern uint8_t volatile g_u8SDDataReadyFlag; |
| chuanga | 0:43ff9e3bc244 | 627 | g_u8SDDataReadyFlag = TRUE; |
| chuanga | 0:43ff9e3bc244 | 628 | _sdh_base->INTSTS = SDH_INTSTS_BLKDIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 629 | } |
| chuanga | 0:43ff9e3bc244 | 630 | |
| chuanga | 0:43ff9e3bc244 | 631 | if (_sdh_base->INTSTS & SDH_INTSTS_CDIF_Msk) { // port 0 card detect |
| chuanga | 0:43ff9e3bc244 | 632 | _sdh_base->INTSTS = SDH_INTSTS_CDIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 633 | // TBD: Support PnP |
| chuanga | 0:43ff9e3bc244 | 634 | } |
| chuanga | 0:43ff9e3bc244 | 635 | |
| chuanga | 0:43ff9e3bc244 | 636 | // CRC error interrupt |
| chuanga | 0:43ff9e3bc244 | 637 | if (_sdh_base->INTSTS & SDH_INTSTS_CRCIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 638 | _sdh_base->INTSTS = SDH_INTSTS_CRCIF_Msk; // clear interrupt flag |
| chuanga | 0:43ff9e3bc244 | 639 | } |
| chuanga | 0:43ff9e3bc244 | 640 | |
| chuanga | 0:43ff9e3bc244 | 641 | if (_sdh_base->INTSTS & SDH_INTSTS_DITOIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 642 | _sdh_base->INTSTS = SDH_INTSTS_DITOIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 643 | } |
| chuanga | 0:43ff9e3bc244 | 644 | |
| chuanga | 0:43ff9e3bc244 | 645 | // Response in timeout interrupt |
| chuanga | 0:43ff9e3bc244 | 646 | if (_sdh_base->INTSTS & SDH_INTSTS_RTOIF_Msk) { |
| chuanga | 0:43ff9e3bc244 | 647 | _sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; |
| chuanga | 0:43ff9e3bc244 | 648 | } |
| chuanga | 0:43ff9e3bc244 | 649 | |
| chuanga | 0:43ff9e3bc244 | 650 | #endif |
| chuanga | 0:43ff9e3bc244 | 651 | } |
| chuanga | 0:43ff9e3bc244 | 652 | |
| chuanga | 0:43ff9e3bc244 | 653 | static bool sd_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to) |
| chuanga | 0:43ff9e3bc244 | 654 | { |
| chuanga | 0:43ff9e3bc244 | 655 | uint32_t buff_ = (uint32_t) buff; |
| chuanga | 0:43ff9e3bc244 | 656 | |
| chuanga | 0:43ff9e3bc244 | 657 | return (((buff_ & 0x03) == 0) && // Word-aligned buffer base address |
| chuanga | 0:43ff9e3bc244 | 658 | ((buff_size & (size_aligned_to - 1)) == 0) && // 'size_aligned_to'-aligned buffer size |
| chuanga | 0:43ff9e3bc244 | 659 | #if TARGET_NUMAKER_PFM_M2351 && (defined(DOMAIN_NS) && DOMAIN_NS) |
| chuanga | 0:43ff9e3bc244 | 660 | (((buff_ >> 28) == 0x3) && (buff_size <= (0x40000000 - buff_)))); // 0x30000000-0x3FFFFFFF |
| chuanga | 0:43ff9e3bc244 | 661 | #else |
| chuanga | 0:43ff9e3bc244 | 662 | (((buff_ >> 28) == 0x2) && (buff_size <= (0x30000000 - buff_)))); // 0x20000000-0x2FFFFFFF |
| chuanga | 0:43ff9e3bc244 | 663 | #endif |
| chuanga | 0:43ff9e3bc244 | 664 | } |
| chuanga | 0:43ff9e3bc244 | 665 | |
| chuanga | 0:43ff9e3bc244 | 666 | const char *NuSDBlockDevice::get_type() const |
| chuanga | 0:43ff9e3bc244 | 667 | { |
| chuanga | 0:43ff9e3bc244 | 668 | return "NUSD"; |
| chuanga | 0:43ff9e3bc244 | 669 | } |
| chuanga | 0:43ff9e3bc244 | 670 | |
| chuanga | 0:43ff9e3bc244 | 671 | #endif /* TARGET_NUVOTON */ |