7dda5db06584bea0b74507fb3ebf32923e56baef
[bertos.git] / drv / dflash.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 AT45DB081D Flash memory.
34  *
35  *
36  * \version $Id: dflash.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/dflash.h>
50
51 #include "hw_spi.h"
52
53 /**
54  * Send a generic command to data flash memory.
55  * This function send only 4 byte, for opcode, page address and
56  * byte address.
57  */
58 static void send_cmd(dflashAddr_t page_addr, dflashAddr_t byte_addr, DFlashOpcode opcode)
59 {
60
61         /*
62          * Make sure to toggle CS signal in order,
63          * and reset dflash command decoder.
64          *
65          * Note:
66          * #define CS_TOGGLE() \
67          *              CS_DISABLE(); \
68          *              CS_ENABLE(); \
69          */
70         CS_TOGGLE();
71
72
73         /*
74          * To send one command to data flash memory, we send 4 byte.
75          * First byte is opcode command, second and third byte are
76          * page address, in last byte we write a byte page address.
77          * (see datasheet for more detail).
78          *
79          * \note Generaly a defaul memory page size is more than 256 byte.
80          *  In this case we need for addressing a byte in one page more than
81          *  8 bit, so we put in fourth byte low part of address byte, and
82          *  hight part of address byte in third byte togheter low par of page
83          *  address.
84          *
85          * \{
86          */
87
88         /*
89          * Send opcode.
90          */
91         spi_sendRecv(opcode);
92
93         /*
94          *  Send page address.
95          * \{
96          */
97         spi_sendRecv((uint8_t)(page_addr >> (16 - DFLASH_PAGE_ADDRESS_BIT)));
98         spi_sendRecv((uint8_t)((page_addr << (DFLASH_PAGE_ADDRESS_BIT - 8)) + (byte_addr >> 8)));
99         /*\}*/
100
101         /*
102          * Send byte page address.
103          */
104         spi_sendRecv((uint8_t)byte_addr);
105
106         /* \} */
107
108 }
109
110 /**
111  * Reset dataflash memory function.
112  *
113  * This function reset data flash memory
114  * with one pulse reset long about 10usec.
115  *
116  */
117 static void dflash_reset(void)
118 {
119         CS_ENABLE();
120         RESET_ENABLE();
121         timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
122         CS_DISABLE();
123         RESET_DISABLE();
124         timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
125 }
126
127 /**
128  * dflash init function.
129  * This function initialize a micro pin and
130  * SPI driver, and test if data flash memory
131  * density is the same wich define in dflash.h.
132  */
133 MOD_DEFINE(dflash);
134 static bool dflash_pin_init(void)
135 {
136         uint8_t stat;
137
138         MOD_CHECK(spi);
139
140         RESET_DISABLE();
141         WRITE_ENABLE(); //pilot wp pin.
142
143         RESET_OUT();
144         WP_OUT();
145
146         dflash_reset();
147
148         stat = dflash_stat();
149
150         MOD_INIT(dflash);
151
152         /*
153          * 2,3,4,5 bit of 1 byte status register
154          * indicate a device density of dflash memory
155          * (see datasheet for more detail.)
156          */
157         GET_ID_DESITY_DEVICE(stat);
158
159         if(stat == DFLASH_ID_DEVICE_DENSITY)
160                 return true;
161         else
162                 return false;
163
164 }
165
166
167 /**
168  * Read status register of dataflah memory.
169  *
170  */
171 static uint8_t dflash_stat(void)
172 {
173         uint8_t stat;
174
175         /*
176          * Make sure to toggle CS signal in order,
177          * and reset dflash command decoder.
178          * \{
179          */
180         CS_TOGGLE();
181
182         stat = spi_sendRecv(DFO_READ_STATUS);
183         stat = spi_sendRecv(0x00);
184
185         return stat;
186 }
187
188
189 /**
190  * Send one command to data flash memory, and
191  * return status register value.
192  *
193  */
194 static uint8_t dflash_cmd(dflashAddr_t page_addr, dflashAddr_t byte_addr, DFlashOpcode opcode)
195 {
196
197         send_cmd(page_addr, byte_addr, opcode);
198
199         CS_DISABLE();
200         CS_ENABLE();
201
202         /*
203          * We chech data flash memory state, and wait until busy-flag
204          * is hight.
205          */
206         while(!(dflash_stat() & BUSY_BIT));
207
208         return (dflash_stat());
209
210 }
211
212 /**
213  * Read one byte from main data flash memory or buffer data
214  * flash memory.
215  */
216 static uint8_t dflash_read_byte(dflashAddr_t page_addr, dflashAddr_t byte_addr, DFlashOpcode opcode)
217 {
218         uint8_t data;
219
220         send_cmd(page_addr, byte_addr, opcode);
221
222 #if CONFIG_DATA_FLASH == AT45DB041B
223         if(opcode == DFO_READ_FLASH_MEM_BYTE)
224         {
225                 /*
226                  * Send 24 don't care bit.
227                  * \{
228                  */
229                 spi_sendRecv(0x00);
230                 spi_sendRecv(0x00);
231                 spi_sendRecv(0x00);
232                 /* \} */
233
234         }
235 #endif
236
237         spi_sendRecv(0x00);         //Send 8 don't care bit.
238         data = spi_sendRecv(0x00);  //Read byte.
239         CS_DISABLE();
240
241         return data;
242 }
243
244 /**
245  * Read \a len bytes from main data flash memory or buffer data
246  * flash memory, and put it in \a *block.
247  */
248 static void dflash_read_block(dflashAddr_t page_addr, dflashAddr_t byte_addr, DFlashOpcode opcode, uint8_t *block, dflashSize_t len)
249 {
250
251         send_cmd(page_addr, byte_addr, opcode);
252
253         if(opcode == DFO_READ_FLASH_MEM_BYTE)
254         {
255                 /*
256                  * Send 24 don't care bit.
257                  * \{
258                  */
259                 spi_sendRecv(0x00);
260                 spi_sendRecv(0x00);
261                 spi_sendRecv(0x00);
262                 /* \} */
263         }
264
265         spi_sendRecv(0x00);   //Send 8 don't care bit.
266         spi_read(block, len); //Read len bytes ad put in block buffer.
267
268
269         CS_DISABLE();
270
271 }
272
273
274 /**
275  * Write \a len bytes in buffer buffer data flash memory.
276  *
277  * \note Isn't possible to write bytes directly in main memory data
278  * flash. To perform write in main memory you must before write in buffer
279  * data flash memory, an then send command to write page in main memory.
280  */
281 static void dflash_write_block(dflashAddr_t byte_addr, DFlashOpcode opcode, uint8_t *block, dflashSize_t len)
282 {
283
284         send_cmd(0x00, byte_addr, opcode);
285
286         spi_write(block, len); //Write len bytes.
287
288         CS_DISABLE();
289
290 }
291
292 /* Kfile interface section */
293
294 /**
295  * Open data flash file \a fd
296  * \a name and \a mode are unused, cause flash memory is
297  * threated like one file.
298  */
299 static bool dflash_open(struct _KFile *fd, UNUSED_ARG(const char *, name), UNUSED_ARG(int, mode))
300 {
301 }
302
303 /**
304  * Close file \a fd
305  */
306 static bool dflash_close(UNUSED_ARG(struct _KFile *,fd))
307 {
308 }
309
310 /**
311  * Move \a fd file seek position of \a offset bytes
312  * from current position.
313  */
314 static int32_t dflash_seek(struct _KFile *fd, int32_t offset, KSeekMode whence)
315 {
316 }
317
318 /**
319  * Read from file \a fd \a size bytes and put it in buffer \a buf
320  * \return the number of bytes read.
321  */
322 static size_t dflash_read(struct _KFile *fd, void *buf, size_t size)
323 {
324 }
325
326 /**
327  * Init data flash memory interface.
328  */
329 void dflash_init(struct _KFile *fd)
330 {
331         // Set up data flash programming functions.
332         fd->open = dflash_open;
333         fd->close = dflash_close;
334         fd->read = dflash_read;
335         fd->write = dflash_write;
336         fd->seek = dflash_seek;
337
338         // Init data flash memory and micro pin.
339         ASSERT(dflash_pin_init());
340 }