00001 /* ---------------------------------------------------------------------------- 00002 * SAM Software Package License 00003 * ---------------------------------------------------------------------------- 00004 * Copyright (c) 2012, Atmel Corporation 00005 * 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * 00011 * - Redistributions of source code must retain the above copyright notice, 00012 * this list of conditions and the disclaimer below. 00013 * 00014 * Atmel's name may not be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR 00018 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00019 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 00020 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, 00021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00022 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 00023 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00024 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00025 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 00026 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 * ---------------------------------------------------------------------------- 00028 */ 00029 00030 /** 00031 * \file 00032 * 00033 * Implementation of media layer for the flash. 00034 * 00035 */ 00036 00037 /*------------------------------------------------------------------------------ 00038 * Includes 00039 *----------------------------------------------------------------------------*/ 00040 00041 #include "libstoragemedia.h" 00042 #include <assert.h> 00043 00044 /*------------------------------------------------------------------------------ 00045 * Internal Functions 00046 *----------------------------------------------------------------------------*/ 00047 00048 /** 00049 * \brief Reads a specified amount of data from a flash memory 00050 * \param media Pointer to a Media instance 00051 * \param address Address of the data to read 00052 * \param data Pointer to the buffer in which to store the retrieved 00053 * data 00054 * \param length Length of the buffer 00055 * \param callback Optional pointer to a callback function to invoke when 00056 * the operation is finished 00057 * \param argument Optional pointer to an argument for the callback 00058 * \return Operation result code 00059 */ 00060 static uint8_t FLA_Read(sMedia *media, 00061 uint32_t address, 00062 void *data, 00063 uint32_t length, 00064 MediaCallback callback, 00065 void *argument) 00066 { 00067 uint8_t *source = (uint8_t *) address; 00068 uint8_t *dest = (uint8_t *) data; 00069 00070 // Check that the media is ready 00071 if (media->state != MED_STATE_READY) { 00072 TRACE_INFO("Media busy\n\r"); 00073 return MED_STATUS_BUSY; 00074 } 00075 00076 // Check that the data to read is not too big 00077 if ((length + address) > media->size) { 00078 TRACE_WARNING("FLA_Read: Data too big\n\r"); 00079 return MED_STATUS_ERROR; 00080 } 00081 00082 // Enter Busy state 00083 media->state = MED_STATE_BUSY; 00084 00085 // Read data 00086 while (length > 0) { 00087 *dest = *source; 00088 dest++; 00089 source++; 00090 length--; 00091 } 00092 00093 // Leave the Busy state 00094 media->state = MED_STATE_READY; 00095 00096 // Invoke callback 00097 if (callback != 0) { 00098 callback(argument, MED_STATUS_SUCCESS, 0, 0); 00099 } 00100 00101 return MED_STATUS_SUCCESS; 00102 } 00103 00104 /** 00105 * \brief Writes data on a flash media 00106 * \param media Pointer to a Media instance 00107 * \param address Address at which to write 00108 * \param data Pointer to the data to write 00109 * \param length Size of the data buffer 00110 * \param callback Optional pointer to a callback function to invoke when 00111 * the write operation terminates 00112 * \param argument Optional argument for the callback function 00113 * \return Operation result code 00114 * \see Media 00115 * \see Callback_f 00116 */ 00117 static uint8_t FLA_Write(sMedia *media, 00118 uint32_t address, 00119 void *data, 00120 uint32_t length, 00121 MediaCallback callback, 00122 void *argument) 00123 { 00124 uint8_t error; 00125 00126 // Check that the media if ready 00127 if (media->state != MED_STATE_READY) { 00128 00129 TRACE_WARNING("FLA_Write: Media is busy\n\r"); 00130 return MED_STATUS_BUSY; 00131 } 00132 00133 // Check that address is dword-aligned 00134 if (address%4 != 0) { 00135 TRACE_DEBUG("address = 0x%X\n\r", address); 00136 TRACE_WARNING("FLA_Write: Address must be dword-aligned\n\r"); 00137 return MED_STATUS_ERROR; 00138 } 00139 00140 // Check that length is a multiple of 4 00141 if (length%4 != 0) { 00142 00143 TRACE_WARNING("FLA_Write: Data length must be a multiple of 4 bytes\n\r"); 00144 return MED_STATUS_ERROR; 00145 } 00146 00147 // Check that the data to write is not too big 00148 if ((length + address) > media->size) { 00149 00150 TRACE_WARNING("FLA_Write: Data too big\n\r"); 00151 return MED_STATUS_ERROR; 00152 } 00153 00154 // Put the media in Busy state 00155 media->state = MED_STATE_BUSY; 00156 00157 // Initialize the transfer descriptor 00158 media->transfer.data = data; 00159 media->transfer.address = address; 00160 media->transfer.length = length; 00161 media->transfer.callback = callback; 00162 media->transfer.argument = argument; 00163 00164 // Start the write operation 00165 error = FLASHD_Write( address, data, length); 00166 if( error ) { 00167 TRACE_ERROR("-F- Error when trying to write page (0x%02X)\n\r", error); 00168 return MED_STATUS_ERROR; 00169 } 00170 // End of transfer 00171 // Put the media in Ready state 00172 media->state = MED_STATE_READY; 00173 00174 // Invoke the callback if it exists 00175 if (media->transfer.callback != 0) { 00176 media->transfer.callback(media->transfer.argument, 0, 0, 0); 00177 } 00178 00179 return MED_STATUS_SUCCESS; 00180 } 00181 00182 /** 00183 * \brief Lock all the regions in the given address range. The actual unlock 00184 * range is reported through two output parameters. 00185 * \param media Pointer to Media instance. 00186 * \param start Start address of unlock range. 00187 * \param end End address of unlock range. 00188 * \param pActualStart Start address of the actual unlock range (optional). 00189 * \param pActualEnd End address of the actual unlock range (optional). 00190 * \return 0 if successful; otherwise returns an error code. 00191 */ 00192 static uint8_t FLA_Lock( sMedia* media, uint32_t start, uint32_t end, 00193 uint32_t *pActualStart, uint32_t *pActualEnd ) 00194 { 00195 media = media; 00196 00197 if ( FLASHD_Lock( start, end, pActualStart, pActualEnd ) ) { 00198 return MED_STATUS_ERROR ; 00199 } 00200 return MED_STATUS_SUCCESS ; 00201 } 00202 00203 /** 00204 * \brief Unlock all the regions in the given address range. The actual unlock 00205 * range is reported through two output parameters. 00206 * \param media Pointer to Media instance. 00207 * \param start Start address of unlock range. 00208 * \param end End address of unlock range. 00209 * \param pActualStart Start address of the actual unlock range (optional). 00210 * \param pActualEnd End address of the actual unlock range (optional). 00211 * \return 0 if successful; otherwise returns an error code. 00212 */ 00213 static uint8_t FLA_Unlock( sMedia* media, uint32_t start, uint32_t end, 00214 uint32_t *pActualStart, uint32_t *pActualEnd ) 00215 { 00216 media = media; 00217 00218 if ( FLASHD_Unlock( start, end, pActualStart, pActualEnd ) ) { 00219 return MED_STATUS_ERROR ; 00220 } 00221 00222 return MED_STATUS_SUCCESS ; 00223 } 00224 00225 /*------------------------------------------------------------------------------ 00226 * Exported Functions 00227 *------------------------------------------------------------------------------*/ 00228 /** 00229 * \brief Initializes a Media instance and the associated physical interface 00230 * \param media Pointer to the Media instance to initialize 00231 * \param efc Pointer to AT91S_EFC interface. 00232 * \see Media 00233 */ 00234 void FLA_Initialize( sMedia *media, Efc *efc ) 00235 { 00236 TRACE_INFO("Flash init\n\r"); 00237 00238 // Initialize media fields 00239 media->write = FLA_Write; 00240 media->read = FLA_Read; 00241 media->lock = FLA_Lock; 00242 media->unlock = FLA_Unlock; 00243 media->flush = 0; 00244 media->handler = 0; 00245 00246 media->blockSize = 1; 00247 media->baseAddress = 0; // Address based on whole memory space 00248 media->size = IFLASH_SIZE; 00249 media->interface = efc; 00250 00251 media->mappedRD = 0; 00252 media->mappedWR = 0; 00253 media->protected = 0; 00254 media->removable = 0; 00255 media->state = MED_STATE_READY; 00256 00257 media->transfer.data = 0; 00258 media->transfer.address = 0; 00259 media->transfer.length = 0; 00260 media->transfer.callback = 0; 00261 media->transfer.argument = 0; 00262 00263 // Initialize low-level interface 00264 // Configure Flash Mode register 00265 efc->EEFC_FMR |= (BOARD_MCK / 666666) << 16; 00266 } 00267 00268