source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifi_dnld/src/SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY/DATA_FLASH/AT45DBX/at45dbx.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 3 years ago

Adding new version

File size: 21.5 KB
Line 
1/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2
3/*This file is prepared for Doxygen automatic documentation generation.*/
4/*! \file *********************************************************************
5 *
6 * \brief Management of the AT45DBX data flash controller through SPI.
7 *
8 * This file manages the accesses to the AT45DBX data flash components.
9 *
10 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32
11 * - Supported devices:  All AVR32 devices with an SPI module can be used.
12 * - AppNote:
13 *
14 * \author               Atmel Corporation: http://www.atmel.com \n
15 *                       Support and FAQ: http://support.atmel.no/
16 *
17 ******************************************************************************/
18
19/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 *
24 * 1. Redistributions of source code must retain the above copyright notice, this
25 * list of conditions and the following disclaimer.
26 *
27 * 2. Redistributions in binary form must reproduce the above copyright notice,
28 * this list of conditions and the following disclaimer in the documentation
29 * and/or other materials provided with the distribution.
30 *
31 * 3. The name of Atmel may not be used to endorse or promote products derived
32 * from this software without specific prior written permission.
33 *
34 * 4. This software may only be redistributed and used in connection with an Atmel
35 * AVR product.
36 *
37 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
39 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
40 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
41 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
47 *
48 */
49
50//_____  I N C L U D E S ___________________________________________________
51
52#include "conf_access.h"
53
54
55#if AT45DBX_MEM == ENABLE
56
57#include "compiler.h"
58#include "board.h"
59#include "gpio.h"
60#include "spi.h"
61#include "conf_at45dbx.h"
62#include "at45dbx.h"
63#include "printf-stdarg.h"
64
65#if AT45DBX_MEM_CNT > 4
66  #error AT45DBX_MEM_CNT must not exceed 4
67#endif
68
69
70//_____ D E F I N I T I O N S ______________________________________________
71
72/*! \name AT45DBX Group A Commands
73 */
74//! @{
75#define AT45DBX_CMDA_RD_PAGE              0xD2        //!< Main Memory Page Read (Serial/8-bit Mode).
76#define AT45DBX_CMDA_RD_ARRAY_LEG         0xE8        //!< Continuous Array Read, Legacy Command (Serial/8-bit Mode).
77#define AT45DBX_CMDA_RD_ARRAY_LF_SM       0x03        //!< Continuous Array Read, Low-Frequency Mode (Serial Mode).
78#define AT45DBX_CMDA_RD_ARRAY_AF_SM       0x0B        //!< Continuous Array Read, Any-Frequency Mode (Serial Mode).
79#define AT45DBX_CMDA_RD_SECTOR_PROT_REG   0x32        //!< Read Sector Protection Register (Serial/8-bit Mode).
80#define AT45DBX_CMDA_RD_SECTOR_LKDN_REG   0x35        //!< Read Sector Lockdown Register (Serial/8-bit Mode).
81#define AT45DBX_CMDA_RD_SECURITY_REG      0x77        //!< Read Security Register (Serial/8-bit Mode).
82//! @}
83
84/*! \name AT45DBX Group B Commands
85 */
86//! @{
87#define AT45DBX_CMDB_ER_PAGE              0x81        //!< Page Erase (Serial/8-bit Mode).
88#define AT45DBX_CMDB_ER_BLOCK             0x50        //!< Block Erase (Serial/8-bit Mode).
89#define AT45DBX_CMDB_ER_SECTOR            0x7C        //!< Sector Erase (Serial/8-bit Mode).
90#define AT45DBX_CMDB_ER_CHIP              0xC794809A  //!< Chip Erase (Serial/8-bit Mode).
91#define AT45DBX_CMDB_XFR_PAGE_TO_BUF1     0x53        //!< Main Memory Page to Buffer 1 Transfer (Serial/8-bit Mode).
92#define AT45DBX_CMDB_XFR_PAGE_TO_BUF2     0x55        //!< Main Memory Page to Buffer 2 Transfer (Serial/8-bit Mode).
93#define AT45DBX_CMDB_CMP_PAGE_TO_BUF1     0x60        //!< Main Memory Page to Buffer 1 Compare (Serial/8-bit Mode).
94#define AT45DBX_CMDB_CMP_PAGE_TO_BUF2     0x61        //!< Main Memory Page to Buffer 2 Compare (Serial/8-bit Mode).
95#define AT45DBX_CMDB_PR_BUF1_TO_PAGE_ER   0x83        //!< Buffer 1 to Main Memory Page Program with Built-in Erase (Serial/8-bit Mode).
96#define AT45DBX_CMDB_PR_BUF2_TO_PAGE_ER   0x86        //!< Buffer 2 to Main Memory Page Program with Built-in Erase (Serial/8-bit Mode).
97#define AT45DBX_CMDB_PR_BUF1_TO_PAGE      0x88        //!< Buffer 1 to Main Memory Page Program without Built-in Erase (Serial/8-bit Mode).
98#define AT45DBX_CMDB_PR_BUF2_TO_PAGE      0x89        //!< Buffer 2 to Main Memory Page Program without Built-in Erase (Serial/8-bit Mode).
99#define AT45DBX_CMDB_PR_PAGE_TH_BUF1      0x82        //!< Main Memory Page Program through Buffer 1 (Serial/8-bit Mode).
100#define AT45DBX_CMDB_PR_PAGE_TH_BUF2      0x85        //!< Main Memory Page Program through Buffer 2 (Serial/8-bit Mode).
101#define AT45DBX_CMDB_RWR_PAGE_TH_BUF1     0x58        //!< Auto Page Rewrite through Buffer 1 (Serial/8-bit Mode).
102#define AT45DBX_CMDB_RWR_PAGE_TH_BUF2     0x59        //!< Auto Page Rewrite through Buffer 2 (Serial/8-bit Mode).
103//! @}
104
105/*! \name AT45DBX Group C Commands
106 */
107//! @{
108#define AT45DBX_CMDC_RD_BUF1_LF_SM        0xD1        //!< Buffer 1 Read, Low-Frequency Mode (Serial Mode).
109#define AT45DBX_CMDC_RD_BUF2_LF_SM        0xD3        //!< Buffer 2 Read, Low-Frequency Mode (Serial Mode).
110#define AT45DBX_CMDC_RD_BUF1_AF_SM        0xD4        //!< Buffer 1 Read, Any-Frequency Mode (Serial Mode).
111#define AT45DBX_CMDC_RD_BUF2_AF_SM        0xD6        //!< Buffer 2 Read, Any-Frequency Mode (Serial Mode).
112#define AT45DBX_CMDC_RD_BUF1_AF_8M        0x54        //!< Buffer 1 Read, Any-Frequency Mode (8-bit Mode).
113#define AT45DBX_CMDC_RD_BUF2_AF_8M        0x56        //!< Buffer 2 Read, Any-Frequency Mode (8-bit Mode).
114#define AT45DBX_CMDC_WR_BUF1              0x84        //!< Buffer 1 Write (Serial/8-bit Mode).
115#define AT45DBX_CMDC_WR_BUF2              0x87        //!< Buffer 2 Write (Serial/8-bit Mode).
116#define AT45DBX_CMDC_RD_STATUS_REG        0xD7        //!< Status Register Read (Serial/8-bit Mode).
117#define AT45DBX_CMDC_RD_MNFCT_DEV_ID_SM   0x9F        //!< Manufacturer and Device ID Read (Serial Mode).
118//! @}
119
120/*! \name AT45DBX Group D Commands
121 */
122//! @{
123#define AT45DBX_CMDD_EN_SECTOR_PROT       0x3D2A7FA9  //!< Enable Sector Protection (Serial/8-bit Mode).
124#define AT45DBX_CMDD_DIS_SECTOR_PROT      0x3D2A7F9A  //!< Disable Sector Protection (Serial/8-bit Mode).
125#define AT45DBX_CMDD_ER_SECTOR_PROT_REG   0x3D2A7FCF  //!< Erase Sector Protection Register (Serial/8-bit Mode).
126#define AT45DBX_CMDD_PR_SECTOR_PROT_REG   0x3D2A7FFC  //!< Program Sector Protection Register (Serial/8-bit Mode).
127#define AT45DBX_CMDD_LKDN_SECTOR          0x3D2A7F30  //!< Sector Lockdown (Serial/8-bit Mode).
128#define AT45DBX_CMDD_PR_SECURITY_REG      0x9B000000  //!< Program Security Register (Serial/8-bit Mode).
129#define AT45DBX_CMDD_PR_CONF_REG          0x3D2A80A6  //!< Program Configuration Register (Serial/8-bit Mode).
130#define AT45DBX_CMDD_DEEP_PWR_DN          0xB9        //!< Deep Power-down (Serial/8-bit Mode).
131#define AT45DBX_CMDD_RSM_DEEP_PWR_DN      0xAB        //!< Resume from Deep Power-down (Serial/8-bit Mode).
132//! @}
133
134
135/*! \name Bit-Masks and Values for the Status Register
136 */
137//! @{
138#define AT45DBX_MSK_BUSY                  0x80        //!< Busy status bit-mask.
139#define AT45DBX_BUSY                      0x00        //!< Busy status value (0x00 when busy, 0x80 when ready).
140#define AT45DBX_MSK_DENSITY               0x3C        //!< Device density bit-mask.
141//! @}
142#if AT45DBX_MEM_SIZE == AT45DBX_1MB
143
144/*! \name AT45DB081 Memories
145 */
146//! @{
147#define AT45DB021D_DENSITY                0x14        //!< Device density value.
148#define AT45DBX_DENSITY                   0x24        //!< Device density value.
149#define AT45DBX_BYTE_ADDR_BITS             9          //!< Address bits for byte position within buffer.
150
151//! @}
152#elif AT45DBX_MEM_SIZE == AT45DBX_2MB
153/*! \name AT45DB021D Memories
154 */
155//! @{
156#define AT45DBX_DENSITY                   0x21        //!< Device density value.
157#define AT45DBX_BYTE_ADDR_BITS                  10        //!< Address bits for byte position within buffer.
158
159//! @}
160#if 0
161/*! \name AT45DB161 Memories
162 */
163//! @{
164#define AT45DBX_DENSITY                   0x2C        //!< Device density value.
165#define AT45DBX_BYTE_ADDR_BITS                  10        //!< Address bits for byte position within buffer.
166
167//! @}
168#endif
169
170#elif AT45DBX_MEM_SIZE == AT45DBX_4MB
171
172/*! \name AT45DB321 Memories
173 */
174//! @{
175#define AT45DBX_DENSITY                   0x34        //!< Device density value.
176#define AT45DBX_BYTE_ADDR_BITS            10          //!< Address bits for byte position within buffer.
177
178//! @}
179
180#elif AT45DBX_MEM_SIZE == AT45DBX_8MB
181
182/*! \name AT45DB642 Memories
183 */
184//! @{
185#define AT45DBX_DENSITY                   0x3C        //!< Device density value.
186#define AT45DBX_BYTE_ADDR_BITS            11          //!< Address bits for byte position within buffer.
187
188
189//! @}
190
191#else
192  #error AT45DBX_MEM_SIZE is not defined to a supported value
193#endif
194
195
196
197//! Address bits for page selection.
198#define AT45DBX_PAGE_ADDR_BITS            (AT45DBX_MEM_SIZE - AT45DBX_PAGE_BITS)
199
200//! Number of bits for addresses within pages.
201#define AT45DBX_PAGE_BITS                 (AT45DBX_BYTE_ADDR_BITS - 1)
202
203//! Page size in bytes.
204#define AT45DBX_PAGE_SIZE                 (1 << AT45DBX_PAGE_BITS)
205
206//! Bit-mask for byte position within buffer in \ref gl_ptr_mem.
207#define AT45DBX_MSK_PTR_BYTE              ((1 << AT45DBX_PAGE_BITS) - 1)
208
209//! Bit-mask for page selection in \ref gl_ptr_mem.
210#define AT45DBX_MSK_PTR_PAGE              (((1 << AT45DBX_PAGE_ADDR_BITS) - 1) << AT45DBX_PAGE_BITS)
211
212//! Bit-mask for byte position within sector in \ref gl_ptr_mem.
213#define AT45DBX_MSK_PTR_SECTOR            ((1 << AT45DBX_SECTOR_BITS) - 1)
214
215
216/*! \brief Sends a dummy byte through SPI.
217 */
218#define spi_write_dummy()                 spi_write(AT45DBX_SPI, 0xFF)
219
220
221//! Boolean indicating whether memory is in busy state.
222static Bool at45dbx_busy;
223
224//! Memory data pointer.
225static U32 gl_ptr_mem;
226
227//! Sector buffer.
228static U8 sector_buf[AT45DBX_SECTOR_SIZE];
229
230
231/*! \name Control Functions
232 */
233//! @{
234
235
236Bool at45dbx_init(spi_options_t spiOptions, unsigned int pba_hz)
237{
238  // Setup SPI registers according to spiOptions.
239  for (spiOptions.reg = AT45DBX_SPI_FIRST_NPCS;
240       spiOptions.reg < AT45DBX_SPI_FIRST_NPCS + AT45DBX_MEM_CNT;
241       spiOptions.reg++)
242  {
243    if (spi_setupChipReg(AT45DBX_SPI, &spiOptions, pba_hz) != SPI_OK) return KO;
244  }
245
246  // Memory ready.
247  at45dbx_busy = FALSE;
248
249  return OK;
250}
251
252
253/*! \brief Selects or unselects a DF memory.
254 *
255 * \param memidx  Memory ID of DF to select or unselect.
256 * \param bSelect Boolean indicating whether the DF memory has to be selected.
257 */
258static void at45dbx_chipselect_df(U8 memidx, Bool bSelect)
259{
260  if (bSelect)
261  {
262    // Select SPI chip.
263    spi_selectChip(AT45DBX_SPI, AT45DBX_SPI_FIRST_NPCS + memidx);
264  }
265  else
266  {
267    // Unselect SPI chip.
268    spi_unselectChip(AT45DBX_SPI, AT45DBX_SPI_FIRST_NPCS + memidx);
269  }
270}
271
272
273Bool at45dbx_mem_check(void)
274{
275  U8 df;
276  U16 status = 0;
277
278  // DF memory check.
279  for (df = 0; df < AT45DBX_MEM_CNT; df++)
280  {
281    // Select the DF memory to check.
282    at45dbx_chipselect_df(df, TRUE);
283
284    // Send the Status Register Read command.
285    spi_write(AT45DBX_SPI, AT45DBX_CMDC_RD_STATUS_REG);
286
287    // Send a dummy byte to read the status register.
288    spi_write_dummy();
289    spi_read(AT45DBX_SPI, &status);
290
291    // Unselect the checked DF memory.
292    at45dbx_chipselect_df(df, FALSE);
293
294    // Unexpected device density value.
295    if ((status & AT45DBX_MSK_DENSITY) < AT45DB021D_DENSITY)
296    {
297        printk("Unexpected device density value: %d (0x%x)\n", (status & AT45DBX_MSK_DENSITY), status);
298        return KO;
299    }
300  }
301
302  return OK;
303}
304
305
306/*! \brief Waits until the DF is ready.
307 */
308static void at45dbx_wait_ready(void)
309{
310  U16 status;
311
312  // Select the DF memory gl_ptr_mem points to.
313  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, TRUE);
314
315  // Send the Status Register Read command.
316  spi_write(AT45DBX_SPI, AT45DBX_CMDC_RD_STATUS_REG);
317
318  // Read the status register until the DF is ready.
319  do
320  {
321    // Send a dummy byte to read the status register.
322    spi_write_dummy();
323    spi_read(AT45DBX_SPI, &status);
324  } while ((status & AT45DBX_MSK_BUSY) == AT45DBX_BUSY);
325
326  // Unselect the DF memory gl_ptr_mem points to.
327  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
328}
329
330
331Bool at45dbx_read_open(U32 sector)
332{
333  U32 addr;
334
335  // Set the global memory pointer to a byte address.
336  gl_ptr_mem = sector << AT45DBX_SECTOR_BITS; // gl_ptr_mem = sector * AT45DBX_SECTOR_SIZE.
337
338  // If the DF memory is busy, wait until it's ready.
339  if (at45dbx_busy) at45dbx_wait_ready();
340  at45dbx_busy = FALSE;
341
342  // Select the DF memory gl_ptr_mem points to.
343  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, TRUE);
344
345  // Initiate a page read at a given sector.
346
347  // Send the Main Memory Page Read command.
348  spi_write(AT45DBX_SPI, AT45DBX_CMDA_RD_PAGE);
349
350  // Send the three address bytes, which comprise:
351  //  - (24 - (AT45DBX_PAGE_ADDR_BITS + AT45DBX_BYTE_ADDR_BITS)) reserved bits;
352  //  - then AT45DBX_PAGE_ADDR_BITS bits specifying the page in main memory to be read;
353  //  - then AT45DBX_BYTE_ADDR_BITS bits specifying the starting byte address within that page.
354  // NOTE: The bits of gl_ptr_mem above the AT45DBX_MEM_SIZE bits are useless for the local
355  // DF addressing. They are used for DF discrimination when there are several DFs.
356  addr = (Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_PAGE) << AT45DBX_BYTE_ADDR_BITS) |
357         Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_BYTE);
358  spi_write(AT45DBX_SPI, LSB2W(addr));
359  spi_write(AT45DBX_SPI, LSB1W(addr));
360  spi_write(AT45DBX_SPI, LSB0W(addr));
361
362  // Send 32 don't care clock cycles to initialize the read operation.
363  spi_write_dummy();
364  spi_write_dummy();
365  spi_write_dummy();
366  spi_write_dummy();
367
368  return OK;
369}
370
371
372void at45dbx_read_close(void)
373{
374  // Unselect the DF memory gl_ptr_mem points to.
375  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
376
377  // Memory ready.
378  at45dbx_busy = FALSE;
379}
380
381
382Bool at45dbx_write_open(U32 sector)
383{
384  U32 addr;
385
386  // Set the global memory pointer to a byte address.
387  gl_ptr_mem = sector << AT45DBX_SECTOR_BITS; // gl_ptr_mem = sector * AT45DBX_SECTOR_SIZE.
388
389  // If the DF memory is busy, wait until it's ready.
390  if (at45dbx_busy) at45dbx_wait_ready();
391  at45dbx_busy = FALSE;
392
393#if AT45DBX_PAGE_SIZE > AT45DBX_SECTOR_SIZE
394  // Select the DF memory gl_ptr_mem points to.
395  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, TRUE);
396
397  // Transfer the content of the current page to buffer 1.
398
399  // Send the Main Memory Page to Buffer 1 Transfer command.
400  spi_write(AT45DBX_SPI, AT45DBX_CMDB_XFR_PAGE_TO_BUF1);
401
402  // Send the three address bytes, which comprise:
403  //  - (24 - (AT45DBX_PAGE_ADDR_BITS + AT45DBX_BYTE_ADDR_BITS)) reserved bits;
404  //  - then AT45DBX_PAGE_ADDR_BITS bits specifying the page in main memory to be read;
405  //  - then AT45DBX_BYTE_ADDR_BITS don't care bits.
406  // NOTE: The bits of gl_ptr_mem above the AT45DBX_MEM_SIZE bits are useless for the local
407  // DF addressing. They are used for DF discrimination when there are several DFs.
408  addr = Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_PAGE) << AT45DBX_BYTE_ADDR_BITS;
409  spi_write(AT45DBX_SPI, LSB2W(addr));
410  spi_write(AT45DBX_SPI, LSB1W(addr));
411  spi_write(AT45DBX_SPI, LSB0W(addr));
412
413  // Unselect the DF memory gl_ptr_mem points to.
414  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
415
416  // Wait for end of page transfer.
417  at45dbx_wait_ready();
418#endif
419
420  // Select the DF memory gl_ptr_mem points to.
421  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, TRUE);
422
423  // Initiate a page write at a given sector.
424
425  // Send the Main Memory Page Program through Buffer 1 command.
426  spi_write(AT45DBX_SPI, AT45DBX_CMDB_PR_PAGE_TH_BUF1);
427
428  // Send the three address bytes, which comprise:
429  //  - (24 - (AT45DBX_PAGE_ADDR_BITS + AT45DBX_BYTE_ADDR_BITS)) reserved bits;
430  //  - then AT45DBX_PAGE_ADDR_BITS bits specifying the page in main memory to be written;
431  //  - then AT45DBX_BYTE_ADDR_BITS bits specifying the starting byte address within that page.
432  // NOTE: The bits of gl_ptr_mem above the AT45DBX_MEM_SIZE bits are useless for the local
433  // DF addressing. They are used for DF discrimination when there are several DFs.
434  addr = (Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_PAGE) << AT45DBX_BYTE_ADDR_BITS) |
435         Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_BYTE);
436  spi_write(AT45DBX_SPI, LSB2W(addr));
437  spi_write(AT45DBX_SPI, LSB1W(addr));
438  spi_write(AT45DBX_SPI, LSB0W(addr));
439
440  return OK;
441}
442
443
444void at45dbx_write_close(void)
445{
446  // While end of logical sector not reached, zero-fill remaining memory bytes.
447  while (Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_SECTOR))
448  {
449    spi_write(AT45DBX_SPI, 0x00);
450    gl_ptr_mem++;
451  }
452
453  // Unselect the DF memory gl_ptr_mem points to.
454  at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
455
456  // Memory busy.
457  at45dbx_busy = TRUE;
458}
459
460
461//! @}
462
463
464/*! \name Single-Byte Access Functions
465 */
466//! @{
467
468
469U8 at45dbx_read_byte(void)
470{
471  U16 data;
472
473  // Memory busy.
474  if (at45dbx_busy)
475  {
476    // Being here, we know that we previously finished a page read.
477    // => We have to access the next page.
478
479    // Memory ready.
480    at45dbx_busy = FALSE;
481
482    // Eventually select the next DF and open the next page.
483    // NOTE: at45dbx_read_open input parameter is a sector.
484    at45dbx_read_open(gl_ptr_mem >> AT45DBX_SECTOR_BITS); // gl_ptr_mem / AT45DBX_SECTOR_SIZE.
485  }
486
487  // Send a dummy byte to read the next data byte.
488  spi_write_dummy();
489  spi_read(AT45DBX_SPI, &data);
490  gl_ptr_mem++;
491
492  // If end of page reached,
493  if (!Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_BYTE))
494  {
495    // unselect the DF memory gl_ptr_mem points to.
496    at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
497
498    // Memory busy.
499    at45dbx_busy = TRUE;
500  }
501
502  return data;
503}
504
505
506Bool at45dbx_write_byte(U8 b)
507{
508  // Memory busy.
509  if (at45dbx_busy)
510  {
511    // Being here, we know that we previously launched a page programming.
512    // => We have to access the next page.
513
514    // Eventually select the next DF and open the next page.
515    // NOTE: at45dbx_write_open input parameter is a sector.
516    at45dbx_write_open(gl_ptr_mem >> AT45DBX_SECTOR_BITS); // gl_ptr_mem / AT45DBX_SECTOR_SIZE.
517  }
518
519  // Write the next data byte.
520  spi_write(AT45DBX_SPI, b);
521  gl_ptr_mem++;
522
523  // If end of page reached,
524  if (!Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_BYTE))
525  {
526    // unselect the DF memory gl_ptr_mem points to in order to program the page.
527    at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
528
529    // Memory busy.
530    at45dbx_busy = TRUE;
531  }
532
533  return OK;
534}
535
536
537//! @}
538
539
540/*! \name Multiple-Sector Access Functions
541 */
542//! @{
543
544
545Bool at45dbx_read_multiple_sector(U16 nb_sector)
546{
547  while (nb_sector--)
548  {
549    // Read the next sector.
550    at45dbx_read_sector_2_ram(sector_buf);
551    at45dbx_read_multiple_sector_callback(sector_buf);
552  }
553
554  return OK;
555}
556
557
558Bool at45dbx_write_multiple_sector(U16 nb_sector)
559{
560  while (nb_sector--)
561  {
562    // Write the next sector.
563    at45dbx_write_multiple_sector_callback(sector_buf);
564    at45dbx_write_sector_from_ram(sector_buf);
565  }
566
567  return OK;
568}
569
570
571//! @}
572
573
574/*! \name Single-Sector Access Functions
575 */
576//! @{
577
578
579Bool at45dbx_read_sector_2_ram(void *ram)
580{
581  U8 *_ram = ram;
582  U16 i;
583  U16 data;
584
585  // Memory busy.
586  if (at45dbx_busy)
587  {
588    // Being here, we know that we previously finished a page read.
589    // => We have to access the next page.
590
591    // Memory ready.
592    at45dbx_busy = FALSE;
593
594    // Eventually select the next DF and open the next page.
595    // NOTE: at45dbx_read_open input parameter is a sector.
596    at45dbx_read_open(gl_ptr_mem >> AT45DBX_SECTOR_BITS); // gl_ptr_mem / AT45DBX_SECTOR_SIZE.
597  }
598
599  // Read the next sector.
600  for (i = AT45DBX_SECTOR_SIZE; i; i--)
601  {
602    // Send a dummy byte to read the next data byte.
603    spi_write_dummy();
604    spi_read(AT45DBX_SPI, &data);
605    *_ram++ = data;
606  }
607
608  // Update the memory pointer.
609  gl_ptr_mem += AT45DBX_SECTOR_SIZE;
610
611#if AT45DBX_PAGE_SIZE > AT45DBX_SECTOR_SIZE
612  // If end of page reached,
613  if (!Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_BYTE))
614#endif
615  {
616    // unselect the DF memory gl_ptr_mem points to.
617    at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
618
619    // Memory busy.
620    at45dbx_busy = TRUE;
621  }
622
623  return OK;
624}
625
626
627Bool at45dbx_write_sector_from_ram(const void *ram)
628{
629  const U8 *_ram = ram;
630  U16 i;
631
632  // Memory busy.
633  if (at45dbx_busy)
634  {
635    // Being here, we know that we previously launched a page programming.
636    // => We have to access the next page.
637
638    // Eventually select the next DF and open the next page.
639    // NOTE: at45dbx_write_open input parameter is a sector.
640    at45dbx_write_open(gl_ptr_mem >> AT45DBX_SECTOR_BITS); // gl_ptr_mem / AT45DBX_SECTOR_SIZE.
641  }
642
643  // Write the next sector.
644  for (i = AT45DBX_SECTOR_SIZE; i; i--)
645  {
646    // Write the next data byte.
647    spi_write(AT45DBX_SPI, *_ram++);
648  }
649
650  // Update the memory pointer.
651  gl_ptr_mem += AT45DBX_SECTOR_SIZE;
652
653#if AT45DBX_PAGE_SIZE > AT45DBX_SECTOR_SIZE
654  // If end of page reached,
655  if (!Rd_bitfield(gl_ptr_mem, AT45DBX_MSK_PTR_BYTE))
656#endif
657  {
658    // unselect the DF memory gl_ptr_mem points to in order to program the page.
659    at45dbx_chipselect_df(gl_ptr_mem >> AT45DBX_MEM_SIZE, FALSE);
660
661    // Memory busy.
662    at45dbx_busy = TRUE;
663  }
664
665  return OK;
666}
667
668
669//! @}
670
671
672#endif  // AT45DBX_MEM == ENABLE
Note: See TracBrowser for help on using the repository browser.