From c3d1d75f50ecfe9ae36f58de67d2baf57be1be39 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Wed, 11 May 2016 11:22:46 +0000 Subject: Added smart polling and preparation for erase suspend. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9463 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/dox/flash.dox | 75 +++++++++++++++++++ os/hal/lib/peripherals/flash/hal_flash.c | 75 +++++++++++++++++++ os/hal/lib/peripherals/flash/hal_flash.h | 121 +++++++++++++++++++------------ 3 files changed, 224 insertions(+), 47 deletions(-) create mode 100644 os/hal/dox/flash.dox create mode 100644 os/hal/lib/peripherals/flash/hal_flash.c (limited to 'os/hal') diff --git a/os/hal/dox/flash.dox b/os/hal/dox/flash.dox new file mode 100644 index 000000000..01b519fff --- /dev/null +++ b/os/hal/dox/flash.dox @@ -0,0 +1,75 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @defgroup NOR_FLASH Abstract NOR Flash Class + * @brief Generic NOR Flash interface. + * @details This module implements a generic class for NOR Flash devices. + * + * @section flash_1 Driver State Machine + * The flash driver implements a state machine internally, not all the driver + * functionalities can be used in any moment, any transition not explicitly + * shown in the following diagram has to be considered an error and shall + * be captured by an assertion (if enabled). + * @dot + digraph example { + rankdir="LR"; + node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"]; + edge [fontname=Helvetica, fontsize=8]; + stop [label="FLS_STOP\nLow Power"]; + uninit [label="FLS_UNINIT", style="bold"]; + ready [label="FLS_READY\nClock Enabled"]; + read [label="FLS_READ\nReading"]; + program [label="FLS_PGM\nProgramming"]; + erasea [label="FLS_ERASEA\nErasing All"]; + erases [label="FLS_ERASES\nErasing Sector"]; + uninit -> stop [label=" flashInit()", constraint=false]; + stop -> stop [label=" flashStop()"]; + stop -> ready [label=" flashStart()"]; + ready -> stop [label=" flashStop()"]; + ready -> read [label=" flashRead()\nflashVerifyErase()"]; + read -> ready [label=" return"]; + ready -> program [label=" flashProgram()"]; + program -> ready [label=" return"]; + ready -> erasea [label=" flashEraseAll)"]; + erasea -> ready [label=" flashQueryErase()\nFLASH_NO_ERROR\nFLASH_ERROR_*"]; + erasea -> erasea [label=" flashQueryErase()\nflashProgram()\nflashRead()\nFLASH_BUSY_ERASE"]; + ready -> erases [label=" flashEraseSector()"]; + erases -> ready [label=" flashQueryErase()\nFLASH_NO_ERROR\nFLASH_ERROR_*"]; + erases -> erases [label=" flashQueryErase()\nflashProgram()\nflashRead()\nFLASH_BUSY_ERASE"]; + } + * @enddot + * + * @section flash_2 Flash Operations. + * This driver abstracts a generic PWM timer composed of: + * - A clock prescaler. + * - A main up counter. + * - A comparator register that resets the main counter to zero when the limit + * is reached. An optional callback can be generated when this happens. + * - An array of @p PWM_CHANNELS PWM channels, each channel has an output, + * a comparator and is able to invoke an optional callback when a comparator + * match with the main counter happens. + * . + * A PWM channel output can be in two different states: + * - IDLE, when the channel is disabled or after a match occurred. + * - ACTIVE, when the channel is enabled and a match didn't occur yet + * in the current PWM cycle. + * . + * Note that the two states can be associated to both logical zero or one in + * the @p PWMChannelConfig structure. + * + * @ingroup HAL_INTERFACES + */ diff --git a/os/hal/lib/peripherals/flash/hal_flash.c b/os/hal/lib/peripherals/flash/hal_flash.c new file mode 100644 index 000000000..b65ca3768 --- /dev/null +++ b/os/hal/lib/peripherals/flash/hal_flash.c @@ -0,0 +1,75 @@ +/* + N25Q128 Flash Driver - Copyright (C) 2016 Giovanni Di Sirio + + This file is part of ChibiOS. + + ChibiOS 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 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 . +*/ + +/** + * @file hal_flash.c + * @brief Generic flash driver class code. + * + * @addtogroup HAL_FLASH + * @{ + */ + +#include "hal.h" + +#include "hal_flash.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Waits until the current erase operation is finished. + * + * @param[in] devp pointer to a @p BaseFlash object + * @param[in] cb polling callback or @p NULL + */ +flash_error_t flashWaitErase(BaseFlash *devp) { + + while (true) { + flash_error_t err; + uint32_t msec; + + /* Checking operation state.*/ + err = flashQueryErase(devp, &msec); + if (err != FLASH_BUSY_ERASING) { + return err; + } + + /* Interval because nice waiting.*/ + osalThreadSleepMilliseconds(msec); + } +} + +/** @} */ diff --git a/os/hal/lib/peripherals/flash/hal_flash.h b/os/hal/lib/peripherals/flash/hal_flash.h index b62f73d66..d0416b353 100644 --- a/os/hal/lib/peripherals/flash/hal_flash.h +++ b/os/hal/lib/peripherals/flash/hal_flash.h @@ -16,7 +16,7 @@ /** * @file hal_flash.h - * @brief Generic flash interface header. + * @brief Generic flash driver class header. * * @addtogroup HAL_FLASH * @{ @@ -59,10 +59,9 @@ typedef enum { FLASH_UNINIT = 0, FLASH_STOP = 1, FLASH_READY = 2, - FLASH_READING = 3, - FLASH_WRITING = 4, - FLASH_ERASING = 5, - FLASH_SUSPENDED = 6 + FLASH_READ = 3, + FLASH_PGM = 4, + FLASH_ERASE = 5 } flash_state_t; /** @@ -70,12 +69,12 @@ typedef enum { */ typedef enum { FLASH_NO_ERROR = 0, /* No error. */ - FLASH_ECC_ERROR = 1, /* ECC error during read operation. */ - FLASH_PROGRAM_FAILURE = 2, /* Program operation failed. */ - FLASH_ERASE_FAILURE = 3, /* Erase operation failed. */ - FLASH_VERIFY_FAILURE = 4, /* Verify operation failed. */ - FLASH_BUSY = 5, /* Attempt to access a sector being erased. */ - FLASH_HW_FAILURE = 6 /* Controller or communication error. */ + FLASH_BUSY_ERASING = 1, /* Erase operation in progress. */ + FLASH_ERROR_READ = 2, /* ECC or other error during read operation.*/ + FLASH_ERROR_PROGRAM = 3, /* Program operation failed. */ + FLASH_ERROR_ERASE = 4, /* Erase operation failed. */ + FLASH_ERROR_VERIFY = 5, /* Verify operation failed. */ + FLASH_ERROR_HW_FAILURE = 6 /* Controller or communication error. */ } flash_error_t; /** @@ -144,20 +143,20 @@ typedef struct { #define _base_flash_methods_alone \ /* Get flash device attributes.*/ \ const flash_descriptor_t * (*get_descriptor)(void *instance); \ - /* Erase whole flash device.*/ \ - flash_error_t (*erase_all)(void *instance); \ - /* Erase single sector.*/ \ - flash_error_t (*erase_sector)(void *instance, \ - flash_sector_t sector); \ - /* Erase single sector.*/ \ - flash_error_t (*verify_erase)(void *instance, \ - flash_sector_t sector); \ - /* Write operation.*/ \ - flash_error_t (*program)(void *instance, flash_address_t addr, \ - const uint8_t *pp, size_t n); \ /* Read operation.*/ \ flash_error_t (*read)(void *instance, flash_address_t addr, \ - uint8_t *rp, size_t n); + uint8_t *rp, size_t n); \ + /* Program operation.*/ \ + flash_error_t (*program)(void *instance, flash_address_t addr, \ + const uint8_t *pp, size_t n); \ + /* Erase whole flash device.*/ \ + flash_error_t (*start_erase_all)(void *instance); \ + /* Erase single sector.*/ \ + flash_error_t (*start_erase_sector)(void *instance, \ + flash_sector_t sector); \ + flash_error_t (*query_erase)(void *instance, uint32_t *wait_time); \ + /* Verify erase single sector.*/ \ + flash_error_t (*verify_erase)(void *instance, flash_sector_t sector); /** * @brief @p BaseFlash specific methods with inherited ones. @@ -211,68 +210,96 @@ typedef struct { (ip)->vmt_baseflash->get_descriptor(ip) /** - * @brief Whole device erase operation. + * @brief Read operation. * * @param[in] ip pointer to a @p BaseFlash or derived class + * @param[in] addr flash address + * @param[out] rp pointer to the data buffer + * @param[in] n number of bytes to be read * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_READ if the read operation failed. * * @api */ -#define flashEraseAll(ip) \ - (ip)->vmt_baseflash->erase_all(ip) +#define flashRead(ip, addr, rp, n) \ + (ip)->vmt_baseflash->read(ip, addr, rp, n) /** - * @brief Erase operation on a sector. + * @brief Program operation. * * @param[in] ip pointer to a @p BaseFlash or derived class - * @param[in] sector sector to be erased + * @param[in] addr flash address + * @param[in] wp pointer to the data buffer + * @param[in] n number of bytes to be programmed * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_PROGRAM if the program operation failed. * * @api */ -#define flashEraseSector(ip, sector) \ - (ip)->vmt_baseflash->erase_sector(ip, sector) +#define flashProgram(ip, addr, pp, n) \ + (ip)->vmt_baseflash->program(ip, addr, pp, n) /** - * @brief Returns the erase state of a sector. + * @brief Starts a whole-device erase operation. * * @param[in] ip pointer to a @p BaseFlash or derived class - * @param[in] sector sector to be verified * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. * * @api */ -#define flashVerifyErase(ip, sector) \ - (ip)->vmt_baseflash->verify_erase(ip, sector) +#define flashStartEraseAll(ip) \ + (ip)->vmt_baseflash->start_erase_all(ip) /** - * @brief Write operation. + * @brief Starts an sector erase operation. * * @param[in] ip pointer to a @p BaseFlash or derived class - * @param[in] addr flash address - * @param[in] wp pointer to the data buffer - * @param[in] n number of bytes to be programmed + * @param[in] sector sector to be erased * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. * * @api */ -#define flashProgram(ip, addr, pp, n) \ - (ip)->vmt_baseflash->program(ip, addr, pp, n) +#define flashStartEraseSector(ip, sector) \ + (ip)->vmt_baseflash->start_erase_sector(ip, sector) /** - * @brief Read operation. + * @brief Queries the driver for erase operation progress. * * @param[in] ip pointer to a @p BaseFlash or derived class - * @param[in] addr flash address - * @param[out] rp pointer to the data buffer - * @param[in] n number of bytes to be read + * @param[out] msec recommended time, in milliseconds, that what should be + * spent before calling this function again, can be @p NULL * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_ERASE if the erase operation failed. * * @api */ -#define flashRead(ip, addr, rp, n) \ - (ip)->vmt_baseflash->read(ip, addr, rp, n) +#define flashQueryErase(ip, msec) \ + (ip)->vmt_baseflash->query_erase(ip, msec) +/** + * @brief Returns the erase state of a sector. + * + * @param[in] ip pointer to a @p BaseFlash or derived class + * @param[in] sector sector to be verified + * @return An error code. + * @retval FLASH_NO_ERROR if there is no erase operation in progress. + * @retval FLASH_BUSY_ERASING if there is an erase operation in progress. + * @retval FLASH_ERROR_VERIFY if the verify operation failed. + * + * @api + */ +#define flashVerifyErase(ip, sector) \ + (ip)->vmt_baseflash->verify_erase(ip, sector) /** @} */ /*===========================================================================*/ @@ -282,7 +309,7 @@ typedef struct { #ifdef __cplusplus extern "C" { #endif - + flash_error_t flashWaitErase(BaseFlash *devp); #ifdef __cplusplus } #endif -- cgit v1.2.3