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.
FlashAccess.cpp
00001 /******************************************************************************* 00002 * DISCLAIMER 00003 * This software is supplied by Renesas Electronics Corporation and is only 00004 * intended for use with Renesas products. No other uses are authorized. This 00005 * software is owned by Renesas Electronics Corporation and is protected under 00006 * all applicable laws, including copyright laws. 00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING 00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT 00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. 00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS 00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE 00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR 00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE 00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00016 * Renesas reserves the right, without notice, to make changes to this software 00017 * and to discontinue the availability of this software. By using this software, 00018 * you agree to the additional terms and conditions found by accessing the 00019 * following link: 00020 * http://www.renesas.com/disclaimer 00021 * 00022 * Copyright (C) 2017 Renesas Electronics Corporation. All rights reserved. 00023 *******************************************************************************/ 00024 00025 #include "mbed.h" 00026 #include "FlashAccess.h" 00027 00028 /* ---- serial flash command ---- */ 00029 #define SFLASHCMD_SECTOR_ERASE (0x20u) /* SE 3-byte address(1bit) */ 00030 #define SFLASHCMD_PAGE_PROGRAM (0x02u) /* PP 3-byte address(1bit), data(1bit) */ 00031 #define SFLASHCMD_READ (0x03u) /* READ 3-byte address(1bit), data(1bit) */ 00032 #define SFLASHCMD_READ_STATUS_REG (0x05u) /* RDSR data(1bit) */ 00033 #define SFLASHCMD_WRITE_ENABLE (0x06u) /* WREN */ 00034 /* ---- serial flash register definitions ---- */ 00035 #define STREG_BUSY_BIT (0x01u) /* SR.[0]BUSY Erase/Write In Progress (RO) */ 00036 00037 /* Definition of the base address for the MMU translation table */ 00038 #if defined(__CC_ARM) || defined(__GNUC__) 00039 extern uint32_t Image$$TTB$$ZI$$Base; 00040 #define TTB ((uint32_t)&Image$$TTB$$ZI$$Base) /* using linker symbol */ 00041 #elif defined(__ICCARM__) 00042 #pragma section="TTB" 00043 #define TTB ((uint32_t)__section_begin("TTB")) 00044 #endif 00045 00046 /** public **/ 00047 00048 FlashAccess::FlashAccess() : SPIBSC(&SPIBSC0) { 00049 } 00050 00051 bool FlashAccess::SectorErase(uint32_t addr) { 00052 bool ret; 00053 #if defined (__ICCARM__) 00054 int was_masked = __disable_irq_iar(); 00055 #else 00056 int was_masked = __disable_irq(); 00057 #endif 00058 spi_mode(); 00059 ret = _SectorErase(addr); 00060 ex_mode(); 00061 if (0 == was_masked) { 00062 __enable_irq(); 00063 } 00064 return ret; 00065 } 00066 00067 bool FlashAccess::PageProgram(uint32_t addr, uint8_t * buf, int32_t size) { 00068 bool ret; 00069 #if defined (__ICCARM__) 00070 int was_masked = __disable_irq_iar(); 00071 #else 00072 int was_masked = __disable_irq(); 00073 #endif 00074 spi_mode(); 00075 ret = _PageProgram(addr, buf, size); 00076 ex_mode(); 00077 if (0 == was_masked) { 00078 __enable_irq(); 00079 } 00080 return ret; 00081 } 00082 00083 bool FlashAccess::Read(uint32_t addr, uint8_t * buf, int32_t size) { 00084 bool ret; 00085 #if defined (__ICCARM__) 00086 int was_masked = __disable_irq_iar(); 00087 #else 00088 int was_masked = __disable_irq(); 00089 #endif 00090 spi_mode(); 00091 ret = _Read(addr, buf, size); 00092 ex_mode(); 00093 if (0 == was_masked) { 00094 __enable_irq(); 00095 } 00096 return ret; 00097 } 00098 00099 /** protected **/ 00100 00101 bool FlashAccess::_SectorErase(uint32_t addr) { 00102 bool ret; 00103 00104 /* ---- Write enable ---- */ 00105 ret = _WriteEnable(); /* WREN Command */ 00106 if (ret == false) { 00107 return ret; 00108 } 00109 00110 /* ---- spimd_reg init ---- */ 00111 clear_spimd_reg(&spimd_reg); 00112 00113 /* ---- command ---- */ 00114 spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; 00115 spimd_reg.cdb = SPIBSC_1BIT; 00116 spimd_reg.cmd = SFLASHCMD_SECTOR_ERASE; 00117 00118 /* ---- address ---- */ 00119 spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24; 00120 spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */ 00121 spimd_reg.adb = SPIBSC_1BIT; 00122 spimd_reg.addr = addr; 00123 00124 ret = spibsc_transfer(&spimd_reg); 00125 if (ret == false) { 00126 return ret; 00127 } 00128 00129 ret = _busy_wait(); 00130 00131 return ret; 00132 } 00133 00134 bool FlashAccess::_PageProgram(uint32_t addr, uint8_t * buf, int32_t size) { 00135 bool ret; 00136 00137 /* ---- Write enable ---- */ 00138 ret = _WriteEnable(); /* WREN Command */ 00139 if (ret == false) { 00140 return ret; 00141 } 00142 00143 /* ----------- 1. Command, Address ---------------*/ 00144 /* ---- spimd_reg init ---- */ 00145 clear_spimd_reg(&spimd_reg); 00146 00147 /* ---- command ---- */ 00148 spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; 00149 spimd_reg.cdb = SPIBSC_1BIT; 00150 spimd_reg.cmd = SFLASHCMD_PAGE_PROGRAM; 00151 00152 /* ---- address ---- */ 00153 spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24; 00154 spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */ 00155 spimd_reg.adb = SPIBSC_1BIT; 00156 spimd_reg.addr = addr; 00157 00158 /* ---- Others ---- */ 00159 spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ 00160 00161 ret = spibsc_transfer(&spimd_reg); /* Command,Address */ 00162 if (ret == false) { 00163 return ret; 00164 } 00165 00166 /* ----------- 2. Data ---------------*/ 00167 ret = data_send(SPIBSC_1BIT, SPIBSC_SPISSL_NEGATE, buf, size); 00168 if (ret == false) { 00169 return ret; 00170 } 00171 00172 ret = _busy_wait(); 00173 00174 return ret; 00175 } 00176 00177 bool FlashAccess::_Read(uint32_t addr, uint8_t * buf, int32_t size) { 00178 bool ret; 00179 00180 /* ----------- 1. Command, Address ---------------*/ 00181 /* ---- spimd_reg init ---- */ 00182 clear_spimd_reg(&spimd_reg); 00183 00184 /* ---- command ---- */ 00185 spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; 00186 spimd_reg.cdb = SPIBSC_1BIT; 00187 spimd_reg.cmd = SFLASHCMD_READ; 00188 00189 /* ---- address ---- */ 00190 spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24; 00191 spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */ 00192 spimd_reg.adb = SPIBSC_1BIT; 00193 spimd_reg.addr = addr; 00194 00195 /* ---- Others ---- */ 00196 spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ 00197 00198 ret = spibsc_transfer(&spimd_reg); /* Command,Address */ 00199 if (ret == false) { 00200 return ret; 00201 } 00202 00203 /* ----------- 2. Data ---------------*/ 00204 ret = data_recv(SPIBSC_1BIT, SPIBSC_SPISSL_NEGATE, buf, size); 00205 00206 return ret; 00207 } 00208 00209 bool FlashAccess::_WriteEnable(void) { 00210 bool ret; 00211 00212 /* ---- spimd_reg init ---- */ 00213 clear_spimd_reg(&spimd_reg); 00214 00215 /* ---- command ---- */ 00216 spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; 00217 spimd_reg.cdb = SPIBSC_1BIT; 00218 spimd_reg.cmd = SFLASHCMD_WRITE_ENABLE; 00219 00220 ret = spibsc_transfer(&spimd_reg); 00221 00222 return ret; 00223 } 00224 00225 bool FlashAccess::_busy_wait(void) { 00226 bool ret; 00227 uint8_t st_reg; 00228 00229 while (1) { 00230 ret = _read_register(SFLASHCMD_READ_STATUS_REG, &st_reg); 00231 if (ret == false) { 00232 break; 00233 } 00234 if ((st_reg & STREG_BUSY_BIT) == 0) { 00235 break; 00236 } 00237 } 00238 00239 return ret; 00240 } 00241 00242 bool FlashAccess::_read_register(uint8_t cmd, uint8_t * status) { 00243 bool ret; 00244 00245 /* ---- spimd_reg init ---- */ 00246 clear_spimd_reg(&spimd_reg); 00247 00248 /* ---- command ---- */ 00249 spimd_reg.cde = SPIBSC_OUTPUT_ENABLE; 00250 spimd_reg.cdb = SPIBSC_1BIT; 00251 spimd_reg.cmd = cmd; 00252 00253 /* ---- Others ---- */ 00254 spimd_reg.sslkp = SPIBSC_SPISSL_NEGATE; /* SPBSSL level */ 00255 spimd_reg.spire = SPIBSC_SPIDATA_ENABLE; /* read enable/disable */ 00256 spimd_reg.spiwe = SPIBSC_SPIDATA_ENABLE; /* write enable/disable */ 00257 00258 /* ---- data ---- */ 00259 spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */ 00260 spimd_reg.spidre = SPIBSC_SDR_TRANS; /* SDR */ 00261 spimd_reg.spidb = SPIBSC_1BIT; 00262 spimd_reg.smwdr[0] = 0x00; /* Output 0 in read status */ 00263 spimd_reg.smwdr[1] = 0x00; /* Output 0 in read status */ 00264 00265 ret = spibsc_transfer(&spimd_reg); 00266 if (ret != false) { 00267 *status = (uint8_t)(spimd_reg.smrdr[0]); /* Data[7:0] */ 00268 } 00269 00270 return ret; 00271 } 00272 00273 bool FlashAccess::data_send(uint32_t bit_width, uint32_t spbssl_level, uint8_t * buf, int32_t size) { 00274 bool ret = true; 00275 int32_t unit; 00276 uint8_t *buf_b; 00277 uint16_t *buf_s; 00278 uint32_t *buf_l; 00279 00280 /* ---- spimd_reg init ---- */ 00281 clear_spimd_reg(&spimd_reg); 00282 00283 /* ---- Others ---- */ 00284 spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ 00285 spimd_reg.spiwe = SPIBSC_SPIDATA_ENABLE; /* write enable/disable */ 00286 00287 /* ---- data ---- */ 00288 spimd_reg.spidb = bit_width; 00289 spimd_reg.spidre= SPIBSC_SDR_TRANS; /* SDR */ 00290 00291 if (((uint32_t)size & 0x3) == 0) { 00292 spimd_reg.spide = SPIBSC_OUTPUT_SPID_32; /* Enable(32bit) */ 00293 unit = 4; 00294 } else if (((uint32_t)size & 0x1) == 0) { 00295 spimd_reg.spide = SPIBSC_OUTPUT_SPID_16; /* Enable(16bit) */ 00296 unit = 2; 00297 } else { 00298 spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */ 00299 unit = 1; 00300 } 00301 00302 while (size > 0) { 00303 if (unit == 1) { 00304 buf_b = (uint8_t *)buf; 00305 spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)*buf_b) & 0x000000FF); 00306 } else if (unit == 2) { 00307 buf_s = (uint16_t *)buf; 00308 spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)*buf_s) & 0x0000FFFF); 00309 } else if (unit == 4) { 00310 buf_l = (uint32_t *)buf; 00311 spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)(*buf_l)) & 0xfffffffful); 00312 } else { 00313 /* Do Nothing */ 00314 } 00315 00316 buf += unit; 00317 size -= unit; 00318 00319 if (size <= 0) { 00320 spimd_reg.sslkp = spbssl_level; 00321 } 00322 00323 ret = spibsc_transfer(&spimd_reg); /* Data */ 00324 if (ret == false) { 00325 return ret; 00326 } 00327 } 00328 00329 return ret; 00330 } 00331 00332 bool FlashAccess::data_recv(uint32_t bit_width, uint32_t spbssl_level, uint8_t * buf, int32_t size) { 00333 bool ret = true; 00334 int32_t unit; 00335 uint8_t *buf_b; 00336 uint16_t *buf_s; 00337 uint32_t *buf_l; 00338 00339 /* ---- spimd_reg init ---- */ 00340 clear_spimd_reg(&spimd_reg); 00341 00342 /* ---- Others ---- */ 00343 spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */ 00344 spimd_reg.spire = SPIBSC_SPIDATA_ENABLE; /* read enable/disable */ 00345 00346 /* ---- data ---- */ 00347 spimd_reg.spidb = bit_width; 00348 spimd_reg.spidre = SPIBSC_SDR_TRANS; /* SDR */ 00349 00350 if (((uint32_t)size & 0x3) == 0) { 00351 spimd_reg.spide = SPIBSC_OUTPUT_SPID_32; /* Enable(32bit) */ 00352 unit = 4; 00353 } else if (((uint32_t)size & 0x1) == 0) { 00354 spimd_reg.spide = SPIBSC_OUTPUT_SPID_16; /* Enable(16bit) */ 00355 unit = 2; 00356 } else { 00357 spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */ 00358 unit = 1; 00359 } 00360 00361 while (size > 0) { 00362 if (unit >= size) { 00363 spimd_reg.sslkp = spbssl_level; 00364 } 00365 00366 ret = spibsc_transfer(&spimd_reg); /* Data */ 00367 if (ret == false) { 00368 return ret; 00369 } 00370 00371 if (unit == 1) { 00372 buf_b = (uint8_t *)buf; 00373 *buf_b = (uint8_t)((spimd_reg.smrdr[0]) & 0x000000fful); 00374 } else if (unit == 2) { 00375 buf_s = (uint16_t *)buf; 00376 *buf_s = (uint16_t)((spimd_reg.smrdr[0]) & 0x0000fffful); 00377 } else if (unit == 4) { 00378 buf_l = (uint32_t *)buf; 00379 *buf_l = (uint32_t)((spimd_reg.smrdr[0]) & 0xfffffffful); 00380 } else { 00381 /* Do Nothing */ 00382 } 00383 00384 buf += unit; 00385 size -= unit; 00386 } 00387 00388 return ret; 00389 } 00390 00391 void FlashAccess::spi_mode(void) { 00392 volatile uint32_t dummy_read_32; 00393 00394 if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_SPI) { 00395 /* ==== Change the MMU translation table SPI Multi-I/O bus space settings 00396 for use in SPI operating mode ==== */ 00397 change_mmu_ttbl_spibsc(0); 00398 00399 /* ==== Cleaning and invalidation of cache ==== */ 00400 cache_control(); 00401 00402 /* ==== Switch to SPI operating mode ==== */ 00403 spibsc_stop(); 00404 00405 dummy_read_32 = SPIBSC->CMNCR; /* dummy read */ 00406 /* SPI Mode */ 00407 RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SPI, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD); 00408 dummy_read_32 = SPIBSC->CMNCR; /* dummy read */ 00409 00410 } 00411 (void)dummy_read_32; 00412 } 00413 00414 void FlashAccess::ex_mode(void) { 00415 volatile uint32_t dummy_read_32; 00416 00417 if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_EXTRD) { 00418 /* ==== Switch to external address space read mode and clear SPIBSC read cache ==== */ 00419 spibsc_stop(); 00420 00421 /* Flush SPIBSC's read cache */ 00422 RegWwrite_32(&SPIBSC->DRCR, SPIBSC_DRCR_RCF_EXE, SPIBSC_DRCR_RCF_SHIFT, SPIBSC_DRCR_RCF); 00423 dummy_read_32 = SPIBSC->DRCR; /* dummy read */ 00424 00425 /* External address space read mode */ 00426 RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_EXTRD, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD); 00427 dummy_read_32 = SPIBSC->CMNCR; /* dummy read */ 00428 00429 /* ==== Change the MMU translation table SPI Multi-I/O bus space settings 00430 for use in external address space read mode ==== */ 00431 change_mmu_ttbl_spibsc(1); 00432 00433 /* ==== Cleaning and invalidation of cache ==== */ 00434 cache_control(); 00435 } 00436 (void)dummy_read_32; 00437 } 00438 00439 void FlashAccess::clear_spimd_reg(st_spibsc_spimd_reg_t * regset) { 00440 /* ---- command ---- */ 00441 regset->cde = SPIBSC_OUTPUT_DISABLE; 00442 regset->cdb = SPIBSC_1BIT; 00443 regset->cmd = 0x00; 00444 00445 /* ---- optional command ---- */ 00446 regset->ocde = SPIBSC_OUTPUT_DISABLE; 00447 regset->ocdb = SPIBSC_1BIT; 00448 regset->ocmd = 0x00; 00449 00450 /* ---- address ---- */ 00451 regset->ade = SPIBSC_OUTPUT_DISABLE; 00452 regset->addre = SPIBSC_SDR_TRANS; /* SDR */ 00453 regset->adb = SPIBSC_1BIT; 00454 regset->addr = 0x00000000; 00455 00456 /* ---- option data ---- */ 00457 regset->opde = SPIBSC_OUTPUT_DISABLE; 00458 regset->opdre = SPIBSC_SDR_TRANS; /* SDR */ 00459 regset->opdb = SPIBSC_1BIT; 00460 regset->opd[0] = 0x00; /* OPD3 */ 00461 regset->opd[1] = 0x00; /* OPD2 */ 00462 regset->opd[2] = 0x00; /* OPD1 */ 00463 regset->opd[3] = 0x00; /* OPD0 */ 00464 00465 /* ---- dummy cycle ---- */ 00466 regset->dme = SPIBSC_DUMMY_CYC_DISABLE; 00467 regset->dmdb = SPIBSC_1BIT; 00468 regset->dmcyc = SPIBSC_DUMMY_1CYC; 00469 00470 /* ---- data ---- */ 00471 regset->spide = SPIBSC_OUTPUT_DISABLE; 00472 regset->spidre = SPIBSC_SDR_TRANS; /* SDR */ 00473 regset->spidb = SPIBSC_1BIT; 00474 00475 /* ---- Others ---- */ 00476 regset->sslkp = SPIBSC_SPISSL_NEGATE; /* SPBSSL level */ 00477 regset->spire = SPIBSC_SPIDATA_DISABLE; /* read enable/disable */ 00478 regset->spiwe = SPIBSC_SPIDATA_DISABLE; /* write enable/disable */ 00479 } 00480 00481 bool FlashAccess::spibsc_transfer(st_spibsc_spimd_reg_t * regset) { 00482 if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_SPI) { 00483 if (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_SSLF_SHIFT, SPIBSC_CMNSR_SSLF) != SPIBSC_SSL_NEGATE) { 00484 return false; 00485 } 00486 /* SPI Mode */ 00487 RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SPI, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD); 00488 } 00489 00490 if (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) { 00491 return false; 00492 } 00493 00494 /* ---- Command ---- */ 00495 /* Enable/Disable */ 00496 RegWwrite_32(&SPIBSC->SMENR, regset->cde, SPIBSC_SMENR_CDE_SHIFT, SPIBSC_SMENR_CDE); 00497 if (regset->cde != SPIBSC_OUTPUT_DISABLE) { 00498 /* Command */ 00499 RegWwrite_32(&SPIBSC->SMCMR, regset->cmd, SPIBSC_SMCMR_CMD_SHIFT, SPIBSC_SMCMR_CMD); 00500 /* Single/Dual/Quad */ 00501 RegWwrite_32(&SPIBSC->SMENR, regset->cdb, SPIBSC_SMENR_CDB_SHIFT, SPIBSC_SMENR_CDB); 00502 } 00503 00504 /* ---- Option Command ---- */ 00505 /* Enable/Disable */ 00506 RegWwrite_32(&SPIBSC->SMENR, regset->ocde, SPIBSC_SMENR_OCDE_SHIFT, SPIBSC_SMENR_OCDE); 00507 if (regset->ocde != SPIBSC_OUTPUT_DISABLE) { 00508 /* Option Command */ 00509 RegWwrite_32(&SPIBSC->SMCMR, regset->ocmd, SPIBSC_SMCMR_OCMD_SHIFT, SPIBSC_SMCMR_OCMD); 00510 /* Single/Dual/Quad */ 00511 RegWwrite_32(&SPIBSC->SMENR, regset->ocdb, SPIBSC_SMENR_OCDB_SHIFT, SPIBSC_SMENR_OCDB); 00512 } 00513 00514 /* ---- Address ---- */ 00515 /* Enable/Disable */ 00516 RegWwrite_32(&SPIBSC->SMENR, regset->ade, SPIBSC_SMENR_ADE_SHIFT, SPIBSC_SMENR_ADE); 00517 if (regset->ade != SPIBSC_OUTPUT_DISABLE) { 00518 /* Address */ 00519 RegWwrite_32(&SPIBSC->SMADR, regset->addr, SPIBSC_SMADR_ADR_SHIFT, SPIBSC_SMADR_ADR); 00520 /* Single/Dual/Quad */ 00521 RegWwrite_32(&SPIBSC->SMENR, regset->adb, SPIBSC_SMENR_ADB_SHIFT, SPIBSC_SMENR_ADB); 00522 } 00523 00524 /* ---- Option Data ---- */ 00525 /* Enable/Disable */ 00526 RegWwrite_32(&SPIBSC->SMENR, regset->opde, SPIBSC_SMENR_OPDE_SHIFT, SPIBSC_SMENR_OPDE); 00527 if (regset->opde != SPIBSC_OUTPUT_DISABLE) { 00528 /* Option Data */ 00529 RegWwrite_32(&SPIBSC->SMOPR, regset->opd[0], SPIBSC_SMOPR_OPD3_SHIFT, SPIBSC_SMOPR_OPD3); 00530 RegWwrite_32(&SPIBSC->SMOPR, regset->opd[1], SPIBSC_SMOPR_OPD2_SHIFT, SPIBSC_SMOPR_OPD2); 00531 RegWwrite_32(&SPIBSC->SMOPR, regset->opd[2], SPIBSC_SMOPR_OPD1_SHIFT, SPIBSC_SMOPR_OPD1); 00532 RegWwrite_32(&SPIBSC->SMOPR, regset->opd[3], SPIBSC_SMOPR_OPD0_SHIFT, SPIBSC_SMOPR_OPD0); 00533 /* Single/Dual/Quad */ 00534 RegWwrite_32(&SPIBSC->SMENR, regset->opdb, SPIBSC_SMENR_OPDB_SHIFT, SPIBSC_SMENR_OPDB); 00535 } 00536 00537 /* ---- Dummy ---- */ 00538 /* Enable/Disable */ 00539 RegWwrite_32(&SPIBSC->SMENR, regset->dme, SPIBSC_SMENR_DME_SHIFT, SPIBSC_SMENR_DME); 00540 if (regset->dme != SPIBSC_DUMMY_CYC_DISABLE) { 00541 RegWwrite_32(&SPIBSC->SMDMCR, regset->dmdb, SPIBSC_SMDMCR_DMDB_SHIFT, SPIBSC_SMDMCR_DMDB); 00542 /* Dummy Cycle */ 00543 RegWwrite_32(&SPIBSC->SMDMCR, regset->dmcyc, SPIBSC_SMDMCR_DMCYC_SHIFT, SPIBSC_SMDMCR_DMCYC); 00544 } 00545 00546 /* ---- Data ---- */ 00547 /* Enable/Disable */ 00548 RegWwrite_32(&SPIBSC->SMENR, regset->spide, SPIBSC_SMENR_SPIDE_SHIFT, SPIBSC_SMENR_SPIDE); 00549 if (regset->spide != SPIBSC_OUTPUT_DISABLE) { 00550 if (SPIBSC_OUTPUT_SPID_8 == regset->spide) { 00551 if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { 00552 SPIBSC->SMWDR0.UINT8[0] = (uint8_t)(regset->smwdr[0]); 00553 } else { 00554 SPIBSC->SMWDR0.UINT16[0] = (uint16_t)(regset->smwdr[0]); 00555 } 00556 } else if (regset->spide == SPIBSC_OUTPUT_SPID_16) { 00557 if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { 00558 SPIBSC->SMWDR0.UINT16[0] = (uint16_t)(regset->smwdr[0]); 00559 } else { 00560 SPIBSC->SMWDR0.UINT32 = regset->smwdr[0]; 00561 } 00562 } else if (regset->spide == SPIBSC_OUTPUT_SPID_32) { 00563 if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { 00564 SPIBSC->SMWDR0.UINT32 = (uint32_t)(regset->smwdr[0]); 00565 } else { 00566 SPIBSC->SMWDR0.UINT32 = (uint32_t)(regset->smwdr[0]); 00567 SPIBSC->SMWDR1.UINT32 = (uint32_t)(regset->smwdr[1]); /* valid in two serial-flash */ 00568 } 00569 } else { 00570 /* none */ 00571 } 00572 00573 /* Single/Dual/Quad */ 00574 RegWwrite_32(&SPIBSC->SMENR, regset->spidb, SPIBSC_SMENR_SPIDB_SHIFT, SPIBSC_SMENR_SPIDB); 00575 } 00576 00577 RegWwrite_32(&SPIBSC->SMCR, regset->sslkp, SPIBSC_SMCR_SSLKP_SHIFT, SPIBSC_SMCR_SSLKP); 00578 00579 if ((regset->spidb != SPIBSC_1BIT) && (regset->spide != SPIBSC_OUTPUT_DISABLE)) { 00580 if ((regset->spire == SPIBSC_SPIDATA_ENABLE) && (regset->spiwe == SPIBSC_SPIDATA_ENABLE)) { 00581 /* not set in same time */ 00582 return false; 00583 } 00584 } 00585 00586 RegWwrite_32(&SPIBSC->SMCR, regset->spire, SPIBSC_SMCR_SPIRE_SHIFT, SPIBSC_SMCR_SPIRE); 00587 RegWwrite_32(&SPIBSC->SMCR, regset->spiwe, SPIBSC_SMCR_SPIWE_SHIFT, SPIBSC_SMCR_SPIWE); 00588 00589 /* SDR Transmission/DDR Transmission Setting */ 00590 RegWwrite_32(&SPIBSC->SMDRENR, regset->addre, SPIBSC_SMDRENR_ADDRE_SHIFT, SPIBSC_SMDRENR_ADDRE); 00591 RegWwrite_32(&SPIBSC->SMDRENR, regset->opdre, SPIBSC_SMDRENR_OPDRE_SHIFT, SPIBSC_SMDRENR_OPDRE); 00592 RegWwrite_32(&SPIBSC->SMDRENR, regset->spidre, SPIBSC_SMDRENR_SPIDRE_SHIFT, SPIBSC_SMDRENR_SPIDRE); 00593 00594 /* execute after setting SPNDL bit */ 00595 RegWwrite_32(&SPIBSC->SMCR, SPIBSC_SPI_ENABLE, SPIBSC_SMCR_SPIE_SHIFT, SPIBSC_SMCR_SPIE); 00596 00597 /* wait for transfer-start */ 00598 while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) { 00599 /* wait for transfer-end */ 00600 } 00601 00602 if (SPIBSC_OUTPUT_SPID_8 == regset->spide) { 00603 if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { 00604 regset->smrdr[0] = SPIBSC->SMRDR0.UINT8[0]; 00605 } else { 00606 regset->smrdr[0] = SPIBSC->SMRDR0.UINT16[0]; /* valid in two serial-flash */ 00607 } 00608 } else if (regset->spide == SPIBSC_OUTPUT_SPID_16) { 00609 if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { 00610 regset->smrdr[0] = SPIBSC->SMRDR0.UINT16[0]; 00611 } else { 00612 regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; /* valid in two serial-flash */ 00613 } 00614 } else if (regset->spide == SPIBSC_OUTPUT_SPID_32) { 00615 if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) { 00616 regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; 00617 } else { 00618 regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; /* valid in two serial-flash */ 00619 regset->smrdr[1] = SPIBSC->SMRDR1.UINT32; 00620 } 00621 } else { 00622 /* none */ 00623 } 00624 00625 return true; 00626 } 00627 00628 uint32_t FlashAccess::RegRead_32(volatile uint32_t * ioreg, uint32_t shift, uint32_t mask) { 00629 uint32_t reg_value; 00630 00631 reg_value = *ioreg; /* Read from register */ 00632 reg_value = (reg_value & mask) >> shift; /* Clear other bit and Bit shift */ 00633 00634 return reg_value; 00635 } 00636 00637 void FlashAccess::RegWwrite_32(volatile uint32_t * ioreg, uint32_t write_value, uint32_t shift, uint32_t mask) { 00638 uint32_t reg_value; 00639 00640 reg_value = *ioreg; /* Read from register */ 00641 reg_value = (reg_value & (~mask)) | (write_value << shift); /* Modify value */ 00642 *ioreg = reg_value; /* Write to register */ 00643 } 00644 00645 /** private **/ 00646 00647 void FlashAccess::change_mmu_ttbl_spibsc(uint32_t type) { 00648 uint32_t index; /* Loop variable: table index */ 00649 mmu_ttbl_desc_section_t desc; /* Loop variable: descriptor */ 00650 mmu_ttbl_desc_section_t * table = (mmu_ttbl_desc_section_t *)TTB; 00651 00652 /* ==== Modify SPI Multi-I/O bus space settings in the MMU translation table ==== */ 00653 for (index = (SPIBSC_ADDR_START >> 20); index <= (SPIBSC_ADDR_END >> 20); index++) { 00654 /* Modify memory attribute descriptor */ 00655 if (type == 0) { /* Spi */ 00656 desc = table[index]; 00657 desc_tbl[index - (SPIBSC_ADDR_START >> 20)] = desc; 00658 desc.AP1_0 = 0x0u; /* AP[2:0] = b'000 (No access) */ 00659 desc.AP2 = 0x0u; 00660 desc.XN = 0x1u; /* XN = 1 (Execute never) */ 00661 } else { /* Xip */ 00662 desc = desc_tbl[index - (SPIBSC_ADDR_START >> 20)]; 00663 } 00664 /* Write descriptor back to translation table */ 00665 table[index] = desc; 00666 } 00667 } 00668 00669 void FlashAccess::spibsc_stop(void) { 00670 if (((SPIBSC->DRCR & SPIBSC_DRCR_RBE) != 0) && 00671 ((SPIBSC->DRCR & SPIBSC_DRCR_SSLE) != 0)) { 00672 RegWwrite_32(&SPIBSC->DRCR, 1, SPIBSC_DRCR_SSLN_SHIFT, SPIBSC_DRCR_SSLN); 00673 } 00674 00675 while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_SSLF_SHIFT, SPIBSC_CMNSR_SSLF) != SPIBSC_SSL_NEGATE) { 00676 ; 00677 } 00678 00679 while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) { 00680 ; 00681 } 00682 } 00683 00684 #ifndef __STATIC_FORCEINLINE 00685 #if defined ( __CC_ARM ) 00686 #define __STATIC_FORCEINLINE static __forceinline 00687 #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 00688 #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline 00689 #elif defined ( __GNUC__ ) 00690 #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline 00691 #elif defined ( __ICCARM__ ) 00692 #define __STATIC_FORCEINLINE _Pragma("inline=forced") static inline 00693 #endif 00694 #endif 00695 00696 #if defined ( __CC_ARM ) 00697 __STATIC_FORCEINLINE __ASM void L1C_CleanInvalidateCache_sforce(uint32_t op) { 00698 ARM 00699 00700 PUSH {R4-R11} 00701 00702 MRC p15, 1, R6, c0, c0, 1 // Read CLIDR 00703 ANDS R3, R6, #0x07000000 // Extract coherency level 00704 MOV R3, R3, LSR #23 // Total cache levels << 1 00705 BEQ Finished // If 0, no need to clean 00706 00707 MOV R10, #0 // R10 holds current cache level << 1 00708 Loop1 ADD R2, R10, R10, LSR #1 // R2 holds cache "Set" position 00709 MOV R1, R6, LSR R2 // Bottom 3 bits are the Cache-type for this level 00710 AND R1, R1, #7 // Isolate those lower 3 bits 00711 CMP R1, #2 00712 BLT Skip // No cache or only instruction cache at this level 00713 00714 MCR p15, 2, R10, c0, c0, 0 // Write the Cache Size selection register 00715 ISB // ISB to sync the change to the CacheSizeID reg 00716 MRC p15, 1, R1, c0, c0, 0 // Reads current Cache Size ID register 00717 AND R2, R1, #7 // Extract the line length field 00718 ADD R2, R2, #4 // Add 4 for the line length offset (log2 16 bytes) 00719 LDR R4, =0x3FF 00720 ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned) 00721 CLZ R5, R4 // R5 is the bit position of the way size increment 00722 LDR R7, =0x7FFF 00723 ANDS R7, R7, R1, LSR #13 // R7 is the max number of the index size (right aligned) 00724 00725 Loop2 MOV R9, R4 // R9 working copy of the max way size (right aligned) 00726 00727 Loop3 ORR R11, R10, R9, LSL R5 // Factor in the Way number and cache number into R11 00728 ORR R11, R11, R7, LSL R2 // Factor in the Set number 00729 CMP R0, #0 00730 BNE Dccsw 00731 MCR p15, 0, R11, c7, c6, 2 // DCISW. Invalidate by Set/Way 00732 B cont 00733 Dccsw CMP R0, #1 00734 BNE Dccisw 00735 MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way 00736 B cont 00737 Dccisw MCR p15, 0, R11, c7, c14, 2 // DCCISW. Clean and Invalidate by Set/Way 00738 cont SUBS R9, R9, #1 // Decrement the Way number 00739 BGE Loop3 00740 SUBS R7, R7, #1 // Decrement the Set number 00741 BGE Loop2 00742 Skip ADD R10, R10, #2 // Increment the cache number 00743 CMP R3, R10 00744 BGT Loop1 00745 00746 Finished 00747 DSB 00748 POP {R4-R11} 00749 BX lr 00750 } 00751 00752 #elif (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || defined ( __GNUC__ ) 00753 __STATIC_FORCEINLINE void L1C_CleanInvalidateCache_sforce(uint32_t op) { 00754 __ASM volatile( 00755 " PUSH {R4-R11} \n" 00756 00757 " MRC p15, 1, R6, c0, c0, 1 \n" // Read CLIDR 00758 " ANDS R3, R6, #0x07000000 \n" // Extract coherency level 00759 " MOV R3, R3, LSR #23 \n" // Total cache levels << 1 00760 " BEQ Finished \n" // If 0, no need to clean 00761 00762 " MOV R10, #0 \n" // R10 holds current cache level << 1 00763 "Loop1: ADD R2, R10, R10, LSR #1 \n" // R2 holds cache "Set" position 00764 " MOV R1, R6, LSR R2 \n" // Bottom 3 bits are the Cache-type for this level 00765 " AND R1, R1, #7 \n" // Isolate those lower 3 bits 00766 " CMP R1, #2 \n" 00767 " BLT Skip \n" // No cache or only instruction cache at this level 00768 00769 " MCR p15, 2, R10, c0, c0, 0 \n" // Write the Cache Size selection register 00770 " ISB \n" // ISB to sync the change to the CacheSizeID reg 00771 " MRC p15, 1, R1, c0, c0, 0 \n" // Reads current Cache Size ID register 00772 " AND R2, R1, #7 \n" // Extract the line length field 00773 " ADD R2, R2, #4 \n" // Add 4 for the line length offset (log2 16 bytes) 00774 " LDR R4, =0x3FF \n" 00775 " ANDS R4, R4, R1, LSR #3 \n" // R4 is the max number on the way size (right aligned) 00776 " CLZ R5, R4 \n" // R5 is the bit position of the way size increment 00777 " LDR R7, =0x7FFF \n" 00778 " ANDS R7, R7, R1, LSR #13 \n" // R7 is the max number of the index size (right aligned) 00779 00780 "Loop2: MOV R9, R4 \n" // R9 working copy of the max way size (right aligned) 00781 00782 "Loop3: ORR R11, R10, R9, LSL R5 \n" // Factor in the Way number and cache number into R11 00783 " ORR R11, R11, R7, LSL R2 \n" // Factor in the Set number 00784 " CMP R0, #0 \n" 00785 " BNE Dccsw \n" 00786 " MCR p15, 0, R11, c7, c6, 2 \n" // DCISW. Invalidate by Set/Way 00787 " B cont \n" 00788 "Dccsw: CMP R0, #1 \n" 00789 " BNE Dccisw \n" 00790 " MCR p15, 0, R11, c7, c10, 2 \n" // DCCSW. Clean by Set/Way 00791 " B cont \n" 00792 "Dccisw: MCR p15, 0, R11, c7, c14, 2 \n" // DCCISW. Clean and Invalidate by Set/Way 00793 "cont: SUBS R9, R9, #1 \n" // Decrement the Way number 00794 " BGE Loop3 \n" 00795 " SUBS R7, R7, #1 \n" // Decrement the Set number 00796 " BGE Loop2 \n" 00797 "Skip: ADD R10, R10, #2 \n" // Increment the cache number 00798 " CMP R3, R10 \n" 00799 " BGT Loop1 \n" 00800 00801 "Finished: \n" 00802 " DSB \n" 00803 " POP {R4-R11} " 00804 ); 00805 } 00806 00807 #else 00808 __STATIC_FORCEINLINE void __L1C_MaintainDCacheSetWay_sforce(uint32_t level, uint32_t maint) { 00809 register volatile uint32_t Dummy; 00810 register volatile uint32_t ccsidr; 00811 uint32_t num_sets; 00812 uint32_t num_ways; 00813 uint32_t shift_way; 00814 uint32_t log2_linesize; 00815 uint32_t log2_num_ways; 00816 00817 Dummy = level << 1; 00818 /* set csselr, select ccsidr register */ 00819 __set_CCSIDR(Dummy); 00820 /* get current ccsidr register */ 00821 ccsidr = __get_CCSIDR(); 00822 num_sets = ((ccsidr & 0x0FFFE000) >> 13) + 1; 00823 num_ways = ((ccsidr & 0x00001FF8) >> 3) + 1; 00824 log2_linesize = (ccsidr & 0x00000007) + 2 + 2; 00825 log2_num_ways = log2_up(num_ways); 00826 shift_way = 32 - log2_num_ways; 00827 for (int way = num_ways-1; way >= 0; way--) { 00828 for (int set = num_sets-1; set >= 0; set--) { 00829 Dummy = (level << 1) | (set << log2_linesize) | (way << shift_way); 00830 switch (maint) { 00831 case 0: 00832 // DCISW. Invalidate by Set/Way 00833 __ASM volatile("MCR p15, 0, %0, c7, c6, 2" : : "r"(Dummy) : "memory"); 00834 break; 00835 case 1: 00836 // DCCSW. Clean by Set/Way 00837 __ASM volatile("MCR p15, 0, %0, c7, c10, 2" : : "r"(Dummy) : "memory"); 00838 break; 00839 default: 00840 // DCCISW. Clean and Invalidate by Set/Way 00841 __ASM volatile("MCR p15, 0, %0, c7, c14, 2" : : "r"(Dummy) : "memory"); 00842 break; 00843 } 00844 } 00845 } 00846 __DMB(); 00847 } 00848 00849 __STATIC_FORCEINLINE void L1C_CleanInvalidateCache_sforce(uint32_t op) { 00850 register volatile uint32_t clidr; 00851 uint32_t cache_type; 00852 clidr = __get_CLIDR(); 00853 for (uint32_t i = 0; i<7; i++) { 00854 cache_type = (clidr >> i*3) & 0x7UL; 00855 if ((cache_type >= 2) && (cache_type <= 4)) { 00856 __L1C_MaintainDCacheSetWay_sforce(i, op); 00857 } 00858 } 00859 } 00860 #endif 00861 00862 #ifdef MBED_VERSION 00863 00864 void FlashAccess::cache_control(void) { 00865 unsigned int assoc; 00866 00867 /* ==== Cleaning and invalidation of the L1 data cache ==== */ 00868 L1C_CleanInvalidateCache_sforce(2); 00869 __DSB(); 00870 00871 /* ==== Cleaning and invalidation of the L2 cache ==== */ 00872 if (PL310->AUX_CNT & (1<<16)) { 00873 assoc = 16; 00874 } else { 00875 assoc = 8; 00876 } 00877 PL310->INV_WAY = (1 << assoc) - 1; 00878 while(PL310->INV_WAY & ((1 << assoc) - 1)); // poll invalidate 00879 PL310->CACHE_SYNC = 0x0; 00880 00881 /* ==== Invalidate all TLB entries ==== */ 00882 __ca9u_inv_tlb_all(); 00883 00884 /* ==== Invalidate the L1 instruction cache ==== */ 00885 __v7_inv_icache_all(); 00886 __DSB(); 00887 __ISB(); 00888 } 00889 00890 #else // mbed-os 5.6.4 00891 00892 void FlashAccess::cache_control(void) { 00893 unsigned int assoc; 00894 00895 /* ==== Cleaning and invalidation of the L1 data cache ==== */ 00896 L1C_CleanInvalidateCache_sforce(2); 00897 __DSB(); 00898 00899 /* ==== Cleaning and invalidation of the L2 cache ==== */ 00900 if (L2C_310->AUX_CNT & (1U << 16U)) { 00901 assoc = 16U; 00902 } else { 00903 assoc = 8U; 00904 } 00905 L2C_310->CLEAN_INV_WAY = (1U << assoc) - 1U; 00906 while (L2C_310->CLEAN_INV_WAY & ((1U << assoc) - 1U)); // poll invalidate 00907 L2C_310->CACHE_SYNC = 0x0; 00908 00909 /* ==== Invalidate all TLB entries ==== */ 00910 __set_TLBIALL(0); 00911 __DSB(); // ensure completion of the invalidation 00912 __ISB(); // ensure instruction fetch path sees new state 00913 00914 /* ==== Invalidate the L1 instruction cache ==== */ 00915 __set_ICIALLU(0); 00916 __DSB(); // ensure completion of the invalidation 00917 __ISB(); // ensure instruction fetch path sees new I cache state 00918 } 00919 #endif
Generated on Fri Jul 29 2022 15:06:33 by
1.7.2