1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// The AT26 serial firmware Dataflash driver is based on top of the
/// corresponding Spi driver. A Dataflash structure instance has to be
/// initialized using the DF_Init function. Then basic dataflash
/// operations can be launched using macros such as DF_continuous_read.
/// These macros invoke the DF_Command() function which invokes the
/// DPI low driver using the SPI_SendCommand() function.
/// Beware to compute the dataflash internal address, the dataflash sector
/// description must be known (DataflashDesc). Dataflash can be automatically
/// detected using the DF_Scan() function.
///
/// !Usage
///
/// -# Initializes an AT26 instance and configures SPI chip select pin
/// using AT26_Configure().
/// -# Detect DF and returns DF description corresponding to the device
/// connected using AT26_FindDevice().This function shall be called by
/// the application before AT26_SendCommand().
/// -# Sends a command to the DF through the SPI using AT26_SendCommand().
/// The command is identified by its command code and the number of
/// bytes to transfer.
/// -# Example code for sending command to write a page to DF.
/// \code
/// // Program page
/// error = AT26_SendCommand(pAt26, AT26_BYTE_PAGE_PROGRAM, 4,
/// pData, writeSize, address, 0, 0);
/// \endcode
/// -# Example code for sending command to read a page from DF.
/// If data needs to be received, then a data buffer must be
/// provided.
/// \code
/// // Start a read operation
/// error = AT26_SendCommand(pAt26, AT26_READ_ARRAY_LF,
/// 4, pData, size, address, 0, 0);
/// \endcode
/// -# This function does not block; its optional callback will
/// be invoked when the transfer completes.
/// -# Check the AT26 driver is ready or not by polling AT26_IsBusy().
///
//------------------------------------------------------------------------------
#ifndef AT26_H
#define AT26_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "spid.h"
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
#define AT26_Size(pAt26) ((pAt26)->pDesc->size)
#define AT26_PageSize(pAt26) ((pAt26)->pDesc->pageSize)
#define AT26_BlockSize(pAt26) ((pAt26)->pDesc->blockSize)
#define AT26_Name(pAt26) ((pAt26)->pDesc->name)
#define AT26_PageNumber(pAt26) (AT26_Size(pAt26) / AT26_PageSize(pAt26))
#define AT26_BlockNumber(pAt26) (AT26_Size(pAt26) / AT26_BlockSize(pAt26))
#define AT26_PagePerBlock(pAt26) (AT26_BlockSize(pAt26) / AT26_PageSize(pAt26))
#define AT26_BlockEraseCmd(pAt26) ((pAt26)->pDesc->blockEraseCmd)
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// Device is protected, operation cannot be carried out.
#define AT26_ERROR_PROTECTED 1
/// Device is busy executing a command.
#define AT26_ERROR_BUSY 2
/// There was a problem while trying to program page data.
#define AT26_ERROR_PROGRAM 3
/// There was an SPI communication error.
#define AT26_ERROR_SPI 4
/// Device ready/busy status bit.
#define AT26_STATUS_RDYBSY (1 << 0)
/// Device is ready.
#define AT26_STATUS_RDYBSY_READY (0 << 0)
/// Device is busy with internal operations.
#define AT26_STATUS_RDYBSY_BUSY (1 << 0)
/// Write enable latch status bit.
#define AT26_STATUS_WEL (1 << 1)
/// Device is not write enabled.
#define AT26_STATUS_WEL_DISABLED (0 << 1)
/// Device is write enabled.
#define AT26_STATUS_WEL_ENABLED (1 << 1)
/// Software protection status bitfield.
#define AT26_STATUS_SWP (3 << 2)
/// All sectors are software protected.
#define AT26_STATUS_SWP_PROTALL (3 << 2)
/// Some sectors are software protected.
#define AT26_STATUS_SWP_PROTSOME (1 << 2)
/// No sector is software protected.
#define AT26_STATUS_SWP_PROTNONE (0 << 2)
/// Write protect pin status bit.
#define AT26_STATUS_WPP (1 << 4)
/// Write protect signal is not asserted.
#define AT26_STATUS_WPP_NOTASSERTED (0 << 4)
/// Write protect signal is asserted.
#define AT26_STATUS_WPP_ASSERTED (1 << 4)
/// Erase/program error bit.
#define AT26_STATUS_EPE (1 << 5)
/// Erase or program operation was successful.
#define AT26_STATUS_EPE_SUCCESS (0 << 5)
/// Erase or program error detected.
#define AT26_STATUS_EPE_ERROR (1 << 5)
/// Sector protection registers locked bit.
#define AT26_STATUS_SPRL (1 << 7)
/// Sector protection registers are unlocked.
#define AT26_STATUS_SPRL_UNLOCKED (0 << 7)
/// Sector protection registers are locked.
#define AT26_STATUS_SPRL_LOCKED (1 << 7)
/// Read array command code.
#define AT26_READ_ARRAY 0x0B
/// Read array (low frequency) command code.
#define AT26_READ_ARRAY_LF 0x03
/// Block erase command code (4K block).
#define AT26_BLOCK_ERASE_4K 0x20
/// Block erase command code (32K block).
#define AT26_BLOCK_ERASE_32K 0x52
/// Block erase command code (64K block).
#define AT26_BLOCK_ERASE_64K 0xD8
/// Chip erase command code 1.
#define AT26_CHIP_ERASE_1 0x60
/// Chip erase command code 2.
#define AT26_CHIP_ERASE_2 0xC7
/// Byte/page program command code.
#define AT26_BYTE_PAGE_PROGRAM 0x02
/// Sequential program mode command code 1.
#define AT26_SEQUENTIAL_PROGRAM_1 0xAD
/// Sequential program mode command code 2.
#define AT26_SEQUENTIAL_PROGRAM_2 0xAF
/// Write enable command code.
#define AT26_WRITE_ENABLE 0x06
/// Write disable command code.
#define AT26_WRITE_DISABLE 0x04
/// Protect sector command code.
#define AT26_PROTECT_SECTOR 0x36
/// Unprotect sector command code.
#define AT26_UNPROTECT_SECTOR 0x39
/// Read sector protection registers command code.
#define AT26_READ_SECTOR_PROT 0x3C
/// Read status register command code.
#define AT26_READ_STATUS 0x05
/// Write status register command code.
#define AT26_WRITE_STATUS 0x01
/// Read manufacturer and device ID command code.
#define AT26_READ_JEDEC_ID 0x9F
/// Deep power-down command code.
#define AT26_DEEP_PDOWN 0xB9
/// Resume from deep power-down command code.
#define AT26_RES_DEEP_PDOWN 0xAB
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Describes a serial firmware flash device parameters.
//------------------------------------------------------------------------------
typedef struct _At26Desc {
/// Device string name.
const char *name;
/// JEDEC ID of device.
unsigned int jedecId;
/// Size of device in bytes.
unsigned int size;
/// Size of one page in bytes.
unsigned int pageSize;
/// Block erase size in bytes.
unsigned int blockSize;
/// Block erase command.
unsigned int blockEraseCmd;
} At26Desc;
//------------------------------------------------------------------------------
/// Serial flash driver structure. Holds the current state of the driver,
/// including the current command and the descriptor for the underlying device.
//------------------------------------------------------------------------------
typedef struct _At26 {
/// Pointer to the underlying SPI driver.
Spid *pSpid;
/// Current SPI command sent to the SPI driver.
SpidCmd command;
/// Pointer to a descriptor for the serial firmware flash device.
const At26Desc *pDesc;
/// Command buffer.
unsigned int pCmdBuffer[2];
} At26;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void AT26_Configure(At26 *pAt26, Spid *pSpid, unsigned char cs);
extern unsigned char AT26_SendCommand(
At26 *pAt26,
unsigned char cmd,
unsigned char cmdSize,
unsigned char *pData,
unsigned int dataSize,
unsigned int address,
SpidCallback callback,
void *pArgument);
extern unsigned char AT26_IsBusy(At26 *pAt26);
extern const At26Desc * AT26_FindDevice(
At26 *pAt26,
unsigned int jedecId);
#endif //#ifndef AT26_H
|