4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
33 * \brief Function library for AT45DBXX Data Flash memory.
36 * \version $Id: dataflash.c 15379 2007-03-28 15:46:09Z asterix $
37 * \author Daniele Basile <asterix@develer.com>
41 #include <appconfig.h>
44 #include <cfg/macros.h>
45 #include <cfg/debug.h>
46 #include <cfg/module.h>
47 #include <drv/timer.h>
49 #include <drv/dataflash.h>
55 * Global variable for store current and previous data
56 * flash memory page address during operation of writing.
58 dataflash_t previous_page = 0;
59 bool page_modified = false;
63 * Send a generic command to data flash memory.
64 * This function send only 4 byte, for opcode, page address and
67 static void send_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode opcode)
71 * Make sure to toggle CS signal in order,
72 * and reset dataflash command decoder.
74 * \note This is equivalent to CS_DISABLE() immediately followed by CS_ENABLE()
80 * To send one command to data flash memory, we send 4 byte.
81 * First byte is opcode command, second and third byte are
82 * page address, in last byte we write a byte page address.
83 * (see datasheet for more detail).
85 * \note Generaly a defaul memory page size is more than 256 byte.
86 * In this case we need for addressing a byte in one page more than
87 * 8 bit, so we put in fourth byte low part of address byte, and
88 * hight part of address byte in third byte togheter low par of page
103 spi_sendRecv((uint8_t)(page_addr >> (16 - DATAFLASH_PAGE_ADDRESS_BIT)));
104 spi_sendRecv((uint8_t)((page_addr << (DATAFLASH_PAGE_ADDRESS_BIT - 8)) + (byte_addr >> 8)));
108 * Send byte page address.
110 spi_sendRecv((uint8_t)byte_addr);
117 * Reset dataflash memory function.
119 * This function reset data flash memory
120 * with one pulse reset long about 10usec.
123 static void dataflash_reset(void)
127 timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
130 timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
134 * dataflash init function.
135 * This function initialize a micro pin and
136 * SPI driver, and test if data flash memory
137 * density is the same wich define in dataflash.h.
139 MOD_DEFINE(dataflash);
140 static bool dataflash_pin_init(void)
147 WRITE_ENABLE(); //pilot wp pin.
154 stat = dataflash_stat();
159 * 2,3,4,5 bits of 1 byte status register
160 * indicate a device density of dataflash memory
161 * (see datasheet for more detail.)
163 GET_ID_DESITY_DEVICE(stat);
165 if(stat == DATAFLASH_ID_DEVICE_DENSITY)
174 * Read status register of dataflah memory.
177 static uint8_t dataflash_stat(void)
182 * Make sure to toggle CS signal in order,
183 * and reset dataflash command decoder.
188 stat = spi_sendRecv(DFO_READ_STATUS);
189 stat = spi_sendRecv(0x00);
196 * Send one command to data flash memory, and
197 * return status register value.
200 static uint8_t dataflash_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode opcode)
203 send_cmd(page_addr, byte_addr, opcode);
209 * We chech data flash memory state, and wait until busy-flag
212 while(!(dataflash_stat() & BUSY_BIT));
214 return (dataflash_stat());
219 * Read one byte from main data flash memory or buffer data
222 static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode opcode)
226 send_cmd(page_addr, byte_addr, opcode);
228 #if CONFIG_DATA_FLASH == DATAFLASH_AT45DB041B
229 if(opcode == DFO_READ_FLASH_MEM_BYTE)
232 * Send 24 don't care bit.
243 spi_sendRecv(0x00); //Send 8 don't care bit.
244 data = spi_sendRecv(0x00); //Read byte.
251 * Read \a len bytes from main data flash memory or buffer data
252 * flash memory, and put it in \a *block.
254 static void dataflash_read_block(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
257 send_cmd(page_addr, byte_addr, opcode);
259 if(opcode == DFO_READ_FLASH_MEM_BYTE)
262 * Send 24 don't care bit.
271 spi_sendRecv(0x00); //Send 8 don't care bit.
272 spi_read(block, len); //Read len bytes ad put in block buffer.
281 * Write \a len bytes in buffer buffer data flash memory.
283 * \note Isn't possible to write bytes directly in main memory data
284 * flash. To perform write in main memory you must before write in buffer
285 * data flash memory, an then send command to write page in main memory.
287 static void dataflash_write_block(dataflash_t byte_addr, DFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
290 send_cmd(0x00, byte_addr, opcode);
292 spi_write(block, len); //Write len bytes.
300 * Load selct page from dataflash memory to buffer.
302 static void dataflash_loadPage(dataflash_t page_addr)
304 dataflash_cmd(page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1);
310 * Flush select page (stored in buffer) in data flash main memory page.
312 void dataflash_flush(void)
316 dataflash_cmd(previous_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E);
319 page_modified = false;
321 kprintf("\n::=> Flush page:... <%ld>\n", previous_page);
325 /* Kfile interface section */
328 * Open data flash file \a fd
329 * \a name and \a mode are unused, cause flash memory is
330 * threated like one file.
332 static bool dataflash_open(struct _KFile *fd, UNUSED_ARG(const char *, name), UNUSED_ARG(int, mode))
334 MOD_CHECK(dataflash);
338 /* Load select page memory from data flash memory*/
339 dataflash_loadPage(previous_page);
341 kprintf("dataflash file opened\n");
348 static bool dataflash_close(UNUSED_ARG(struct _KFile *,fd))
351 kprintf("dataflash file closed\n");
356 * Move \a fd file seek position of \a offset bytes
357 * from current position.
359 static int32_t dataflash_seek(struct _KFile *fd, int32_t offset, KSeekMode whence)
364 * Read from file \a fd \a size bytes and put it in buffer \a buf
365 * \return the number of bytes read.
367 static size_t dataflash_read(struct _KFile *fd, void *buf, size_t size)
372 dataflashAddr_t byte_addr;
373 dataflashAddr_t page_addr;
377 kprintf(" Read at address:... %ld ",addr);
380 * We select from absolute address page address
381 * and byte address in page.
384 page_addr = addr / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
385 byte_addr = addr % (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
388 kprintf(" [page-<%ld>, byte-<%ld>]", page_addr, byte_addr);
391 * Flush current page in main memory if
392 * we had been written a byte in memory
397 * Read byte in main page data flash memory.
399 data = dataflash_read_byte(page_addr, byte_addr, DFO_READ_FLASH_MEM_BYTE);
401 kprintf(" ::=> Read data: %02x\n",data);
407 * Write program memory.
408 * Write \a size bytes from buffer \a _buf to file \a fd
409 * \note Write operations are buffered.
411 static size_t dataflash_write(struct _KFile *fd, const void *_buf, size_t size)
416 * Init data flash memory interface.
418 void dataflash_init(struct _KFile *fd)
420 // Set up data flash programming functions.
421 fd->open = dataflash_open;
422 fd->close = dataflash_close;
423 fd->read = dataflash_read;
424 fd->write = dataflash_write;
425 fd->seek = dataflash_seek;
427 // Init data flash memory and micro pin.
428 ASSERT(dataflash_pin_init());