Seiji Ainoguchi / SerialFlash

Dependents:   SerialFlashTest

Fork of SerialFlash by Seiji Ainoguchi

Committer:
s_ain
Date:
Wed Mar 02 16:09:09 2011 +0000
Revision:
2:6f8ab876b516
Parent:
1:385965a14c7c
change SPI interface

Who changed what in which revision?

UserRevisionLine numberNew contents of line
s_ain 2:6f8ab876b516 1 #include "ISPICommand.h"
s_ain 0:d0117f54a7ee 2 #include <string.h>
s_ain 0:d0117f54a7ee 3 #include "M25PDeviceImpl.h"
s_ain 0:d0117f54a7ee 4
s_ain 2:6f8ab876b516 5 const M25PDeviceImpl::DeviceProperty* M25PDeviceImpl::findMatchDevice(ISPICommand* pSPICommand)
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 2:6f8ab876b516 10 readId(pSPICommand, 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 2:6f8ab876b516 49 bool M25PDeviceImpl::IsSupported(ISPICommand* pSPICommand)
s_ain 0:d0117f54a7ee 50 {
s_ain 2:6f8ab876b516 51 return findMatchDevice(pSPICommand) != NULL;
s_ain 0:d0117f54a7ee 52 }
s_ain 0:d0117f54a7ee 53
s_ain 2:6f8ab876b516 54 M25PDeviceImpl* M25PDeviceImpl::Create(ISPICommand* pSPICommand)
s_ain 0:d0117f54a7ee 55 {
s_ain 2:6f8ab876b516 56 const DeviceProperty* property = findMatchDevice(pSPICommand);
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 2:6f8ab876b516 61 return new M25PDeviceImpl(pSPICommand, *property);
s_ain 0:d0117f54a7ee 62 }
s_ain 0:d0117f54a7ee 63
s_ain 2:6f8ab876b516 64 M25PDeviceImpl::M25PDeviceImpl(ISPICommand* pSPICommand, const DeviceProperty& property)
s_ain 2:6f8ab876b516 65 : _pSPICommand(pSPICommand)
s_ain 0:d0117f54a7ee 66 , _property(property)
s_ain 0:d0117f54a7ee 67 {
s_ain 0:d0117f54a7ee 68 clearBlockProtection();
s_ain 0:d0117f54a7ee 69 }
s_ain 0:d0117f54a7ee 70
s_ain 0:d0117f54a7ee 71 M25PDeviceImpl::~M25PDeviceImpl(void)
s_ain 0:d0117f54a7ee 72 {
s_ain 0:d0117f54a7ee 73
s_ain 0:d0117f54a7ee 74 }
s_ain 0:d0117f54a7ee 75
s_ain 2:6f8ab876b516 76 void M25PDeviceImpl::readId(ISPICommand* pSPICommand, int& manufacturerId, int& memoryType, int& memoryCapacity)
s_ain 0:d0117f54a7ee 77 {
s_ain 0:d0117f54a7ee 78 const static int DefaultOperationFrequency = 20000000;
s_ain 2:6f8ab876b516 79 pSPICommand->SetMaxFrequency(DefaultOperationFrequency);
s_ain 0:d0117f54a7ee 80
s_ain 2:6f8ab876b516 81 unsigned char id[3];
s_ain 2:6f8ab876b516 82 pSPICommand->Read(0x9f, id, sizeof(id));
s_ain 2:6f8ab876b516 83 manufacturerId = id[0];
s_ain 2:6f8ab876b516 84 memoryType = id[1];
s_ain 2:6f8ab876b516 85 memoryCapacity = id[2];
s_ain 0:d0117f54a7ee 86 }
s_ain 0:d0117f54a7ee 87
s_ain 0:d0117f54a7ee 88 int M25PDeviceImpl::readStatusRegister(void)
s_ain 0:d0117f54a7ee 89 {
s_ain 2:6f8ab876b516 90 unsigned char status;
s_ain 2:6f8ab876b516 91 _pSPICommand->Read(0x05, &status, 1);
s_ain 2:6f8ab876b516 92 return status;
s_ain 0:d0117f54a7ee 93 }
s_ain 0:d0117f54a7ee 94
s_ain 0:d0117f54a7ee 95 void M25PDeviceImpl::writeStatusRegister(int value)
s_ain 0:d0117f54a7ee 96 {
s_ain 2:6f8ab876b516 97 char vb = static_cast<char>(value);
s_ain 2:6f8ab876b516 98 _pSPICommand->Write(0x01, &vb, 1);
s_ain 0:d0117f54a7ee 99 }
s_ain 0:d0117f54a7ee 100
s_ain 0:d0117f54a7ee 101 void M25PDeviceImpl::writeEnable()
s_ain 0:d0117f54a7ee 102 {
s_ain 2:6f8ab876b516 103 _pSPICommand->Write(0x06);
s_ain 0:d0117f54a7ee 104 }
s_ain 0:d0117f54a7ee 105
s_ain 0:d0117f54a7ee 106 void M25PDeviceImpl::writeDisable()
s_ain 0:d0117f54a7ee 107 {
s_ain 2:6f8ab876b516 108 _pSPICommand->Write(0x04);
s_ain 0:d0117f54a7ee 109 }
s_ain 0:d0117f54a7ee 110
s_ain 0:d0117f54a7ee 111 void M25PDeviceImpl::clearBlockProtection(void)
s_ain 0:d0117f54a7ee 112 {
s_ain 0:d0117f54a7ee 113 writeEnable();
s_ain 0:d0117f54a7ee 114
s_ain 0:d0117f54a7ee 115 int status = readStatusRegister();
s_ain 0:d0117f54a7ee 116 status &= _property.blockProtectionMask;
s_ain 0:d0117f54a7ee 117 writeStatusRegister(status);
s_ain 0:d0117f54a7ee 118 }
s_ain 0:d0117f54a7ee 119
s_ain 0:d0117f54a7ee 120 std::string M25PDeviceImpl::GetDeviceName(void) const
s_ain 0:d0117f54a7ee 121 {
s_ain 0:d0117f54a7ee 122 return _property.deviceName;
s_ain 0:d0117f54a7ee 123 }
s_ain 0:d0117f54a7ee 124
s_ain 0:d0117f54a7ee 125 int M25PDeviceImpl::GetCapacity(void) const
s_ain 0:d0117f54a7ee 126 {
s_ain 0:d0117f54a7ee 127 return _property.capacity;
s_ain 0:d0117f54a7ee 128 }
s_ain 0:d0117f54a7ee 129
s_ain 0:d0117f54a7ee 130 int M25PDeviceImpl::Read(int address, void* buffer, int length)
s_ain 0:d0117f54a7ee 131 {
s_ain 0:d0117f54a7ee 132 if (address >= GetCapacity())
s_ain 0:d0117f54a7ee 133 {
s_ain 0:d0117f54a7ee 134 return 0;
s_ain 0:d0117f54a7ee 135 }
s_ain 0:d0117f54a7ee 136 if (address + length > GetCapacity())
s_ain 0:d0117f54a7ee 137 {
s_ain 0:d0117f54a7ee 138 length = GetCapacity() - address;
s_ain 0:d0117f54a7ee 139 }
s_ain 0:d0117f54a7ee 140 if (length == 0)
s_ain 0:d0117f54a7ee 141 {
s_ain 0:d0117f54a7ee 142 return 0;
s_ain 0:d0117f54a7ee 143 }
s_ain 0:d0117f54a7ee 144
s_ain 2:6f8ab876b516 145 char param[] = { 0, 0, 0, 0xff };
s_ain 2:6f8ab876b516 146 fillAddress(param, address);
s_ain 2:6f8ab876b516 147 _pSPICommand->Read(0x0b, param, sizeof(param), buffer, length);
s_ain 0:d0117f54a7ee 148 return length;
s_ain 0:d0117f54a7ee 149 }
s_ain 0:d0117f54a7ee 150
s_ain 2:6f8ab876b516 151 void M25PDeviceImpl::fillAddress(char* pBuffer, int address)
s_ain 2:6f8ab876b516 152 {
s_ain 2:6f8ab876b516 153 *(pBuffer + 0) = (address & 0xff0000) >> 16;
s_ain 2:6f8ab876b516 154 *(pBuffer + 1) = (address & 0x00ff00) >> 8;
s_ain 2:6f8ab876b516 155 *(pBuffer + 2) = (address & 0x0000ff);
s_ain 2:6f8ab876b516 156 }
s_ain 2:6f8ab876b516 157
s_ain 0:d0117f54a7ee 158 int M25PDeviceImpl::Write(int address, const void* buffer, int length)
s_ain 0:d0117f54a7ee 159 {
s_ain 0:d0117f54a7ee 160 if (address >= GetCapacity())
s_ain 0:d0117f54a7ee 161 {
s_ain 0:d0117f54a7ee 162 return 0;
s_ain 0:d0117f54a7ee 163 }
s_ain 0:d0117f54a7ee 164 if (address + length > GetCapacity())
s_ain 0:d0117f54a7ee 165 {
s_ain 0:d0117f54a7ee 166 length = GetCapacity() - address;
s_ain 0:d0117f54a7ee 167 }
s_ain 0:d0117f54a7ee 168 if (length == 0)
s_ain 0:d0117f54a7ee 169 {
s_ain 0:d0117f54a7ee 170 return 0;
s_ain 0:d0117f54a7ee 171 }
s_ain 0:d0117f54a7ee 172
s_ain 0:d0117f54a7ee 173 int result = length;
s_ain 0:d0117f54a7ee 174
s_ain 0:d0117f54a7ee 175 const int pageSize = 256;
s_ain 0:d0117f54a7ee 176 const int pageSizeMask = pageSize - 1;
s_ain 0:d0117f54a7ee 177 const int pageAddressMask = ~pageSizeMask;
s_ain 0:d0117f54a7ee 178
s_ain 0:d0117f54a7ee 179 const unsigned char* p = static_cast<const unsigned char*>(buffer);
s_ain 0:d0117f54a7ee 180 if ((address & pageSizeMask) != 0)
s_ain 0:d0117f54a7ee 181 {
s_ain 0:d0117f54a7ee 182 int readLen = address & pageSizeMask;
s_ain 0:d0117f54a7ee 183 int copyLen = pageSize - readLen;
s_ain 0:d0117f54a7ee 184 if (copyLen > length)
s_ain 0:d0117f54a7ee 185 {
s_ain 0:d0117f54a7ee 186 copyLen = length;
s_ain 0:d0117f54a7ee 187 }
s_ain 0:d0117f54a7ee 188 char buf[pageSize];
s_ain 0:d0117f54a7ee 189 int writeAddress = address & pageAddressMask;
s_ain 0:d0117f54a7ee 190 Read(writeAddress, buf, readLen);
s_ain 0:d0117f54a7ee 191 memcpy(&buf[address & pageSizeMask], buffer, copyLen);
s_ain 0:d0117f54a7ee 192 pageProgram(writeAddress, buf);
s_ain 0:d0117f54a7ee 193 p += readLen;
s_ain 0:d0117f54a7ee 194 address += pageSize - readLen;
s_ain 0:d0117f54a7ee 195 length -= copyLen;
s_ain 0:d0117f54a7ee 196 }
s_ain 0:d0117f54a7ee 197 while (length >= pageSize)
s_ain 0:d0117f54a7ee 198 {
s_ain 0:d0117f54a7ee 199 pageProgram(address, p);
s_ain 0:d0117f54a7ee 200 address += pageSize;
s_ain 0:d0117f54a7ee 201 p += pageSize;
s_ain 0:d0117f54a7ee 202 length -= pageSize;
s_ain 0:d0117f54a7ee 203 }
s_ain 0:d0117f54a7ee 204 if (length != 0)
s_ain 0:d0117f54a7ee 205 {
s_ain 0:d0117f54a7ee 206 char buf[pageSize];
s_ain 0:d0117f54a7ee 207 memcpy(buf, p, length);
s_ain 0:d0117f54a7ee 208 memset(&buf[length], 0xff, pageSize - length);
s_ain 0:d0117f54a7ee 209 pageProgram(address, buf);
s_ain 0:d0117f54a7ee 210 }
s_ain 0:d0117f54a7ee 211 return result;
s_ain 0:d0117f54a7ee 212 }
s_ain 0:d0117f54a7ee 213
s_ain 0:d0117f54a7ee 214 void M25PDeviceImpl::BulkErase()
s_ain 0:d0117f54a7ee 215 {
s_ain 0:d0117f54a7ee 216 writeEnable();
s_ain 0:d0117f54a7ee 217
s_ain 2:6f8ab876b516 218 _pSPICommand->Write(0xc7);
s_ain 2:6f8ab876b516 219
s_ain 0:d0117f54a7ee 220 while (readStatusRegister() & 0x01)
s_ain 0:d0117f54a7ee 221 ;
s_ain 0:d0117f54a7ee 222
s_ain 0:d0117f54a7ee 223 clearBlockProtection();
s_ain 0:d0117f54a7ee 224 }
s_ain 0:d0117f54a7ee 225
s_ain 0:d0117f54a7ee 226 void M25PDeviceImpl::pageProgram(int address, const void* buffer)
s_ain 0:d0117f54a7ee 227 {
s_ain 0:d0117f54a7ee 228 writeEnable();
s_ain 0:d0117f54a7ee 229
s_ain 2:6f8ab876b516 230 char param[256 + 3];
s_ain 2:6f8ab876b516 231 fillAddress(param, address);
s_ain 2:6f8ab876b516 232 memcpy(param + 3, buffer, 256);
s_ain 2:6f8ab876b516 233 _pSPICommand->Write(0x02, param, sizeof(param));
s_ain 0:d0117f54a7ee 234
s_ain 0:d0117f54a7ee 235 while (readStatusRegister() & 0x01)
s_ain 0:d0117f54a7ee 236 ;
s_ain 0:d0117f54a7ee 237 }