Contiki 3.x
xmem.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006, Swedish Institute of Computer Science
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 /**
32  * \file
33  * Device driver for the ST M25P80 40MHz 1Mbyte external memory.
34  * \author
35  * Björn Grönvall <bg@sics.se>
36  * Sumankumar Panchal <suman@ece.iisc.ernet.in>
37  *
38  *
39  * Data is written bit inverted (~-operator) to flash so that
40  * unwritten data will read as zeros (UNIX style).
41  */
42 
43 
44 #include "contiki.h"
45 #include <stdio.h>
46 #include <string.h>
47 
48 #include "dev/spi.h"
49 #include "dev/xmem.h"
50 #include "dev/watchdog.h"
51 
52 #if 0
53 #define PRINTF(...) printf(__VA_ARGS__)
54 #else
55 #define PRINTF(...) do {} while (0)
56 #endif
57 
58 #define SPI_FLASH_INS_WREN 0x06
59 #define SPI_FLASH_INS_WRDI 0x04
60 #define SPI_FLASH_INS_RDSR 0x05
61 #define SPI_FLASH_INS_WRSR 0x01
62 #define SPI_FLASH_INS_READ 0x03
63 #define SPI_FLASH_INS_FAST_READ 0x0b
64 #define SPI_FLASH_INS_PP 0x02
65 #define SPI_FLASH_INS_SE 0xd8
66 #define SPI_FLASH_INS_BE 0xc7
67 #define SPI_FLASH_INS_DP 0xb9
68 #define SPI_FLASH_INS_RES 0xab
69 /*---------------------------------------------------------------------------*/
70 static void
71 write_enable(void)
72 {
73  int s;
74 
75  s = splhigh();
76  SPI_FLASH_ENABLE();
77 
78  SPI_WRITE(SPI_FLASH_INS_WREN);
79 
80  SPI_FLASH_DISABLE();
81  splx(s);
82 }
83 /*---------------------------------------------------------------------------*/
84 static unsigned
85 read_status_register(void)
86 {
87  unsigned char u;
88 
89  int s;
90 
91  s = splhigh();
92  SPI_FLASH_ENABLE();
93 
94  SPI_WRITE(SPI_FLASH_INS_RDSR);
95 
96  SPI_FLUSH();
97  SPI_READ(u);
98 
99  SPI_FLASH_DISABLE();
100  splx(s);
101 
102  return u;
103 }
104 /*---------------------------------------------------------------------------*/
105 /*
106  * Wait for a write/erase operation to finish.
107  */
108 static unsigned
109 wait_ready(void)
110 {
111  unsigned u;
112  do {
113  u = read_status_register();
115  } while(u & 0x01); /* WIP=1, write in progress */
116  return u;
117 }
118 /*---------------------------------------------------------------------------*/
119 /*
120  * Erase 64k bytes of data. It takes about 1s before WIP goes low!
121  */
122 static void
123 erase_sector(unsigned long offset)
124 {
125  int s;
126 
127  wait_ready();
128  write_enable();
129 
130  s = splhigh();
131  SPI_FLASH_ENABLE();
132 
133  SPI_WRITE_FAST(SPI_FLASH_INS_SE);
134  SPI_WRITE_FAST(offset >> 16); /* MSB */
135  SPI_WRITE_FAST(offset >> 8);
136  SPI_WRITE_FAST(offset >> 0); /* LSB */
137  SPI_WAITFORTx_ENDED();
138 
139  SPI_FLASH_DISABLE();
140  splx(s);
141 }
142 /*---------------------------------------------------------------------------*/
143 /*
144  * Initialize external flash *and* SPI bus!
145  */
146 void
147 xmem_init(void)
148 {
149  int s;
150  spi_init();
151 
152 
153  P4DIR |= BIT0;
154 
155  /* Release from Deep Power-down */
156  s = splhigh();
157  SPI_FLASH_ENABLE();
158  SPI_WRITE_FAST(SPI_FLASH_INS_RES);
159  SPI_WAITFORTx_ENDED();
160  SPI_FLASH_DISABLE(); /* Unselect flash. */
161  splx(s);
162 
163  SPI_FLASH_UNHOLD();
164 }
165 /*---------------------------------------------------------------------------*/
166 int
167 xmem_pread(void *_p, int size, unsigned long offset)
168 {
169  unsigned char *p = _p;
170  const unsigned char *end = p + size;
171  int s;
172 
173  wait_ready();
174 
175  ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
176 
177  s = splhigh();
178  SPI_FLASH_ENABLE();
179 
180  SPI_WRITE_FAST(SPI_FLASH_INS_READ);
181  SPI_WRITE_FAST(offset >> 16); /* MSB */
182  SPI_WRITE_FAST(offset >> 8);
183  SPI_WRITE_FAST(offset >> 0); /* LSB */
184  SPI_WAITFORTx_ENDED();
185 
186  SPI_FLUSH();
187  for(; p < end; p++) {
188  unsigned char u;
189  SPI_READ(u);
190  *p = ~u;
191  }
192 
193  SPI_FLASH_DISABLE();
194  splx(s);
195 
196  ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
197 
198  return size;
199 }
200 /*---------------------------------------------------------------------------*/
201 static const unsigned char *
202 program_page(unsigned long offset, const unsigned char *p, int nbytes)
203 {
204  const unsigned char *end = p + nbytes;
205  int s;
206 
207  wait_ready();
208  write_enable();
209 
210  s = splhigh();
211  SPI_FLASH_ENABLE();
212 
213  SPI_WRITE_FAST(SPI_FLASH_INS_PP);
214  SPI_WRITE_FAST(offset >> 16); /* MSB */
215  SPI_WRITE_FAST(offset >> 8);
216  SPI_WRITE_FAST(offset >> 0); /* LSB */
217 
218  for(; p < end; p++) {
219  SPI_WRITE_FAST(~*p);
220  }
221  SPI_WAITFORTx_ENDED();
222 
223  SPI_FLASH_DISABLE();
224  splx(s);
225 
226  return p;
227 }
228 /*---------------------------------------------------------------------------*/
229 int
230 xmem_pwrite(const void *_buf, int size, unsigned long addr)
231 {
232  const unsigned char *p = _buf;
233  const unsigned long end = addr + size;
234  unsigned long i, next_page;
235 
236  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
237 
238  for(i = addr; i < end;) {
239  next_page = (i | 0xff) + 1;
240  if(next_page > end) {
241  next_page = end;
242  }
243  p = program_page(i, p, next_page - i);
244  i = next_page;
245  }
246 
247  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
248 
249  return size;
250 }
251 /*---------------------------------------------------------------------------*/
252 int
253 xmem_erase(long size, unsigned long addr)
254 {
255  unsigned long end = addr + size;
256 
257  if(size % XMEM_ERASE_UNIT_SIZE != 0) {
258  PRINTF("xmem_erase: bad size\n");
259  return -1;
260  }
261 
262  if(addr % XMEM_ERASE_UNIT_SIZE != 0) {
263  PRINTF("xmem_erase: bad offset\n");
264  return -1;
265  }
266 
267  for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
268  erase_sector(addr);
269  }
270 
271  return size;
272 }
273 /*---------------------------------------------------------------------------*/
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
static bool wait_ready(void)
Wait till previous erase/program operation completes.
Definition: ext-flash.c:114
static bool write_enable(void)
Enable write.
Definition: ext-flash.c:255
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64