Contiki-Inga 3.x
at45db.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, TU Braunschweig.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /**
31  * \file
32  * Atmel Flash EEPROM AT45DB interface implementation
33  * \author
34  * Ulf Kulau <kulau@ibr.cs.tu-bs.de>
35  */
36 
37 /**
38  * \addtogroup inga_device_driver
39  * @{
40  */
41 
42 /**
43  * \addtogroup AT45DB_interface
44  * @{
45  */
46 
47 #include "at45db.h"
48 
49 #define DEBUG 0
50 
51 #if DEBUG
52 #include <avr/pgmspace.h>
53 #include <stdio.h>
54 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
55 #else
56 #define PRINTF(...)
57 #endif
58 
59 /*!
60  * Buffer manager allows it to improve write times, by switching
61  * the dual buffer and parallelize flash write operations. (e.g. Write
62  * to buffer 1 while buffer 2 is transfered to flash EEPROM)
63  */
64 static bufmgr_t buffer_mgr;
65 static uint8_t initialized = 0;
66 
67 int8_t
68 at45db_init(void) {
69  uint8_t i = 0, id = 0;
70  /*setup buffer manager to perform write and read operations*/
71  buffer_mgr.active_buffer = 0;
72  buffer_mgr.buffer_addr[0] = AT45DB_BUFFER_1;
73  buffer_mgr.buffer_addr[1] = AT45DB_BUFFER_2;
74  buffer_mgr.buf_to_page_addr[0] = AT45DB_BUF_1_TO_PAGE;
75  buffer_mgr.buf_to_page_addr[1] = AT45DB_BUF_2_TO_PAGE;
76  buffer_mgr.page_program[0] = AT45DB_PAGE_PROGRAM_1;
77  buffer_mgr.page_program[1] = AT45DB_PAGE_PROGRAM_2;
78 
80  /*init mspi in mode3, at chip select pin 3 and max baud rate*/
82 
83  while (id != 0x1F) {
85  mspi_transceive(0x9F);
86  id = mspi_transceive(0x00);
88  _delay_ms(10);
89  if (i++ > 10) {
90  PRINTF("at45db.c: Initialization failed\n");
91  initialized = 0;
92  return -1;
93  }
94  }
95  initialized = 1;
96  return 0;
97 
98 }
99 /*----------------------------------------------------------------------------*/
100 void
102  if (!initialized) return;
103  /*chip erase command consists of 4 byte*/
104  uint8_t cmd[4] = {0xC7, 0x94, 0x80, 0x9A};
105  at45db_write_cmd(&cmd[0]);
107  /*wait until AT45DB161 is ready again*/
111 }
112 /*----------------------------------------------------------------------------*/
113 void
114 at45db_erase_block(uint16_t addr) {
115  if (!initialized) return;
116  /*block erase command consists of 4 byte*/
117  uint8_t cmd[4] = {AT45DB_BLOCK_ERASE, (uint8_t) (addr >> 3),
118  (uint8_t) (addr << 5), 0x00};
119  at45db_write_cmd(&cmd[0]);
121  /*wait until AT45DB161 is ready again*/
125 }
126 /*----------------------------------------------------------------------------*/
127 void
128 at45db_erase_page(uint16_t addr) {
129  if (!initialized) return;
130  /*block erase command consists of 4 byte*/
131  uint8_t cmd[4] = {AT45DB_PAGE_ERASE, (uint8_t) (addr >> 6),
132  (uint8_t) (addr << 2), 0x00};
133  at45db_write_cmd(&cmd[0]);
135  /*wait until AT45DB161 is ready again*/
139 }
140 /*----------------------------------------------------------------------------*/
141 void
142 at45db_write_buffer(uint16_t addr, uint8_t *buffer, uint16_t bytes) {
143  uint16_t i;
144  if (!initialized) return;
145  /*block erase command consists of 4 byte*/
146  uint8_t cmd[4] = {buffer_mgr.buffer_addr[buffer_mgr.active_buffer], 0x00,
147  (uint8_t) (addr >> 8), (uint8_t) (addr)};
148 
149  at45db_write_cmd(&cmd[0]);
150 
151  for (i = 0; i < bytes; i++) {
152  mspi_transceive(~(*buffer++));
153  }
154 
156 }
157 /*----------------------------------------------------------------------------*/
158 void
159 at45db_buffer_to_page(uint16_t addr) {
160  if (!initialized) return;
161  /*wait until AT45DB161 is ready again*/
163  /*write active buffer to page command consists of 4 byte*/
164  uint8_t cmd[4] = {buffer_mgr.buf_to_page_addr[buffer_mgr.active_buffer],
165  (uint8_t) (addr >> 6), (uint8_t) (addr << 2), 0x00};
166  at45db_write_cmd(&cmd[0]);
168  /* switch active buffer to allow the other one to be written,
169  * while these buffer is copied to the Flash EEPROM page*/
170  buffer_mgr.active_buffer ^= 1;
171 }
172 /*----------------------------------------------------------------------------*/
173 void
174 at45db_write_page(uint16_t p_addr, uint16_t b_addr, uint8_t *buffer, uint16_t bytes) {
175  uint16_t i;
176  if (!initialized) return;
177  /*block erase command consists of 4 byte*/
178  uint8_t cmd[4] = {buffer_mgr.page_program[buffer_mgr.active_buffer],
179  (uint8_t) (p_addr >> 6),
180  ((uint8_t) (p_addr << 2) & 0xFC) | ((uint8_t) (b_addr >> 8) & 0x3),
181  (uint8_t) (b_addr)};
182  at45db_write_cmd(&cmd[0]);
183 
184  for (i = 0; i < bytes; i++) {
185  mspi_transceive(~(*buffer++));
186  }
187 
189 
190  /* switch active buffer to allow the other one to be written,
191  * while these buffer is copied to the Flash EEPROM page*/
192  buffer_mgr.active_buffer ^= 1;
193 }
194 /*----------------------------------------------------------------------------*/
195 void
196 at45db_read_page_buffered(uint16_t p_addr, uint16_t b_addr,
197  uint8_t *buffer, uint16_t bytes) {
198  if (!initialized) return;
199  /* wait until AT45DB161 is ready again */
201  at45db_page_to_buf(p_addr);
202  at45db_read_buffer(b_addr, buffer, bytes);
203 }
204 /*----------------------------------------------------------------------------*/
205 void
206 at45db_read_page_bypassed(uint16_t p_addr, uint16_t b_addr,
207  uint8_t *buffer, uint16_t bytes) {
208  uint16_t i;
209  if (!initialized) return;
210  /* wait until AT45DB161 is ready again */
212  /* read bytes directly from page command consists of 4 cmd bytes and
213  * 4 don't care */
214  uint8_t cmd[4] = {AT45DB_PAGE_READ,
215  (uint8_t) (p_addr >> 6),
216  (((uint8_t) (p_addr << 2)) & 0xFC) | ((uint8_t) (b_addr >> 8)),
217  (uint8_t) (b_addr)};
218  at45db_write_cmd(&cmd[0]);
219 
220  for (i = 0; i < 4; i++) {
221  mspi_transceive(0x00);
222  }
223  /*now the data bytes can be received*/
224  for (i = 0; i < bytes; i++) {
225  *buffer++ = ~mspi_transceive(MSPI_DUMMY_BYTE);
226  }
228 }
229 /*----------------------------------------------------------------------------*/
230 void
231 at45db_page_to_buf(uint16_t addr) {
232 
233  if (!initialized) return;
234  /* write active buffer to page command consists of 4 byte */
235  uint8_t cmd[4] = {AT45DB_PAGE_TO_BUF,
236  (uint8_t) (addr >> 6),
237  (uint8_t) (addr << 2),
238  0x00};
239  at45db_write_cmd(&cmd[0]);
241  /* switch active buffer to allow the other one to be written,
242  * while these buffer is copied to the Flash EEPROM page*/
243  //buffer_mgr.active_buffer ^= 1;
245 
246 }
247 /*----------------------------------------------------------------------------*/
248 void
249 at45db_read_buffer(uint16_t b_addr, uint8_t *buffer, uint16_t bytes) {
250  uint16_t i;
251  if (!initialized) return;
252  uint8_t cmd[4] = {AT45DB_READ_BUFFER, 0x00, (uint8_t) (b_addr >> 8),
253  (uint8_t) (b_addr)};
255  at45db_write_cmd(&cmd[0]);
256  mspi_transceive(0x00);
257 
258  for (i = 0; i < bytes; i++) {
259  *buffer++ = ~mspi_transceive(0x00);
260  }
262 }
263 /*----------------------------------------------------------------------------*/
264 void
265 at45db_write_cmd(uint8_t *cmd) {
266  uint8_t i;
267  if (!initialized) return;
269  for (i = 0; i < 4; i++) {
270  mspi_transceive(*cmd++);
271  }
272 }
273 /*----------------------------------------------------------------------------*/
274 void
276  uint16_t i = 0;
277  if (!initialized) return;
280  while ((mspi_transceive(MSPI_DUMMY_BYTE) >> 7) != 0x01) {
281  _delay_ms(1);
282  if (i++ > 500) {
283  PRINTF("at45db.c: at45db_busy_wait timeout\n");
284  return;
285  }
286  }
288 }