spiflash.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
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 copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log: spiflash.c,v $
00036  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00037  * Moved from dev.
00038  *
00039  * Revision 1.2  2004/03/18 14:06:52  haraldkipp
00040  * Deprecated header file replaced
00041  *
00042  * Revision 1.1.1.1  2003/05/09 14:40:50  haraldkipp
00043  * Initial using 3.2.1
00044  *
00045  * Revision 1.4  2003/02/04 17:50:54  harald
00046  * Version 3 released
00047  *
00048  * Revision 1.3  2002/09/15 16:39:44  harald
00049  * *** empty log message ***
00050  *
00051  * Revision 1.2  2002/08/08 17:20:47  harald
00052  * Imagecraft support by Klaus Ummenhofer
00053  *
00054  */
00055 
00056 #include <string.h>
00057 
00058 #include <sys/atom.h>
00059 #include <sys/event.h>
00060 #include <sys/timer.h>
00061 #include <sys/heap.h>
00062 #include <sys/device.h>
00063 
00064 #include <dev/spiflash.h>
00065 
00070 
00074 #ifdef __GNUC__
00075 static __inline u_char SpiByte(u_char c)
00076 #else
00077 static u_char SpiByte(u_char c)
00078 #endif
00079 {
00080     outp(c, SPDR);
00081     loop_until_bit_is_set(SPSR, SPIF);
00082     return inp(SPDR);
00083 }
00084 
00090 int SpiFlashEnable(void)
00091 {
00092     u_char i;
00093     u_char rc;
00094 
00095     /*
00096      * PB0(O): SS
00097      * PB1(O): SCK
00098      * PB2(O): MOSI
00099      * PB3(I): MISO
00100      *
00101      * PB4(O): Reset target
00102      * PB5(-): Unused
00103      * PB6(-): Unused
00104      * PB7(-): Unused
00105      */
00106 
00107     /*
00108      * SCK and MOSI outputs need configuration, 
00109      * even if SPI mode is enabled.
00110      */
00111     cbi(PORTB, 1);
00112     sbi(DDRB, 1);
00113     cbi(PORTB, 2);
00114     sbi(DDRB, 2);
00115 
00116     /*
00117      * Enable pull-up on MISO.
00118      */
00119     sbi(PORTB, 3);
00120 
00121     for (i = 0; i < 32; i++) {
00122 
00123         /*
00124          * Set reset low.
00125          */
00126         cbi(PORTB, 4);
00127         sbi(DDRB, 4);
00128 
00129         /*
00130          * Set slave select pin  to output. Otherwise a low signal 
00131          * on this pin might force us to SPI slave mode.
00132          */
00133         sbi(DDRB, 0);
00134         outp(BV(MSTR) | BV(SPE) | BV(SPR0), SPCR);
00135 
00136         /*
00137          * Try to enable programming.
00138          */
00139         SpiByte(0xAC);
00140         SpiByte(0x53);
00141         rc = SpiByte(0xFF);
00142         SpiByte(0xff);
00143 
00144         if (rc == 0x53)
00145             return 0;
00146 
00147         /*
00148          * Programming enable failed. This may be because the
00149          * target is not synchronized. A positive pulse on the
00150          * clock line should help.
00151          */
00152         outp(0, SPCR);
00153         sbi(PORTB, 1);
00154         cbi(PORTB, 1);
00155     }
00156     return -1;
00157 }
00158 
00165 void SpiFlashId(u_char * id)
00166 {
00167     u_char i;
00168 
00169     for (i = 0; i < 3; i++) {
00170         SpiByte(0x30);
00171         SpiByte(0x00);
00172         SpiByte(i);
00173         id[i] = SpiByte(0x00);
00174     }
00175 }
00176 
00190 int SpiFlashWriteByte(u_char high, u_short addr, u_char data)
00191 {
00192     u_char d;
00193 
00194     if (data != 0xff) {
00195         SpiByte(0x40 | high);
00196         SpiByte(addr >> 8);
00197         SpiByte(addr & 0xFF);
00198         SpiByte(data);
00199 
00200         /*
00201          * During programming a value of 0x7F appears at the memory location. 
00202          * If we are programming this value, we delay execution by 10 ms.
00203          * Otherwise we poll the memory location until we read back the 
00204          * programmed value.
00205          */
00206         if (data == 0x7f)
00207             NutDelay(10);
00208         else {
00209             for (d = 0; d < 255; d++) {
00210 
00211                 /*
00212                  * Read program flash byte.
00213                  */
00214                 SpiByte(0x20 | high);
00215                 SpiByte(addr >> 8);
00216                 SpiByte(addr & 0xFF);
00217                 if (SpiByte(0xFF) == data)
00218                     break;
00219             }
00220             if (d == 255)
00221                 return -1;
00222         }
00223     }
00224     return 0;
00225 }
00226 
00235 int SpiFlashWriteWord(u_short addr, u_short data)
00236 {
00237     if (SpiFlashWriteByte(0, addr, data & 0xFF))
00238         return -1;
00239     if (SpiFlashWriteByte(8, addr, data >> 8))
00240         return -1;
00241 
00242     return 0;
00243 }
00244 
00251 void SpiFlashErase(void)
00252 {
00253     /*
00254      * Send chip erase command.
00255      */
00256     SpiByte(0xAC);
00257     SpiByte(0x80);
00258     SpiByte(0x00);
00259     SpiByte(0x00);
00260     NutDelay(25);
00261 }
00262 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/