Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Loughborough University - Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 */ 00031 00032 /** 00033 * \file 00034 * This file provides functions to control the M25P16 on sensinode N740s. 00035 * This is a Numonyx Forte Serial Flash Memory (16Mbit) 00036 * The S signal (Chip Select) is controlled via 0x02 on the 74HC595D 00037 * The other instructions and timing are performed with bit bang 00038 * 00039 * We can enable, disable, read/write data, erase pages, hold, enter/exit 00040 * deep sleep etc. 00041 * 00042 * Clock (C) => P1_5, 00043 * Ser. I (D) => P1_6, 00044 * Ser. O (Q) => P1_7, 00045 * Hold => Pull Up, 00046 * Write Prot => Pull Up, 00047 * Chip Sel => 74HC595D (0x02) 00048 * 00049 * This file can be placed in any bank. 00050 * 00051 * \author 00052 * George Oikonomou - <oikonomou@users.sourceforge.net> 00053 */ 00054 00055 #include "dev/n740.h" 00056 #include "dev/m25p16.h" 00057 #include "sys/clock.h" 00058 #include "sys/energest.h" 00059 #include "cc2430_sfr.h" 00060 00061 #define CLOCK_RISING() {M25P16_PIN_CLOCK = 1; M25P16_PIN_CLOCK = 0;} 00062 #define CLOCK_FALLING() {M25P16_PIN_CLOCK = 0; M25P16_PIN_CLOCK = 1;} 00063 /*---------------------------------------------------------------------------*/ 00064 /* Bit-Bang write a byte to the chip */ 00065 static void 00066 bit_bang_write(uint8_t byte) CC_NON_BANKED 00067 { 00068 uint8_t i; 00069 uint8_t bit; 00070 00071 /* bit-by-bit */ 00072 for(i = 0x80; i > 0; i >>= 1) { 00073 /* Is the bit set? */ 00074 bit = 0; 00075 if(i & byte) { 00076 /* If it was set, we want to send 1 */ 00077 bit = 1; 00078 } 00079 /* Send the bit */ 00080 M25P16_PIN_SER_I = bit; 00081 /* Clock - Rising */ 00082 CLOCK_RISING(); 00083 } 00084 } 00085 /*---------------------------------------------------------------------------*/ 00086 /* Bit-Bang read a byte from the chip */ 00087 static uint8_t 00088 bit_bang_read() CC_NON_BANKED 00089 { 00090 int8_t i; 00091 uint8_t bits = 0; 00092 00093 /* bit-by-bit */ 00094 for(i = 7; i >= 0; i--) { 00095 /* Clock - Falling */ 00096 CLOCK_FALLING(); 00097 00098 /* Read the bit */ 00099 bits |= (M25P16_PIN_SER_O << i); 00100 } 00101 return bits; 00102 } 00103 /*---------------------------------------------------------------------------*/ 00104 static void 00105 select() CC_NON_BANKED 00106 { 00107 /* Read current ser/par value */ 00108 uint8_t ser_par = n740_ser_par_get(); 00109 00110 M25P16_PIN_CLOCK = 0; 00111 00112 ser_par &= ~N740_SER_PAR_CHIP_SEL; /* Select Flash */ 00113 00114 /* Write the new status back to the ser/par */ 00115 n740_ser_par_set(ser_par); 00116 } 00117 /*---------------------------------------------------------------------------*/ 00118 static void 00119 deselect() CC_NON_BANKED 00120 { 00121 /* Read current ser/par value */ 00122 uint8_t ser_par = n740_ser_par_get(); 00123 00124 ser_par |= N740_SER_PAR_CHIP_SEL; /* De-Select Flash */ 00125 00126 /* Write the new status back to the ser/par */ 00127 n740_ser_par_set(ser_par); 00128 } 00129 /*---------------------------------------------------------------------------*/ 00130 void 00131 m25p16_wren() 00132 { 00133 select(); 00134 bit_bang_write(M25P16_I_WREN); 00135 deselect(); 00136 00137 while(!M25P16_WEL()); 00138 } 00139 /*---------------------------------------------------------------------------*/ 00140 void 00141 m25p16_wrdi() 00142 { 00143 select(); 00144 bit_bang_write(M25P16_I_WRDI); 00145 deselect(); 00146 } 00147 /*---------------------------------------------------------------------------*/ 00148 void 00149 m25p16_rdid(struct m25p16_rdid * rdid) 00150 { 00151 uint8_t i; 00152 00153 select(); 00154 bit_bang_write(M25P16_I_RDID); 00155 00156 rdid->man_id = bit_bang_read(); 00157 rdid->mem_type = bit_bang_read(); /* Device ID MSB */ 00158 rdid->mem_size = bit_bang_read(); /* Device ID LSB */ 00159 rdid->uid_len = bit_bang_read(); 00160 for(i = 0; i < rdid->uid_len; i++) { 00161 rdid->uid[i] = bit_bang_read(); 00162 } 00163 deselect(); 00164 } 00165 /*---------------------------------------------------------------------------*/ 00166 uint8_t 00167 m25p16_rdsr() 00168 { 00169 uint8_t rv; 00170 00171 select(); 00172 bit_bang_write(M25P16_I_RDSR); 00173 rv = bit_bang_read(); 00174 deselect(); 00175 00176 return rv; 00177 } 00178 /*---------------------------------------------------------------------------*/ 00179 void 00180 m25p16_wrsr(uint8_t val) 00181 { 00182 m25p16_wren(); /* Write Enable */ 00183 00184 select(); 00185 ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE); 00186 bit_bang_write(M25P16_I_WRSR); 00187 bit_bang_write(val); 00188 ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE); 00189 deselect(); 00190 } 00191 /*---------------------------------------------------------------------------*/ 00192 void 00193 m25p16_read(uint8_t * addr, uint8_t * buff, uint8_t buff_len) 00194 { 00195 uint8_t i; 00196 00197 select(); 00198 ENERGEST_ON(ENERGEST_TYPE_FLASH_READ); 00199 00200 #if M25P16_READ_FAST 00201 bit_bang_write(M25P16_I_FAST_READ); 00202 #else 00203 bit_bang_write(M25P16_I_READ); 00204 #endif 00205 00206 /* Write the address, MSB in addr[0], bits [7:5] of the MSB: 'don't care' */ 00207 for(i = 0; i < 3; i++) { 00208 bit_bang_write(addr[i]); 00209 } 00210 00211 /* For FAST_READ, send the dummy byte */ 00212 #if M25P16_READ_FAST 00213 bit_bang_write(M25P16_DUMMY_BYTE); 00214 #endif 00215 00216 for(i = 0; i < buff_len; i++) { 00217 buff[i] = ~bit_bang_read(); 00218 } 00219 ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ); 00220 deselect(); 00221 } 00222 /*---------------------------------------------------------------------------*/ 00223 void 00224 m25p16_pp(uint8_t * addr, uint8_t * buff, uint8_t buff_len) 00225 { 00226 uint8_t i; 00227 00228 m25p16_wren(); /* Write Enable */ 00229 00230 select(); 00231 ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE); 00232 bit_bang_write(M25P16_I_PP); 00233 00234 /* Write the address, MSB in addr[0] */ 00235 for(i = 0; i < 3; i++) { 00236 bit_bang_write(addr[i]); 00237 } 00238 00239 /* Write the bytes */ 00240 for(i=0; i<buff_len; i++) { 00241 bit_bang_write(~buff[i]); 00242 } 00243 ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE); 00244 deselect(); 00245 } 00246 /*---------------------------------------------------------------------------*/ 00247 void 00248 m25p16_se(uint8_t s) 00249 { 00250 m25p16_wren(); /* Write Enable */ 00251 00252 select(); 00253 ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE); 00254 bit_bang_write(M25P16_I_SE); 00255 bit_bang_write(s); 00256 bit_bang_write(0x00); 00257 bit_bang_write(0x00); 00258 deselect(); 00259 ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE); 00260 } 00261 /*---------------------------------------------------------------------------*/ 00262 void 00263 m25p16_be() 00264 { 00265 m25p16_wren(); /* Write Enable */ 00266 00267 select(); 00268 bit_bang_write(M25P16_I_BE); 00269 deselect(); 00270 } 00271 /*---------------------------------------------------------------------------*/ 00272 void 00273 m25p16_dp() 00274 { 00275 select(); 00276 bit_bang_write(M25P16_I_DP); 00277 deselect(); 00278 } 00279 /*---------------------------------------------------------------------------*/ 00280 /* 00281 * Release Deep Power Down. We do NOT read the Electronic Signature 00282 */ 00283 void 00284 m25p16_res() { 00285 select(); 00286 bit_bang_write(M25P16_I_RES); 00287 deselect(); 00288 /* a few usec between RES and standby */ 00289 while(M25P16_WIP()); 00290 } 00291 /*---------------------------------------------------------------------------*/ 00292 /** 00293 * Release Deep Power Down. Read and return the Electronic Signature 00294 * must return 0x14 00295 * 00296 * \return The old style Electronic Signature. This must be 0x14 00297 */ 00298 uint8_t 00299 m25p16_res_res() { 00300 uint8_t rv; 00301 00302 select(); 00303 bit_bang_write(M25P16_I_RES); 00304 bit_bang_write(M25P16_DUMMY_BYTE); 00305 bit_bang_write(M25P16_DUMMY_BYTE); 00306 bit_bang_write(M25P16_DUMMY_BYTE); 00307 00308 rv = bit_bang_read(); 00309 00310 deselect(); 00311 00312 /* a few usec between RES and standby */ 00313 while(M25P16_WIP()); 00314 return rv; 00315 } 00316 /*---------------------------------------------------------------------------*/