Modify the file main.cpp for M487

Dependencies:   BufferedSerial

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NuSDBlockDevice.cpp Source File

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)