PN532 updates
[hackover2013-badge-firmware.git] / drivers / eeprom / at25040 / at25040.c
1 /**************************************************************************/
2 /*!
3 @file at25040.c
4 @author K. Townsend (microBuilder.eu)
5 @date 22 March 2010
6 @version 0.10
7
8 @section DESCRIPTION
9
10 Driver for Atmel's AT25010a/AT25020a/AT25040a 1K/2K/4K serial EEPROM.
11
12 @note The AT25xxx has an 8-byte buffer, including 1 command byte
13 and one address offset byte, meaning that a maximum of 6
14 bytes can be read or written in one operation. An error
15 will be returned if a value greater than 6 is passed in
16 for bufferLength with the eepromRead and eepromWrite
17 methods.
18
19 @section Example
20
21 @code
22 #include "core/cpu/cpu.h"
23 #include "drivers/eeprom/at25040/at25040.h"
24
25 int main(void)
26 {
27 cpuInit();
28 at25Init();
29
30 // Set read and write buffers
31 uint8_t wBuffer[1];
32 uint8_t rBuffer[1];
33
34 // Instantiate error message placeholder
35 at25Error_e error = AT25_ERROR_OK;
36
37 // Write 0xAA to EEPROM at address 0x0000
38 wBuffer[0] = 0xAA;
39 error = at25Write(0x0000, wBuffer, 1);
40 if (error)
41 {
42 // Log the error message or take appropriate actions
43 switch (error)
44 {
45 case (AT25_ERROR_TIMEOUT_WFINISH):
46 // EEPROM timed out waiting for the write to finish
47 break;
48 case (AT25_ERROR_TIMEOUT_WE):
49 // EEPROM timed out waiting for write-enable
50 break;
51 case (AT25_ERROR_ADDRERR):
52 // Address is out of range
53 break;
54 }
55 }
56
57 // Read the EEPROM at address 0x0000
58 at25Read(0x0000, rBuffer, 1);
59 ...
60 }
61 @endcode
62
63 @section LICENSE
64
65 Software License Agreement (BSD License)
66
67 Copyright (c) 2010, microBuilder SARL
68 All rights reserved.
69
70 Redistribution and use in source and binary forms, with or without
71 modification, are permitted provided that the following conditions are met:
72 1. Redistributions of source code must retain the above copyright
73 notice, this list of conditions and the following disclaimer.
74 2. Redistributions in binary form must reproduce the above copyright
75 notice, this list of conditions and the following disclaimer in the
76 documentation and/or other materials provided with the distribution.
77 3. Neither the name of the copyright holders nor the
78 names of its contributors may be used to endorse or promote products
79 derived from this software without specific prior written permission.
80
81 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
82 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
83 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
84 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
85 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
86 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
87 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
88 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
89 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
90 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91 */
92 /**************************************************************************/
93
94 #include "at25040.h"
95 #include "core/ssp/ssp.h"
96 #include "core/gpio/gpio.h"
97
98 #define AT25_SELECT() gpioSetValue(0, 2, 0)
99 #define AT25_DESELECT() gpioSetValue(0, 2, 1)
100
101 uint32_t i, timeout;
102 uint8_t src_addr[SSP_FIFOSIZE];
103 uint8_t dest_addr[SSP_FIFOSIZE];
104
105 /**************************************************************************/
106 /*!
107 @brief Sends the write enable command (WREN/0x06)
108 */
109 /**************************************************************************/
110 void at25WriteEnable()
111 {
112 AT25_SELECT();
113 src_addr[0] = AT25_WREN;
114 sspSend(0, (uint8_t *)src_addr, 1);
115 AT25_DESELECT();
116
117 // Delay for at least 250nS (1nS @ 72MHz = ~0.0072 ticks)
118 for (i = 0; i < 100; i++);
119 }
120
121 /**************************************************************************/
122 /*!
123 @brief Gets the value of the Read Status Register (RDSR/0x05)
124
125 @return The 8-bit value returned by the Read Status Register
126 */
127 /**************************************************************************/
128 uint8_t at25GetRSR()
129 {
130 AT25_SELECT();
131 src_addr[0] = AT25_RDSR;
132 sspSend(0, (uint8_t *)src_addr, 1);
133 sspReceive(0, (uint8_t *)dest_addr, 1);
134 AT25_DESELECT();
135 return dest_addr[0] & (AT25_RDSR_WEN | AT25_RDSR_RDY);
136 }
137
138 /**************************************************************************/
139 /*!
140 @brief Initialises the SPI block (CLK set low when inactive, trigger
141 on leading edge).
142 */
143 /**************************************************************************/
144 void at25Init (void)
145 {
146 sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
147 }
148
149 /**************************************************************************/
150 /*!
151 @brief Reads the specified number of bytes from the supplied address.
152
153 This function will read one or more bytes starting at the supplied
154 address.
155
156 @param[in] address
157 The 16-bit address where the read will start. The maximum
158 value for the address depends on the size of the EEPROM
159 @param[in] *buffer
160 Pointer to the buffer that will store the read results
161 @param[in] bufferLength
162 Length of the buffer
163 */
164 /**************************************************************************/
165 at25Error_e at25Read (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
166 {
167 if (address >= AT25_MAXADDRESS)
168 {
169 return AT25_ERROR_ADDRERR;
170 }
171
172 if (bufferLength > 6)
173 {
174 return AT25_ERROR_BUFFEROVERFLOW;
175 }
176
177 timeout = 0;
178 while ( timeout < SSP_MAX_TIMEOUT )
179 {
180 // Wait until the device is ready
181 uint8_t status = at25GetRSR() & AT25_RDSR_RDY;
182 if (status == 0)
183 {
184 break;
185 }
186 timeout++;
187 }
188 if ( timeout == SSP_MAX_TIMEOUT )
189 {
190 return AT25_ERROR_TIMEOUT_WE;
191 }
192
193 AT25_SELECT();
194 // Read command (0x03), append A8 if > addr 256 bytes
195 src_addr[0] = address > 0xFF ? AT25_READ | AT25_A8 : AT25_READ;
196 src_addr[1] = (address);
197 sspSend(0, (uint8_t *)src_addr, 2);
198 sspReceive(0, (uint8_t *)&dest_addr[2], bufferLength);
199 AT25_DESELECT();
200
201 // Fill response buffer
202 for (i = 0; i < bufferLength; i++)
203 {
204 buffer[i] = dest_addr[i + 2];
205 }
206
207 return AT25_ERROR_OK;
208 }
209
210 /**************************************************************************/
211 /*!
212 @brief Writes the supplied bytes at a specified address.
213
214 This function will write one or more bytes starting at the supplied
215 address.
216
217 @param[in] address
218 The 16-bit address where the write will start. The
219 maximum value for the address depends on the size of the
220 EEPROM
221 @param[in] *buffer
222 Pointer to the buffer that contains the values to write.
223 @param[in] bufferLength
224 Length of the buffer
225 */
226 /**************************************************************************/
227 at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
228 {
229 if (address >= AT25_MAXADDRESS)
230 {
231 return AT25_ERROR_ADDRERR;
232 }
233
234 if (bufferLength > 6)
235 {
236 return AT25_ERROR_BUFFEROVERFLOW;
237 }
238
239 // Set write enable latch
240 at25WriteEnable();
241
242 timeout = 0;
243 while ( timeout < SSP_MAX_TIMEOUT )
244 {
245 // Wait until the device is write enabled
246 if (at25GetRSR() == AT25_RDSR_WEN)
247 {
248 break;
249 }
250 timeout++;
251 }
252 if ( timeout == SSP_MAX_TIMEOUT )
253 {
254 return AT25_ERROR_TIMEOUT_WE;
255 }
256
257 for (i = 0; i < bufferLength; i++) // Init RD and WR buffer
258 {
259 src_addr[i+2] = buffer[i]; // leave two bytes for cmd and offset(8 bits)
260 dest_addr[i] = 0;
261 }
262
263 AT25_SELECT();
264 // Write command (0x02), append A8 if addr > 256 bytes
265 src_addr[0] = address > 0xFF ? AT25_WRITE | AT25_A8 : AT25_WRITE;
266 src_addr[1] = (address);
267 sspSend(0, (uint8_t *)src_addr, bufferLength + 2);
268 AT25_DESELECT();
269
270 // Wait at least 3ms
271 for (i = 0; i < ((CFG_CPU_CCLK / 1000) * 3); i++);
272
273 timeout = 0;
274 while ( timeout < SSP_MAX_TIMEOUT )
275 {
276 // Check status to see if write cycle is done or not
277 AT25_SELECT();
278 src_addr[0] = AT25_RDSR;
279 sspSend(0, (uint8_t *)src_addr, 1);
280 sspReceive(0, (uint8_t *)dest_addr, 1);
281 AT25_DESELECT();
282 // Wait until device is ready
283 if ((dest_addr[0] & AT25_RDSR_RDY) == 0x00)
284 {
285 break;
286 }
287 timeout++;
288 }
289 if ( timeout == SSP_MAX_TIMEOUT )
290 {
291 return AT25_ERROR_TIMEOUT_WFINISH;
292 }
293
294 for (i = 0; i < 300; i++); // Wait at least 250ns
295
296 return AT25_ERROR_OK;
297 }
This page took 0.052507 seconds and 5 git commands to generate.