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