SAMV71 Xplained Ultra Software Package 1.5

MEDDdram.c

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