Contiki-NG
Loading...
Searching...
No Matches
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
42#include "contiki.h"
43#include <stdio.h>
44#include <string.h>
45
46#include "dev/spi-legacy.h"
47#include "dev/xmem.h"
48#include "dev/watchdog.h"
49
50#if 0
51#define PRINTF(...) printf(__VA_ARGS__)
52#else
53#define PRINTF(...) do {} while (0)
54#endif
55
56#define SPI_FLASH_INS_WREN 0x06
57#define SPI_FLASH_INS_WRDI 0x04
58#define SPI_FLASH_INS_RDSR 0x05
59#define SPI_FLASH_INS_WRSR 0x01
60#define SPI_FLASH_INS_READ 0x03
61#define SPI_FLASH_INS_FAST_READ 0x0b
62#define SPI_FLASH_INS_PP 0x02
63#define SPI_FLASH_INS_SE 0xd8
64#define SPI_FLASH_INS_BE 0xc7
65#define SPI_FLASH_INS_DP 0xb9
66#define SPI_FLASH_INS_RES 0xab
67/*---------------------------------------------------------------------------*/
68static void
69write_enable(void)
70{
71 int s;
72
73 s = splhigh();
74 SPI_FLASH_ENABLE();
75
76 SPI_WRITE(SPI_FLASH_INS_WREN);
77
78 SPI_FLASH_DISABLE();
79 splx(s);
80}
81/*---------------------------------------------------------------------------*/
82static unsigned
83read_status_register(void)
84{
85 unsigned char u;
86
87 int s;
88
89 s = splhigh();
90 SPI_FLASH_ENABLE();
91
92 SPI_WRITE(SPI_FLASH_INS_RDSR);
93
94 SPI_FLUSH();
95 SPI_READ(u);
96
97 SPI_FLASH_DISABLE();
98 splx(s);
99
100 return u;
101}
102/*---------------------------------------------------------------------------*/
103/*
104 * Wait for a write/erase operation to finish.
105 */
106static unsigned
107wait_ready(void)
108{
109 unsigned u;
110 do {
111 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 */
120static void
121erase_sector(unsigned long offset)
122{
123 int s;
124
125 wait_ready();
126 write_enable();
127
128 s = splhigh();
129 SPI_FLASH_ENABLE();
130
131 SPI_WRITE_FAST(SPI_FLASH_INS_SE);
132 SPI_WRITE_FAST(offset >> 16); /* MSB */
133 SPI_WRITE_FAST(offset >> 8);
134 SPI_WRITE_FAST(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 */
144void
146{
147 int s;
148 spi_init();
149
150 P4DIR |= BV(FLASH_CS) | BV(FLASH_HOLD) | BV(FLASH_PWR);
151 P4OUT |= BV(FLASH_PWR); /* P4.3 Output, turn on power! */
152
153 /* Release from Deep Power-down */
154 s = splhigh();
155 SPI_FLASH_ENABLE();
156 SPI_WRITE_FAST(SPI_FLASH_INS_RES);
157 SPI_WAITFORTx_ENDED();
158 SPI_FLASH_DISABLE(); /* Unselect flash. */
159 splx(s);
160
161 SPI_FLASH_UNHOLD();
162}
163/*---------------------------------------------------------------------------*/
164int
165xmem_pread(void *_p, int size, unsigned long offset)
166{
167 unsigned char *p = _p;
168 const unsigned char *end = p + size;
169 int s;
170
171 wait_ready();
172
173 s = splhigh();
174 SPI_FLASH_ENABLE();
175
176 SPI_WRITE_FAST(SPI_FLASH_INS_READ);
177 SPI_WRITE_FAST(offset >> 16); /* MSB */
178 SPI_WRITE_FAST(offset >> 8);
179 SPI_WRITE_FAST(offset >> 0); /* LSB */
180 SPI_WAITFORTx_ENDED();
181
182 SPI_FLUSH();
183 for(; p < end; p++) {
184 unsigned char u;
185 SPI_READ(u);
186 *p = ~u;
187 }
188
189 SPI_FLASH_DISABLE();
190 splx(s);
191
192 return size;
193}
194/*---------------------------------------------------------------------------*/
195static const unsigned char *
196program_page(unsigned long offset, const unsigned char *p, int nbytes)
197{
198 const unsigned char *end = p + nbytes;
199 int s;
200
201 wait_ready();
202 write_enable();
203
204 s = splhigh();
205 SPI_FLASH_ENABLE();
206
207 SPI_WRITE_FAST(SPI_FLASH_INS_PP);
208 SPI_WRITE_FAST(offset >> 16); /* MSB */
209 SPI_WRITE_FAST(offset >> 8);
210 SPI_WRITE_FAST(offset >> 0); /* LSB */
211
212 for(; p < end; p++) {
213 SPI_WRITE_FAST(~*p);
214 }
215 SPI_WAITFORTx_ENDED();
216
217 SPI_FLASH_DISABLE();
218 splx(s);
219
220 return p;
221}
222/*---------------------------------------------------------------------------*/
223int
224xmem_pwrite(const void *_buf, int size, unsigned long addr)
225{
226 const unsigned char *p = _buf;
227 const unsigned long end = addr + size;
228 unsigned long i, next_page;
229
230 for(i = addr; i < end;) {
231 next_page = (i | 0xff) + 1;
232 if(next_page > end) {
233 next_page = end;
234 }
235 p = program_page(i, p, next_page - i);
236 i = next_page;
237 }
238
239 return size;
240}
241/*---------------------------------------------------------------------------*/
242int
243xmem_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 for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
258 erase_sector(addr);
259 }
260
261 return size;
262}
263/*---------------------------------------------------------------------------*/
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition watchdog.c:85
void xmem_init(void)
Initialize the external memory.
Definition xmem.c:59
int xmem_erase(long size, unsigned long addr)
Erase a sector in the flash memory.
Definition xmem.c:128
int xmem_pwrite(const void *_buf, int size, unsigned long addr)
Definition xmem.c:94
int xmem_pread(void *_p, int size, unsigned long addr)
Read a number of bytes from an offset in the external memory.
Definition xmem.c:64
Basic SPI macros.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107
Header file to the external flash memory (XMem) API.