Macronix Low Power Serial NOR Flash in SPI mode.

Dependents:   MX25Rxx35F_Serial_NOR_Flash_Testbench MX25Rxx35F_Serial_NOR_Flash_Testbench Coragem_all_sensors 1_Test_Flash_ADC_RTT

Committer:
alec1
Date:
Wed Jul 08 20:59:40 2015 +0000
Revision:
0:a16ad6f5c788
Child:
1:8403da5975cb
Rev0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
alec1 0:a16ad6f5c788 1 /*
alec1 0:a16ad6f5c788 2 * SPI_MX25R SPI-Flash Memory
alec1 0:a16ad6f5c788 3 * Macronix Low Power Serial Flash Memory
alec1 0:a16ad6f5c788 4 * Standard Pin-out
alec1 0:a16ad6f5c788 5 */
alec1 0:a16ad6f5c788 6
alec1 0:a16ad6f5c788 7 #include "SPI_MX25R.h"
alec1 0:a16ad6f5c788 8
alec1 0:a16ad6f5c788 9 #define CMD_RDSR 0x05 // Read Status Register
alec1 0:a16ad6f5c788 10 #define CMD_RDCR 0x15 // Read Configuration Register
alec1 0:a16ad6f5c788 11 #define CMD_RDID 0x9F // Read Identification
alec1 0:a16ad6f5c788 12 #define CMD_WREN 0x06 // Write Enable
alec1 0:a16ad6f5c788 13 #define CMD_WRDI 0x04 // Write Disable
alec1 0:a16ad6f5c788 14 #define CMD_WRSR 0x01 // Write Status Register
alec1 0:a16ad6f5c788 15 #define CMD_READ 0x03 // Read Data Byte
alec1 0:a16ad6f5c788 16 #define CMD_PP 0x02 // Page Program
alec1 0:a16ad6f5c788 17 #define CMD_BE 0xD8 // 64KB Block Erase
alec1 0:a16ad6f5c788 18 #define CMD_32KBE 0x52 // 32KB Block Erase
alec1 0:a16ad6f5c788 19 #define CMD_SE 0x20 // 4KB Sector Erase
alec1 0:a16ad6f5c788 20 #define CMD_CE 0xC7 // Chip Erase
alec1 0:a16ad6f5c788 21 #define CMD_RSTEN 0x66 // Reset Enable
alec1 0:a16ad6f5c788 22 #define CMD_RST 0x99 // Reset
alec1 0:a16ad6f5c788 23 #define CMD_RDSFDP 0x5A // Read SFDP
alec1 0:a16ad6f5c788 24 #define CMD_FREAD 0x0B // x1 FREAD
alec1 0:a16ad6f5c788 25 #define CMD_2READ 0xBB // x2 2READ
alec1 0:a16ad6f5c788 26 #define CMD_DREAD 0x3B // x2 DREAD
alec1 0:a16ad6f5c788 27 #define CMD_4READ 0xEB // x4 4READ
alec1 0:a16ad6f5c788 28 #define CMD_QREAD 0x6B // x4 QREAD
alec1 0:a16ad6f5c788 29 #define CMD_PESUS 0xB0 // x4 Program/Erase Suspend
alec1 0:a16ad6f5c788 30 #define CMD_PERES 0x30 // x4 Program/Erase Resume
alec1 0:a16ad6f5c788 31 #define CMD_DP 0xB9 // Enter Deep Power Down
alec1 0:a16ad6f5c788 32
alec1 0:a16ad6f5c788 33
alec1 0:a16ad6f5c788 34 SPI_MX25R::SPI_MX25R(PinName mosi, PinName miso, PinName sclk, PinName cs) :
alec1 0:a16ad6f5c788 35 m_spi(mosi, miso, sclk), m_cs(cs) { }
alec1 0:a16ad6f5c788 36
alec1 0:a16ad6f5c788 37 SPI_MX25R::~SPI_MX25R() { }
alec1 0:a16ad6f5c788 38
alec1 0:a16ad6f5c788 39 void SPI_MX25R::writeEnable(void)
alec1 0:a16ad6f5c788 40 {
alec1 0:a16ad6f5c788 41 m_cs = 0 ;
alec1 0:a16ad6f5c788 42 m_spi.write(CMD_WREN) ;
alec1 0:a16ad6f5c788 43 m_cs = 1 ;
alec1 0:a16ad6f5c788 44 }
alec1 0:a16ad6f5c788 45
alec1 0:a16ad6f5c788 46 void SPI_MX25R::writeDisable(void)
alec1 0:a16ad6f5c788 47 {
alec1 0:a16ad6f5c788 48 m_cs = 0 ;
alec1 0:a16ad6f5c788 49 m_spi.write(CMD_WRDI) ;
alec1 0:a16ad6f5c788 50 m_cs = 1 ;
alec1 0:a16ad6f5c788 51 }
alec1 0:a16ad6f5c788 52
alec1 0:a16ad6f5c788 53 void SPI_MX25R::resetEnable(void)
alec1 0:a16ad6f5c788 54 {
alec1 0:a16ad6f5c788 55 m_cs = 0 ;
alec1 0:a16ad6f5c788 56 m_spi.write(CMD_RSTEN) ;
alec1 0:a16ad6f5c788 57 m_cs = 1 ;
alec1 0:a16ad6f5c788 58 }
alec1 0:a16ad6f5c788 59
alec1 0:a16ad6f5c788 60 void SPI_MX25R::reset(void)
alec1 0:a16ad6f5c788 61 {
alec1 0:a16ad6f5c788 62 m_cs = 0 ;
alec1 0:a16ad6f5c788 63 m_spi.write(CMD_RST) ;
alec1 0:a16ad6f5c788 64 m_cs = 1 ;
alec1 0:a16ad6f5c788 65 }
alec1 0:a16ad6f5c788 66 uint8_t SPI_MX25R::readStatus(void)
alec1 0:a16ad6f5c788 67 {
alec1 0:a16ad6f5c788 68 uint8_t data ;
alec1 0:a16ad6f5c788 69 m_cs = 0 ;
alec1 0:a16ad6f5c788 70 m_spi.write(CMD_RDSR) ;
alec1 0:a16ad6f5c788 71 data = m_spi.write(CMD_RDSR) ; // dummy
alec1 0:a16ad6f5c788 72 m_spi.write(CMD_RDSR) ;
alec1 0:a16ad6f5c788 73 data = m_spi.write(CMD_RDSR) ; // dummy
alec1 0:a16ad6f5c788 74 m_cs = 1 ;
alec1 0:a16ad6f5c788 75 return( data ) ;
alec1 0:a16ad6f5c788 76 }
alec1 0:a16ad6f5c788 77
alec1 0:a16ad6f5c788 78 uint32_t SPI_MX25R::readConfig(void)
alec1 0:a16ad6f5c788 79 {
alec1 0:a16ad6f5c788 80 uint8_t data;
alec1 0:a16ad6f5c788 81 uint32_t config32 = 0 ;
alec1 0:a16ad6f5c788 82 m_cs = 0 ;
alec1 0:a16ad6f5c788 83 m_spi.write(CMD_RDCR) ; // send 15h
alec1 0:a16ad6f5c788 84 data= m_spi.write(0x55) ; // dumy to get 1st Byte out
alec1 0:a16ad6f5c788 85 config32 = config32 | data ; // put in 32b reg
alec1 0:a16ad6f5c788 86 data= m_spi.write(0x55) ; //dummy to get 2nd Byte out
alec1 0:a16ad6f5c788 87 config32 = (config32 << 8) | data ; // shift and put in reg
alec1 0:a16ad6f5c788 88 m_cs = 1 ;
alec1 0:a16ad6f5c788 89 return( config32 ) ;
alec1 0:a16ad6f5c788 90 }
alec1 0:a16ad6f5c788 91
alec1 0:a16ad6f5c788 92 uint32_t SPI_MX25R::readID(void)
alec1 0:a16ad6f5c788 93 {
alec1 0:a16ad6f5c788 94 uint8_t data;
alec1 0:a16ad6f5c788 95 uint32_t data32 = 0 ;
alec1 0:a16ad6f5c788 96 m_cs = 0 ;
alec1 0:a16ad6f5c788 97 m_spi.write(CMD_RDID) ; // send 9Fh
alec1 0:a16ad6f5c788 98 data= m_spi.write(0x55) ; // dumy to get 1st Byte out
alec1 0:a16ad6f5c788 99 data32 = data32 | data ; // put in 32b reg
alec1 0:a16ad6f5c788 100 data= m_spi.write(CMD_RDID) ; //dummy to get 2nd Byte out
alec1 0:a16ad6f5c788 101 data32 = (data32 << 8) | data ; // shift and put in reg
alec1 0:a16ad6f5c788 102 data= m_spi.write(0x55) ; //dummy to get 3rd Byte out
alec1 0:a16ad6f5c788 103 data32 = (data32 << 8) | data ; // shift again and put in reg
alec1 0:a16ad6f5c788 104 m_cs = 1 ;
alec1 0:a16ad6f5c788 105 return( data32 ) ;
alec1 0:a16ad6f5c788 106 }
alec1 0:a16ad6f5c788 107
alec1 0:a16ad6f5c788 108 void SPI_MX25R::programPage(int addr, uint8_t *data, int numData)
alec1 0:a16ad6f5c788 109 {
alec1 0:a16ad6f5c788 110 int i ;
alec1 0:a16ad6f5c788 111 m_cs = 0 ;
alec1 0:a16ad6f5c788 112 m_spi.write(CMD_PP) ; // Program Page 02h
alec1 0:a16ad6f5c788 113 m_spi.write((addr >> 16)&0xFF) ; // adr 23:16
alec1 0:a16ad6f5c788 114 m_spi.write((addr >> 8)&0xFF) ; // adr 15:8
alec1 0:a16ad6f5c788 115 m_spi.write(addr & 0xFF) ; // adr 7:0
alec1 0:a16ad6f5c788 116 for (i = 0 ; i < numData ; i++ ) { // data = 00, 01, 02, .. to FEh, FFh = all 256 Bytes in 1 page.
alec1 0:a16ad6f5c788 117 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 118 }
alec1 0:a16ad6f5c788 119 m_cs = 1 ;
alec1 0:a16ad6f5c788 120 // poll in main
alec1 0:a16ad6f5c788 121 }
alec1 0:a16ad6f5c788 122
alec1 0:a16ad6f5c788 123 void SPI_MX25R::hpmode(void)
alec1 0:a16ad6f5c788 124 {
alec1 0:a16ad6f5c788 125 m_cs = 0 ;
alec1 0:a16ad6f5c788 126 m_spi.write(CMD_WRSR) ; // Write SR cmd 01h
alec1 0:a16ad6f5c788 127 m_spi.write(0x00) ; // SR = 00h
alec1 0:a16ad6f5c788 128 m_spi.write(0x00) ; // CR1 = 00h
alec1 0:a16ad6f5c788 129 m_spi.write(0x02) ; // CR2 = 02h, To set Config Reg 2 <1> = 1 to enter High Performance mode
alec1 0:a16ad6f5c788 130 m_cs = 1 ;
alec1 0:a16ad6f5c788 131 }
alec1 0:a16ad6f5c788 132
alec1 0:a16ad6f5c788 133 void SPI_MX25R::lpmode(void)
alec1 0:a16ad6f5c788 134 {
alec1 0:a16ad6f5c788 135 m_cs = 0 ;
alec1 0:a16ad6f5c788 136 m_spi.write(CMD_WRSR) ; // Write SR cmd 01h
alec1 0:a16ad6f5c788 137 m_spi.write(0x00) ; // SR = 00h
alec1 0:a16ad6f5c788 138 m_spi.write(0x00) ; // CR1 = 00h
alec1 0:a16ad6f5c788 139 m_spi.write(0x00) ; // CR2 = 00h, To set Config Reg 2 <1> = 0 to enter Low Power mode
alec1 0:a16ad6f5c788 140 m_cs = 1 ;
alec1 0:a16ad6f5c788 141 }
alec1 0:a16ad6f5c788 142
alec1 0:a16ad6f5c788 143 void SPI_MX25R::blockErase(int addr)
alec1 0:a16ad6f5c788 144 {
alec1 0:a16ad6f5c788 145 uint8_t data[3] ;
alec1 0:a16ad6f5c788 146 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 147 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 148 data[2] = (addr & 0xFF) ;
alec1 0:a16ad6f5c788 149 m_cs = 0 ;
alec1 0:a16ad6f5c788 150 m_spi.write(CMD_BE) ;
alec1 0:a16ad6f5c788 151 for (int i = 0 ; i < 3 ; i++ ) {
alec1 0:a16ad6f5c788 152 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 153 }
alec1 0:a16ad6f5c788 154 m_cs = 1 ;
alec1 0:a16ad6f5c788 155 // poll in main
alec1 0:a16ad6f5c788 156 }
alec1 0:a16ad6f5c788 157
alec1 0:a16ad6f5c788 158 void SPI_MX25R::blockErase32KB(int addr)
alec1 0:a16ad6f5c788 159 {
alec1 0:a16ad6f5c788 160 uint8_t data[3] ;
alec1 0:a16ad6f5c788 161 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 162 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 163 data[2] = (addr & 0xFF) ;
alec1 0:a16ad6f5c788 164 m_cs = 0 ;
alec1 0:a16ad6f5c788 165 m_spi.write(CMD_32KBE) ;
alec1 0:a16ad6f5c788 166 for (int i = 0 ; i < 3 ; i++ ) {
alec1 0:a16ad6f5c788 167 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 168 }
alec1 0:a16ad6f5c788 169 m_cs = 1 ;
alec1 0:a16ad6f5c788 170 // poll in main
alec1 0:a16ad6f5c788 171 }
alec1 0:a16ad6f5c788 172
alec1 0:a16ad6f5c788 173 void SPI_MX25R::sectorErase(int addr)
alec1 0:a16ad6f5c788 174 {
alec1 0:a16ad6f5c788 175 uint8_t data[3] ;
alec1 0:a16ad6f5c788 176 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 177 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 178 data[2] = (addr & 0xFF) ;
alec1 0:a16ad6f5c788 179 m_cs = 0 ;
alec1 0:a16ad6f5c788 180 m_spi.write(CMD_SE) ;
alec1 0:a16ad6f5c788 181 for (int i = 0 ; i < 3 ; i++ ) {
alec1 0:a16ad6f5c788 182 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 183 }
alec1 0:a16ad6f5c788 184 m_cs = 1 ;
alec1 0:a16ad6f5c788 185 // poll in main
alec1 0:a16ad6f5c788 186 }
alec1 0:a16ad6f5c788 187 void SPI_MX25R::chipErase(void)
alec1 0:a16ad6f5c788 188 {
alec1 0:a16ad6f5c788 189 m_cs = 0 ;
alec1 0:a16ad6f5c788 190 m_spi.write(CMD_CE) ;
alec1 0:a16ad6f5c788 191 m_cs = 1 ;
alec1 0:a16ad6f5c788 192 // poll in main
alec1 0:a16ad6f5c788 193 }
alec1 0:a16ad6f5c788 194
alec1 0:a16ad6f5c788 195 uint8_t SPI_MX25R::read8(int addr)
alec1 0:a16ad6f5c788 196 {
alec1 0:a16ad6f5c788 197 uint8_t data ;
alec1 0:a16ad6f5c788 198 m_cs = 0 ;
alec1 0:a16ad6f5c788 199 m_spi.write(CMD_READ) ;
alec1 0:a16ad6f5c788 200 m_spi.write((addr >> 16)&0xFF) ;
alec1 0:a16ad6f5c788 201 m_spi.write((addr >> 8)&0xFF) ;
alec1 0:a16ad6f5c788 202 m_spi.write(addr & 0xFF) ;
alec1 0:a16ad6f5c788 203 data = m_spi.write(addr & 0xFF) ; // write data is dummy
alec1 0:a16ad6f5c788 204 m_cs = 1 ;
alec1 0:a16ad6f5c788 205 return( data ) ;
alec1 0:a16ad6f5c788 206 }
alec1 0:a16ad6f5c788 207
alec1 0:a16ad6f5c788 208 uint32_t SPI_MX25R::rd32(int addr)
alec1 0:a16ad6f5c788 209 {
alec1 0:a16ad6f5c788 210 uint8_t data;
alec1 0:a16ad6f5c788 211 uint32_t data32 = 0 ;
alec1 0:a16ad6f5c788 212 m_cs = 0 ;
alec1 0:a16ad6f5c788 213 m_spi.write(CMD_READ) ; // send 03h
alec1 0:a16ad6f5c788 214
alec1 0:a16ad6f5c788 215 m_spi.write((addr >> 16)&0xFF) ; // address
alec1 0:a16ad6f5c788 216 m_spi.write((addr >> 8)&0xFF) ;
alec1 0:a16ad6f5c788 217 m_spi.write(addr & 0xFF) ;
alec1 0:a16ad6f5c788 218
alec1 0:a16ad6f5c788 219 data= m_spi.write(0xFF) ; // dumy to get 1st Byte out
alec1 0:a16ad6f5c788 220 data32 = data32 | data ; // put in 32b reg
alec1 0:a16ad6f5c788 221 data= m_spi.write(0xFF) ; //dummy to get 2nd Byte out
alec1 0:a16ad6f5c788 222 data32 = (data32 << 8) | data ; // shift and put in reg
alec1 0:a16ad6f5c788 223 data= m_spi.write(0xFF) ; //dummy to get 3rd Byte out
alec1 0:a16ad6f5c788 224 data32 = (data32 << 8) | data ; // shift again and put in reg
alec1 0:a16ad6f5c788 225 data= m_spi.write(0xFF) ; //dummy to get 4th Byte out
alec1 0:a16ad6f5c788 226 data32 = (data32 << 8) | data ; // shift again and put in reg
alec1 0:a16ad6f5c788 227 m_cs = 1 ;
alec1 0:a16ad6f5c788 228 return( data32 ) ;
alec1 0:a16ad6f5c788 229 }