SAMV71 Xplained Ultra Software Package 1.3

MEDDdram.c

Go to the documentation of this file.
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  * \file
00031  *
00032  * Implementation of media layer for the DDRAM.
00033  *
00034  */
00035 
00036 /*------------------------------------------------------------------------------
00037  *         Headers
00038  *-----------------------------------------------------------------------------*/
00039 
00040 #include "libstoragemedia.h"
00041 
00042 #if defined(AT91C_BASE_DDR2C) || defined(AT91C_BASE_SDDRC)
00043 
00044 #if defined(AT91C_DDR2)
00045 #define AT91C_BASE_ADDRESS_DDR AT91C_DDR2
00046 #endif
00047 
00048 #if defined(AT91C_EBI_DDRAM)
00049 #define AT91C_BASE_ADDRESS_DDR AT91C_EBI_DDRAM
00050 #endif
00051 
00052 /*------------------------------------------------------------------------------
00053  *          Types
00054  *----------------------------------------------------------------------------*/
00055 
00056 /// Do copy and modify pointer
00057 typedef void copyFunction(uint8_t **, uint8_t **, uint32_t);
00058 
00059 /*------------------------------------------------------------------------------
00060  *         Internal Functions
00061  *----------------------------------------------------------------------------*/
00062 
00063 /**
00064  * Do copy for 8-byte aligned data
00065  */
00066 static void AlignedCopy(uint8_t * *src,
00067                         uint8_t * *dst,
00068                         uint32_t len)
00069 {
00070     uint32_t *src32, *dst32;
00071     src32 = (uint32_t*)*src;
00072     dst32 = (uint32_t*)*dst;
00073     for (;len > 0; len -= 8) {
00074         *dst32 ++ = *src32 ++;
00075         *dst32 ++ = *src32 ++;
00076     }
00077     *src = (uint8_t*)src32;
00078     *dst = (uint8_t*)dst32;
00079 }
00080 
00081 /**
00082  * Do copy for byte-aligned data
00083  */
00084 static void UnalignedCopy(uint8_t * *src,
00085                           uint8_t * *dst,
00086                           uint32_t  len)
00087 {
00088     for (;len > 0; len --) {
00089         *(*dst) ++ = *(*src) ++;
00090     }
00091 }
00092 
00093 /**
00094  * \brief  Reads a specified amount of data from a DDRAM memory
00095  * \param  media    Pointer to a Media instance
00096  * \param  address  Address of the data to read
00097  * \param  data     Pointer to the buffer in which to store the retrieved
00098  *                   data
00099  * \param  length   Length of the buffer
00100  * \param  callback Optional pointer to a callback function to invoke when
00101  *                   the operation is finished
00102  * \param  argument Optional pointer to an argument for the callback
00103  * \return Operation result code
00104  */
00105 static uint8_t MEDDdram_Read(Media *media,
00106                                  uint32_t address,
00107                                  void *data,
00108                                  uint32_t  length,
00109                                  MediaCallback callback,
00110                                  void *argument)
00111 {
00112     uint8_t *source;
00113     uint8_t *dest;
00114     copyFunction  *pCpy;
00115 
00116     // Check that the media is ready
00117     if (media->state != MED_STATE_READY) {
00118 
00119         TRACE_INFO("Media busy\n\r");
00120         return MED_STATUS_BUSY;
00121     }
00122 
00123     // Check that the data to read is not too big
00124     if ((length + address) > media->size) {
00125 
00126         TRACE_WARNING("MEDDdram_Read: Data too big: %u, 0x%08X\n\r",
00127                       length, address);
00128         return MED_STATUS_ERROR;
00129     }
00130 
00131     // Enter Busy state
00132     media->state = MED_STATE_BUSY;
00133 
00134     // Source & Destination
00135     source = (uint8_t *)(media->blockSize
00136                     * (address + media->baseAddress));
00137     dest   = (uint8_t *)data;
00138 
00139     // Align/Unaligned copy
00140     pCpy   = (((uint32_t)source%4) == 0 && (media->blockSize%8) == 0)
00141                         ? AlignedCopy : UnalignedCopy;
00142 
00143     for (; length > 0; length --) {
00144         pCpy(&source, &dest, media->blockSize);
00145     }
00146 
00147     // Leave the Busy state
00148     media->state = MED_STATE_READY;
00149 
00150     // Invoke callback
00151     if (callback != 0) {
00152         callback(argument, MED_STATUS_SUCCESS, 0, 0);
00153     }
00154 
00155     return MED_STATUS_SUCCESS;
00156 }
00157 
00158 /*------------------------------------------------------------------------------
00159  * \brief  Writes data on a DDRAM media
00160  * \param  media    Pointer to a Media instance
00161  * \param  address  Address at which to write
00162  * \param  data     Pointer to the data to write
00163  * \param  length   Size of the data buffer
00164  * \param  callback Optional pointer to a callback function to invoke when
00165  *                   the write operation terminates
00166  * \param  argument Optional argument for the callback function
00167  * \return Operation result code
00168  * \see    Media
00169  * \see    MediaCallback
00170  */
00171 static uint8_t MEDDdram_Write(Media   *media,
00172                                     uint32_t  address,
00173                                     void          *data,
00174                                     uint32_t  length,
00175                                     MediaCallback callback,
00176                                     void          *argument)
00177 {
00178     uint8_t *source;
00179     uint8_t *dest;
00180     copyFunction  *pCpy;
00181 
00182     //TRACE_DEBUG("MEDDdram_Write\n\r");
00183 
00184     // Check that the media if ready
00185     if (media->state != MED_STATE_READY) {
00186 
00187         TRACE_INFO("MEDDdram_Write: Busy\n\r");
00188         return MED_STATUS_BUSY;
00189     }
00190 
00191     // Check that the data to write is not too big
00192     if ((length + address) > media->size) {
00193 
00194         TRACE_WARNING("MEDDdram_Write: Data too big\n\r");
00195         return MED_STATUS_ERROR;
00196     }
00197 
00198     // Put the media in Busy state
00199     media->state = MED_STATE_BUSY;
00200 
00201     // Compute function parameters
00202     source = (uint8_t *) data;
00203     dest = (uint8_t *) (media->blockSize *
00204                                     (media->baseAddress + address));
00205 
00206     // Align/Unaligned copy
00207     pCpy   = (((uint32_t)source%4) == 0 && (media->blockSize%8) == 0)
00208                         ? AlignedCopy : UnalignedCopy;
00209 
00210     for (; length > 0; length --) {
00211         pCpy(&source, &dest, media->blockSize);
00212     }
00213 
00214     // Leave the Busy state
00215     media->state = MED_STATE_READY;
00216 
00217     // Invoke the callback if it exists
00218     if (callback != 0) {
00219 
00220         callback(argument, MED_STATUS_SUCCESS, 0, 0);
00221     }
00222 
00223     return MED_STATUS_SUCCESS;
00224 }
00225 
00226 /*------------------------------------------------------------------------------
00227  *      Exported Functions
00228  *------------------------------------------------------------------------------*/
00229 /**
00230  *\brief  Initializes a Media instance and the associated physical interface
00231  *\param  media       Pointer to the Media instance to initialize
00232  *\param  blockSize   Block size of the media, in bytes.
00233  * \param  baseAddress Basic address of the media, in number of blocks.
00234  * \param  size        Size of the media, in number of blocks.
00235  * \see    Media
00236  */
00237 void MEDDdram_Initialize(Media *media,
00238                          uint32_t blockSize,
00239                          uint32_t baseAddress,
00240                          uint32_t size)
00241 {
00242     uint32_t value;
00243 
00244     TRACE_INFO("MEDDdram init\n\r");
00245 
00246     // Initialize DDRAM if not already done
00247     //--------------------------------------------------------------------------
00248     value = *((volatile uint32_t *) AT91C_BASE_ADDRESS_DDR);
00249     *((volatile uint32_t *) AT91C_BASE_ADDRESS_DDR) = 0xDEADBEEF;
00250 
00251     if (*((volatile uint32_t *) AT91C_BASE_ADDRESS_DDR) == 0xDEADBEEF) {
00252 
00253         *((volatile uint32_t *) AT91C_BASE_ADDRESS_DDR) = value;
00254         TRACE_INFO("DDRAM initialized\n\r");
00255     }
00256     else {
00257 
00258         *((volatile uint32_t *) AT91C_BASE_ADDRESS_DDR) = value;
00259         TRACE_INFO("Initialize DDRAM ...\n\r");
00260         BOARD_ConfigureDdram(0, BOARD_DDRAM_BUSWIDTH);
00261     }
00262 
00263     // Initialize media fields
00264     //--------------------------------------------------------------------------
00265     media->write = MEDDdram_Write;
00266     media->read = MEDDdram_Read;
00267     media->lock = 0;
00268     media->unlock = 0;
00269     media->handler = 0;
00270     media->flush = 0;
00271 
00272     media->blockSize = blockSize;
00273     media->baseAddress = baseAddress;
00274     media->size = size;
00275 
00276     media->mappedRD  = 1;
00277     media->mappedWR  = 1;
00278     media->protected = 0;
00279     media->removable = 0;
00280     media->state = MED_STATE_READY;
00281 
00282     media->transfer.data = 0;
00283     media->transfer.address = 0;
00284     media->transfer.length = 0;
00285     media->transfer.callback = 0;
00286     media->transfer.argument = 0;
00287 }
00288 #endif //#if defined(AT91C_BASE_DDR2C)
00289 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines