Nut/OS  4.10.3
API Reference
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$
00036  * Revision 1.2  2008/08/11 06:59:17  haraldkipp
00037  * BSD types replaced by stdint types (feature request #1282721).
00038  *
00039  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00040  * Moved from dev.
00041  *
00042  * Revision 1.2  2004/03/18 14:06:52  haraldkipp
00043  * Deprecated header file replaced
00044  *
00045  * Revision 1.1.1.1  2003/05/09 14:40:50  haraldkipp
00046  * Initial using 3.2.1
00047  *
00048  * Revision 1.4  2003/02/04 17:50:54  harald
00049  * Version 3 released
00050  *
00051  * Revision 1.3  2002/09/15 16:39:44  harald
00052  * *** empty log message ***
00053  *
00054  * Revision 1.2  2002/08/08 17:20:47  harald
00055  * Imagecraft support by Klaus Ummenhofer
00056  *
00057  */
00058 
00059 #include <string.h>
00060 
00061 #include <sys/atom.h>
00062 #include <sys/event.h>
00063 #include <sys/timer.h>
00064 #include <sys/heap.h>
00065 #include <sys/device.h>
00066 
00067 #include <dev/spiflash.h>
00068 
00073 
00077 #ifdef __GNUC__
00078 static __inline uint8_t SpiByte(uint8_t c)
00079 #else
00080 static uint8_t SpiByte(uint8_t c)
00081 #endif
00082 {
00083     outb(SPDR, c);
00084     loop_until_bit_is_set(SPSR, SPIF);
00085     return inb(SPDR);
00086 }
00087 
00093 int SpiFlashEnable(void)
00094 {
00095     uint8_t i;
00096     uint8_t rc;
00097 
00098     /*
00099      * PB0(O): SS
00100      * PB1(O): SCK
00101      * PB2(O): MOSI
00102      * PB3(I): MISO
00103      *
00104      * PB4(O): Reset target
00105      * PB5(-): Unused
00106      * PB6(-): Unused
00107      * PB7(-): Unused
00108      */
00109 
00110     /*
00111      * SCK and MOSI outputs need configuration, 
00112      * even if SPI mode is enabled.
00113      */
00114     cbi(PORTB, 1);
00115     sbi(DDRB, 1);
00116     cbi(PORTB, 2);
00117     sbi(DDRB, 2);
00118 
00119     /*
00120      * Enable pull-up on MISO.
00121      */
00122     sbi(PORTB, 3);
00123 
00124     for (i = 0; i < 32; i++) {
00125 
00126         /*
00127          * Set reset low.
00128          */
00129         cbi(PORTB, 4);
00130         sbi(DDRB, 4);
00131 
00132         /*
00133          * Set slave select pin  to output. Otherwise a low signal 
00134          * on this pin might force us to SPI slave mode.
00135          */
00136         sbi(DDRB, 0);
00137         outb(SPCR, BV(MSTR) | BV(SPE) | BV(SPR0));
00138 
00139         /*
00140          * Try to enable programming.
00141          */
00142         SpiByte(0xAC);
00143         SpiByte(0x53);
00144         rc = SpiByte(0xFF);
00145         SpiByte(0xff);
00146 
00147         if (rc == 0x53)
00148             return 0;
00149 
00150         /*
00151          * Programming enable failed. This may be because the
00152          * target is not synchronized. A positive pulse on the
00153          * clock line should help.
00154          */
00155         outb(SPCR, 0);
00156         sbi(PORTB, 1);
00157         cbi(PORTB, 1);
00158     }
00159     return -1;
00160 }
00161 
00168 void SpiFlashId(uint8_t * id)
00169 {
00170     uint8_t i;
00171 
00172     for (i = 0; i < 3; i++) {
00173         SpiByte(0x30);
00174         SpiByte(0x00);
00175         SpiByte(i);
00176         id[i] = SpiByte(0x00);
00177     }
00178 }
00179 
00193 int SpiFlashWriteByte(uint8_t high, uint16_t addr, uint8_t data)
00194 {
00195     uint8_t d;
00196 
00197     if (data != 0xff) {
00198         SpiByte(0x40 | high);
00199         SpiByte(addr >> 8);
00200         SpiByte(addr & 0xFF);
00201         SpiByte(data);
00202 
00203         /*
00204          * During programming a value of 0x7F appears at the memory location. 
00205          * If we are programming this value, we delay execution by 10 ms.
00206          * Otherwise we poll the memory location until we read back the 
00207          * programmed value.
00208          */
00209         if (data == 0x7f)
00210             NutDelay(10);
00211         else {
00212             for (d = 0; d < 255; d++) {
00213 
00214                 /*
00215                  * Read program flash byte.
00216                  */
00217                 SpiByte(0x20 | high);
00218                 SpiByte(addr >> 8);
00219                 SpiByte(addr & 0xFF);
00220                 if (SpiByte(0xFF) == data)
00221                     break;
00222             }
00223             if (d == 255)
00224                 return -1;
00225         }
00226     }
00227     return 0;
00228 }
00229 
00238 int SpiFlashWriteWord(uint16_t addr, uint16_t data)
00239 {
00240     if (SpiFlashWriteByte(0, addr, data & 0xFF))
00241         return -1;
00242     if (SpiFlashWriteByte(8, addr, data >> 8))
00243         return -1;
00244 
00245     return 0;
00246 }
00247 
00254 void SpiFlashErase(void)
00255 {
00256     /*
00257      * Send chip erase command.
00258      */
00259     SpiByte(0xAC);
00260     SpiByte(0x80);
00261     SpiByte(0x00);
00262     SpiByte(0x00);
00263     NutDelay(25);
00264 }
00265