MX25R6435F Library

Dependents:   Demo_MX25Rxx35F_Serial_NOR_Flash_Testbench mbed-lorawan-pulga mbed-lorawan-pulga-serial_rx mbed-lorawan-pulga-gps-added_shared

Fork of SPI_MX25R by alec cohen

Committer:
Arkadi
Date:
Wed Mar 28 13:17:02 2018 +0000
Revision:
3:b6bb8d236251
Parent:
2:f72110475fec
Modified for page read, n bytes read

Who changed what in which revision?

UserRevisionLine numberNew contents of line
alec1 0:a16ad6f5c788 1 /*
alec1 2:f72110475fec 2 * SPI_MX25R Series 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
alec1 0:a16ad6f5c788 10 SPI_MX25R::SPI_MX25R(PinName mosi, PinName miso, PinName sclk, PinName cs) :
alec1 0:a16ad6f5c788 11 m_spi(mosi, miso, sclk), m_cs(cs) { }
alec1 2:f72110475fec 12
alec1 0:a16ad6f5c788 13 SPI_MX25R::~SPI_MX25R() { }
alec1 2:f72110475fec 14
alec1 0:a16ad6f5c788 15 void SPI_MX25R::writeEnable(void)
alec1 0:a16ad6f5c788 16 {
alec1 2:f72110475fec 17 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 18 m_spi.write(CMD_WREN) ;
alec1 2:f72110475fec 19 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 20 }
alec1 2:f72110475fec 21
alec1 0:a16ad6f5c788 22 void SPI_MX25R::writeDisable(void)
alec1 0:a16ad6f5c788 23 {
alec1 2:f72110475fec 24 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 25 m_spi.write(CMD_WRDI) ;
alec1 2:f72110475fec 26 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 27 }
alec1 2:f72110475fec 28
alec1 0:a16ad6f5c788 29 void SPI_MX25R::resetEnable(void)
alec1 0:a16ad6f5c788 30 {
alec1 2:f72110475fec 31 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 32 m_spi.write(CMD_RSTEN) ;
alec1 2:f72110475fec 33 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 34 }
alec1 2:f72110475fec 35
alec1 0:a16ad6f5c788 36 void SPI_MX25R::reset(void)
alec1 0:a16ad6f5c788 37 {
alec1 2:f72110475fec 38 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 39 m_spi.write(CMD_RST) ;
alec1 2:f72110475fec 40 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 41 }
alec1 2:f72110475fec 42
alec1 1:8403da5975cb 43 void SPI_MX25R::pgmersSuspend(void)
alec1 1:8403da5975cb 44 {
alec1 2:f72110475fec 45 m_cs = CS_LOW ;
alec1 1:8403da5975cb 46 m_spi.write(CMD_PESUS) ;
alec1 2:f72110475fec 47 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 48 }
alec1 2:f72110475fec 49
alec1 1:8403da5975cb 50 void SPI_MX25R::pgmersResume(void)
alec1 1:8403da5975cb 51 {
alec1 2:f72110475fec 52 m_cs = CS_LOW ;
alec1 1:8403da5975cb 53 m_spi.write(CMD_PERES) ;
alec1 2:f72110475fec 54 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 55 }
alec1 2:f72110475fec 56
alec1 1:8403da5975cb 57 void SPI_MX25R::deepPowerdown(void)
alec1 1:8403da5975cb 58 {
alec1 2:f72110475fec 59 m_cs = CS_LOW ;
alec1 1:8403da5975cb 60 m_spi.write(CMD_DP) ;
alec1 2:f72110475fec 61 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 62 }
alec1 2:f72110475fec 63
alec1 1:8403da5975cb 64 void SPI_MX25R::setBurstlength(void)
alec1 1:8403da5975cb 65 {
alec1 2:f72110475fec 66 m_cs = CS_LOW ;
alec1 1:8403da5975cb 67 m_spi.write(CMD_SBL) ;
alec1 2:f72110475fec 68 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 69 }
alec1 2:f72110475fec 70
alec1 1:8403da5975cb 71 void SPI_MX25R::releaseReadenhaced(void)
alec1 1:8403da5975cb 72 {
alec1 2:f72110475fec 73 m_cs = CS_LOW ;
alec1 1:8403da5975cb 74 m_spi.write(CMD_RRE) ;
alec1 2:f72110475fec 75 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 76 }
alec1 2:f72110475fec 77
alec1 1:8403da5975cb 78 void SPI_MX25R::noOperation(void)
alec1 1:8403da5975cb 79 {
alec1 2:f72110475fec 80 m_cs = CS_LOW ;
alec1 1:8403da5975cb 81 m_spi.write(CMD_NOP) ;
alec1 2:f72110475fec 82 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 83 }
alec1 2:f72110475fec 84
alec1 1:8403da5975cb 85 void SPI_MX25R::enterSecureOTP(void)
alec1 1:8403da5975cb 86 {
alec1 2:f72110475fec 87 m_cs = CS_LOW ;
alec1 1:8403da5975cb 88 m_spi.write(CMD_ENSO) ;
alec1 2:f72110475fec 89 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 90 }
alec1 1:8403da5975cb 91
alec1 1:8403da5975cb 92 void SPI_MX25R::exitSecureOTP(void)
alec1 1:8403da5975cb 93 {
alec1 2:f72110475fec 94 m_cs = CS_LOW ;
alec1 1:8403da5975cb 95 m_spi.write(CMD_EXSO) ;
alec1 2:f72110475fec 96 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 97 }
alec1 2:f72110475fec 98
alec1 0:a16ad6f5c788 99 uint8_t SPI_MX25R::readStatus(void)
alec1 0:a16ad6f5c788 100 {
alec1 0:a16ad6f5c788 101 uint8_t data ;
alec1 2:f72110475fec 102 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 103 m_spi.write(CMD_RDSR) ;
alec1 2:f72110475fec 104 data = m_spi.write(DUMMY) ; // dummy
alec1 2:f72110475fec 105 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 106 return( data ) ;
alec1 2:f72110475fec 107 }
alec1 0:a16ad6f5c788 108
alec1 0:a16ad6f5c788 109 uint32_t SPI_MX25R::readConfig(void)
alec1 0:a16ad6f5c788 110 {
alec1 0:a16ad6f5c788 111 uint8_t data;
alec1 0:a16ad6f5c788 112 uint32_t config32 = 0 ;
alec1 2:f72110475fec 113 m_cs = CS_LOW ;
alec1 1:8403da5975cb 114 m_spi.write(CMD_RDCR) ; // send 15h
alec1 2:f72110475fec 115 data= m_spi.write(DUMMY) ; // dumy to get 1st Byte out
alec1 2:f72110475fec 116 config32 = config32 | data ; // put in 32b reg
alec1 2:f72110475fec 117 data= m_spi.write(DUMMY) ; // dummy to get 2nd Byte out
alec1 2:f72110475fec 118 config32 = (config32 << 8) | data ; // shift and put in reg
alec1 2:f72110475fec 119 m_cs = CS_HIGH ;
alec1 2:f72110475fec 120 return( config32 ) ;
alec1 2:f72110475fec 121 }
alec1 2:f72110475fec 122
alec1 2:f72110475fec 123 uint8_t SPI_MX25R::readSecurity(void)
alec1 2:f72110475fec 124 {
alec1 2:f72110475fec 125 uint8_t data ;
alec1 2:f72110475fec 126 m_cs = CS_LOW ;
alec1 2:f72110475fec 127 m_spi.write(CMD_RDSCUR) ; // send 2Bh
alec1 2:f72110475fec 128 data = m_spi.write(DUMMY) ; // dummy
alec1 2:f72110475fec 129 m_cs = CS_HIGH ;
alec1 2:f72110475fec 130 return( data ) ;
alec1 0:a16ad6f5c788 131 }
alec1 0:a16ad6f5c788 132
alec1 0:a16ad6f5c788 133 uint32_t SPI_MX25R::readID(void)
alec1 0:a16ad6f5c788 134 {
alec1 0:a16ad6f5c788 135 uint8_t data;
alec1 2:f72110475fec 136 uint32_t data32 = 0 ;
alec1 2:f72110475fec 137 m_cs = CS_LOW ;
alec1 1:8403da5975cb 138 m_spi.write(CMD_RDID) ; // send 9Fh
alec1 2:f72110475fec 139 data= m_spi.write(DUMMY) ; // dumy to get 1st Byte out
alec1 2:f72110475fec 140 data32 = data32 | data ; // put in 32b reg
alec1 2:f72110475fec 141 data= m_spi.write(DUMMY) ; // dummy to get 2nd Byte out
alec1 2:f72110475fec 142 data32 = (data32 << 8) | data ; // shift and put in reg
alec1 2:f72110475fec 143 data= m_spi.write(DUMMY) ; // dummy to get 3rd Byte out
alec1 2:f72110475fec 144 data32 = (data32 << 8) | data ; // shift again and put in reg
alec1 2:f72110475fec 145 m_cs = CS_HIGH ;
alec1 2:f72110475fec 146 return( data32 ) ;
alec1 0:a16ad6f5c788 147 }
alec1 0:a16ad6f5c788 148
alec1 2:f72110475fec 149 uint32_t SPI_MX25R::readREMS(void)
alec1 2:f72110475fec 150 {
alec1 2:f72110475fec 151 uint8_t data;
alec1 2:f72110475fec 152 uint32_t data32 = 0 ;
alec1 2:f72110475fec 153 m_cs = CS_LOW ;
alec1 2:f72110475fec 154 m_spi.write(CMD_REMS) ; // send 90h
alec1 2:f72110475fec 155 m_spi.write(DUMMY) ; // send DUMMY1
alec1 2:f72110475fec 156 m_spi.write(DUMMY) ; // send DUMMY2
alec1 2:f72110475fec 157 m_spi.write(0) ; // send address=0x00 to get Manu ID 1st.
alec1 2:f72110475fec 158 data= m_spi.write(DUMMY) ; // dumy to get Manufacturer ID= C2h out
alec1 2:f72110475fec 159 data32 = data32 | data ; // put in 32b reg
alec1 2:f72110475fec 160 data= m_spi.write(DUMMY) ; // dummy to get 2nd Byte = Device ID out
alec1 2:f72110475fec 161 data32 = (data32 << 8) | data ; // shift and put in reg
alec1 2:f72110475fec 162 m_cs = CS_HIGH ;
alec1 2:f72110475fec 163 return( data32 ) ;
alec1 2:f72110475fec 164 }
alec1 2:f72110475fec 165
alec1 2:f72110475fec 166 uint8_t SPI_MX25R::readRES(void)
alec1 2:f72110475fec 167 {
alec1 2:f72110475fec 168 uint8_t data;
alec1 2:f72110475fec 169 m_cs = CS_LOW ;
alec1 2:f72110475fec 170 m_spi.write(CMD_RES) ; // send ABh
alec1 2:f72110475fec 171 m_spi.write(DUMMY) ; // send DUMMY1
alec1 2:f72110475fec 172 m_spi.write(DUMMY) ; // send DUMMY2
alec1 2:f72110475fec 173 m_spi.write(DUMMY) ; // send DUMMY3
alec1 2:f72110475fec 174 data= m_spi.write(DUMMY) ; // dumy to get Electronic Sig. out
alec1 2:f72110475fec 175 m_cs = CS_HIGH ;
alec1 2:f72110475fec 176 return( data ) ;
alec1 2:f72110475fec 177 }
alec1 2:f72110475fec 178
alec1 0:a16ad6f5c788 179 void SPI_MX25R::programPage(int addr, uint8_t *data, int numData)
alec1 0:a16ad6f5c788 180 {
alec1 0:a16ad6f5c788 181 int i ;
alec1 2:f72110475fec 182 m_cs = CS_LOW ;
alec1 1:8403da5975cb 183 m_spi.write(CMD_PP) ; // Program Page 02h
alec1 1:8403da5975cb 184 m_spi.write((addr >> 16)&0xFF) ; // adr 23:16
alec1 1:8403da5975cb 185 m_spi.write((addr >> 8)&0xFF) ; // adr 15:8
alec1 1:8403da5975cb 186 m_spi.write(addr & 0xFF) ; // adr 7:0
alec1 1:8403da5975cb 187 for (i = 0 ; i < numData ; i++ ) { // data = 00, 01, 02, .. to FEh, FFh = all 256 Bytes in 1 page.
alec1 0:a16ad6f5c788 188 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 189 }
alec1 2:f72110475fec 190 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 191 // poll in main
alec1 0:a16ad6f5c788 192 }
alec1 2:f72110475fec 193
alec1 1:8403da5975cb 194 void SPI_MX25R::writeStatusreg(int addr) // Write SR cmd 01h + 3B data
alec1 1:8403da5975cb 195 {
alec1 2:f72110475fec 196 m_cs = CS_LOW ;
alec1 1:8403da5975cb 197 m_spi.write(CMD_WRSR) ; // Write SR cmd 01h
alec1 1:8403da5975cb 198 m_spi.write((addr >> 16)&0xFF) ; // address
alec1 1:8403da5975cb 199 m_spi.write((addr >> 8)&0xFF) ;
alec1 1:8403da5975cb 200 m_spi.write(addr & 0xFF) ;
alec1 2:f72110475fec 201 m_cs = CS_HIGH ;
alec1 2:f72110475fec 202 }
alec1 2:f72110475fec 203
alec1 2:f72110475fec 204 void SPI_MX25R::writeSecurityreg(int addr) // WRSCUR cmd 2Fh + 1B data
alec1 2:f72110475fec 205 {
alec1 2:f72110475fec 206 m_cs = CS_LOW ;
alec1 2:f72110475fec 207 m_spi.write(CMD_WRSCUR) ; // Write SR cmd 01h
alec1 2:f72110475fec 208 m_spi.write(addr & 0xFF) ;
alec1 2:f72110475fec 209 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 210 }
alec1 0:a16ad6f5c788 211
alec1 1:8403da5975cb 212 void SPI_MX25R::blockErase(int addr) // 64KB 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 2:f72110475fec 218 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 219 m_spi.write(CMD_BE) ;
alec1 2:f72110475fec 220 for (int i = 0 ; i < 3 ; i++ ) { // Address setting
alec1 0:a16ad6f5c788 221 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 222 }
alec1 2:f72110475fec 223 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 224 // poll in main
alec1 0:a16ad6f5c788 225 }
alec1 2:f72110475fec 226
alec1 1:8403da5975cb 227 void SPI_MX25R::blockErase32KB(int addr) // 32KB Block 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 2:f72110475fec 233 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 234 m_spi.write(CMD_32KBE) ;
alec1 2:f72110475fec 235 for (int i = 0 ; i < 3 ; i++ ) { // Address Setting
alec1 0:a16ad6f5c788 236 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 237 }
alec1 2:f72110475fec 238 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 239 // poll in main
alec1 0:a16ad6f5c788 240 }
alec1 2:f72110475fec 241
alec1 1:8403da5975cb 242 void SPI_MX25R::sectorErase(int addr) // 4KB Sector Erase
alec1 0:a16ad6f5c788 243 {
alec1 0:a16ad6f5c788 244 uint8_t data[3] ;
alec1 0:a16ad6f5c788 245 data[0] = (addr >> 16) & 0xFF ;
alec1 0:a16ad6f5c788 246 data[1] = (addr >> 8) & 0xFF ;
alec1 0:a16ad6f5c788 247 data[2] = (addr & 0xFF) ;
alec1 2:f72110475fec 248 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 249 m_spi.write(CMD_SE) ;
alec1 2:f72110475fec 250 for (int i = 0 ; i < 3 ; i++ ) { // Address Setting
alec1 0:a16ad6f5c788 251 m_spi.write(data[i]) ;
alec1 0:a16ad6f5c788 252 }
alec1 2:f72110475fec 253 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 254 // poll in main
alec1 0:a16ad6f5c788 255 }
alec1 2:f72110475fec 256
alec1 1:8403da5975cb 257 void SPI_MX25R::chipErase(void) // Chip Erase
alec1 0:a16ad6f5c788 258 {
alec1 2:f72110475fec 259 m_cs = CS_LOW ;
alec1 0:a16ad6f5c788 260 m_spi.write(CMD_CE) ;
alec1 2:f72110475fec 261 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 262 // poll in main
alec1 0:a16ad6f5c788 263 }
alec1 2:f72110475fec 264
alec1 1:8403da5975cb 265 uint8_t SPI_MX25R::read8(int addr) // Single Byte Read
alec1 0:a16ad6f5c788 266 {
alec1 0:a16ad6f5c788 267 uint8_t data ;
alec1 2:f72110475fec 268 m_cs = CS_LOW ;
alec1 1:8403da5975cb 269 m_spi.write(CMD_READ) ; // send 03h
alec1 0:a16ad6f5c788 270 m_spi.write((addr >> 16)&0xFF) ;
alec1 0:a16ad6f5c788 271 m_spi.write((addr >> 8)&0xFF) ;
alec1 0:a16ad6f5c788 272 m_spi.write(addr & 0xFF) ;
alec1 2:f72110475fec 273 data = m_spi.write(DUMMY) ; // write data is dummy
alec1 2:f72110475fec 274 m_cs = CS_HIGH ;
alec1 1:8403da5975cb 275 return( data ) ; // return 1 byte
alec1 1:8403da5975cb 276 }
alec1 2:f72110475fec 277
alec1 2:f72110475fec 278 uint8_t SPI_MX25R::readSFDP(int addr) // Read SFDP
alec1 1:8403da5975cb 279 {
alec1 1:8403da5975cb 280 uint8_t data ;
alec1 2:f72110475fec 281 m_cs = CS_LOW ;
alec1 1:8403da5975cb 282 m_spi.write(CMD_RDSFDP) ; // send cmd 5Ah
alec1 2:f72110475fec 283 m_spi.write((addr >> 16)&0xFF) ; // address[23:16]
alec1 1:8403da5975cb 284 m_spi.write((addr >> 8)&0xFF) ; // address[15:8]
alec1 1:8403da5975cb 285 m_spi.write(addr & 0xFF) ; // address[7:0]
alec1 2:f72110475fec 286 m_spi.write(DUMMY) ; // dummy cycle
alec1 2:f72110475fec 287 data = m_spi.write(DUMMY) ; // return 1 byte
alec1 2:f72110475fec 288 m_cs = CS_HIGH ;
alec1 2:f72110475fec 289 return( data ) ;
alec1 2:f72110475fec 290 }
alec1 2:f72110475fec 291
alec1 2:f72110475fec 292 uint8_t SPI_MX25R::readFREAD(int addr) // x1 Fast Read Data Byte
alec1 2:f72110475fec 293 {
alec1 2:f72110475fec 294 uint8_t data ;
alec1 2:f72110475fec 295 m_cs = CS_LOW ;
alec1 2:f72110475fec 296 m_spi.write(CMD_FREAD) ; // send cmd 0BH
alec1 2:f72110475fec 297 m_spi.write((addr >> 16)&0xFF) ; // address[23:16]
alec1 2:f72110475fec 298 m_spi.write((addr >> 8)&0xFF) ; // address[15:8]
alec1 2:f72110475fec 299 m_spi.write(addr & 0xFF) ; // address[7:0]
alec1 2:f72110475fec 300 m_spi.write(DUMMY) ; // dummy cycle
alec1 2:f72110475fec 301 data = m_spi.write(DUMMY) ; // return 1 byte
alec1 2:f72110475fec 302 m_cs = CS_HIGH ;
alec1 0:a16ad6f5c788 303 return( data ) ;
alec1 0:a16ad6f5c788 304 }
alec1 0:a16ad6f5c788 305
Arkadi 3:b6bb8d236251 306
Arkadi 3:b6bb8d236251 307 void SPI_MX25R::readNBytes(int addr, uint8_t *data, int nBytes) // read sequential n bytes
Arkadi 3:b6bb8d236251 308 {
Arkadi 3:b6bb8d236251 309 int i;
Arkadi 3:b6bb8d236251 310 m_cs = CS_LOW ;
Arkadi 3:b6bb8d236251 311 m_spi.write(CMD_READ) ; // send 03h
Arkadi 3:b6bb8d236251 312 m_spi.write((addr >> 16)&0xFF) ;
Arkadi 3:b6bb8d236251 313 m_spi.write((addr >> 8)&0xFF) ;
Arkadi 3:b6bb8d236251 314 m_spi.write(addr & 0xFF) ;
Arkadi 3:b6bb8d236251 315 for (i = 0 ; i < nBytes ; i++ ) { // data: sequential data bytes
Arkadi 3:b6bb8d236251 316 data[i] = m_spi.write(DUMMY) ;
Arkadi 3:b6bb8d236251 317 }
Arkadi 3:b6bb8d236251 318 m_cs = CS_HIGH ;
Arkadi 3:b6bb8d236251 319 }