00001 /* ---------------------------------------------------------------------------- */ 00002 /* Atmel Microcontroller Software Support */ 00003 /* SAM Software Package License */ 00004 /* ---------------------------------------------------------------------------- */ 00005 /* Copyright (c) 2015, Atmel Corporation */ 00006 /* */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without */ 00010 /* modification, are permitted provided that the following condition is met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, */ 00013 /* this list of conditions and the disclaimer below. */ 00014 /* */ 00015 /* Atmel's name may not be used to endorse or promote products derived from */ 00016 /* this software without specific prior written permission. */ 00017 /* */ 00018 /* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ 00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ 00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ 00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ 00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ 00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ 00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ 00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 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 return MED_STATUS_SUCCESS; 00101 } 00102 00103 /** 00104 * \brief Writes data on a flash media 00105 * \param media Pointer to a Media instance 00106 * \param address Address at which to write 00107 * \param data Pointer to the data to write 00108 * \param length Size of the data buffer 00109 * \param callback Optional pointer to a callback function to invoke when 00110 * the write operation terminates 00111 * \param argument Optional argument for the callback function 00112 * \return Operation result code 00113 * \see Media 00114 * \see Callback_f 00115 */ 00116 static uint8_t FLA_Write(sMedia *media, 00117 uint32_t address, 00118 void *data, 00119 uint32_t length, 00120 MediaCallback callback, 00121 void *argument) 00122 { 00123 uint8_t error; 00124 00125 // Check that the media if ready 00126 if (media->state != MED_STATE_READY) { 00127 00128 TRACE_WARNING("FLA_Write: Media is busy\n\r"); 00129 return MED_STATUS_BUSY; 00130 } 00131 00132 // Check that address is dword-aligned 00133 if (address % 4 != 0) { 00134 TRACE_DEBUG("address = 0x%X\n\r", address); 00135 TRACE_WARNING("FLA_Write: Address must be dword-aligned\n\r"); 00136 return MED_STATUS_ERROR; 00137 } 00138 00139 // Check that length is a multiple of 4 00140 if (length % 4 != 0) { 00141 00142 TRACE_WARNING("FLA_Write: Data length must be a multiple of 4 bytes\n\r"); 00143 return MED_STATUS_ERROR; 00144 } 00145 00146 // Check that the data to write is not too big 00147 if ((length + address) > media->size) { 00148 00149 TRACE_WARNING("FLA_Write: Data too big\n\r"); 00150 return MED_STATUS_ERROR; 00151 } 00152 00153 // Put the media in Busy state 00154 media->state = MED_STATE_BUSY; 00155 00156 // Initialize the transfer descriptor 00157 media->transfer.data = data; 00158 media->transfer.address = address; 00159 media->transfer.length = length; 00160 media->transfer.callback = callback; 00161 media->transfer.argument = argument; 00162 00163 // Start the write operation 00164 error = FLASHD_Write(address, data, length); 00165 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 00171 // End of transfer 00172 // Put the media in Ready state 00173 media->state = MED_STATE_READY; 00174 00175 // Invoke the callback if it exists 00176 if (media->transfer.callback != 0) 00177 media->transfer.callback(media->transfer.argument, 0, 0, 0); 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 return MED_STATUS_SUCCESS; 00222 } 00223 00224 /*------------------------------------------------------------------------------ 00225 * Exported Functions 00226 *------------------------------------------------------------------------------*/ 00227 /** 00228 * \brief Initializes a Media instance and the associated physical interface 00229 * \param media Pointer to the Media instance to initialize 00230 * \param efc Pointer to AT91S_EFC interface. 00231 * \see Media 00232 */ 00233 void FLA_Initialize(sMedia *media, Efc *efc) 00234 { 00235 TRACE_INFO("Flash init\n\r"); 00236 00237 // Initialize media fields 00238 media->write = FLA_Write; 00239 media->read = FLA_Read; 00240 media->lock = FLA_Lock; 00241 media->unlock = FLA_Unlock; 00242 media->flush = 0; 00243 media->handler = 0; 00244 00245 media->blockSize = 1; 00246 media->baseAddress = 0; // Address based on whole memory space 00247 media->size = IFLASH_SIZE; 00248 media->interface = efc; 00249 00250 media->mappedRD = 0; 00251 media->mappedWR = 0; 00252 media->protected = 0; 00253 media->removable = 0; 00254 media->state = MED_STATE_READY; 00255 00256 media->transfer.data = 0; 00257 media->transfer.address = 0; 00258 media->transfer.length = 0; 00259 media->transfer.callback = 0; 00260 media->transfer.argument = 0; 00261 00262 // Initialize low-level interface 00263 // Configure Flash Mode register 00264 efc->EEFC_FMR |= (BOARD_MCK / 666666) << 16; 00265 } 00266 00267