1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
10 Driver for Atmel's AT25010a/AT25020a/AT25040a 1K/2K/4K serial EEPROM.
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
22 #include "core/cpu/cpu.h"
23 #include "drivers/storage/eeprom/at25040/at25040.h"
30 // Set read and write buffers
34 // Instantiate error message placeholder
35 at25Error_e error = AT25_ERROR_OK;
37 // Write 0xAA to EEPROM at address 0x0000
39 error = at25Write(0x0000, wBuffer, 1);
42 // Log the error message or take appropriate actions
45 case (AT25_ERROR_TIMEOUT_WFINISH):
46 // EEPROM timed out waiting for the write to finish
48 case (AT25_ERROR_TIMEOUT_WE):
49 // EEPROM timed out waiting for write-enable
51 case (AT25_ERROR_ADDRERR):
52 // Address is out of range
57 // Read the EEPROM at address 0x0000
58 at25Read(0x0000, rBuffer, 1);
65 Software License Agreement (BSD License)
67 Copyright (c) 2010, microBuilder SARL
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.
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.
92 /**************************************************************************/
95 #include "core/ssp/ssp.h"
96 #include "core/gpio/gpio.h"
98 #define AT25_SELECT() gpioSetValue(0, 2, 0)
99 #define AT25_DESELECT() gpioSetValue(0, 2, 1)
102 uint8_t src_addr
[SSP_FIFOSIZE
];
103 uint8_t dest_addr
[SSP_FIFOSIZE
];
105 /**************************************************************************/
107 @brief Sends the write enable command (WREN/0x06)
109 /**************************************************************************/
110 void at25WriteEnable()
113 src_addr
[0] = AT25_WREN
;
114 sspSend(0, (uint8_t *)src_addr
, 1);
117 // Delay for at least 250nS (1nS @ 72MHz = ~0.0072 ticks)
118 for (i
= 0; i
< 100; i
++);
121 /**************************************************************************/
123 @brief Gets the value of the Read Status Register (RDSR/0x05)
125 @return The 8-bit value returned by the Read Status Register
127 /**************************************************************************/
131 src_addr
[0] = AT25_RDSR
;
132 sspSend(0, (uint8_t *)src_addr
, 1);
133 sspReceive(0, (uint8_t *)dest_addr
, 1);
135 return dest_addr
[0] & (AT25_RDSR_WEN
| AT25_RDSR_RDY
);
138 /**************************************************************************/
140 @brief Initialises the SPI block (CLK set low when inactive, trigger
143 /**************************************************************************/
146 sspInit(0, sspClockPolarity_Low
, sspClockPhase_RisingEdge
);
149 /**************************************************************************/
151 @brief Reads the specified number of bytes from the supplied address.
153 This function will read one or more bytes starting at the supplied
157 The 16-bit address where the read will start. The maximum
158 value for the address depends on the size of the EEPROM
160 Pointer to the buffer that will store the read results
161 @param[in] bufferLength
164 /**************************************************************************/
165 at25Error_e
at25Read (uint16_t address
, uint8_t *buffer
, uint32_t bufferLength
)
167 if (address
>= AT25_MAXADDRESS
)
169 return AT25_ERROR_ADDRERR
;
172 if (bufferLength
> 6)
174 return AT25_ERROR_BUFFEROVERFLOW
;
178 while ( timeout
< SSP_MAX_TIMEOUT
)
180 // Wait until the device is ready
181 uint8_t status
= at25GetRSR() & AT25_RDSR_RDY
;
188 if ( timeout
== SSP_MAX_TIMEOUT
)
190 return AT25_ERROR_TIMEOUT_WE
;
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
);
201 // Fill response buffer
202 for (i
= 0; i
< bufferLength
; i
++)
204 buffer
[i
] = dest_addr
[i
+ 2];
207 return AT25_ERROR_OK
;
210 /**************************************************************************/
212 @brief Writes the supplied bytes at a specified address.
214 This function will write one or more bytes starting at the supplied
218 The 16-bit address where the write will start. The
219 maximum value for the address depends on the size of the
222 Pointer to the buffer that contains the values to write.
223 @param[in] bufferLength
226 /**************************************************************************/
227 at25Error_e
at25Write (uint16_t address
, uint8_t *buffer
, uint32_t bufferLength
)
229 if (address
>= AT25_MAXADDRESS
)
231 return AT25_ERROR_ADDRERR
;
234 if (bufferLength
> 6)
236 return AT25_ERROR_BUFFEROVERFLOW
;
239 // Set write enable latch
243 while ( timeout
< SSP_MAX_TIMEOUT
)
245 // Wait until the device is write enabled
246 if (at25GetRSR() == AT25_RDSR_WEN
)
252 if ( timeout
== SSP_MAX_TIMEOUT
)
254 return AT25_ERROR_TIMEOUT_WE
;
257 for (i
= 0; i
< bufferLength
; i
++) // Init RD and WR buffer
259 src_addr
[i
+2] = buffer
[i
]; // leave two bytes for cmd and offset(8 bits)
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);
271 for (i
= 0; i
< ((CFG_CPU_CCLK
/ 1000) * 3); i
++);
274 while ( timeout
< SSP_MAX_TIMEOUT
)
276 // Check status to see if write cycle is done or not
278 src_addr
[0] = AT25_RDSR
;
279 sspSend(0, (uint8_t *)src_addr
, 1);
280 sspReceive(0, (uint8_t *)dest_addr
, 1);
282 // Wait until device is ready
283 if ((dest_addr
[0] & AT25_RDSR_RDY
) == 0x00)
289 if ( timeout
== SSP_MAX_TIMEOUT
)
291 return AT25_ERROR_TIMEOUT_WFINISH
;
294 for (i
= 0; i
< 300; i
++); // Wait at least 250ns
296 return AT25_ERROR_OK
;