Ray Liu
/
NuMaker-mbed-Serial-to-Ethernet
Modify the file main.cpp for M487
Embed:
(wiki syntax)
Show/hide line numbers
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 defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M487) 00019 00020 #include "NuSDBlockDevice.h" 00021 #include "PeripheralPins.h" 00022 #include "mbed_debug.h" 00023 #include "nu_modutil.h" 00024 00025 #if defined(TARGET_NUMAKER_PFM_NUC472) 00026 #define NU_SDH_DAT0 PF_5 00027 #define NU_SDH_DAT1 PF_4 00028 #define NU_SDH_DAT2 PF_3 00029 #define NU_SDH_DAT3 PF_2 00030 #define NU_SDH_CMD PF_7 00031 #define NU_SDH_CLK PF_8 00032 #define NU_SDH_CDn PF_6 00033 00034 #elif defined(TARGET_NUMAKER_PFM_M487) 00035 #define NU_SDH_DAT0 PE_2 00036 #define NU_SDH_DAT1 PE_3 00037 #define NU_SDH_DAT2 PE_4 00038 #define NU_SDH_DAT3 PE_5 00039 #define NU_SDH_CMD PE_7 00040 #define NU_SDH_CLK PE_6 00041 #define NU_SDH_CDn PD_13 00042 00043 #endif 00044 00045 #if defined(TARGET_NUMAKER_PFM_NUC472) 00046 extern DISK_DATA_T SD_DiskInfo0; 00047 extern DISK_DATA_T SD_DiskInfo1; 00048 extern SD_INFO_T SD0,SD1; 00049 extern int sd0_ok,sd1_ok; 00050 00051 #elif defined(TARGET_NUMAKER_PFM_M487) 00052 extern int SDH_ok; 00053 extern SDH_INFO_T SD0, SD1; 00054 00055 #endif 00056 00057 00058 static const struct nu_modinit_s sdh_modinit_tab[] = { 00059 #if defined(TARGET_NUMAKER_PFM_NUC472) 00060 {SD_0_0, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, 00061 {SD_0_1, SDH_MODULE, CLK_CLKSEL0_SDHSEL_PLL, CLK_CLKDIV0_SDH(2), SDH_RST, SD_IRQn, NULL}, 00062 #elif defined(TARGET_NUMAKER_PFM_M487) 00063 {SD_0, SDH0_MODULE, CLK_CLKSEL0_SDH0SEL_HCLK, CLK_CLKDIV0_SDH0(2), SDH0_RST, SDH0_IRQn, NULL}, 00064 {SD_1, SDH1_MODULE, CLK_CLKSEL0_SDH1SEL_HCLK, CLK_CLKDIV3_SDH1(2), SDH1_RST, SDH1_IRQn, NULL}, 00065 #endif 00066 00067 {NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL} 00068 }; 00069 00070 00071 00072 #define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ 00073 #define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ 00074 #define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ 00075 #define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ 00076 #define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ 00077 #define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ 00078 00079 00080 NuSDBlockDevice::NuSDBlockDevice() : 00081 _sectors(0), 00082 _is_initialized(false), 00083 _dbg(false), 00084 _sdh_modinit(NULL), 00085 _sdh((SDName) NC), 00086 _sdh_base(NULL), 00087 #if defined(TARGET_NUMAKER_PFM_NUC472) 00088 _sdh_port((uint32_t) -1), 00089 #endif 00090 _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq), 00091 _sd_dat0(NU_SDH_DAT0), 00092 _sd_dat1(NU_SDH_DAT1), 00093 _sd_dat2(NU_SDH_DAT2), 00094 _sd_dat3(NU_SDH_DAT3), 00095 _sd_cmd(NU_SDH_CMD), 00096 _sd_clk(NU_SDH_CLK), 00097 _sd_cdn(NU_SDH_CDn) 00098 { 00099 } 00100 00101 NuSDBlockDevice::NuSDBlockDevice(PinName sd_dat0, PinName sd_dat1, PinName sd_dat2, PinName sd_dat3, 00102 PinName sd_cmd, PinName sd_clk, PinName sd_cdn) : 00103 _sectors(0), 00104 _is_initialized(false), 00105 _dbg(false), 00106 _sdh_modinit(NULL), 00107 _sdh((SDName) NC), 00108 _sdh_base(NULL), 00109 #if defined(TARGET_NUMAKER_PFM_NUC472) 00110 _sdh_port((uint32_t) -1), 00111 #endif 00112 _sdh_irq_thunk(this, &NuSDBlockDevice::_sdh_irq) 00113 { 00114 _sd_dat0 = sd_dat0; 00115 _sd_dat1 = sd_dat1; 00116 _sd_dat2 = sd_dat2; 00117 _sd_dat3 = sd_dat3; 00118 _sd_cmd = sd_cmd; 00119 _sd_clk = sd_clk; 00120 _sd_cdn = sd_cdn; 00121 } 00122 00123 NuSDBlockDevice::~NuSDBlockDevice() 00124 { 00125 if (_is_initialized) { 00126 deinit(); 00127 } 00128 } 00129 00130 int NuSDBlockDevice::init() 00131 { 00132 _lock.lock(); 00133 int err = BD_ERROR_OK; 00134 00135 do { 00136 err = _init_sdh(); 00137 if (err != BD_ERROR_OK) { 00138 break; 00139 } 00140 00141 #if defined(TARGET_NUMAKER_PFM_NUC472) 00142 SD_Open(_sdh_port | CardDetect_From_GPIO); 00143 SD_Probe(_sdh_port); 00144 00145 switch (_sdh_port) { 00146 case SD_PORT0: 00147 _is_initialized = sd0_ok && (SD0.CardType != SD_TYPE_UNKNOWN); 00148 break; 00149 00150 case SD_PORT1: 00151 _is_initialized = sd1_ok && (SD1.CardType != SD_TYPE_UNKNOWN); 00152 break; 00153 } 00154 00155 #elif defined(TARGET_NUMAKER_PFM_M487) 00156 MBED_ASSERT(_sdh_modinit != NULL); 00157 00158 NVIC_SetVector(_sdh_modinit->irq_n, _sdh_irq_thunk.entry()); 00159 NVIC_EnableIRQ(_sdh_modinit->irq_n); 00160 00161 SDH_Open(_sdh_base, CardDetect_From_GPIO); 00162 SDH_Probe(_sdh_base); 00163 00164 switch (NU_MODINDEX(_sdh)) { 00165 case 0: 00166 _is_initialized = SDH_ok && (SD0.CardType != SDH_TYPE_UNKNOWN); 00167 break; 00168 00169 case 1: 00170 _is_initialized = SDH_ok && (SD1.CardType != SDH_TYPE_UNKNOWN); 00171 break; 00172 } 00173 #endif 00174 00175 if (!_is_initialized) { 00176 debug_if(_dbg, "Fail to initialize card\n"); 00177 err = BD_ERROR_DEVICE_ERROR; 00178 } 00179 debug_if(_dbg, "init card = %d\n", _is_initialized); 00180 _sectors = _sd_sectors(); 00181 00182 } while (0); 00183 00184 _lock.unlock(); 00185 00186 return err; 00187 } 00188 00189 int NuSDBlockDevice::deinit() 00190 { 00191 _lock.lock(); 00192 00193 if (_sdh_modinit) { 00194 CLK_DisableModuleClock(_sdh_modinit->clkidx); 00195 } 00196 00197 #if defined(TARGET_NUMAKER_PFM_NUC472) 00198 // TODO 00199 #elif defined(TARGET_NUMAKER_PFM_M487) 00200 // TODO 00201 #endif 00202 00203 _is_initialized = false; 00204 00205 _lock.unlock(); 00206 00207 return BD_ERROR_OK; 00208 } 00209 00210 int NuSDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) 00211 { 00212 if (! is_valid_program(addr, size)) { 00213 return SD_BLOCK_DEVICE_ERROR_PARAMETER; 00214 } 00215 00216 _lock.lock(); 00217 int err = BD_ERROR_OK; 00218 00219 do { 00220 if (! _is_initialized) { 00221 err = SD_BLOCK_DEVICE_ERROR_NO_INIT; 00222 } 00223 00224 #if defined(TARGET_NUMAKER_PFM_NUC472) 00225 if (SD_Write(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { 00226 #elif defined(TARGET_NUMAKER_PFM_M487) 00227 if (SDH_Write(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { 00228 #endif 00229 err = BD_ERROR_DEVICE_ERROR; 00230 } 00231 00232 } while (0); 00233 00234 _lock.unlock(); 00235 00236 return err; 00237 } 00238 00239 int NuSDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) 00240 { 00241 if (! is_valid_read(addr, size)) { 00242 return SD_BLOCK_DEVICE_ERROR_PARAMETER; 00243 } 00244 00245 _lock.lock(); 00246 int err = BD_ERROR_OK; 00247 00248 do { 00249 if (! _is_initialized) { 00250 err = SD_BLOCK_DEVICE_ERROR_NO_INIT; 00251 } 00252 00253 #if defined(TARGET_NUMAKER_PFM_NUC472) 00254 if (SD_Read(_sdh_port, (uint8_t*)b, addr / 512, size / 512) != 0) { 00255 #elif defined(TARGET_NUMAKER_PFM_M487) 00256 if (SDH_Read(_sdh_base, (uint8_t*)b, addr / 512, size / 512) != 0) { 00257 #endif 00258 err = BD_ERROR_DEVICE_ERROR; 00259 } 00260 00261 } while (0); 00262 00263 _lock.unlock(); 00264 00265 return err; 00266 } 00267 00268 int NuSDBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00269 { 00270 return BD_ERROR_OK; 00271 } 00272 00273 bd_size_t NuSDBlockDevice::get_read_size() const 00274 { 00275 return 512; 00276 } 00277 00278 bd_size_t NuSDBlockDevice::get_program_size() const 00279 { 00280 return 512; 00281 } 00282 00283 bd_size_t NuSDBlockDevice::get_erase_size() const 00284 { 00285 return 512; 00286 } 00287 00288 bd_size_t NuSDBlockDevice::size() const 00289 { 00290 return 512 * _sectors; 00291 } 00292 00293 void NuSDBlockDevice::debug(bool dbg) 00294 { 00295 _dbg = dbg; 00296 } 00297 00298 int NuSDBlockDevice::_init_sdh() 00299 { 00300 debug_if(_dbg, "SD MPF Setting & Enable SD IP Clock\n"); 00301 00302 // Check if all pins belong to the same SD module 00303 // Merge SD DAT0/1/2/3 00304 uint32_t sd_dat0_mod = pinmap_peripheral(_sd_dat0, PinMap_SD_DAT0); 00305 uint32_t sd_dat1_mod = pinmap_peripheral(_sd_dat1, PinMap_SD_DAT1); 00306 uint32_t sd_dat2_mod = pinmap_peripheral(_sd_dat2, PinMap_SD_DAT2); 00307 uint32_t sd_dat3_mod = pinmap_peripheral(_sd_dat3, PinMap_SD_DAT3); 00308 uint32_t sd_dat01_mod = (SDName) pinmap_merge(sd_dat0_mod, sd_dat1_mod); 00309 uint32_t sd_dat23_mod = (SDName) pinmap_merge(sd_dat2_mod, sd_dat3_mod); 00310 uint32_t sd_dat0123_mod = (SDName) pinmap_merge(sd_dat01_mod, sd_dat23_mod); 00311 // Merge SD CMD/CLK/CDn 00312 uint32_t sd_cmd_mod = pinmap_peripheral(_sd_cmd, PinMap_SD_CMD); 00313 uint32_t sd_clk_mod = pinmap_peripheral(_sd_clk, PinMap_SD_CLK); 00314 uint32_t sd_cdn_mod = pinmap_peripheral(_sd_cdn, PinMap_SD_CD); 00315 uint32_t sd_cmdclk_mod = (SDName) pinmap_merge(sd_cmd_mod, sd_clk_mod); 00316 uint32_t sd_cmdclkcdn_mod = (SDName) pinmap_merge(sd_cmdclk_mod, sd_cdn_mod); 00317 // Merge SD DAT0/1/2/3 and SD CMD/CLK/CDn 00318 uint32_t sd_mod = (SDName) pinmap_merge(sd_dat0123_mod, sd_cmdclkcdn_mod); 00319 00320 if (sd_mod == (uint32_t) NC) { 00321 debug("SD pinmap error\n"); 00322 return BD_ERROR_DEVICE_ERROR; 00323 } 00324 00325 _sdh_modinit = get_modinit(sd_mod, sdh_modinit_tab); 00326 MBED_ASSERT(_sdh_modinit != NULL); 00327 MBED_ASSERT(_sdh_modinit->modname == sd_mod); 00328 00329 00330 // Configure SD multi-function pins 00331 pinmap_pinout(_sd_dat0, PinMap_SD_DAT0); 00332 pinmap_pinout(_sd_dat1, PinMap_SD_DAT1); 00333 pinmap_pinout(_sd_dat2, PinMap_SD_DAT2); 00334 pinmap_pinout(_sd_dat3, PinMap_SD_DAT3); 00335 pinmap_pinout(_sd_cmd, PinMap_SD_CMD); 00336 pinmap_pinout(_sd_clk, PinMap_SD_CLK); 00337 pinmap_pinout(_sd_cdn, PinMap_SD_CD); 00338 00339 // Configure SD IP clock 00340 SYS_UnlockReg(); 00341 00342 // Determine SDH port dependent on passed-in pins 00343 _sdh = (SDName) sd_mod; 00344 _sdh_base = (SDH_T *) NU_MODBASE(_sdh); 00345 #if defined(TARGET_NUMAKER_PFM_NUC472) 00346 switch (NU_MODSUBINDEX(_sdh)) { 00347 case 0: 00348 _sdh_port = SD_PORT0; 00349 break; 00350 00351 case 1: 00352 _sdh_port = SD_PORT1; 00353 break; 00354 } 00355 #endif 00356 00357 SYS_ResetModule(_sdh_modinit->rsetidx); 00358 CLK_SetModuleClock(_sdh_modinit->clkidx, _sdh_modinit->clksrc, _sdh_modinit->clkdiv); 00359 CLK_EnableModuleClock(_sdh_modinit->clkidx); 00360 00361 SYS_LockReg(); 00362 00363 return BD_ERROR_OK; 00364 } 00365 00366 uint32_t NuSDBlockDevice::_sd_sectors() 00367 { 00368 _lock.lock(); 00369 00370 #if defined(TARGET_NUMAKER_PFM_NUC472) 00371 switch (_sdh_port) { 00372 case SD_PORT0: 00373 _sectors = SD_DiskInfo0.totalSectorN; 00374 break; 00375 case SD_PORT1: 00376 _sectors = SD_DiskInfo1.totalSectorN; 00377 break; 00378 } 00379 00380 #elif defined(TARGET_NUMAKER_PFM_M487) 00381 switch (NU_MODINDEX(_sdh)) { 00382 case 0: 00383 _sectors = SD0.totalSectorN; 00384 break; 00385 case 1: 00386 _sectors = SD1.totalSectorN; 00387 break; 00388 } 00389 00390 #endif 00391 00392 _lock.unlock(); 00393 00394 return _sectors; 00395 } 00396 00397 void NuSDBlockDevice::_sdh_irq() 00398 { 00399 #if defined(TARGET_NUMAKER_PFM_NUC472) 00400 // TODO: Support IRQ 00401 00402 #elif defined(TARGET_NUMAKER_PFM_M487) 00403 // FMI data abort interrupt 00404 if (_sdh_base->GINTSTS & SDH_GINTSTS_DTAIF_Msk) { 00405 _sdh_base->GINTSTS = SDH_GINTSTS_DTAIF_Msk; 00406 /* ResetAllEngine() */ 00407 _sdh_base->GCTL |= SDH_GCTL_GCTLRST_Msk; 00408 } 00409 00410 //----- SD interrupt status 00411 if (_sdh_base->INTSTS & SDH_INTSTS_BLKDIF_Msk) { 00412 // block down 00413 extern uint8_t volatile _SDH_SDDataReady; 00414 _SDH_SDDataReady = TRUE; 00415 _sdh_base->INTSTS = SDH_INTSTS_BLKDIF_Msk; 00416 } 00417 00418 // NOTE: On M487, there are two SDH instances which each support port 0 and don't support port 1. 00419 // Port 0 (support): INTEN.CDIEN0, INTEN.CDSRC0, INTSTS.CDIF0, INTSTS.CDSTS0 00420 // Port 1 (no support): INTEN.CDIEN1, INTEN.CDSRC1, INTSTS.CDIF1, INTSTS.CDSTS1 00421 if (_sdh_base->INTSTS & SDH_INTSTS_CDIF_Msk) { // port 0 card detect 00422 _sdh_base->INTSTS = SDH_INTSTS_CDIF_Msk; 00423 // TBD: Support PnP 00424 } 00425 00426 // CRC error interrupt 00427 if (_sdh_base->INTSTS & SDH_INTSTS_CRCIF_Msk) { 00428 _sdh_base->INTSTS = SDH_INTSTS_CRCIF_Msk; // clear interrupt flag 00429 } 00430 00431 if (_sdh_base->INTSTS & SDH_INTSTS_DITOIF_Msk) { 00432 _sdh_base->INTSTS = SDH_INTSTS_DITOIF_Msk; 00433 } 00434 00435 // Response in timeout interrupt 00436 if (_sdh_base->INTSTS & SDH_INTSTS_RTOIF_Msk) { 00437 _sdh_base->INTSTS |= SDH_INTSTS_RTOIF_Msk; 00438 } 00439 #endif 00440 } 00441 00442 00443 #endif //#if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M487)
Generated on Sat Jul 23 2022 12:40:30 by 1.7.2