Remove cvs logs.
[bertos.git] / drv / dataflash.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
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.
10  *
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.
15  *
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
19  *
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.
28  *
29  * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  *  \brief Function library for AT45DBXX Data Flash memory.
34  *
35  *
36  * \version $Id: dataflash.c 15379 2007-03-28 15:46:09Z asterix $
37  * \author Daniele Basile <asterix@develer.com>
38  */
39
40
41 #include <appconfig.h>
42
43 #include <avr/io.h>
44 #include <cfg/macros.h>
45 #include <cfg/debug.h>
46 #include <cfg/module.h>
47 #include <drv/timer.h>
48 #include <drv/spi.h>
49 #include <drv/dataflash.h>
50
51 #include "hw_spi.h"
52
53
54 /**
55  * Global variable for store current and previous data
56  * flash memory page address during operation of writing.
57  */
58 static dataflash_t previous_page = 0;
59 static bool page_modified = false;
60
61
62 /**
63  * Send a generic command to data flash memory.
64  * This function send only 4 byte, for opcode, page address and
65  * byte address.
66  */
67 static void send_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
68 {
69
70         /*
71          * Make sure to toggle CS signal in order,
72          * and reset dataflash command decoder.
73          *
74          * \note This is equivalent to CS_DISABLE() immediately followed by CS_ENABLE()
75          */
76         CS_TOGGLE();
77
78
79         /*
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).
84          *
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
89          *  address.
90          *
91          */
92
93         /*
94          * Send opcode.
95          */
96         spi_sendRecv(opcode);
97
98         /*
99          *  Send page address.
100          */
101         spi_sendRecv((uint8_t)(page_addr >> (16 - DATAFLASH_PAGE_ADDRESS_BIT)));
102         spi_sendRecv((uint8_t)((page_addr << (DATAFLASH_PAGE_ADDRESS_BIT - 8)) + (byte_addr >> 8)));
103
104         /*
105          * Send byte page address.
106          */
107         spi_sendRecv((uint8_t)byte_addr);
108
109
110 }
111
112 /**
113  * Reset dataflash memory function.
114  *
115  * This function reset data flash memory
116  * with one pulse reset long about 10usec.
117  *
118  */
119 static void dataflash_reset(void)
120 {
121         CS_ENABLE();
122         RESET_ENABLE();
123         timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
124         CS_DISABLE();
125         RESET_DISABLE();
126         timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
127 }
128
129 /**
130  * dataflash init function.
131  * This function initialize a micro pin and
132  * SPI driver, and test if data flash memory
133  * density is the same wich define in dataflash.h.
134  */
135 MOD_DEFINE(dataflash);
136 static bool dataflash_pin_init(void)
137 {
138         uint8_t stat;
139
140         MOD_CHECK(spi);
141
142         RESET_DISABLE();
143         WRITE_ENABLE(); //pilot wp pin.
144
145         RESET_OUT();
146         WP_OUT();
147
148         dataflash_reset();
149
150         stat = dataflash_stat();
151
152         MOD_INIT(dataflash);
153
154         /*
155          * 2,3,4,5 bits of 1 byte status register
156          * indicate a device density of dataflash memory
157          * (see datasheet for more detail.)
158          */
159         GET_ID_DESITY_DEVICE(stat);
160
161         if(stat == DATAFLASH_ID_DEVICE_DENSITY)
162                 return true;
163         else
164                 return false;
165
166 }
167
168
169 /**
170  * Read status register of dataflah memory.
171  *
172  */
173 static uint8_t dataflash_stat(void)
174 {
175         uint8_t stat;
176
177         /*
178          * Make sure to toggle CS signal in order,
179          * and reset dataflash command decoder.
180          */
181         CS_TOGGLE();
182
183         stat = spi_sendRecv(DFO_READ_STATUS);
184         stat = spi_sendRecv(0x00);
185
186         /*
187          * Note: this function could be call one more time
188          * to check register status (es. check if memory has been
189          * teminate one operation), and so we don't disable CS to
190          * allow fast reading of register status.
191          */
192         return stat;
193 }
194
195
196 /**
197  * Send one command to data flash memory, and
198  * return status register value.
199  *
200  */
201 static uint8_t dataflash_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
202 {
203
204         uint8_t stat;
205
206         send_cmd(page_addr, byte_addr, opcode);
207
208         CS_TOGGLE();
209
210         /*
211          * We chech data flash memory state, and wait until busy-flag
212          * is hight.
213          */
214         while(!(dataflash_stat() & BUSY_BIT));
215
216         stat = dataflash_stat();
217
218         /*
219          * Data flash has completed a bus cycle, so disable CS.
220          */
221         CS_DISABLE();
222
223         return (stat);
224
225 }
226
227 /**
228  * Read one byte from main data flash memory or buffer data
229  * flash memory.
230  */
231 static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
232 {
233         uint8_t data;
234
235         send_cmd(page_addr, byte_addr, opcode);
236
237 #if CONFIG_DATA_FLASH == DATAFLASH_AT45DB041B
238         if(opcode == DFO_READ_FLASH_MEM_BYTE)
239         {
240                 /*
241                  * Send 24 don't care bit.
242                  */
243                 spi_sendRecv(0x00);
244                 spi_sendRecv(0x00);
245                 spi_sendRecv(0x00);
246
247         }
248 #endif
249
250         spi_sendRecv(0x00);         //Send 8 don't care bit.
251         data = spi_sendRecv(0x00);  //Read byte.
252
253         CS_DISABLE();
254
255         return data;
256 }
257
258 /**
259  * Read \a len bytes from main data flash memory or buffer data
260  * flash memory, and put it in \a *block.
261  */
262 static void dataflash_read_block(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
263 {
264
265         send_cmd(page_addr, byte_addr, opcode);
266
267         if(opcode == DFO_READ_FLASH_MEM_BYTE)
268         {
269                 /*
270                  * Send 24 don't care bit.
271                  */
272                 spi_sendRecv(0x00);
273                 spi_sendRecv(0x00);
274                 spi_sendRecv(0x00);
275
276         }
277
278         spi_sendRecv(0x00);   //Send 8 don't care bit.
279         spi_read(block, len); //Read len bytes ad put in block buffer.
280
281
282         CS_DISABLE();
283
284 }
285
286
287 /**
288  * Write \a len bytes in buffer buffer data flash memory.
289  *
290  * \note Isn't possible to write bytes directly in main memory data
291  * flash. To perform write in main memory you must before write in buffer
292  * data flash memory, an then send command to write page in main memory.
293  */
294 static void dataflash_write_block(dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
295 {
296
297         send_cmd(0x00, byte_addr, opcode);
298
299         spi_write(block, len); //Write len bytes.
300
301         CS_DISABLE();
302
303 }
304
305
306 /**
307  * Load selct page from dataflash memory to buffer.
308  */
309 static void dataflash_loadPage(dataflash_t page_addr)
310 {
311         dataflash_cmd(page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1);
312 }
313
314 /**
315  * Flush select page (stored in buffer) in data flash main memory page.
316  */
317 void dataflash_flush(void)
318 {
319         if (page_modified)
320         {
321                 dataflash_cmd(previous_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E);
322
323                 page_modified = false;
324
325                 kprintf("\n::=> Flush page:... <%ld>\n", previous_page);
326         }
327 }
328
329 /* Kfile interface section */
330
331 /**
332  * Open data flash file \a fd
333  * \a name and \a mode are unused, cause flash memory is
334  * threated like one file.
335  */
336 static bool dataflash_open(struct _KFile *fd, UNUSED_ARG(const char *, name), UNUSED_ARG(int, mode))
337 {
338         MOD_CHECK(dataflash);
339
340         previous_page = 0;
341         fd->seek_pos = 0;
342         fd->size = (dataflashAddr_t)DATAFLASH_PAGE_SIZE * (dataflashAddr_t)DATAFLASH_NUM_PAGE;
343
344         /* Load select page memory from data flash memory*/
345         dataflash_loadPage(previous_page);
346
347         kprintf("dataflash file opened\n");
348         return true;
349 }
350
351 /**
352  * Close file \a fd
353  */
354 static bool dataflash_close(UNUSED_ARG(struct _KFile *,fd))
355 {
356         dataflash_flush();
357         kprintf("dataflash file closed\n");
358         return true;
359 }
360
361 /**
362  * Move \a fd file seek position of \a offset bytes
363  * from current position.
364  */
365 static int32_t dataflash_seek(struct _KFile *fd, kfile_off_t offset, KSeekMode whence)
366 {
367         uint32_t seek_pos;
368
369         switch(whence)
370         {
371
372         case KSM_SEEK_SET:
373                 seek_pos = 0;
374                 break;
375         case KSM_SEEK_END:
376                 seek_pos = fd->size - 1;
377                 break;
378         case KSM_SEEK_CUR:
379                 seek_pos = fd->seek_pos;
380                 break;
381         default:
382                 ASSERT(0);
383                 return -1;
384                 break;
385
386         }
387
388         /* Bound check */
389         if (seek_pos + offset > fd->size)
390         {
391                 ASSERT(0);
392                 return -1;
393         }
394
395         fd->seek_pos = seek_pos + offset;
396         kprintf("Flash seek to [%u]\n", fd->seek_pos);
397
398         return fd->seek_pos;
399 }
400
401 /**
402  * Read \a _buf lenght \a size byte from data flash memmory.
403  *
404  * \note For read in data flash memory, we
405  * check flag page_modified, if is true (that mean
406  * we had been written a byte in buffer memory) we
407  * flush current page in data flash main memory, and
408  * then read byte from memory, else we read byte
409  * directly from data flash main memory.
410  *
411  * \return the number of bytes read.
412  */
413 static size_t dataflash_read(struct _KFile *fd, void *buf, size_t size)
414 {
415         dataflashOffset_t byte_addr;
416         dataflashAddr_t page_addr;
417         uin8_t *data = (uint8_t *)buf;
418
419
420         ASSERT(fd->seek_pos + size <= fd->size);
421         size = MIN((uint32_t)size, fd->size - fd->seek_pos);
422
423         kprintf("Reading at pos[%u]\n", fd->seek_pos);
424
425         /*
426          * We select page and offest from absolute address.
427          */
428         page_addr = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
429         byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
430
431
432         kprintf(" [page-<%ld>, byte-<%ld>]", page_addr, byte_addr);
433
434         /*
435          * Flush current page in main memory if
436          * we had been written a byte in memory
437          */
438         dataflash_flush();
439
440         /*
441          * Read byte in main page data flash memory.
442          */
443         dataflash_read_block(page_addr, byte_addr, DFO_READ_FLASH_MEM_BYTE, data, size);
444
445         fd->seek_pos += size;
446         kprintf(" ::=> Read data: %02x\n",data);
447
448         return size;
449 }
450
451 /**
452  * Write \a _buf in data flash memory
453  *
454  * \note For write \a _buf in data flash memory, we must
455  * before write in buffer data flash memory, and at end of write,
456  * we put page in data flash main memory. If we write in two
457  * different page, we put in main memory current page and reload
458  * page witch we want write.
459  *
460  * \return the number of bytes write.
461  */
462 static size_t dataflash_write(struct _KFile *fd, const void *_buf, size_t size)
463 {
464
465         dataflashOffset_t byte_addr;
466         dataflashAddr_t current_page;
467
468         uint8_t *data = (uint8_t *) _buf;
469
470         ASSERT(fd->seek_pos + size <= fd->size);
471         size = MIN((uint32_t)size, fd->size - fd->seek_pos);
472
473         kprintf("Writing at pos[%u]\n", fd->seek_pos);
474
475         while (size)
476         {
477                 /*
478                 * We select page and offest from absolute address.
479                 */
480                 current_page = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
481                 byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
482
483
484                 size_t wr_len = MIN(size, DATAFLASH_PAGE_SIZE - byte_addr);
485
486                 kprintf(" [page-<%ld>, byte-<%ld>]",current_page, byte_addr);
487
488                 if (current_page != previous_page)
489                 {
490                         /* Flush current page in main memory*/
491                         dataflash_flush();
492                         /* Load select page memory from data flash memory*/
493                         dataflash_loadPage(current_page);
494
495                         previous_page = current_page;
496                         kprintf(" >> Load page: <%ld> ",current_page);
497                 }
498                 /*
499                 * Write byte in current page, and set true
500                 * page_modified flag.
501                 */
502                 dataflash_write_byte(byte_addr, DFO_WRITE_BUFF1, data);
503                 page_modified = true;
504
505
506                 data += wr_len;
507                 fd->seek_pos += wr_len;
508                 size -= wr_len;
509                 total_write += wr_len;
510         }
511
512         kprintf("written %u bytes\n", total_write);
513         return total_write;
514 }
515
516 /**
517  * Init data flash memory interface.
518  */
519 void dataflash_init(struct _KFile *fd)
520 {
521         // Set up data flash programming functions.
522         fd->open = dataflash_open;
523         fd->close = dataflash_close;
524         fd->read = dataflash_read;
525         fd->write = dataflash_write;
526         fd->seek = dataflash_seek;
527
528         // Init data flash memory and micro pin.
529         ASSERT(dataflash_pin_init());
530 }
531
532 /**
533  * Test function for dataflash.
534  *
535  * This function test check low level driver for
536  * AT45xx (see dataflash.h for more info) data flash memory.
537  * We write a string in memory in some page ad read it.
538  */
539 void dataflash_test(void)
540 {
541         KFile fd;
542
543         dataflash_init(&fd);
544
545         uint8_t test_buf[] = "0123456789 Develer s.r.l.";
546         uint8_t cmp_buf[];
547
548         int tb_len = sizeof(test_buf);
549         int tmp_len = 0;
550
551         kprintf("\n======= Data Flash test function =========================================\n");
552         kprintf("\nThe string test is: %s\n\n", test_buf);
553
554         fd.open(&fd, NULL, 0);
555
556         /*  TEST 1 */
557
558         // Seek to addr 0
559         if (!fd.seek(&fd, 0, SEEK_SET))
560                 goto dataflash_test_end;
561
562         // Test flash write to address 0 (page 0)
563         tmp_len = fd->write(&fd, test_buf, len_tb)
564         if (len_tb != tmp_len)
565         {
566                 kprintf("Test 1: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
567                 goto dataflash_test_end;
568         }
569
570         // Seek to addr 0
571         if (fd.seek(&fd, 0, SEEK_SET) != 0)
572                 goto dataflash_test_end;
573         tmp_len = 0;
574
575         // Test flash read to address 0 (page 0)
576         tmp_len = fd->read(&fd, cmp_buf, len_tb);
577         if (len_tb != tmp_len)
578         {
579                 kprintf("Test 1: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
580                 goto dataflash_test_end;
581         }
582
583         // Compare if they are equal
584         if ((memcmp(cmp_buf,test_buf, len_tb) == 0)
585         {
586                 kprintf("Test 1: Readed test buf don't much!\n");
587                 goto dataflash_test_end;
588         }
589
590         /*  TEST 2 */
591
592         // Go to middle address memory.
593         if (!fd.seek(&fd, (((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) / 2), SEEK_CUR))
594                 goto dataflash_test_end;
595         tmp_len = 0;
596
597         // Test flash write at the middle of memory
598         tmp_len = fd->write(&fd, test_buf, len_tb);
599         if (len_tb != tmp_len)
600         {
601                 kprintf("Test 2: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
602                 goto dataflash_test_end;
603         }
604
605         // Go to middle address memory.
606         if (!fd.seek(&fd, (((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) / 2), SEEK_CUR))
607                 goto dataflash_test_end;
608         tmp_len = 0;
609
610         // Test flash read  at the middle of memory
611         tmp_len = fd->read(&fd, cmp_buf, len_tb);
612         if (len_tb != tmp_len)
613         {
614                 kprintf("Test 2: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
615                 goto dataflash_test_end;
616         }
617
618         // Compare if they are equal
619         if ((memcmp(cmp_buf,test_buf, len_tb) == 0)
620         {
621                 kprintf("Test 2: Readed test buf don't much!\n");
622                 goto dataflash_test_end;
623         }
624         /*  TEST 3 */
625
626         // Go to end of data flash.
627         if(!fd.seek(&fd, ((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) - len_tb, SEEK_END));
628                 goto dataflash_test_end;
629         tmp_len = 0;
630
631         // Test flash write at the end of memory
632         tmp_len = fd->write(&fd, test_buf, len_tb);
633         if (len_tb != tmp_len)
634         {
635                 kprintf("Test 3: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
636                 goto dataflash_test_end;
637         }
638
639         // Go to end of data flash.
640         if(!fd.seek(&fd, ((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) - len_tb, SEEK_END));
641                 goto dataflash_test_end;
642         tmp_len = 0
643
644         // Test flash read at the end of memory
645         tmp_len = fd->read(&fd, cmp_buf, len_tb);
646         if (len_tb != tmp_len)
647         {
648                 kprintf("Test 3: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
649                 goto dataflash_test_end;
650         }
651
652         // Compare if they are equal
653         if ((memcmp(cmp_buf,test_buf, len_tb) == 0)
654         {
655                 kprintf("Test 3: Readed test buf don't much!\n");
656                 goto dataflash_test_end;
657         }
658
659         kprintf("\n");
660
661         kprintf("\n====== Test end ===========================================================\n");
662         fd.close(&fd);
663         return true;
664
665 dataflash_test_end:
666         fd.close(&fd);
667         return false;
668
669 }
670