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.
NuSDBlockDevice.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2015-2016 Nuvoton 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /* Nuvoton mbed enabled targets which support SD card of SD bus mode */ 00018 #if TARGET_NUVOTON 00019 00020 #include "NuSDBlockDevice.h" 00021 #include "PeripheralPins.h" 00022 #include "mbed_debug.h" 00023 #include "nu_modutil.h" 00024 #include "mbed_critical.h" 00025 #include "mbed_toolchain.h" 00026 00027 /* SD DMA compatible buffer if user buffer doesn't meet requirements 00028 * 00029 * SD DMA buffer location requires to be: 00030 * (1) Word-aligned 00031 * (2) Located in 0x2xxxxxxx/0x3xxxxxxx region. Check linker files to ensure global/static 00032 * variables are placed in this region. 00033 * 00034 * SD DMA buffer size DMA_BUF_SIZE must be a multiple of 512-byte block size. 00035 * Its value is estimated to trade memory footprint off against performance. 00036 * 00037 */ 00038 #define DMA_BUFF_SIZE 512 00039 MBED_ALIGN(4) static uint8_t dma_buff[DMA_BUFF_SIZE]; 00040 00041 /* Check if specified buffer is SD DMA-compatible */ 00042 static bool sd_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to); 00043 00044 #if TARGET_NUMAKER_PFM_NUC472 00045 #define NU_SDH_DAT0 PF_5 00046 #define NU_SDH_DAT1 PF_4 00047 #define NU_SDH_DAT2 PF_3 00048 #define NU_SDH_DAT3 PF_2 00049 #define NU_SDH_CMD PF_7 00050 #define NU_SDH_CLK PF_8 00051 #define NU_SDH_CDn PF_6 00052 00053 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00054 #define NU_SDH_DAT0 PE_2 00055 #define NU_SDH_DAT1 PE_3 00056 #define NU_SDH_DAT2 PB_4 00057 #define NU_SDH_DAT3 PB_5 00058 #define NU_SDH_CMD PE_7 00059 #define NU_SDH_CLK PE_6 00060 #define NU_SDH_CDn PD_13 00061 00062 #elif TARGET_NUMAKER_PFM_M2351 00063 #define NU_SDH_DAT0 PE_2 00064 #define NU_SDH_DAT1 PE_3 00065 #define NU_SDH_DAT2 PE_4 00066 #define NU_SDH_DAT3 PE_5 00067 #define NU_SDH_CMD PE_7 00068 #define NU_SDH_CLK PE_6 00069 #define NU_SDH_CDn PD_13 00070 00071 #endif 00072 00073 #if TARGET_NUMAKER_PFM_NUC472 00074 extern DISK_DATA_T SD_DiskInfo0; 00075 extern DISK_DATA_T SD_DiskInfo1; 00076 extern SD_INFO_T SD0,SD1; 00077 extern int sd0_ok,sd1_ok; 00078 00079 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00080 extern int SDH_ok; 00081 extern SDH_INFO_T SD0, SD1; 00082 00083 #elif TARGET_NUMAKER_PFM_M2351 00084 extern int SDH_ok; 00085 extern SDH_INFO_T SD0; 00086 00087 #endif 00088 00089 00090 static const struct nu_modinit_s sdh_modinit_tab[] = { 00091 #if TARGET_NUMAKER_PFM_NUC472 00092 {SD_0_0, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, 00093 {SD_0_1, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, 00094 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00095 {SD_0, SDH0_MODULE, CLK_CLKSEL0_SDH0SEL_HCLK, CLK_CLKDIV0_SDH0(2), SDH0_RST, SDH0_IRQn, NULL}, 00096 {SD_1, SDH1_MODULE, CLK_CLKSEL0_SDH1SEL_HCLK, CLK_CLKDIV3_SDH1(2), SDH1_RST, SDH1_IRQn, NULL}, 00097 #elif TARGET_NUMAKER_PFM_M2351 00098 {SD_0, SDH0_MODULE, CLK_CLKSEL0_SDH0SEL_HCLK, CLK_CLKDIV0_SDH0(2), SDH0_RST, SDH0_IRQn, NULL}, 00099 #endif 00100 00101 {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} 00102 }; 00103 00104 00105 00106 #define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ 00107 #define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ 00108 #define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ 00109 #define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ 00110 #define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ 00111 #define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ 00112 00113 00114 NuSDBlockDevice::NuSDBlockDevice() : 00115 _sectors(0), 00116 _dbg(false), 00117 _sdh_modinit(NULL), 00118 _sdh((SDName) NC), 00119 _sdh_base(NULL), 00120 #if TARGET_NUMAKER_PFM_NUC472 00121 _sdh_port((uint32_t) -1), 00122 #endif 00123 _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq), 00124 _sd_dat0(NU_SDH_DAT0), 00125 _sd_dat1(NU_SDH_DAT1), 00126 _sd_dat2(NU_SDH_DAT2), 00127 _sd_dat3(NU_SDH_DAT3), 00128 _sd_cmd(NU_SDH_CMD), 00129 _sd_clk(NU_SDH_CLK), 00130 _sd_cdn(NU_SDH_CDn), 00131 _is_initialized(false), 00132 _init_ref_count(0) 00133 { 00134 } 00135 00136 NuSDBlockDevice::NuSDBlockDevice(PinName sd_dat0, PinName sd_dat1, PinName sd_dat2, PinName sd_dat3, 00137 PinName sd_cmd, PinName sd_clk, PinName sd_cdn) : 00138 _sectors(0), 00139 _dbg(false), 00140 _sdh_modinit(NULL), 00141 _sdh((SDName) NC), 00142 _sdh_base(NULL), 00143 #if TARGET_NUMAKER_PFM_NUC472 00144 _sdh_port((uint32_t) -1), 00145 #endif 00146 _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq), 00147 _is_initialized(false), 00148 _init_ref_count(0) 00149 { 00150 _sd_dat0 = sd_dat0; 00151 _sd_dat1 = sd_dat1; 00152 _sd_dat2 = sd_dat2; 00153 _sd_dat3 = sd_dat3; 00154 _sd_cmd = sd_cmd; 00155 _sd_clk = sd_clk; 00156 _sd_cdn = sd_cdn; 00157 } 00158 00159 NuSDBlockDevice::~NuSDBlockDevice() 00160 { 00161 if (_is_initialized) { 00162 deinit(); 00163 } 00164 } 00165 00166 int NuSDBlockDevice::init() 00167 { 00168 _lock.lock(); 00169 int err = BD_ERROR_OK; 00170 00171 do { 00172 if (_is_initialized) { 00173 _init_ref_count ++; 00174 break; 00175 } else { 00176 _init_ref_count = 0; 00177 } 00178 00179 err = _init_sdh(); 00180 if (err != BD_ERROR_OK) { 00181 break; 00182 } 00183 00184 #if TARGET_NUMAKER_PFM_NUC472 00185 SD_Open(_sdh_port | CardDetect_From_GPIO); 00186 SD_Probe(_sdh_port); 00187 00188 switch (_sdh_port) { 00189 case SD_PORT0: 00190 _is_initialized = sd0_ok && (SD0.CardType != SD_TYPE_UNKNOWN); 00191 break; 00192 00193 case SD_PORT1: 00194 _is_initialized = sd1_ok && (SD1.CardType != SD_TYPE_UNKNOWN); 00195 break; 00196 } 00197 00198 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00199 MBED_ASSERT(_sdh_modinit != NULL); 00200 00201 NVIC_SetVector(_sdh_modinit->irq_n, _sdh_irq_thunk.entry()); 00202 NVIC_EnableIRQ(_sdh_modinit->irq_n); 00203 00204 SDH_Open(_sdh_base, CardDetect_From_GPIO); 00205 SDH_Probe(_sdh_base); 00206 00207 switch (NU_MODINDEX(_sdh)) { 00208 case 0: 00209 _is_initialized = SDH_ok && (SD0.CardType != SDH_TYPE_UNKNOWN); 00210 break; 00211 00212 case 1: 00213 _is_initialized = SDH_ok && (SD1.CardType != SDH_TYPE_UNKNOWN); 00214 break; 00215 } 00216 00217 #elif TARGET_NUMAKER_PFM_M2351 00218 MBED_ASSERT(_sdh_modinit != NULL); 00219 00220 NVIC_SetVector(_sdh_modinit->irq_n, _sdh_irq_thunk.entry()); 00221 NVIC_EnableIRQ(_sdh_modinit->irq_n); 00222 00223 SDH_Open(_sdh_base, CardDetect_From_GPIO); 00224 SDH_Probe(_sdh_base); 00225 00226 switch (NU_MODINDEX(_sdh)) { 00227 case 0: 00228 _is_initialized = SDH_ok && (SD0.CardType != SDH_TYPE_UNKNOWN); 00229 break; 00230 } 00231 #endif 00232 00233 if (_is_initialized) { 00234 _init_ref_count = 1; 00235 } else { 00236 debug_if(_dbg, "Fail to initialize card\n"); 00237 err = BD_ERROR_DEVICE_ERROR; 00238 } 00239 debug_if(_dbg, "init card = %d\n", _is_initialized); 00240 _sectors = _sd_sectors(); 00241 00242 } while (0); 00243 00244 _lock.unlock(); 00245 00246 return err; 00247 } 00248 00249 int NuSDBlockDevice::deinit() 00250 { 00251 _lock.lock(); 00252 int err = BD_ERROR_OK; 00253 00254 do { 00255 if (_is_initialized && _init_ref_count > 1) { 00256 _init_ref_count --; 00257 break; 00258 } else if (! _is_initialized) { 00259 _init_ref_count = 0; 00260 break; 00261 } 00262 00263 if (_sdh_modinit) { 00264 #if defined(DOMAIN_NS) && DOMAIN_NS 00265 CLK_DisableModuleClock_S(_sdh_modinit->clkidx); 00266 #else 00267 CLK_DisableModuleClock(_sdh_modinit->clkidx); 00268 #endif 00269 } 00270 00271 #if TARGET_NUMAKER_PFM_NUC472 00272 // TODO 00273 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00274 // TODO 00275 #elif TARGET_NUMAKER_PFM_M2351 00276 // TODO 00277 #endif 00278 00279 _is_initialized = false; 00280 _init_ref_count = 0; 00281 } while (0); 00282 00283 _lock.unlock(); 00284 00285 return err; 00286 } 00287 00288 int NuSDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) 00289 { 00290 if (! is_valid_program(addr, size)) { 00291 return SD_BLOCK_DEVICE_ERROR_PARAMETER; 00292 } 00293 00294 _lock.lock(); 00295 int err = BD_ERROR_OK; 00296 00297 do { 00298 if (! _is_initialized) { 00299 err = SD_BLOCK_DEVICE_ERROR_NO_INIT; 00300 break; 00301 } 00302 00303 /* Check if user buffer is SD DMA-compatible */ 00304 if (sd_dma_buff_compat(b, static_cast<size_t>(size), 512)) { 00305 /* User buffer is DMA-compatible. We can transfer directly. */ 00306 #if TARGET_NUMAKER_PFM_NUC472 00307 if (SD_Write(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { 00308 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 00309 if (SDH_Write(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { 00310 #endif 00311 err = BD_ERROR_DEVICE_ERROR; 00312 } 00313 } else { 00314 /* User buffer is not SD DMA-compatible. We must transfer via DMA intermediate buffer. */ 00315 const uint8_t *b_pos = static_cast<const uint8_t *>(b); 00316 bd_addr_t addr_pos = addr; 00317 bd_size_t rmn = size; 00318 00319 while (rmn) { 00320 size_t todo_size = (rmn >= DMA_BUFF_SIZE) ? DMA_BUFF_SIZE : static_cast<size_t>(rmn); 00321 memcpy(dma_buff, b_pos, todo_size); 00322 00323 #if TARGET_NUMAKER_PFM_NUC472 00324 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) { 00325 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 00326 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) { 00327 #endif 00328 err = BD_ERROR_DEVICE_ERROR; 00329 break; 00330 } 00331 00332 b_pos += todo_size; 00333 addr_pos += todo_size; 00334 rmn -= todo_size; 00335 } 00336 } 00337 } while (0); 00338 00339 _lock.unlock(); 00340 00341 return err; 00342 } 00343 00344 int NuSDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) 00345 { 00346 if (! is_valid_read(addr, size)) { 00347 return SD_BLOCK_DEVICE_ERROR_PARAMETER; 00348 } 00349 00350 _lock.lock(); 00351 int err = BD_ERROR_OK; 00352 00353 do { 00354 if (! _is_initialized) { 00355 err = SD_BLOCK_DEVICE_ERROR_NO_INIT; 00356 break; 00357 } 00358 00359 /* Check if user buffer is SD DMA-compatible */ 00360 if (sd_dma_buff_compat(b, static_cast<size_t>(size), 512)) { 00361 /* User buffer is SD DMA-compatible. We can transfer directly. */ 00362 #if TARGET_NUMAKER_PFM_NUC472 00363 if (SD_Read(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { 00364 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 00365 if (SDH_Read(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { 00366 #endif 00367 err = BD_ERROR_DEVICE_ERROR; 00368 } 00369 } else { 00370 /* User buffer is not SD DMA-compatible. We must transfer via DMA intermediate buffer. */ 00371 uint8_t *b_pos = static_cast<uint8_t *>(b); 00372 bd_addr_t addr_pos = addr; 00373 bd_size_t rmn = size; 00374 00375 while (rmn) { 00376 size_t todo_size = (rmn >= DMA_BUFF_SIZE) ? DMA_BUFF_SIZE : static_cast<size_t>(rmn); 00377 00378 #if TARGET_NUMAKER_PFM_NUC472 00379 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) { 00380 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 || TARGET_NUMAKER_PFM_M2351 00381 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) { 00382 #endif 00383 err = BD_ERROR_DEVICE_ERROR; 00384 break; 00385 } 00386 00387 memcpy(b_pos, dma_buff, todo_size); 00388 00389 b_pos += todo_size; 00390 addr_pos += todo_size; 00391 rmn -= todo_size; 00392 } 00393 } 00394 } while (0); 00395 00396 _lock.unlock(); 00397 00398 return err; 00399 } 00400 00401 int NuSDBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00402 { 00403 if (! _is_initialized) { 00404 return SD_BLOCK_DEVICE_ERROR_NO_INIT; 00405 } 00406 00407 return BD_ERROR_OK; 00408 } 00409 00410 bd_size_t NuSDBlockDevice::get_read_size() const 00411 { 00412 return 512; 00413 } 00414 00415 bd_size_t NuSDBlockDevice::get_program_size() const 00416 { 00417 return 512; 00418 } 00419 00420 bd_size_t NuSDBlockDevice::get_erase_size() const 00421 { 00422 return 512; 00423 } 00424 00425 bd_size_t NuSDBlockDevice::get_erase_size(bd_addr_t addr) const 00426 { 00427 return 512; 00428 } 00429 00430 bd_size_t NuSDBlockDevice::size() const 00431 { 00432 if (! _is_initialized) { 00433 return SD_BLOCK_DEVICE_ERROR_NO_INIT; 00434 } 00435 00436 return 512 * _sectors; 00437 } 00438 00439 void NuSDBlockDevice::debug(bool dbg) 00440 { 00441 _dbg = dbg; 00442 } 00443 00444 int NuSDBlockDevice::_init_sdh() 00445 { 00446 debug_if(_dbg, "SD MPF Setting & Enable SD IP Clock\n"); 00447 00448 // Check if all pins belong to the same SD module 00449 // Merge SD DAT0/1/2/3 00450 uint32_t sd_dat0_mod = pinmap_peripheral(_sd_dat0, PinMap_SD_DAT0); 00451 uint32_t sd_dat1_mod = pinmap_peripheral(_sd_dat1, PinMap_SD_DAT1); 00452 uint32_t sd_dat2_mod = pinmap_peripheral(_sd_dat2, PinMap_SD_DAT2); 00453 uint32_t sd_dat3_mod = pinmap_peripheral(_sd_dat3, PinMap_SD_DAT3); 00454 uint32_t sd_dat01_mod = (SDName) pinmap_merge(sd_dat0_mod, sd_dat1_mod); 00455 uint32_t sd_dat23_mod = (SDName) pinmap_merge(sd_dat2_mod, sd_dat3_mod); 00456 uint32_t sd_dat0123_mod = (SDName) pinmap_merge(sd_dat01_mod, sd_dat23_mod); 00457 // Merge SD CMD/CLK/CDn 00458 uint32_t sd_cmd_mod = pinmap_peripheral(_sd_cmd, PinMap_SD_CMD); 00459 uint32_t sd_clk_mod = pinmap_peripheral(_sd_clk, PinMap_SD_CLK); 00460 uint32_t sd_cdn_mod = pinmap_peripheral(_sd_cdn, PinMap_SD_CD); 00461 uint32_t sd_cmdclk_mod = (SDName) pinmap_merge(sd_cmd_mod, sd_clk_mod); 00462 uint32_t sd_cmdclkcdn_mod = (SDName) pinmap_merge(sd_cmdclk_mod, sd_cdn_mod); 00463 // Merge SD DAT0/1/2/3 and SD CMD/CLK/CDn 00464 uint32_t sd_mod = (SDName) pinmap_merge(sd_dat0123_mod, sd_cmdclkcdn_mod); 00465 00466 if (sd_mod == (uint32_t) NC) { 00467 debug("SD pinmap error\n"); 00468 return BD_ERROR_DEVICE_ERROR; 00469 } 00470 00471 _sdh_modinit = get_modinit(sd_mod, sdh_modinit_tab); 00472 MBED_ASSERT(_sdh_modinit != NULL); 00473 MBED_ASSERT(_sdh_modinit->modname == sd_mod); 00474 00475 00476 // Configure SD multi-function pins 00477 pinmap_pinout(_sd_dat0, PinMap_SD_DAT0); 00478 pinmap_pinout(_sd_dat1, PinMap_SD_DAT1); 00479 pinmap_pinout(_sd_dat2, PinMap_SD_DAT2); 00480 pinmap_pinout(_sd_dat3, PinMap_SD_DAT3); 00481 pinmap_pinout(_sd_cmd, PinMap_SD_CMD); 00482 pinmap_pinout(_sd_clk, PinMap_SD_CLK); 00483 pinmap_pinout(_sd_cdn, PinMap_SD_CD); 00484 00485 // Configure SD IP clock 00486 #if defined(DOMAIN_NS) && DOMAIN_NS 00487 SYS_UnlockReg_S(); 00488 #else 00489 SYS_UnlockReg(); 00490 #endif 00491 00492 // Determine SDH port dependent on passed-in pins 00493 _sdh = (SDName) sd_mod; 00494 _sdh_base = (SDH_T *) NU_MODBASE(_sdh); 00495 #if TARGET_NUMAKER_PFM_NUC472 00496 switch (NU_MODSUBINDEX(_sdh)) { 00497 case 0: 00498 _sdh_port = SD_PORT0; 00499 break; 00500 00501 case 1: 00502 _sdh_port = SD_PORT1; 00503 break; 00504 } 00505 #endif 00506 00507 #if defined(DOMAIN_NS) && DOMAIN_NS 00508 SYS_ResetModule_S(_sdh_modinit->rsetidx); 00509 #else 00510 SYS_ResetModule(_sdh_modinit->rsetidx); 00511 #endif 00512 00513 #if defined(DOMAIN_NS) && DOMAIN_NS 00514 CLK_SetModuleClock_S(_sdh_modinit->clkidx, _sdh_modinit->clksrc, _sdh_modinit->clkdiv); 00515 #else 00516 CLK_SetModuleClock(_sdh_modinit->clkidx, _sdh_modinit->clksrc, _sdh_modinit->clkdiv); 00517 #endif 00518 00519 #if defined(DOMAIN_NS) && DOMAIN_NS 00520 CLK_EnableModuleClock_S(_sdh_modinit->clkidx); 00521 #else 00522 CLK_EnableModuleClock(_sdh_modinit->clkidx); 00523 #endif 00524 00525 #if defined(DOMAIN_NS) && DOMAIN_NS 00526 SYS_LockReg_S(); 00527 #else 00528 SYS_LockReg(); 00529 #endif 00530 00531 return BD_ERROR_OK; 00532 } 00533 00534 uint32_t NuSDBlockDevice::_sd_sectors() 00535 { 00536 _lock.lock(); 00537 00538 #if TARGET_NUMAKER_PFM_NUC472 00539 switch (_sdh_port) { 00540 case SD_PORT0: 00541 _sectors = SD_DiskInfo0.totalSectorN; 00542 break; 00543 case SD_PORT1: 00544 _sectors = SD_DiskInfo1.totalSectorN; 00545 break; 00546 } 00547 00548 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00549 switch (NU_MODINDEX(_sdh)) { 00550 case 0: 00551 _sectors = SD0.totalSectorN; 00552 break; 00553 case 1: 00554 _sectors = SD1.totalSectorN; 00555 break; 00556 } 00557 00558 #elif TARGET_NUMAKER_PFM_M2351 00559 switch (NU_MODINDEX(_sdh)) { 00560 case 0: 00561 _sectors = SD0.totalSectorN; 00562 break; 00563 } 00564 00565 #endif 00566 00567 _lock.unlock(); 00568 00569 return _sectors; 00570 } 00571 00572 void NuSDBlockDevice::_sdh_irq() 00573 { 00574 #if TARGET_NUMAKER_PFM_NUC472 00575 // TODO: Support IRQ 00576 00577 #elif TARGET_NUMAKER_PFM_M487 || TARGET_NUMAKER_IOT_M487 00578 // FMI data abort interrupt 00579 if (_sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) { 00580 _sdh_base->GINTSTS = SDH_GINTSTS_DTAIF_Msk; 00581 /* ResetAllEngine() */ 00582 _sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; 00583 } 00584 00585 //----- SD interrupt status 00586 if (_sdh_base->INTSTS & SDH_INTSTS_BLKDIF_Msk) { 00587 // block down 00588 extern uint8_t volatile _SDH_SDDataReady; 00589 _SDH_SDDataReady = TRUE; 00590 _sdh_base->INTSTS = SDH_INTSTS_BLKDIF_Msk; 00591 } 00592 00593 // NOTE: On M487, there are two SDH instances which each support port 0 and don't support port 1. 00594 // Port 0 (support): INTEN.CDIEN0, INTEN.CDSRC0, INTSTS.CDIF0, INTSTS.CDSTS0 00595 // Port 1 (no support): INTEN.CDIEN1, INTEN.CDSRC1, INTSTS.CDIF1, INTSTS.CDSTS1 00596 if (_sdh_base->INTSTS & SDH_INTSTS_CDIF_Msk) { // port 0 card detect 00597 _sdh_base->INTSTS = SDH_INTSTS_CDIF_Msk; 00598 // TBD: Support PnP 00599 } 00600 00601 // CRC error interrupt 00602 if (_sdh_base->INTSTS & SDH_INTSTS_CRCIF_Msk) { 00603 _sdh_base->INTSTS = SDH_INTSTS_CRCIF_Msk; // clear interrupt flag 00604 } 00605 00606 if (_sdh_base->INTSTS & SDH_INTSTS_DITOIF_Msk) { 00607 _sdh_base->INTSTS = SDH_INTSTS_DITOIF_Msk; 00608 } 00609 00610 // Response in timeout interrupt 00611 if (_sdh_base->INTSTS & SDH_INTSTS_RTOIF_Msk) { 00612 _sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; 00613 } 00614 00615 #elif TARGET_NUMAKER_PFM_M2351 00616 // FMI data abort interrupt 00617 if (_sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) { 00618 _sdh_base->GINTSTS = SDH_GINTSTS_DTAIF_Msk; 00619 /* ResetAllEngine() */ 00620 _sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; 00621 } 00622 00623 //----- SD interrupt status 00624 if (_sdh_base->INTSTS & SDH_INTSTS_BLKDIF_Msk) { 00625 // block down 00626 extern uint8_t volatile g_u8SDDataReadyFlag; 00627 g_u8SDDataReadyFlag = TRUE; 00628 _sdh_base->INTSTS = SDH_INTSTS_BLKDIF_Msk; 00629 } 00630 00631 if (_sdh_base->INTSTS & SDH_INTSTS_CDIF_Msk) { // port 0 card detect 00632 _sdh_base->INTSTS = SDH_INTSTS_CDIF_Msk; 00633 // TBD: Support PnP 00634 } 00635 00636 // CRC error interrupt 00637 if (_sdh_base->INTSTS & SDH_INTSTS_CRCIF_Msk) { 00638 _sdh_base->INTSTS = SDH_INTSTS_CRCIF_Msk; // clear interrupt flag 00639 } 00640 00641 if (_sdh_base->INTSTS & SDH_INTSTS_DITOIF_Msk) { 00642 _sdh_base->INTSTS = SDH_INTSTS_DITOIF_Msk; 00643 } 00644 00645 // Response in timeout interrupt 00646 if (_sdh_base->INTSTS & SDH_INTSTS_RTOIF_Msk) { 00647 _sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; 00648 } 00649 00650 #endif 00651 } 00652 00653 static bool sd_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to) 00654 { 00655 uint32_t buff_ = (uint32_t) buff; 00656 00657 return (((buff_ & 0x03) == 0) && // Word-aligned buffer base address 00658 ((buff_size & (size_aligned_to - 1)) == 0) && // 'size_aligned_to'-aligned buffer size 00659 #if TARGET_NUMAKER_PFM_M2351 && (defined(DOMAIN_NS) && DOMAIN_NS) 00660 (((buff_ >> 28) == 0x3) && (buff_size <= (0x40000000 - buff_)))); // 0x30000000-0x3FFFFFFF 00661 #else 00662 (((buff_ >> 28) == 0x2) && (buff_size <= (0x30000000 - buff_)))); // 0x20000000-0x2FFFFFFF 00663 #endif 00664 } 00665 00666 const char *NuSDBlockDevice::get_type() const 00667 { 00668 return "NUSD"; 00669 } 00670 00671 #endif /* TARGET_NUVOTON */
Generated on Tue Jul 12 2022 16:59:38 by
1.7.2