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:
Mon Jul 20 20:45:33 2015 +0000
Revision:
1:8403da5975cb
Parent:
0:a16ad6f5c788
Child:
2:f72110475fec
Initial Library Release

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 1:8403da5975cb 3 * Macronix Low Power Serial NOR Flash
alec1 1:8403da5975cb 4 * (x2, and x4 I/O modes not implemented)
alec1 0:a16ad6f5c788 5 */
alec1 0:a16ad6f5c788 6
alec1 0:a16ad6f5c788 7 #include "SPI_MX25R.h"
alec1 0:a16ad6f5c788 8
alec1 1:8403da5975cb 9 #define CMD_READ 0x03 // x1 Normal Read Data Byte
alec1 1:8403da5975cb 10 #define CMD_FREAD 0x0B // x1 Fast Read Data Byte
alec1 1:8403da5975cb 11 #define CMD_PP 0x02 // Page Program
alec1 1:8403da5975cb 12 #define CMD_SE 0x20 // 4KB Sector Erase
alec1 1:8403da5975cb 13 #define CMD_32KBE 0x52 // 32KB Block Erase
alec1 1:8403da5975cb 14 #define CMD_BE 0xD8 // 64KB Block Erase
alec1 1:8403da5975cb 15 #define CMD_CE 0xC7 // Chip Erase
alec1 1:8403da5975cb 16 #define CMD_RDID 0x9F // Read Identification
alec1 1:8403da5975cb 17 #define CMD_RDSFDP 0x5A // Read SFDP
alec1 0:a16ad6f5c788 18 #define CMD_RDSR 0x05 // Read Status Register
alec1 0:a16ad6f5c788 19 #define CMD_RDCR 0x15 // Read Configuration Register
alec1 0:a16ad6f5c788 20 #define CMD_WREN 0x06 // Write Enable
alec1 0:a16ad6f5c788 21 #define CMD_WRDI 0x04 // Write Disable
alec1 0:a16ad6f5c788 22 #define CMD_WRSR 0x01 // Write Status Register
alec1 0:a16ad6f5c788 23 #define CMD_RSTEN 0x66 // Reset Enable
alec1 0:a16ad6f5c788 24 #define CMD_RST 0x99 // Reset
alec1 0:a16ad6f5c788 25 #define CMD_PESUS 0xB0 // x4 Program/Erase Suspend
alec1 0:a16ad6f5c788 26 #define CMD_PERES 0x30 // x4 Program/Erase Resume
alec1 0:a16ad6f5c788 27 #define CMD_DP 0xB9 // Enter Deep Power Down
alec1 1:8403da5975cb 28 #define CMD_SBL 0xC0 // Set Burst Length
alec1 1:8403da5975cb 29 #define CMD_RRE 0xFF // Release Read Enhanced Mode
alec1 1:8403da5975cb 30 #define CMD_NOP 0x00 // No Operation
alec1 1:8403da5975cb 31 #define CMD_ENSO 0xB1 // Enter Secure OTP
alec1 1:8403da5975cb 32 #define CMD_EXSO 0xC1 // Exit Secure OTP
alec1 1:8403da5975cb 33 // x2 and x4 commands not currently supported with FRDM K64F platform
alec1 1:8403da5975cb 34 //#define CMD_2READ 0xBB // x2 2READ
alec1 1:8403da5975cb 35 //#define CMD_DREAD 0x3B // x2 DREAD
alec1 1:8403da5975cb 36 //#define CMD_4READ 0xEB // x4 4READ
alec1 1:8403da5975cb 37 //#define CMD_QREAD 0x6B // x4 QREAD
alec1 1:8403da5975cb 38 //#define CMD_4PP 0x38 // x4 PP
alec1 1:8403da5975cb 39
alec1 0:a16ad6f5c788 40
alec1 0:a16ad6f5c788 41 SPI_MX25R::SPI_MX25R(PinName mosi, PinName miso, PinName sclk, PinName cs) :
alec1 0:a16ad6f5c788 42 m_spi(mosi, miso, sclk), m_cs(cs) { }
alec1 0:a16ad6f5c788 43
alec1 0:a16ad6f5c788 44 SPI_MX25R::~SPI_MX25R() { }
alec1 0:a16ad6f5c788 45
alec1 0:a16ad6f5c788 46 void SPI_MX25R::writeEnable(void)
alec1 0:a16ad6f5c788 47 {
alec1 0:a16ad6f5c788 48 m_cs = 0 ;
alec1 0:a16ad6f5c788 49 m_spi.write(CMD_WREN) ;
alec1 0:a16ad6f5c788 50 m_cs = 1 ;
alec1 0:a16ad6f5c788 51 }
alec1 0:a16ad6f5c788 52
alec1 0:a16ad6f5c788 53 void SPI_MX25R::writeDisable(void)
alec1 0:a16ad6f5c788 54 {
alec1 0:a16ad6f5c788 55 m_cs = 0 ;
alec1 0:a16ad6f5c788 56 m_spi.write(CMD_WRDI) ;
alec1 0:a16ad6f5c788 57 m_cs = 1 ;
alec1 0:a16ad6f5c788 58 }
alec1 0:a16ad6f5c788 59
alec1 0:a16ad6f5c788 60 void SPI_MX25R::resetEnable(void)
alec1 0:a16ad6f5c788 61 {
alec1 0:a16ad6f5c788 62 m_cs = 0 ;
alec1 0:a16ad6f5c788 63 m_spi.write(CMD_RSTEN) ;
alec1 0:a16ad6f5c788 64 m_cs = 1 ;
alec1 0:a16ad6f5c788 65 }
alec1 0:a16ad6f5c788 66
alec1 0:a16ad6f5c788 67 void SPI_MX25R::reset(void)
alec1 0:a16ad6f5c788 68 {
alec1 0:a16ad6f5c788 69 m_cs = 0 ;
alec1 0:a16ad6f5c788 70 m_spi.write(CMD_RST) ;
alec1 0:a16ad6f5c788 71 m_cs = 1 ;
alec1 0:a16ad6f5c788 72 }
alec1 1:8403da5975cb 73
alec1 1:8403da5975cb 74 void SPI_MX25R::pgmersSuspend(void)
alec1 1:8403da5975cb 75 {
alec1 1:8403da5975cb 76 m_cs = 0 ;
alec1 1:8403da5975cb 77 m_spi.write(CMD_PESUS) ;
alec1 1:8403da5975cb 78 m_cs = 1 ;
alec1 1:8403da5975cb 79 }
alec1 1:8403da5975cb 80
alec1 1:8403da5975cb 81 void SPI_MX25R::pgmersResume(void)
alec1 1:8403da5975cb 82 {
alec1 1:8403da5975cb 83 m_cs = 0 ;
alec1 1:8403da5975cb 84 m_spi.write(CMD_PERES) ;
alec1 1:8403da5975cb 85 m_cs = 1 ;
alec1 1:8403da5975cb 86 }
alec1 1:8403da5975cb 87
alec1 1:8403da5975cb 88 void SPI_MX25R::deepPowerdown(void)
alec1 1:8403da5975cb 89 {
alec1 1:8403da5975cb 90 m_cs = 0 ;
alec1 1:8403da5975cb 91 m_spi.write(CMD_DP) ;
alec1 1:8403da5975cb 92 m_cs = 1 ;
alec1 1:8403da5975cb 93 }
alec1 1:8403da5975cb 94
alec1 1:8403da5975cb 95 void SPI_MX25R::setBurstlength(void)
alec1 1:8403da5975cb 96 {
alec1 1:8403da5975cb 97 m_cs = 0 ;
alec1 1:8403da5975cb 98 m_spi.write(CMD_SBL) ;
alec1 1:8403da5975cb 99 m_cs = 1 ;
alec1 1:8403da5975cb 100 }
alec1 1:8403da5975cb 101
alec1 1:8403da5975cb 102 void SPI_MX25R::releaseReadenhaced(void)
alec1 1:8403da5975cb 103 {
alec1 1:8403da5975cb 104 m_cs = 0 ;
alec1 1:8403da5975cb 105 m_spi.write(CMD_RRE) ;
alec1 1:8403da5975cb 106 m_cs = 1 ;
alec1 1:8403da5975cb 107 }
alec1 1:8403da5975cb 108
alec1 1:8403da5975cb 109 void SPI_MX25R::noOperation(void)
alec1 1:8403da5975cb 110 {
alec1 1:8403da5975cb 111 m_cs = 0 ;
alec1 1:8403da5975cb 112 m_spi.write(CMD_NOP) ;
alec1 1:8403da5975cb 113 m_cs = 1 ;
alec1 1:8403da5975cb 114 }
alec1 1:8403da5975cb 115
alec1 1:8403da5975cb 116 void SPI_MX25R::enterSecureOTP(void)
alec1 1:8403da5975cb 117 {
alec1 1:8403da5975cb 118 m_cs = 0 ;
alec1 1:8403da5975cb 119 m_spi.write(CMD_ENSO) ;
alec1 1:8403da5975cb 120 m_cs = 1 ;
alec1 1:8403da5975cb 121 }
alec1 1:8403da5975cb 122
alec1 1:8403da5975cb 123 void SPI_MX25R::exitSecureOTP(void)
alec1 1:8403da5975cb 124 {
alec1 1:8403da5975cb 125 m_cs = 0 ;
alec1 1:8403da5975cb 126 m_spi.write(CMD_EXSO) ;
alec1 1:8403da5975cb 127 m_cs = 1 ;
alec1 1:8403da5975cb 128 }
alec1 1:8403da5975cb 129
alec1 0:a16ad6f5c788 130 uint8_t SPI_MX25R::readStatus(void)
alec1 0:a16ad6f5c788 131 {
alec1 0:a16ad6f5c788 132 uint8_t data ;
alec1 0:a16ad6f5c788 133 m_cs = 0 ;
alec1 0:a16ad6f5c788 134 m_spi.write(CMD_RDSR) ;
alec1 1:8403da5975cb 135 data = m_spi.write(CMD_RDSR) ; // dummy
alec1 1:8403da5975cb 136 m_spi.write(CMD_RDSR) ;
alec1 1:8403da5975cb 137 data = m_spi.write(CMD_RDSR) ; // dummy
alec1 0:a16ad6f5c788 138 m_cs = 1 ;
alec1 0:a16ad6f5c788 139 return( data ) ;
alec1 0:a16ad6f5c788 140 }
alec1 0:a16ad6f5c788 141
alec1 0:a16ad6f5c788 142 uint32_t SPI_MX25R::readConfig(void)
alec1 0:a16ad6f5c788 143 {
alec1 0:a16ad6f5c788 144 uint8_t data;
alec1 0:a16ad6f5c788 145 uint32_t config32 = 0 ;
alec1 0:a16ad6f5c788 146 m_cs = 0 ;
alec1 1:8403da5975cb 147 m_spi.write(CMD_RDCR) ; // send 15h
alec1 1:8403da5975cb 148 data= m_spi.write(0x55) ; // dumy to get 1st Byte out
alec1 1:8403da5975cb 149 config32 = config32 | data ; // put in 32b reg
alec1 1:8403da5975cb 150 data= m_spi.write(0x55) ; // dummy to get 2nd Byte out
alec1 1:8403da5975cb 151 config32 = (config32 << 8) | data ; // shift and put in reg
alec1 0:a16ad6f5c788 152 m_cs = 1 ;
alec1 0:a16ad6f5c788 153 return( config32 ) ;
alec1 0:a16ad6f5c788 154 }
alec1 0:a16ad6f5c788 155
alec1 0:a16ad6f5c788 156 uint32_t SPI_MX25R::readID(void)
alec1 0:a16ad6f5c788 157 {
alec1 0:a16ad6f5c788 158 uint8_t data;
alec1 0:a16ad6f5c788 159 uint32_t data32 = 0 ;
alec1 0:a16ad6f5c788 160 m_cs = 0 ;
alec1 1:8403da5975cb 161 m_spi.write(CMD_RDID) ; // send 9Fh
alec1 1:8403da5975cb 162 data= m_spi.write(0x55) ; // dumy to get 1st Byte out
alec1 1:8403da5975cb 163 data32 = data32 | data ; // put in 32b reg
alec1 1:8403da5975cb 164 data= m_spi.write(CMD_RDID) ; // dummy to get 2nd Byte out
alec1 1:8403da5975cb 165 data32 = (data32 << 8) | data ; // shift and put in reg
alec1 1:8403da5975cb 166 data= m_spi.write(0x55) ; // dummy to get 3rd Byte out
alec1 1:8403da5975cb 167 data32 = (data32 << 8) | data ; // shift again and put in reg
alec1 0:a16ad6f5c788 168 m_cs = 1 ;
alec1 0:a16ad6f5c788 169 return( data32 ) ;
alec1 0:a16ad6f5c788 170 }
alec1 0:a16ad6f5c788 171
alec1 0:a16ad6f5c788 172 void SPI_MX25R::programPage(int addr, uint8_t *data, int numData)
alec1 0:a16ad6f5c788 173 {
alec1 0:a16ad6f5c788 174 int i ;
alec1 0:a16ad6f5c788 175 m_cs = 0 ;
alec1 1:8403da5975cb 176 m_spi.write(CMD_PP) ; // Program Page 02h
alec1 1:8403da5975cb 177 m_spi.write((addr >> 16)&0xFF) ; // adr 23:16
alec1 1:8403da5975cb 178 m_spi.write((addr >> 8)&0xFF) ; // adr 15:8
alec1 1:8403da5975cb 179 m_spi.write(addr & 0xFF) ; // adr 7:0
alec1 1:8403da5975cb 180 for (i = 0 ; i < numData ; i++ ) { // data = 00, 01, 02, .. to FEh, FFh = all 256 Bytes in 1 page.
alec1 0:a16ad6f5c788 181 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 182 }
alec1 0:a16ad6f5c788 183 m_cs = 1 ;
alec1 0:a16ad6f5c788 184 // poll in main
alec1 0:a16ad6f5c788 185 }
alec1 0:a16ad6f5c788 186
alec1 1:8403da5975cb 187 void SPI_MX25R::writeStatusreg(int addr) // Write SR cmd 01h + 3B data
alec1 1:8403da5975cb 188 {
alec1 0:a16ad6f5c788 189 m_cs = 0 ;
alec1 1:8403da5975cb 190 m_spi.write(CMD_WRSR) ; // Write SR cmd 01h
alec1 1:8403da5975cb 191 m_spi.write((addr >> 16)&0xFF) ; // address
alec1 1:8403da5975cb 192 m_spi.write((addr >> 8)&0xFF) ;
alec1 1:8403da5975cb 193 m_spi.write(addr & 0xFF) ;
alec1 0:a16ad6f5c788 194 m_cs = 1 ;
alec1 0:a16ad6f5c788 195 }
alec1 0:a16ad6f5c788 196
alec1 1:8403da5975cb 197 void SPI_MX25R::blockErase(int addr) // 64KB Block Erase
alec1 0:a16ad6f5c788 198 {
alec1 0:a16ad6f5c788 199 uint8_t data[3] ;
alec1 0:a16ad6f5c788 200 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 201 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 202 data[2] = (addr & 0xFF) ;
alec1 0:a16ad6f5c788 203 m_cs = 0 ;
alec1 0:a16ad6f5c788 204 m_spi.write(CMD_BE) ;
alec1 0:a16ad6f5c788 205 for (int i = 0 ; i < 3 ; i++ ) {
alec1 0:a16ad6f5c788 206 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 207 }
alec1 0:a16ad6f5c788 208 m_cs = 1 ;
alec1 0:a16ad6f5c788 209 // poll in main
alec1 0:a16ad6f5c788 210 }
alec1 0:a16ad6f5c788 211
alec1 1:8403da5975cb 212 void SPI_MX25R::blockErase32KB(int addr) // 32KB Block Erase
alec1 0:a16ad6f5c788 213 {
alec1 0:a16ad6f5c788 214 uint8_t data[3] ;
alec1 0:a16ad6f5c788 215 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 216 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 217 data[2] = (addr & 0xFF) ;
alec1 0:a16ad6f5c788 218 m_cs = 0 ;
alec1 0:a16ad6f5c788 219 m_spi.write(CMD_32KBE) ;
alec1 0:a16ad6f5c788 220 for (int i = 0 ; i < 3 ; i++ ) {
alec1 0:a16ad6f5c788 221 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 222 }
alec1 0:a16ad6f5c788 223 m_cs = 1 ;
alec1 0:a16ad6f5c788 224 // poll in main
alec1 0:a16ad6f5c788 225 }
alec1 0:a16ad6f5c788 226
alec1 1:8403da5975cb 227 void SPI_MX25R::sectorErase(int addr) // 4KB Sector Erase
alec1 0:a16ad6f5c788 228 {
alec1 0:a16ad6f5c788 229 uint8_t data[3] ;
alec1 0:a16ad6f5c788 230 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 231 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 232 data[2] = (addr & 0xFF) ;
alec1 0:a16ad6f5c788 233 m_cs = 0 ;
alec1 0:a16ad6f5c788 234 m_spi.write(CMD_SE) ;
alec1 0:a16ad6f5c788 235 for (int i = 0 ; i < 3 ; i++ ) {
alec1 0:a16ad6f5c788 236 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 237 }
alec1 0:a16ad6f5c788 238 m_cs = 1 ;
alec1 0:a16ad6f5c788 239 // poll in main
alec1 0:a16ad6f5c788 240 }
alec1 1:8403da5975cb 241
alec1 1:8403da5975cb 242 void SPI_MX25R::chipErase(void) // Chip Erase
alec1 0:a16ad6f5c788 243 {
alec1 0:a16ad6f5c788 244 m_cs = 0 ;
alec1 0:a16ad6f5c788 245 m_spi.write(CMD_CE) ;
alec1 0:a16ad6f5c788 246 m_cs = 1 ;
alec1 0:a16ad6f5c788 247 // poll in main
alec1 0:a16ad6f5c788 248 }
alec1 0:a16ad6f5c788 249
alec1 1:8403da5975cb 250 uint8_t SPI_MX25R::read8(int addr) // Single Byte Read
alec1 0:a16ad6f5c788 251 {
alec1 0:a16ad6f5c788 252 uint8_t data ;
alec1 0:a16ad6f5c788 253 m_cs = 0 ;
alec1 1:8403da5975cb 254 m_spi.write(CMD_READ) ; // send 03h
alec1 0:a16ad6f5c788 255 m_spi.write((addr >> 16)&0xFF) ;
alec1 0:a16ad6f5c788 256 m_spi.write((addr >> 8)&0xFF) ;
alec1 0:a16ad6f5c788 257 m_spi.write(addr & 0xFF) ;
alec1 1:8403da5975cb 258 data = m_spi.write(addr & 0xFF) ; // write data is dummy
alec1 1:8403da5975cb 259 m_cs = 1 ;
alec1 1:8403da5975cb 260 return( data ) ; // return 1 byte
alec1 1:8403da5975cb 261 }
alec1 1:8403da5975cb 262
alec1 1:8403da5975cb 263 uint8_t SPI_MX25R::readSFDP(int addr) // Single Byte Read
alec1 1:8403da5975cb 264 {
alec1 1:8403da5975cb 265 uint8_t data ;
alec1 1:8403da5975cb 266 m_cs = 0 ;
alec1 1:8403da5975cb 267 m_spi.write(CMD_RDSFDP) ; // send cmd 5Ah
alec1 1:8403da5975cb 268 m_spi.write((addr >> 16)&0xFF) ; // address[23:16]
alec1 1:8403da5975cb 269 m_spi.write((addr >> 8)&0xFF) ; // address[15:8]
alec1 1:8403da5975cb 270 m_spi.write(addr & 0xFF) ; // address[7:0]
alec1 1:8403da5975cb 271 m_spi.write(0x00 & 0xFF) ; // dummy cycle
alec1 1:8403da5975cb 272 data = m_spi.write(addr & 0xFF) ; // return 1 byte
alec1 0:a16ad6f5c788 273 m_cs = 1 ;
alec1 0:a16ad6f5c788 274 return( data ) ;
alec1 0:a16ad6f5c788 275 }
alec1 0:a16ad6f5c788 276
alec1 1:8403da5975cb 277 uint8_t SPI_MX25R::readFREAD(int addr) // Single Byte Read
alec1 1:8403da5975cb 278 {
alec1 1:8403da5975cb 279 uint8_t data ;
alec1 0:a16ad6f5c788 280 m_cs = 0 ;
alec1 1:8403da5975cb 281 m_spi.write(CMD_FREAD) ; // send cmd 0Bh
alec1 1:8403da5975cb 282 m_spi.write((addr >> 16)&0xFF) ; // address[23:16]
alec1 1:8403da5975cb 283 m_spi.write((addr >> 8)&0xFF) ; // address[15:8]
alec1 1:8403da5975cb 284 m_spi.write(addr & 0xFF) ; // address[7:0]
alec1 1:8403da5975cb 285 m_spi.write(0x00 & 0xFF) ; // dummy cycle
alec1 1:8403da5975cb 286 data = m_spi.write(addr & 0xFF) ; // return 1 byte
alec1 0:a16ad6f5c788 287 m_cs = 1 ;
alec1 1:8403da5975cb 288 return( data ) ;
alec1 0:a16ad6f5c788 289 }
alec1 1:8403da5975cb 290