00001 /* ---------------------------------------------------------------------------- 00002 * SAM Software Package License 00003 * ---------------------------------------------------------------------------- 00004 * Copyright (c) 2014, 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 // Headers 00032 //------------------------------------------------------------------------------ 00033 00034 #include "at45.h" 00035 #include "at45d.h" 00036 #include "board.h" 00037 #include <assert.h> 00038 00039 //------------------------------------------------------------------------------ 00040 // Local functions 00041 //------------------------------------------------------------------------------ 00042 00043 //------------------------------------------------------------------------------ 00044 /// Wait for transfer to finish calling the SPI driver ISR (interrupts are 00045 /// disabled). 00046 /// \param pAt45 Pointer to an AT45 driver instance. 00047 //------------------------------------------------------------------------------ 00048 static void AT45D_Wait(At45 *pAt45) 00049 { 00050 SANITY_CHECK(pAt45); 00051 00052 // Wait for transfer to finish 00053 while (AT45_IsBusy(pAt45)) { 00054 SPID_Handler(pAt45->pSpid); 00055 } 00056 } 00057 00058 00059 //------------------------------------------------------------------------------ 00060 // Global functions 00061 //------------------------------------------------------------------------------ 00062 00063 //------------------------------------------------------------------------------ 00064 /// Waits for the At45 to be ready to accept new commands. 00065 /// \param pAt45 Pointer to a At45 driver instance. 00066 //------------------------------------------------------------------------------ 00067 void AT45D_WaitReady(At45 *pAt45) 00068 { 00069 unsigned char ready = 0; 00070 00071 SANITY_CHECK(pAt45); 00072 00073 // Poll device until it is ready 00074 while (!ready) { 00075 ready = AT45_STATUS_READY(AT45D_GetStatus(pAt45)); 00076 } 00077 } 00078 00079 //------------------------------------------------------------------------------ 00080 /// Retrieves and returns the At45 current status, or 0 if an error 00081 /// happened. 00082 /// \param pAt45 Pointer to a At45 driver instance. 00083 //------------------------------------------------------------------------------ 00084 unsigned char AT45D_GetStatus(At45 *pAt45) 00085 { 00086 unsigned char error; 00087 unsigned char status; 00088 00089 SANITY_CHECK(pAt45); 00090 00091 // Issue a status register read command 00092 error = AT45_SendCommand(pAt45, AT45_STATUS_READ, 1, &status, 1, 0, 0, 0); 00093 ASSERT(!error, "-F- AT45_GetStatus: Failed to issue command.\n\r"); 00094 00095 // Wait for command to terminate 00096 while (AT45_IsBusy(pAt45)) { 00097 00098 AT45D_Wait(pAt45); 00099 } 00100 00101 return status; 00102 } 00103 00104 //------------------------------------------------------------------------------ 00105 /// Reads data from the At45 inside the provided buffer. Since a continuous 00106 /// read command is used, there is no restriction on the buffer size and read 00107 /// address. 00108 /// \param pAt45 Pointer to a At45 driver instance. 00109 /// \param pBuffer Data buffer. 00110 /// \param size Number of bytes to read. 00111 /// \param address Address at which data shall be read. 00112 //------------------------------------------------------------------------------ 00113 void AT45D_Read( 00114 At45 *pAt45, 00115 unsigned char *pBuffer, 00116 unsigned int size, 00117 unsigned int address) 00118 { 00119 unsigned char error; 00120 00121 SANITY_CHECK(pAt45); 00122 SANITY_CHECK(pBuffer); 00123 00124 // Issue a continuous read array command 00125 error = AT45_SendCommand( 00126 pAt45, AT45_CONTINUOUS_READ_LEG, 8, pBuffer, size, address, 0, 0); 00127 ASSERT(!error, "-F- AT45_Read: Failed to issue command\n\r"); 00128 00129 // Wait for the read command to execute 00130 while (AT45_IsBusy(pAt45)) { 00131 00132 AT45D_Wait(pAt45); 00133 } 00134 } 00135 00136 //------------------------------------------------------------------------------ 00137 /// Writes data on the At45 at the specified address. Only one page of 00138 /// data is written that way; if the address is not at the beginning of the 00139 /// page, the data is written starting from this address and wraps around to 00140 /// the beginning of the page. 00141 /// \param pAt45 Pointer to a At45 driver instance. 00142 /// \param pBuffer Buffer containing the data to write. 00143 /// \param size Number of bytes to write. 00144 /// \param address Destination address on the At45. 00145 //------------------------------------------------------------------------------ 00146 void AT45D_Write( 00147 At45 *pAt45, 00148 unsigned char *pBuffer, 00149 unsigned int size, 00150 unsigned int address) 00151 { 00152 unsigned char error; 00153 00154 SANITY_CHECK(pAt45); 00155 SANITY_CHECK(pBuffer); 00156 SANITY_CHECK(size <= pAt45->pDesc->pageSize); 00157 00158 // Issue a page write through buffer 1 command 00159 error = AT45_SendCommand( 00160 pAt45, AT45_PAGE_WRITE_BUF1, 4, pBuffer, size, address, 0, 0); 00161 ASSERT(!error, "-F- AT45_Write: Could not issue command.\n\r"); 00162 00163 // Wait until the command is sent 00164 while (AT45_IsBusy(pAt45)) { 00165 AT45D_Wait(pAt45); 00166 } 00167 00168 // Wait until the At45 becomes ready again 00169 AT45D_WaitReady(pAt45); 00170 } 00171 00172 //------------------------------------------------------------------------------ 00173 /// Erases a page of data at the given address in the At45. 00174 /// \param pAt45 Pointer to a At45 driver instance. 00175 /// \param address Address of page to erase. 00176 //------------------------------------------------------------------------------ 00177 void AT45D_Erase(At45 *pAt45, unsigned int address) 00178 { 00179 unsigned char error; 00180 00181 SANITY_CHECK(pAt45); 00182 00183 // Issue a page erase command. 00184 error = AT45_SendCommand(pAt45, AT45_PAGE_ERASE, 4, 0, 0, address, 0, 0); 00185 ASSERT(!error, "-F- AT45_Erase: Could not issue command.\n\r"); 00186 00187 // Wait for end of transfer 00188 while (AT45_IsBusy(pAt45)) { 00189 AT45D_Wait(pAt45); 00190 } 00191 00192 // Poll until the At45 has completed the erase operation 00193 AT45D_WaitReady(pAt45); 00194 } 00195 00196 //------------------------------------------------------------------------------ 00197 /// Configure power-of-2 binary page size in the At45. 00198 /// \param pAt45 Pointer to a At45 driver instance. 00199 //------------------------------------------------------------------------------ 00200 00201 void AT45D_BinaryPage(At45 *pAt45) 00202 { 00203 unsigned char error; 00204 unsigned char opcode[3]= {AT45_BINARY_PAGE}; 00205 SANITY_CHECK(pAt45); 00206 00207 // Issue a binary page command. 00208 00209 error = AT45_SendCommand( 00210 pAt45, AT45_BINARY_PAGE_FIRST_OPCODE, 1, opcode, 3, 0, 0, 0); 00211 00212 ASSERT(!error, "-F- AT45_Erase: Could not issue command.\n\r"); 00213 00214 // Wait for end of transfer 00215 while (AT45_IsBusy(pAt45)) { 00216 00217 AT45D_Wait(pAt45); 00218 } 00219 00220 // Wait until the At45 becomes ready again 00221 AT45D_WaitReady(pAt45); 00222 }