Generic Pelion Device Management example for various Advantech modules.
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 */ |