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