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 M25P16 40MHz 1Mbyte external memory.
34  * \author
35  * Björn Grönvall <bg@sics.se>
36  * Enric M. Calvo <ecalvo@zolertia.com>
37  *
38  * Data is written bit inverted (~-operator) to flash so that
39  * unwritten data will read as zeros (UNIX style).
40  */
41 
42 #include <stdio.h>
43 #include <string.h>
44 #include "spi-arch.h"
45 #include "contiki.h"
46 #include "board.h"
47 #include "cfs-coffee-arch.h"
48 #include "cpu.h"
49 #include "dev/ssi.h"
50 #include "dev/xmem.h"
51 #include "dev/watchdog.h"
52 
53 #if 1
54 #define PRINTF(...) printf(__VA_ARGS__)
55 #else
56 #define PRINTF(...) do {} while (0)
57 #endif
58 
59 // Macros used provided by the MSP430 that aren't provided for the CC2538
60 /* Write one character to SPI */
61 #define SPI_WRITE(data) \
62  do { \
63  SPIX_WAITFORTxREADY(FLASH_SPI_INSTANCE); \
64  SPIX_BUF(FLASH_SPI_INSTANCE) = data; \
65  SPIX_WAITFOREOTx(FLASH_SPI_INSTANCE); \
66  } while(0)
67 
68 /* Write one character to SPI - will not wait for end
69  useful for multiple writes with wait after final */
70 #define SPI_WRITE_FAST(data) \
71  do { \
72  SPIX_WAITFORTxREADY(FLASH_SPI_INSTANCE); \
73  SPIX_BUF(FLASH_SPI_INSTANCE) = data; \
74  } while(0)
75 
76 /* Read one character from SPI */
77 #define SPI_READ(data) \
78  do { \
79  SPIX_BUF(FLASH_SPI_INSTANCE) = 0; \
80  SPIX_WAITFOREORx(FLASH_SPI_INSTANCE); \
81  data = SPIX_BUF(FLASH_SPI_INSTANCE); \
82  } while(0)
83 
84 /* Flush the SPI read register */
85 #define SPI_FLUSH() SPIX_FLUSH(FLASH_SPI_INSTANCE)
86 
87 #define SPI_FLASH_ENABLE() SPIX_CS_CLR(FLASH_CSN_PORT, FLASH_CSN_PIN)
88 #define SPI_FLASH_DISABLE() SPIX_CS_SET(FLASH_CSN_PORT, FLASH_CSN_PIN)
89 
90 #define SPI_WAITFORTx_ENDED() SPIX_WAITFOREOTx(FLASH_SPI_INSTANCE)
91 
92 #define SPI_FLASH_INS_WREN 0x06
93 #define SPI_FLASH_INS_WRDI 0x04
94 #define SPI_FLASH_INS_RDSR 0x05
95 #define SPI_FLASH_INS_WRSR 0x01
96 #define SPI_FLASH_INS_READ 0x03
97 #define SPI_FLASH_INS_FAST_READ 0x0b
98 #define SPI_FLASH_INS_PP 0x02
99 #define SPI_FLASH_INS_SE 0xd8
100 #define SPI_FLASH_INS_BE 0xc7
101 #define SPI_FLASH_INS_DP 0xb9
102 #define SPI_FLASH_INS_RES 0xab
103 /*---------------------------------------------------------------------------*/
104 static void
105 write_enable(void)
106 {
108  SPI_FLASH_ENABLE();
109 
110  SPI_WRITE(SPI_FLASH_INS_WREN);
111 
112  SPI_FLASH_DISABLE();
114 }
115 /*---------------------------------------------------------------------------*/
116 static unsigned
117 read_status_register(void)
118 {
119  unsigned char u;
120 
122  SPI_FLASH_ENABLE();
123 
124 
125  SPI_WRITE(SPI_FLASH_INS_RDSR);
126 
127  SPI_FLUSH();
128  SPI_READ(u);
129 
130  SPI_FLASH_DISABLE();
132 
133  return u;
134 }
135 /*---------------------------------------------------------------------------*/
136 /*
137  * Wait for a write/erase operation to finish.
138  */
139 static unsigned
140 wait_ready(void)
141 {
142  unsigned u;
143  do {
144  u = read_status_register();
146  } while(u & 0x01); /* WIP=1, write in progress */
147  return u;
148 }
149 /*---------------------------------------------------------------------------*/
150 /*
151  * Erase 64k bytes of data. It takes about 1s before WIP goes low!
152  */
153 static void
154 erase_sector(unsigned long offset)
155 {
156  wait_ready();
157 
158  write_enable();
159 
161  SPI_FLASH_ENABLE();
162 
163  SPI_WRITE_FAST(SPI_FLASH_INS_SE);
164  SPI_WRITE_FAST(offset >> 16); /* MSB */
165  SPI_WRITE_FAST(offset >> 8);
166  SPI_WRITE_FAST(offset >> 0); /* LSB */
167  SPI_WAITFORTx_ENDED();
168 
169  SPI_FLASH_DISABLE();
170 
171  SPI_FLUSH(); //(void)SPI_RXBUF; /* Dummy read of SPI RX Buffer to ensure that there is no stray data. */
172 
174 }
175 /*---------------------------------------------------------------------------*/
176 /*
177  * Initialize external flash *and* SPI bus!
178  */
179 void
180 xmem_init(void)
181 {
182  spix_cs_init(FLASH_CSN_PORT, FLASH_CSN_PIN);
183  spix_init(FLASH_SPI_INSTANCE);
184 
185  SPI_FLASH_DISABLE(); /* Unselect flash. */
186 }
187 /*---------------------------------------------------------------------------*/
188 int
189 xmem_pread(void *_p, int size, unsigned long offset)
190 {
191  unsigned char *p = _p;
192  const unsigned char *end = p + size;
193 
194  wait_ready();
195 
196  ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
197 
199  SPI_FLASH_ENABLE();
200 
201  SPI_WRITE_FAST(SPI_FLASH_INS_READ);
202  SPI_WRITE_FAST(offset >> 16); /* MSB */
203  SPI_WRITE_FAST(offset >> 8);
204  SPI_WRITE_FAST(offset >> 0); /* LSB */
205  SPI_WAITFORTx_ENDED();
206 
207  SPI_FLUSH();
208  for(; p < end; p++) {
209  unsigned char u;
210  SPI_READ(u);
211  *p = ~u;
212  }
213 
214  SPI_FLASH_DISABLE();
216 
217  ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
218 
219  return size;
220 }
221 /*---------------------------------------------------------------------------*/
222 static const unsigned char *
223 program_page(unsigned long offset, const unsigned char *p, int nbytes)
224 {
225  const unsigned char *end = p + nbytes;
226 
227  wait_ready();
228 
229  write_enable();
230 
232  SPI_FLASH_ENABLE();
233 
234  SPI_WRITE_FAST(SPI_FLASH_INS_PP);
235  SPI_WRITE_FAST(offset >> 16); /* MSB */
236  SPI_WRITE_FAST(offset >> 8);
237  SPI_WRITE_FAST(offset >> 0); /* LSB */
238 
239  for(; p < end; p++) {
240  SPI_WRITE_FAST(~*p);
241  }
242  SPI_WAITFORTx_ENDED();
243 
244  SPI_FLASH_DISABLE();
245  SPI_FLUSH(); //(void)SPI_RXBUF; /* Dummy read of SPI RX Buffer to ensure that there is no stray data. */
247 
248  return p;
249 }
250 /*---------------------------------------------------------------------------*/
251 int
252 xmem_pwrite(const void *_buf, int size, unsigned long addr)
253 {
254  const unsigned char *p = _buf;
255  const unsigned long end = addr + size;
256  unsigned long i, next_page;
257 
258  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
259 
260  for(i = addr; i < end;) {
261  next_page = (i | 0xff) + 1;
262  if(next_page > end) {
263  next_page = end;
264  }
265  p = program_page(i, p, next_page - i);
266  i = next_page;
267  }
268 
269  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
270 
271  return size;
272 }
273 /*---------------------------------------------------------------------------*/
274 int
275 xmem_erase(long size, unsigned long addr)
276 {
277  unsigned long end = addr + size;
278 
279  if(size % XMEM_ERASE_UNIT_SIZE != 0) {
280  PRINTF("xmem_erase: bad size\n");
281  return -1;
282  }
283 
284  if(addr % XMEM_ERASE_UNIT_SIZE != 0) {
285  PRINTF("xmem_erase: bad offset\n");
286  return -1;
287  }
288 
289  for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
290  erase_sector(addr);
291  }
292 
293  return size;
294 }
295 /*---------------------------------------------------------------------------*/
Header file with definitions related to the I/O connections on the Muntjac platform, cc2538-based.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
Header file for the cc2538 SPI driver, including macros for the implementation of the low-level SPI p...
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 spix_init(uint8_t spi)
Initialize the SPI bus for the instance given.
Definition: spi.c:207
void spix_cs_init(uint8_t port, uint8_t pin)
Configure a GPIO to be the chip select pin.
Definition: spi.c:319
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
Header file for the cc2538 Synchronous Serial Interface.
#define INTERRUPTS_DISABLE()
Disables all CPU interrupts.
Definition: cpu.h:67
#define INTERRUPTS_ENABLE()
Enables all CPU interrupts.
Definition: cpu.h:64