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  *
37  * Data is written bit inverted (~-operator) to flash so that
38  * unwritten data will read as zeros (UNIX style).
39  */
40 
41 #include "contiki.h"
42 #include <string.h>
43 
44 #include "dev/spi.h"
45 #include "dev/xmem.h"
46 #include "dev/watchdog.h"
47 
48 #if 0
49 #include <stdio.h>
50 #define PRINTF(...) printf(__VA_ARGS__)
51 #else
52 #define PRINTF(...) do {} while (0)
53 #endif
54 
55 #define SPI_FLASH_INS_WREN 0x06
56 #define SPI_FLASH_INS_WRDI 0x04
57 #define SPI_FLASH_INS_RDSR 0x05
58 #define SPI_FLASH_INS_WRSR 0x01
59 #define SPI_FLASH_INS_READ 0x03
60 #define SPI_FLASH_INS_FAST_READ 0x0b
61 #define SPI_FLASH_INS_PP 0x02
62 #define SPI_FLASH_INS_SE 0xd8
63 #define SPI_FLASH_INS_BE 0xc7
64 #define SPI_FLASH_INS_DP 0xb9
65 #define SPI_FLASH_INS_RES 0xab
66 /*---------------------------------------------------------------------------*/
67 static void
68 write_enable(void)
69 {
70  int s;
71 
72  s = splhigh();
73  SPI_FLASH_ENABLE();
74 
75  //FASTSPI_TX(SPI_FLASH_INS_WREN);
76  //SPI_WAITFORTx_ENDED();
77 
78  SPI_FLASH_DISABLE();
79  splx(s);
80 }
81 /*---------------------------------------------------------------------------*/
82 static unsigned
83 read_status_register(void)
84 {
85  unsigned char u;
86 
87  int s;
88 
89  s = splhigh();
90  SPI_FLASH_ENABLE();
91 
92  //FASTSPI_TX(SPI_FLASH_INS_RDSR);
93  //SPI_WAITFORTx_ENDED();
94 
95  //FASTSPI_CLEAR_RX();
96  //FASTSPI_RX(u);
97 
98  SPI_FLASH_DISABLE();
99  splx(s);
100 
101  return u;
102 }
103 /*---------------------------------------------------------------------------*/
104 /*
105  * Wait for a write/erase operation to finish.
106  */
107 static unsigned
108 wait_ready(void)
109 {
110  unsigned u;
111  do {
112  u = read_status_register();
113  } while(u & 0x01); /* WIP=1, write in progress */
114  return u;
115 }
116 /*---------------------------------------------------------------------------*/
117 /*
118  * Erase 64k bytes of data. It takes about 1s before WIP goes low!
119  */
120 static void
121 erase_sector(unsigned long offset)
122 {
123  int s;
124  wait_ready();
125 
126  write_enable();
127 
128  s = splhigh();
129  SPI_FLASH_ENABLE();
130 
131  //FASTSPI_TX(SPI_FLASH_INS_SE);
132  //FASTSPI_TX(offset >> 16); /* MSB */
133  //FASTSPI_TX(offset >> 8);
134  //FASTSPI_TX(offset >> 0); /* LSB */
135  //SPI_WAITFORTx_ENDED();
136 
137  SPI_FLASH_DISABLE();
138  splx(s);
139 }
140 /*---------------------------------------------------------------------------*/
141 /*
142  * Initialize external flash *and* SPI bus!
143  */
144 void
145 xmem_init(void)
146 {
147  spi_init();
148 
149  P4DIR |= BV(FLASH_CS) | BV(FLASH_HOLD) | BV(FLASH_PWR);
150  P4OUT |= BV(FLASH_PWR); /* P4.3 Output, turn on power! */
151 
152  SPI_FLASH_DISABLE(); /* Unselect flash. */
153  SPI_FLASH_UNHOLD();
154 }
155 /*---------------------------------------------------------------------------*/
156 int
157 xmem_pread(void *_p, int size, unsigned long offset)
158 {
159  unsigned char *p = _p;
160  const unsigned char *end = p + size;
161  int s;
162  wait_ready();
163 
164  ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
165 
166  s = splhigh();
167  SPI_FLASH_ENABLE();
168 
169  //FASTSPI_TX(SPI_FLASH_INS_READ);
170  //FASTSPI_TX(offset >> 16); /* MSB */
171  //FASTSPI_TX(offset >> 8);
172  //FASTSPI_TX(offset >> 0); /* LSB */
173  //SPI_WAITFORTx_ENDED();
174 
175  //FASTSPI_CLEAR_RX();
176  for(; p < end; p++) {
177  unsigned char u;
178  //FASTSPI_RX(u);
179  *p = ~u;
180  }
181 
182  SPI_FLASH_DISABLE();
183  splx(s);
184 
185  ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
186 
187  return size;
188 }
189 /*---------------------------------------------------------------------------*/
190 static const char *
191 program_page(unsigned long offset, const unsigned char *p, int nbytes)
192 {
193  const unsigned char *end = p + nbytes;
194  int s;
195 
196  wait_ready();
197 
198  write_enable();
199 
200  s = splhigh();
201  SPI_FLASH_ENABLE();
202 
203  // FASTSPI_TX(SPI_FLASH_INS_PP);
204  //FASTSPI_TX(offset >> 16); /* MSB */
205  //FASTSPI_TX(offset >> 8);
206  //FASTSPI_TX(offset >> 0); /* LSB */
207 
208  for(; p < end; p++) {
209  //FASTSPI_TX(~*p);
210  }
211  //SPI_WAITFORTx_ENDED();
212 
213  SPI_FLASH_DISABLE();
214  splx(s);
215 
216  return p;
217 }
218 /*---------------------------------------------------------------------------*/
219 int
220 xmem_pwrite(const void *_buf, int size, unsigned long addr)
221 {
222  const unsigned char *p = _buf;
223  const unsigned long end = addr + size;
224  unsigned long i, next_page;
225 
226  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
227 
228  for(i = addr; i < end;) {
229  next_page = (i | 0xff) + 1;
230  if(next_page > end) {
231  next_page = end;
232  }
233  p = program_page(i, p, next_page - i);
234  i = next_page;
235  }
236 
237  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
238 
239  return size;
240 }
241 /*---------------------------------------------------------------------------*/
242 int
243 xmem_erase(long size, unsigned long addr)
244 {
245  unsigned long end = addr + size;
246 
247  if(size % XMEM_ERASE_UNIT_SIZE != 0) {
248  PRINTF("xmem_erase: bad size\n");
249  return -1;
250  }
251 
252  if(addr % XMEM_ERASE_UNIT_SIZE != 0) {
253  PRINTF("xmem_erase: bad offset\n");
254  return -1;
255  }
256 
257  watchdog_stop();
258 
259  for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
260  erase_sector(addr);
261  }
262 
263  watchdog_start();
264 
265  return size;
266 }
267 /*---------------------------------------------------------------------------*/
void watchdog_start(void)
Starts the WDT in watchdog mode if enabled by user configuration, maximum interval.
Definition: watchdog.c:49
void watchdog_stop(void)
In watchdog mode, the WDT can not be stopped.
Definition: watchdog.c:58
Basic SPI macros
void spi_init(void)
Initialize the SPI bus.
Definition: spi.c:48