Seiji Ainoguchi / SerialFlash

Dependents:   SerialFlashTest

Fork of SerialFlash by Seiji Ainoguchi

Committer:
s_ain
Date:
Wed Mar 02 00:28:03 2011 +0000
Revision:
1:385965a14c7c
Parent:
0:d0117f54a7ee
Child:
2:6f8ab876b516

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
s_ain 0:d0117f54a7ee 1 #include "ISPI.h"
s_ain 0:d0117f54a7ee 2 #include <string.h>
s_ain 0:d0117f54a7ee 3 #include "M25PDeviceImpl.h"
s_ain 0:d0117f54a7ee 4
s_ain 0:d0117f54a7ee 5 const M25PDeviceImpl::DeviceProperty* M25PDeviceImpl::findMatchDevice(ISPI* pSPI)
s_ain 0:d0117f54a7ee 6 {
s_ain 0:d0117f54a7ee 7 int manufacturerId;
s_ain 0:d0117f54a7ee 8 int memoryType;
s_ain 0:d0117f54a7ee 9 int memoryCapacity;
s_ain 0:d0117f54a7ee 10 readId(pSPI, manufacturerId, memoryType, memoryCapacity);
s_ain 0:d0117f54a7ee 11
s_ain 0:d0117f54a7ee 12 struct SupportedDevice
s_ain 0:d0117f54a7ee 13 {
s_ain 0:d0117f54a7ee 14 int manufacturerId;
s_ain 0:d0117f54a7ee 15 int memoryType;
s_ain 0:d0117f54a7ee 16 int memoryCapacity;
s_ain 0:d0117f54a7ee 17 DeviceProperty property;
s_ain 0:d0117f54a7ee 18 } static const supportedDevices[] =
s_ain 0:d0117f54a7ee 19 {
s_ain 0:d0117f54a7ee 20 //M25P16 16MBit (2MB)
s_ain 0:d0117f54a7ee 21 { 0x20, 0x20, 0x15,
s_ain 0:d0117f54a7ee 22 {
s_ain 0:d0117f54a7ee 23 "M25P16",
s_ain 0:d0117f54a7ee 24 16384 * 1024 / 8,
s_ain 0:d0117f54a7ee 25 0xe3,
s_ain 0:d0117f54a7ee 26 },
s_ain 0:d0117f54a7ee 27 },
s_ain 0:d0117f54a7ee 28 //M25P80 8MBit (1MB)
s_ain 0:d0117f54a7ee 29 { 0x20, 0x20, 0x14,
s_ain 0:d0117f54a7ee 30 {
s_ain 0:d0117f54a7ee 31 "M25P80",
s_ain 0:d0117f54a7ee 32 8192 * 1024 / 8,
s_ain 0:d0117f54a7ee 33 0xe3,
s_ain 0:d0117f54a7ee 34 },
s_ain 0:d0117f54a7ee 35 },
s_ain 0:d0117f54a7ee 36 };
s_ain 0:d0117f54a7ee 37 int count = sizeof(supportedDevices) / sizeof(supportedDevices[0]);
s_ain 0:d0117f54a7ee 38 for (int i = 0; i < count; ++i)
s_ain 0:d0117f54a7ee 39 {
s_ain 0:d0117f54a7ee 40 const SupportedDevice& device = supportedDevices[i];
s_ain 0:d0117f54a7ee 41 if (device.manufacturerId == manufacturerId && device.memoryType == memoryType && device.memoryCapacity == memoryCapacity)
s_ain 0:d0117f54a7ee 42 {
s_ain 0:d0117f54a7ee 43 return &device.property;
s_ain 0:d0117f54a7ee 44 }
s_ain 0:d0117f54a7ee 45 }
s_ain 0:d0117f54a7ee 46 return NULL;
s_ain 0:d0117f54a7ee 47 }
s_ain 0:d0117f54a7ee 48
s_ain 0:d0117f54a7ee 49 bool M25PDeviceImpl::IsSupported(ISPI* pSPI)
s_ain 0:d0117f54a7ee 50 {
s_ain 0:d0117f54a7ee 51 return findMatchDevice(pSPI) != NULL;
s_ain 0:d0117f54a7ee 52 }
s_ain 0:d0117f54a7ee 53
s_ain 0:d0117f54a7ee 54 M25PDeviceImpl* M25PDeviceImpl::Create(ISPI* pSPI)
s_ain 0:d0117f54a7ee 55 {
s_ain 0:d0117f54a7ee 56 const DeviceProperty* property = findMatchDevice(pSPI);
s_ain 0:d0117f54a7ee 57 if (property == NULL)
s_ain 0:d0117f54a7ee 58 {
s_ain 0:d0117f54a7ee 59 return NULL;
s_ain 0:d0117f54a7ee 60 }
s_ain 0:d0117f54a7ee 61 return new M25PDeviceImpl(pSPI, *property);
s_ain 0:d0117f54a7ee 62 }
s_ain 0:d0117f54a7ee 63
s_ain 0:d0117f54a7ee 64 M25PDeviceImpl::M25PDeviceImpl(ISPI* pSPI, const DeviceProperty& property)
s_ain 0:d0117f54a7ee 65 : _pSPI(pSPI)
s_ain 0:d0117f54a7ee 66 , _property(property)
s_ain 0:d0117f54a7ee 67 {
s_ain 0:d0117f54a7ee 68 pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 69 clearBlockProtection();
s_ain 0:d0117f54a7ee 70 }
s_ain 0:d0117f54a7ee 71
s_ain 0:d0117f54a7ee 72 M25PDeviceImpl::~M25PDeviceImpl(void)
s_ain 0:d0117f54a7ee 73 {
s_ain 0:d0117f54a7ee 74
s_ain 0:d0117f54a7ee 75 }
s_ain 0:d0117f54a7ee 76
s_ain 0:d0117f54a7ee 77 void M25PDeviceImpl::readId(ISPI* pSPI, int& manufacturerId, int& memoryType, int& memoryCapacity)
s_ain 0:d0117f54a7ee 78 {
s_ain 0:d0117f54a7ee 79 const static int DefaultOperationFrequency = 20000000;
s_ain 0:d0117f54a7ee 80 pSPI->SetFrequency(DefaultOperationFrequency);
s_ain 0:d0117f54a7ee 81
s_ain 0:d0117f54a7ee 82 pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 83 pSPI->Write(0x9f);
s_ain 0:d0117f54a7ee 84 manufacturerId = pSPI->Read();
s_ain 0:d0117f54a7ee 85 memoryType = pSPI->Read();
s_ain 0:d0117f54a7ee 86 memoryCapacity = pSPI->Read();
s_ain 0:d0117f54a7ee 87 pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 88 }
s_ain 0:d0117f54a7ee 89
s_ain 0:d0117f54a7ee 90 int M25PDeviceImpl::readStatusRegister(void)
s_ain 0:d0117f54a7ee 91 {
s_ain 0:d0117f54a7ee 92 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 93 _pSPI->Write(0x05);
s_ain 0:d0117f54a7ee 94 int result = _pSPI->Read();
s_ain 0:d0117f54a7ee 95 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 96 return result;
s_ain 0:d0117f54a7ee 97 }
s_ain 0:d0117f54a7ee 98
s_ain 0:d0117f54a7ee 99 void M25PDeviceImpl::writeStatusRegister(int value)
s_ain 0:d0117f54a7ee 100 {
s_ain 0:d0117f54a7ee 101 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 102 _pSPI->Write(0x01);
s_ain 0:d0117f54a7ee 103 _pSPI->Write(value);
s_ain 0:d0117f54a7ee 104 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 105 }
s_ain 0:d0117f54a7ee 106
s_ain 0:d0117f54a7ee 107 void M25PDeviceImpl::writeEnable()
s_ain 0:d0117f54a7ee 108 {
s_ain 0:d0117f54a7ee 109 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 110 _pSPI->Write(0x06);
s_ain 0:d0117f54a7ee 111 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 112 }
s_ain 0:d0117f54a7ee 113
s_ain 0:d0117f54a7ee 114 void M25PDeviceImpl::writeDisable()
s_ain 0:d0117f54a7ee 115 {
s_ain 0:d0117f54a7ee 116 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 117 _pSPI->Write(0x04);
s_ain 0:d0117f54a7ee 118 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 119 }
s_ain 0:d0117f54a7ee 120
s_ain 0:d0117f54a7ee 121 void M25PDeviceImpl::clearBlockProtection(void)
s_ain 0:d0117f54a7ee 122 {
s_ain 0:d0117f54a7ee 123 writeEnable();
s_ain 0:d0117f54a7ee 124
s_ain 0:d0117f54a7ee 125 int status = readStatusRegister();
s_ain 0:d0117f54a7ee 126 status &= _property.blockProtectionMask;
s_ain 0:d0117f54a7ee 127 writeStatusRegister(status);
s_ain 0:d0117f54a7ee 128 }
s_ain 0:d0117f54a7ee 129
s_ain 0:d0117f54a7ee 130 std::string M25PDeviceImpl::GetDeviceName(void) const
s_ain 0:d0117f54a7ee 131 {
s_ain 0:d0117f54a7ee 132 return _property.deviceName;
s_ain 0:d0117f54a7ee 133 }
s_ain 0:d0117f54a7ee 134
s_ain 0:d0117f54a7ee 135 int M25PDeviceImpl::GetCapacity(void) const
s_ain 0:d0117f54a7ee 136 {
s_ain 0:d0117f54a7ee 137 return _property.capacity;
s_ain 0:d0117f54a7ee 138 }
s_ain 0:d0117f54a7ee 139
s_ain 0:d0117f54a7ee 140 int M25PDeviceImpl::Read(int address, void* buffer, int length)
s_ain 0:d0117f54a7ee 141 {
s_ain 0:d0117f54a7ee 142 if (address >= GetCapacity())
s_ain 0:d0117f54a7ee 143 {
s_ain 0:d0117f54a7ee 144 return 0;
s_ain 0:d0117f54a7ee 145 }
s_ain 0:d0117f54a7ee 146 if (address + length > GetCapacity())
s_ain 0:d0117f54a7ee 147 {
s_ain 0:d0117f54a7ee 148 length = GetCapacity() - address;
s_ain 0:d0117f54a7ee 149 }
s_ain 0:d0117f54a7ee 150 if (length == 0)
s_ain 0:d0117f54a7ee 151 {
s_ain 0:d0117f54a7ee 152 return 0;
s_ain 0:d0117f54a7ee 153 }
s_ain 0:d0117f54a7ee 154
s_ain 0:d0117f54a7ee 155 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 156 _pSPI->Write(0x0b);
s_ain 0:d0117f54a7ee 157 writeAddress(address);
s_ain 0:d0117f54a7ee 158 _pSPI->Write(0xff);
s_ain 0:d0117f54a7ee 159 _pSPI->Read(buffer, length);
s_ain 0:d0117f54a7ee 160 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 161 return length;
s_ain 0:d0117f54a7ee 162 }
s_ain 0:d0117f54a7ee 163
s_ain 0:d0117f54a7ee 164 int M25PDeviceImpl::Write(int address, const void* buffer, int length)
s_ain 0:d0117f54a7ee 165 {
s_ain 0:d0117f54a7ee 166 if (address >= GetCapacity())
s_ain 0:d0117f54a7ee 167 {
s_ain 0:d0117f54a7ee 168 return 0;
s_ain 0:d0117f54a7ee 169 }
s_ain 0:d0117f54a7ee 170 if (address + length > GetCapacity())
s_ain 0:d0117f54a7ee 171 {
s_ain 0:d0117f54a7ee 172 length = GetCapacity() - address;
s_ain 0:d0117f54a7ee 173 }
s_ain 0:d0117f54a7ee 174 if (length == 0)
s_ain 0:d0117f54a7ee 175 {
s_ain 0:d0117f54a7ee 176 return 0;
s_ain 0:d0117f54a7ee 177 }
s_ain 0:d0117f54a7ee 178
s_ain 0:d0117f54a7ee 179 int result = length;
s_ain 0:d0117f54a7ee 180
s_ain 0:d0117f54a7ee 181 const int pageSize = 256;
s_ain 0:d0117f54a7ee 182 const int pageSizeMask = pageSize - 1;
s_ain 0:d0117f54a7ee 183 const int pageAddressMask = ~pageSizeMask;
s_ain 0:d0117f54a7ee 184
s_ain 0:d0117f54a7ee 185 const unsigned char* p = static_cast<const unsigned char*>(buffer);
s_ain 0:d0117f54a7ee 186 if ((address & pageSizeMask) != 0)
s_ain 0:d0117f54a7ee 187 {
s_ain 0:d0117f54a7ee 188 int readLen = address & pageSizeMask;
s_ain 0:d0117f54a7ee 189 int copyLen = pageSize - readLen;
s_ain 0:d0117f54a7ee 190 if (copyLen > length)
s_ain 0:d0117f54a7ee 191 {
s_ain 0:d0117f54a7ee 192 copyLen = length;
s_ain 0:d0117f54a7ee 193 }
s_ain 0:d0117f54a7ee 194 char buf[pageSize];
s_ain 0:d0117f54a7ee 195 int writeAddress = address & pageAddressMask;
s_ain 0:d0117f54a7ee 196 Read(writeAddress, buf, readLen);
s_ain 0:d0117f54a7ee 197 memcpy(&buf[address & pageSizeMask], buffer, copyLen);
s_ain 0:d0117f54a7ee 198 pageProgram(writeAddress, buf);
s_ain 0:d0117f54a7ee 199 p += readLen;
s_ain 0:d0117f54a7ee 200 address += pageSize - readLen;
s_ain 0:d0117f54a7ee 201 length -= copyLen;
s_ain 0:d0117f54a7ee 202 }
s_ain 0:d0117f54a7ee 203 while (length >= pageSize)
s_ain 0:d0117f54a7ee 204 {
s_ain 0:d0117f54a7ee 205 pageProgram(address, p);
s_ain 0:d0117f54a7ee 206 address += pageSize;
s_ain 0:d0117f54a7ee 207 p += pageSize;
s_ain 0:d0117f54a7ee 208 length -= pageSize;
s_ain 0:d0117f54a7ee 209 }
s_ain 0:d0117f54a7ee 210 if (length != 0)
s_ain 0:d0117f54a7ee 211 {
s_ain 0:d0117f54a7ee 212 char buf[pageSize];
s_ain 0:d0117f54a7ee 213 memcpy(buf, p, length);
s_ain 0:d0117f54a7ee 214 memset(&buf[length], 0xff, pageSize - length);
s_ain 0:d0117f54a7ee 215 pageProgram(address, buf);
s_ain 0:d0117f54a7ee 216 }
s_ain 0:d0117f54a7ee 217 return result;
s_ain 0:d0117f54a7ee 218 }
s_ain 0:d0117f54a7ee 219
s_ain 0:d0117f54a7ee 220 void M25PDeviceImpl::BulkErase()
s_ain 0:d0117f54a7ee 221 {
s_ain 0:d0117f54a7ee 222 writeEnable();
s_ain 0:d0117f54a7ee 223
s_ain 0:d0117f54a7ee 224 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 225 _pSPI->Write(0xc7);
s_ain 0:d0117f54a7ee 226 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 227
s_ain 0:d0117f54a7ee 228 while (readStatusRegister() & 0x01)
s_ain 0:d0117f54a7ee 229 ;
s_ain 0:d0117f54a7ee 230
s_ain 0:d0117f54a7ee 231 clearBlockProtection();
s_ain 0:d0117f54a7ee 232 }
s_ain 0:d0117f54a7ee 233
s_ain 0:d0117f54a7ee 234 void M25PDeviceImpl::writeAddress(int address)
s_ain 0:d0117f54a7ee 235 {
s_ain 0:d0117f54a7ee 236 _pSPI->Write((address & 0xff0000) >> 16);
s_ain 0:d0117f54a7ee 237 _pSPI->Write((address & 0xff00) >> 8);
s_ain 0:d0117f54a7ee 238 _pSPI->Write(address & 0xff);
s_ain 0:d0117f54a7ee 239 }
s_ain 0:d0117f54a7ee 240
s_ain 0:d0117f54a7ee 241 void M25PDeviceImpl::pageProgram(int address, const void* buffer)
s_ain 0:d0117f54a7ee 242 {
s_ain 0:d0117f54a7ee 243 writeEnable();
s_ain 0:d0117f54a7ee 244
s_ain 0:d0117f54a7ee 245 _pSPI->ChangeCS(ISPI::Low);
s_ain 0:d0117f54a7ee 246 _pSPI->Write(0x02);
s_ain 0:d0117f54a7ee 247 writeAddress(address);
s_ain 1:385965a14c7c 248 _pSPI->Write(buffer, 256);
s_ain 0:d0117f54a7ee 249 _pSPI->ChangeCS(ISPI::High);
s_ain 0:d0117f54a7ee 250
s_ain 0:d0117f54a7ee 251 while (readStatusRegister() & 0x01)
s_ain 0:d0117f54a7ee 252 ;
s_ain 0:d0117f54a7ee 253 }