Contiki 2.6

m25p16.c

Go to the documentation of this file.
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 /*---------------------------------------------------------------------------*/