Contiki 3.x
m25p16.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Loughborough University - 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  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \file
34  * This file provides functions to control the M25P16 on sensinode N740s.
35  * This is a Numonyx Forte Serial Flash Memory (16Mbit)
36  * The S signal (Chip Select) is controlled via 0x02 on the 74HC595D
37  * The other instructions and timing are performed with bit bang
38  *
39  * We can enable, disable, read/write data, erase pages, hold, enter/exit
40  * deep sleep etc.
41  *
42  * Clock (C) => P1_5,
43  * Ser. I (D) => P1_6,
44  * Ser. O (Q) => P1_7,
45  * Hold => Pull Up,
46  * Write Prot => Pull Up,
47  * Chip Sel => 74HC595D (0x02)
48  *
49  * This file can be placed in any bank.
50  *
51  * \author
52  * George Oikonomou - <oikonomou@users.sourceforge.net>
53  */
54 
55 #include "dev/n740.h"
56 #include "dev/m25p16.h"
57 #include "sys/clock.h"
58 #include "sys/energest.h"
59 #include "cc2430_sfr.h"
60 
61 #define CLOCK_RISING() {M25P16_PIN_CLOCK = 1; M25P16_PIN_CLOCK = 0;}
62 #define CLOCK_FALLING() {M25P16_PIN_CLOCK = 0; M25P16_PIN_CLOCK = 1;}
63 /*---------------------------------------------------------------------------*/
64 /* Bit-Bang write a byte to the chip */
65 static void
66 bit_bang_write(uint8_t byte) CC_NON_BANKED
67 {
68  uint8_t i;
69  uint8_t bit;
70 
71  /* bit-by-bit */
72  for(i = 0x80; i > 0; i >>= 1) {
73  /* Is the bit set? */
74  bit = 0;
75  if(i & byte) {
76  /* If it was set, we want to send 1 */
77  bit = 1;
78  }
79  /* Send the bit */
80  M25P16_PIN_SER_I = bit;
81  /* Clock - Rising */
82  CLOCK_RISING();
83  }
84 }
85 /*---------------------------------------------------------------------------*/
86 /* Bit-Bang read a byte from the chip */
87 static uint8_t
88 bit_bang_read() CC_NON_BANKED
89 {
90  int8_t i;
91  uint8_t bits = 0;
92 
93  /* bit-by-bit */
94  for(i = 7; i >= 0; i--) {
95  /* Clock - Falling */
96  CLOCK_FALLING();
97 
98  /* Read the bit */
99  bits |= (M25P16_PIN_SER_O << i);
100  }
101  return bits;
102 }
103 /*---------------------------------------------------------------------------*/
104 static void
105 select() CC_NON_BANKED
106 {
107  /* Read current ser/par value */
108  uint8_t ser_par = n740_ser_par_get();
109 
110  M25P16_PIN_CLOCK = 0;
111 
112  ser_par &= ~N740_SER_PAR_CHIP_SEL; /* Select Flash */
113 
114  /* Write the new status back to the ser/par */
115  n740_ser_par_set(ser_par);
116 }
117 /*---------------------------------------------------------------------------*/
118 static void
119 deselect() CC_NON_BANKED
120 {
121  /* Read current ser/par value */
122  uint8_t ser_par = n740_ser_par_get();
123 
124  ser_par |= N740_SER_PAR_CHIP_SEL; /* De-Select Flash */
125 
126  /* Write the new status back to the ser/par */
127  n740_ser_par_set(ser_par);
128 }
129 /*---------------------------------------------------------------------------*/
130 void
132 {
133  select();
134  bit_bang_write(M25P16_I_WREN);
135  deselect();
136 
137  while(!M25P16_WEL());
138 }
139 /*---------------------------------------------------------------------------*/
140 void
142 {
143  select();
144  bit_bang_write(M25P16_I_WRDI);
145  deselect();
146 }
147 /*---------------------------------------------------------------------------*/
148 void
150 {
151  uint8_t i;
152 
153  select();
154  bit_bang_write(M25P16_I_RDID);
155 
156  rdid->man_id = bit_bang_read();
157  rdid->mem_type = bit_bang_read(); /* Device ID MSB */
158  rdid->mem_size = bit_bang_read(); /* Device ID LSB */
159  rdid->uid_len = bit_bang_read();
160  for(i = 0; i < rdid->uid_len; i++) {
161  rdid->uid[i] = bit_bang_read();
162  }
163  deselect();
164 }
165 /*---------------------------------------------------------------------------*/
166 uint8_t
168 {
169  uint8_t rv;
170 
171  select();
172  bit_bang_write(M25P16_I_RDSR);
173  rv = bit_bang_read();
174  deselect();
175 
176  return rv;
177 }
178 /*---------------------------------------------------------------------------*/
179 void
180 m25p16_wrsr(uint8_t val)
181 {
182  m25p16_wren(); /* Write Enable */
183 
184  select();
185  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
186  bit_bang_write(M25P16_I_WRSR);
187  bit_bang_write(val);
188  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
189  deselect();
190 }
191 /*---------------------------------------------------------------------------*/
192 void
193 m25p16_read(uint8_t * addr, uint8_t * buff, uint8_t buff_len)
194 {
195  uint8_t i;
196 
197  select();
198  ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
199 
200 #if M25P16_READ_FAST
201  bit_bang_write(M25P16_I_FAST_READ);
202 #else
203  bit_bang_write(M25P16_I_READ);
204 #endif
205 
206  /* Write the address, MSB in addr[0], bits [7:5] of the MSB: 'don't care' */
207  for(i = 0; i < 3; i++) {
208  bit_bang_write(addr[i]);
209  }
210 
211  /* For FAST_READ, send the dummy byte */
212 #if M25P16_READ_FAST
213  bit_bang_write(M25P16_DUMMY_BYTE);
214 #endif
215 
216  for(i = 0; i < buff_len; i++) {
217  buff[i] = ~bit_bang_read();
218  }
219  ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
220  deselect();
221 }
222 /*---------------------------------------------------------------------------*/
223 void
224 m25p16_pp(uint8_t * addr, uint8_t * buff, uint8_t buff_len)
225 {
226  uint8_t i;
227 
228  m25p16_wren(); /* Write Enable */
229 
230  select();
231  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
232  bit_bang_write(M25P16_I_PP);
233 
234  /* Write the address, MSB in addr[0] */
235  for(i = 0; i < 3; i++) {
236  bit_bang_write(addr[i]);
237  }
238 
239  /* Write the bytes */
240  for(i = 0; i < buff_len; i++) {
241  bit_bang_write(~buff[i]);
242  }
243  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
244  deselect();
245 }
246 /*---------------------------------------------------------------------------*/
247 void
248 m25p16_se(uint8_t s)
249 {
250  m25p16_wren(); /* Write Enable */
251 
252  select();
253  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
254  bit_bang_write(M25P16_I_SE);
255  bit_bang_write(s);
256  bit_bang_write(0x00);
257  bit_bang_write(0x00);
258  deselect();
259  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
260 }
261 /*---------------------------------------------------------------------------*/
262 void
264 {
265  m25p16_wren(); /* Write Enable */
266 
267  select();
268  bit_bang_write(M25P16_I_BE);
269  deselect();
270 }
271 /*---------------------------------------------------------------------------*/
272 void
274 {
275  select();
276  bit_bang_write(M25P16_I_DP);
277  deselect();
278 }
279 /*---------------------------------------------------------------------------*/
280 /*
281  * Release Deep Power Down. We do NOT read the Electronic Signature
282  */
283 void
285 {
286  select();
287  bit_bang_write(M25P16_I_RES);
288  deselect();
289  /* a few usec between RES and standby */
290  while(M25P16_WIP());
291 }
292 /*---------------------------------------------------------------------------*/
293 /**
294  * Release Deep Power Down. Read and return the Electronic Signature
295  * must return 0x14
296  *
297  * \return The old style Electronic Signature. This must be 0x14
298  */
299 uint8_t
301 {
302  uint8_t rv;
303 
304  select();
305  bit_bang_write(M25P16_I_RES);
306  bit_bang_write(M25P16_DUMMY_BYTE);
307  bit_bang_write(M25P16_DUMMY_BYTE);
308  bit_bang_write(M25P16_DUMMY_BYTE);
309 
310  rv = bit_bang_read();
311 
312  deselect();
313 
314  /* a few usec between RES and standby */
315  while(M25P16_WIP());
316  return rv;
317 }
318 /*---------------------------------------------------------------------------*/
CC2430 registers header file for CC2430.
uint8_t uid_len
Memory Size.
Definition: m25p16.h:97
uint8_t m25p16_rdsr()
Read Status Register (RDSR) instruction.
Definition: m25p16.c:167
Header file for the control of the M25P16 on sensinode N740s.
void m25p16_pp(uint8_t *addr, uint8_t *buff, uint8_t buff_len)
Program Page (PP) instruction.
Definition: m25p16.c:224
uint8_t m25p16_res_res()
Release Deep Power Down.
Definition: m25p16.c:300
void m25p16_read(uint8_t *addr, uint8_t *buff, uint8_t buff_len)
Read Data Bytes (READ) instruction.
Definition: m25p16.c:193
Header file for the energy estimation mechanism
void m25p16_wren()
Write Enable (WREN) instruction.
Definition: m25p16.c:131
Header File for the module which controls the Sensinode N740 8-bit serial-in/serial or parall...
Device Identifier.
Definition: m25p16.h:93
void m25p16_rdid(struct m25p16_rdid *rdid)
Read Identifier (RDID)instruction.
Definition: m25p16.c:149
uint8_t uid[16]
Unique ID length.
Definition: m25p16.h:98
void m25p16_wrsr(uint8_t val)
Write Status Register (WRSR) instruction.
Definition: m25p16.c:180
uint8_t mem_type
Manufacturer ID.
Definition: m25p16.h:95
void m25p16_dp()
Deep Power Down (DP) instruction.
Definition: m25p16.c:273
void m25p16_se(uint8_t s)
Sector Erase (SE) instruction.
Definition: m25p16.c:248
#define M25P16_WEL()
Check for Write-Enable.
Definition: m25p16.h:125
void m25p16_be()
Bulk Erase (SE) instruction.
Definition: m25p16.c:263
void m25p16_wrdi()
Write Disable (WRDI) instruction.
Definition: m25p16.c:141
#define M25P16_WIP()
Check for Write in Progress.
Definition: m25p16.h:116
uint8_t mem_size
Memory Type.
Definition: m25p16.h:96
void m25p16_res()
Release from Deep Power Down (RES) instruction.
Definition: m25p16.c:284