diff options
author | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-10-18 12:23:31 +0000 |
---|---|---|
committer | barthess <barthess@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2014-10-18 12:23:31 +0000 |
commit | be302132c782b951b6f81f2833b642a514a70dad (patch) | |
tree | 386f7f8c8677f5110c1aa2edd36c65623df60cdc /os/hal/src | |
parent | 7c0786cae15cf93e09604abcc66c6d017c4238bd (diff) | |
download | ChibiOS-be302132c782b951b6f81f2833b642a514a70dad.tar.gz ChibiOS-be302132c782b951b6f81f2833b642a514a70dad.tar.bz2 ChibiOS-be302132c782b951b6f81f2833b642a514a70dad.zip |
FSMC. Files moved to
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7414 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/src')
-rw-r--r-- | os/hal/src/nand.c | 601 |
1 files changed, 0 insertions, 601 deletions
diff --git a/os/hal/src/nand.c b/os/hal/src/nand.c deleted file mode 100644 index ee2bd3b2d..000000000 --- a/os/hal/src/nand.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - ChibiOS/HAL - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013,2014 Giovanni Di Sirio. - - This file is part of ChibiOS/HAL - - ChibiOS/HAL is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file nand.c - * @brief NAND Driver code. - * - * @addtogroup NAND - * @{ - */ - -#include "hal.h" - -#if HAL_USE_NAND || defined(__DOXYGEN__) - -#include "string.h" /* for memset */ - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Check page size. - * - * @param[in] page_data_size size of page data area - * - * @notapi - */ -static void pagesize_check(size_t page_data_size){ - - /* Page size out of bounds.*/ - osalDbgCheck((page_data_size >= NAND_MIN_PAGE_SIZE) && - (page_data_size <= NAND_MAX_PAGE_SIZE)); - - /* Page size must be power of 2.*/ - osalDbgCheck(((page_data_size - 1) & page_data_size) == 0); -} - -/** - * @brief Translate block-page-offset scheme to NAND internal address. - * - * @param[in] cfg pointer to the @p NANDConfig from - * corresponding NAND driver - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[in] offset data offset related to begin of page - * @param[out] addr buffer to store calculated address - * @param[in] addr_len length of address buffer - * - * @notapi - */ -static void calc_addr(const NANDConfig *cfg, - uint32_t block, uint32_t page, uint32_t offset, - uint8_t *addr, size_t addr_len){ - size_t i = 0; - uint32_t row = 0; - - /* Incorrect buffer length.*/ - osalDbgCheck(cfg->rowcycles + cfg->colcycles == addr_len); - osalDbgCheck((block < cfg->blocks) && (page < cfg->pages_per_block) && - (offset < cfg->page_data_size + cfg->page_spare_size)); - - /* convert address to NAND specific */ - memset(addr, 0, addr_len); - row = (block * cfg->pages_per_block) + page; - for (i=0; i<cfg->colcycles; i++){ - addr[i] = offset & 0xFF; - offset = offset >> 8; - } - for (; i<addr_len; i++){ - addr[i] = row & 0xFF; - row = row >> 8; - } -} - -/** - * @brief Translate block number to NAND internal address. - * @note This function designed for erasing purpose. - * - * @param[in] cfg pointer to the @p NANDConfig from - * corresponding NAND driver - * @param[in] block block number - * @param[out] addr buffer to store calculated address - * @param[in] addr_len length of address buffer - * - * @notapi - */ -static void calc_blk_addr(const NANDConfig *cfg, - uint32_t block, uint8_t *addr, size_t addr_len){ - size_t i = 0; - uint32_t row = 0; - - /* Incorrect buffer length.*/ - osalDbgCheck(cfg->rowcycles == addr_len); - osalDbgCheck((block < cfg->blocks)); - - /* convert address to NAND specific */ - memset(addr, 0, addr_len); - row = block * cfg->pages_per_block; - for (i=0; i<addr_len; i++){ - addr[i] = row & 0xFF; - row = row >> 8; - } -} - -#if NAND_USE_BAD_MAP -/** - * @brief Add new bad block to map. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] map pointer to bad block map - */ -static void bad_map_update(NANDDriver *nandp, size_t block) { - - uint32_t *map = nandp->config->bb_map; - const size_t BPMC = sizeof(uint32_t) * 8; /* bits per map claster */ - size_t i; - size_t shift; - - /* Nand device overflow.*/ - osalDbgCheck(nandp->config->blocks > block); - - i = block / BPMC; - shift = block % BPMC; - /* This block already mapped.*/ - osalDbgCheck(((map[i] >> shift) & 1) != 1); - map[i] |= (uint32_t)1 << shift; -} - -/** - * @brief Scan for bad blocks and fill map with their numbers. - * - * @param[in] nandp pointer to the @p NANDDriver object - */ -static void scan_bad_blocks(NANDDriver *nandp) { - - const size_t blocks = nandp->config->blocks; - const size_t maplen = blocks / 32; - - size_t b; - uint8_t m0; - uint8_t m1; - - /* clear map just to be safe */ - for (b=0; b<maplen; b++) - nandp->config->bb_map[b] = 0; - - /* now write numbers of bad block to map */ - for (b=0; b<blocks; b++){ - m0 = nandReadBadMark(nandp, b, 0); - m1 = nandReadBadMark(nandp, b, 1); - if ((0xFF != m0) || (0xFF != m1)){ - bad_map_update(nandp, b); - } - } -} -#endif /* NAND_USE_BAD_MAP */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief NAND Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void nandInit(void) { - - nand_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p NANDDriver structure. - * - * @param[out] nandp pointer to the @p NANDDriver object - * - * @init - */ -void nandObjectInit(NANDDriver *nandp) { - -#if NAND_USE_MUTUAL_EXCLUSION -#if CH_CFG_USE_MUTEXES - chMtxObjectInit(&nandp->mutex); -#else - chSemObjectInit(&nandp->semaphore, 1); -#endif /* CH_CFG_USE_MUTEXES */ -#endif /* NAND_USE_MUTUAL_EXCLUSION */ - - nandp->state = NAND_STOP; - nandp->config = NULL; -} - -/** - * @brief Configures and activates the NAND peripheral. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] config pointer to the @p NANDConfig object - * - * @api - */ -void nandStart(NANDDriver *nandp, const NANDConfig *config) { - - osalDbgCheck((nandp != NULL) && (config != NULL)); - osalDbgAssert((nandp->state == NAND_STOP) || - (nandp->state == NAND_READY), - "invalid state"); - - nandp->config = config; - pagesize_check(nandp->config->page_data_size); - nand_lld_start(nandp); - nandp->state = NAND_READY; - -#if NAND_USE_BAD_MAP - scan_bad_blocks(nandp); -#endif /* NAND_USE_BAD_MAP */ -} - -/** - * @brief Deactivates the NAND peripheral. - * - * @param[in] nandp pointer to the @p NANDDriver object - * - * @api - */ -void nandStop(NANDDriver *nandp) { - - osalDbgCheck(nandp != NULL); - osalDbgAssert((nandp->state == NAND_STOP) || - (nandp->state == NAND_READY), - "invalid state"); - nand_lld_stop(nandp); - nandp->state = NAND_STOP; -} - -/** - * @brief Read whole page. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[out] data buffer to store data - * @param[in] datalen length of data buffer - * - * @api - */ -void nandReadPageWhole(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *data, size_t datalen) { - - const NANDConfig *cfg = nandp->config; - uint8_t addrbuf[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; - - osalDbgCheck((nandp != NULL) && (data != NULL)); - osalDbgCheck((datalen <= (cfg->page_data_size + cfg->page_spare_size))); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_addr(cfg, block, page, 0, addrbuf, addrlen); - nand_lld_read_data(nandp, data, datalen, addrbuf, addrlen, NULL); -} - -/** - * @brief Write whole page. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[in] data buffer with data to be written - * @param[in] datalen length of data buffer - * - * @return The operation status reported by NAND IC (0x70 command). - * - * @api - */ -uint8_t nandWritePageWhole(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *data, size_t datalen) { - - uint8_t retval; - const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; - - osalDbgCheck((nandp != NULL) && (data != NULL)); - osalDbgCheck((datalen <= (cfg->page_data_size + cfg->page_spare_size))); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_addr(cfg, block, page, 0, addr, addrlen); - retval = nand_lld_write_data(nandp, data, datalen, addr, addrlen, NULL); - return retval; -} - -/** - * @brief Read page data without spare area. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[out] data buffer to store data - * @param[in] datalen length of data buffer - * @param[out] ecc pointer to calculated ECC. Ignored when NULL. - * - * @api - */ -void nandReadPageData(NANDDriver *nandp, uint32_t block, uint32_t page, - uint8_t *data, size_t datalen, uint32_t *ecc) { - - const NANDConfig *cfg = nandp->config; - uint8_t addrbuf[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; - - osalDbgCheck((nandp != NULL) && (data != NULL)); - osalDbgCheck((datalen <= cfg->page_data_size)); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_addr(cfg, block, page, 0, addrbuf, addrlen); - nand_lld_read_data(nandp, data, datalen, addrbuf, addrlen, ecc); -} - -/** - * @brief Write page data without spare area. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[in] data buffer with data to be written - * @param[in] datalen length of data buffer - * @param[out] ecc pointer to calculated ECC. Ignored when NULL. - * - * @return The operation status reported by NAND IC (0x70 command). - * - * @api - */ -uint8_t nandWritePageData(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *data, size_t datalen, uint32_t *ecc) { - - uint8_t retval; - const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; - - osalDbgCheck((nandp != NULL) && (data != NULL)); - osalDbgCheck((datalen <= cfg->page_data_size)); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_addr(cfg, block, page, 0, addr, addrlen); - retval = nand_lld_write_data(nandp, data, datalen, addr, addrlen, ecc); - return retval; -} - -/** - * @brief Read page spare area. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[out] spare buffer to store data - * @param[in] sparelen length of data buffer - * - * @api - */ -void nandReadPageSpare(NANDDriver *nandp, uint32_t block, - uint32_t page, uint8_t *spare, size_t sparelen) { - - const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; - - osalDbgCheck((NULL != spare) && (nandp != NULL)); - osalDbgCheck(sparelen <= cfg->page_spare_size); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_addr(cfg, block, page, cfg->page_data_size, addr, addrlen); - nand_lld_read_data(nandp, spare, sparelen, addr, addrlen, NULL); -} - -/** - * @brief Write page spare area. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * @param[in] spare buffer with spare data to be written - * @param[in] sparelen length of data buffer - * - * @return The operation status reported by NAND IC (0x70 command). - * - * @api - */ -uint8_t nandWritePageSpare(NANDDriver *nandp, uint32_t block, - uint32_t page, const uint8_t *spare, size_t sparelen) { - - uint8_t retVal; - const NANDConfig *cfg = nandp->config; - uint8_t addr[8]; - size_t addrlen = cfg->rowcycles + cfg->colcycles; - - osalDbgCheck((NULL != spare) && (nandp != NULL)); - osalDbgCheck(sparelen <= cfg->page_spare_size); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_addr(cfg, block, page, cfg->page_data_size, addr, addrlen); - retVal = nand_lld_write_data(nandp, spare, sparelen, addr, addrlen, NULL); - return retVal; -} - -/** - * @brief Mark block as bad. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * - * @api - */ -void nandMarkBad(NANDDriver *nandp, uint32_t block) { - - uint8_t bb_mark[2] = {0, 0}; - uint8_t op_status; - op_status = nandWritePageSpare(nandp, block, 0, bb_mark, sizeof(bb_mark)); - osalDbgCheck(0 == (op_status & 1)); /* operation failed*/ - op_status = nandWritePageSpare(nandp, block, 1, bb_mark, sizeof(bb_mark)); - osalDbgCheck(0 == (op_status & 1)); /* operation failed*/ - -#if NAND_USE_BAD_MAP - bad_map_update(nandp, block); -#endif -} - -/** - * @brief Read bad mark out. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * @param[in] page page number related to begin of block - * - * @return Bad mark. - * - * @api - */ -uint8_t nandReadBadMark(NANDDriver *nandp, - uint32_t block, uint32_t page) { - uint8_t bb_mark[1]; - nandReadPageSpare(nandp, block, page, bb_mark, sizeof(bb_mark)); - return bb_mark[0]; -} - -/** - * @brief Erase block. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * - * @return The operation status reported by NAND IC (0x70 command). - * - * @api - */ -uint8_t nandErase(NANDDriver *nandp, uint32_t block){ - - uint8_t retVal; - const NANDConfig *cfg = nandp->config; - uint8_t addr[4]; - size_t addrlen = cfg->rowcycles; - - osalDbgCheck(nandp != NULL); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - - calc_blk_addr(cfg, block, addr, addrlen); - retVal = nand_lld_erase(nandp, addr, addrlen); - return retVal; -} - -/** - * @brief Report block badness. - * - * @param[in] nandp pointer to the @p NANDDriver object - * @param[in] block block number - * - * @return block condition - * @retval true if the block is bad. - * @retval false if the block is good. - * - * @api - */ -bool nandIsBad(NANDDriver *nandp, uint32_t block){ - - osalDbgCheck(nandp != NULL); - osalDbgAssert(nandp->state == NAND_READY, "invalid state"); - -#if NAND_USE_BAD_MAP - uint32_t *map = nandp->config->bb_map; - const size_t BPMC = sizeof(uint32_t) * 8; /* bits per map claster */ - size_t i; - size_t shift; - - i = block / BPMC; - shift = block % BPMC; - if (((map[i] >> shift) & 1) == 1) - return true; - else - return false; -#else - uint8_t m0, m1; - m0 = nandReadBadMark(nandp, block, 0); - m1 = nandReadBadMark(nandp, block, 1); - if ((0xFF != m0) || (0xFF != m1)) - return true; - else - return false; -#endif /* NAND_USE_BAD_MAP */ -} - -#if NAND_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the NAND bus. - * @details This function tries to gain ownership to the NAND bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option - * @p NAND_USE_MUTUAL_EXCLUSION must be enabled. - * - * @param[in] nandp pointer to the @p NANDDriver object - * - * @api - */ -void nandAcquireBus(NANDDriver *nandp) { - - osalDbgCheck(nandp != NULL); - -#if CH_CFG_USE_MUTEXES - chMtxLock(&nandp->mutex); -#elif CH_CFG_USE_SEMAPHORES - chSemWait(&nandp->semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the NAND bus. - * @pre In order to use this function the option - * @p NAND_USE_MUTUAL_EXCLUSION must be enabled. - * - * @param[in] nandp pointer to the @p NANDDriver object - * - * @api - */ -void nandReleaseBus(NANDDriver *nandp) { - - osalDbgCheck(nandp != NULL); - -#if CH_CFG_USE_MUTEXES - chMtxUnlock(&nandp->mutex); -#elif CH_CFG_USE_SEMAPHORES - chSemSignal(&nandp->semaphore); -#endif -} -#endif /* NAND_USE_MUTUAL_EXCLUSION */ - -#endif /* HAL_USE_NAND */ - -/** @} */ - - - - |