Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SerialFlash by
SST25DeviceImpl.cpp
- Committer:
- s_ain
- Date:
- 2011-03-02
- Revision:
- 2:6f8ab876b516
- Parent:
- 1:385965a14c7c
File content as of revision 2:6f8ab876b516:
#include "ISPICommand.h"
#include <string.h>
#include "SST25DeviceImpl.h"
const SST25DeviceImpl::DeviceProperty* SST25DeviceImpl::findMatchDevice(ISPICommand* pSPICommand)
{
int manufacturersId;
int deviceId;
readId(pSPICommand, manufacturersId, deviceId);
struct SupportedDevice
{
int manufacturersId;
int deviceId;
DeviceProperty property;
} static const supportedDevices[] =
{
//SST25xF512A 512KBit (64KByte)
{ 0xbf, 0x48,
{
"SST25xF512A",
512 * 1024 / 8,
0xf3,
1,
&SST25DeviceImpl::writeAAI,
33000000
},
},
//SST25xF010A 1MBit (128KByte)
{ 0xbf, 0x49,
{
"SST25xF010A",
1024 * 1024 / 8,
0xf3,
1,
&SST25DeviceImpl::writeAAI,
33000000
},
},
//SST25xF020A 2MBit (256KByte)
{ 0xbf, 0x43,
{
"SST25xF020A",
2048 * 1024 / 8,
0xf3,
1,
&SST25DeviceImpl::writeAAI,
33000000
},
},
//SST25xF040B 4MBit (512KByte)
{ 0xbf, 0x8d,
{
"SST25xF040B",
4096 * 1024 / 8,
0xe3,
1,
&SST25DeviceImpl::writeAAIWord,
50000000
},
},
//SST25xF080B 8MBit (1MByte)
{ 0xbf, 0x8e,
{
"SST25xF080B",
8192 * 1024 / 8,
0xe3,
1,
&SST25DeviceImpl::writeAAIWord,
50000000
},
},
//SST25xF016B 16MBit (2MByte)
{ 0xbf, 0x41,
{
"SST25xF016B",
16384 * 1024 / 8,
0xe3,
1,
&SST25DeviceImpl::writeAAIWord,
50000000
},
},
//SST25xF032B 32MBit (4MByte)
{ 0xbf, 0x4a,
{
"SST25xF032B",
32768 * 1024 / 8,
0xc3,
1,
&SST25DeviceImpl::writeAAIWord,
50000000
},
},
//SST25xF064C 64MBit (8MByte)
{ 0xbf, 0x4b,
{
"SST25xF064C",
65536 * 1024 / 8,
0xc3,
256,
&SST25DeviceImpl::writePage,
50000000
},
}
};
int count = sizeof(supportedDevices) / sizeof(supportedDevices[0]);
for (int i = 0; i < count; ++i)
{
const SupportedDevice& device = supportedDevices[i];
if (device.manufacturersId == manufacturersId && device.deviceId == deviceId)
{
return &device.property;
}
}
return NULL;
}
bool SST25DeviceImpl::IsSupported(ISPICommand* pSPICommand)
{
return findMatchDevice(pSPICommand) != NULL;
}
SST25DeviceImpl* SST25DeviceImpl::Create(ISPICommand* pSPICommand)
{
const DeviceProperty* property = findMatchDevice(pSPICommand);
if (property == NULL)
{
return NULL;
}
return new SST25DeviceImpl(pSPICommand, *property);
}
SST25DeviceImpl::SST25DeviceImpl(ISPICommand* pSPICommand, const DeviceProperty& property)
: _pSPICommand(pSPICommand)
, _property(property)
{
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
}
SST25DeviceImpl::~SST25DeviceImpl(void)
{
}
void SST25DeviceImpl::readId(ISPICommand* pSPICommand, int& manufacturersId, int& deviceId)
{
const static int DefaultOperationFrequency = 20000000;
pSPICommand->SetMaxFrequency(DefaultOperationFrequency);
unsigned char read[2];
char param[3];
fillAddress(param, 0x000000);
pSPICommand->Read(0x90, param, sizeof(param), read, sizeof(read));
manufacturersId = read[0];
deviceId = read[1];
}
int SST25DeviceImpl::readStatusRegister(void)
{
unsigned char read;
_pSPICommand->Read(0x05, &read, 1);
return read;
}
void SST25DeviceImpl::writeStatusRegister(int value)
{
_pSPICommand->Write(0x50);
char vb = static_cast<char>(value);
_pSPICommand->Write(0x01, &vb, sizeof(vb));
}
void SST25DeviceImpl::writeEnable()
{
int status = readStatusRegister();
status &= _property.blockProtectionMask;
writeStatusRegister(status);
_pSPICommand->Write(0x06);
}
void SST25DeviceImpl::writeDisable()
{
_pSPICommand->Write(0x04);
}
void SST25DeviceImpl::waitForReady()
{
while (readStatusRegister() & 0x01)
;
}
std::string SST25DeviceImpl::GetDeviceName(void) const
{
return _property.deviceName;
}
int SST25DeviceImpl::GetCapacity(void) const
{
return _property.capacity;
}
int SST25DeviceImpl::Read(int address, void* buffer, int length)
{
if (address >= GetCapacity())
{
return 0;
}
if (address + length > GetCapacity())
{
length = GetCapacity() - address;
}
if (length == 0)
{
return 0;
}
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
char param[] = { 0, 0, 0, 0xff };
fillAddress(param, address);
_pSPICommand->Read(0x0b, param, sizeof(param), buffer, length);
return length;
}
int SST25DeviceImpl::Write(int address, const void* buffer, int length)
{
if (address >= GetCapacity())
{
return 0;
}
if (address + length > GetCapacity())
{
length = GetCapacity() - address;
}
if (length == 0)
{
return 0;
}
(this->*_property.pfnWriter)(address, buffer, length);
return length;
}
void SST25DeviceImpl::ChipErase()
{
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
writeEnable();
_pSPICommand->Write(0x60);
waitForReady();
}
void SST25DeviceImpl::byteProgram(int address, int value)
{
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
writeEnable();
char param[] = { 0, 0, 0, value };
fillAddress(param, address);
_pSPICommand->Write(0x02, param, sizeof(param));
waitForReady();
}
void SST25DeviceImpl::beginAAIProgram(int address, int data)
{
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
writeEnable();
char param[] = { 0, 0, 0, data };
fillAddress(param, address);
_pSPICommand->Write(0xaf, param, sizeof(param));
waitForReady();
}
void SST25DeviceImpl::nextAAIProgram(int data)
{
char param = static_cast<char>(data);
_pSPICommand->Write(0xaf, ¶m, 1);
waitForReady();
}
void SST25DeviceImpl::endAAIProgram(void)
{
_pSPICommand->Write(0x04);
waitForReady();
}
void SST25DeviceImpl::beginAAIWordProgram(int address, int data)
{
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
writeEnable();
char param[] = { 0, 0, 0, (data & 0xff00) >> 8, data & 0xff };
fillAddress(param, address);
_pSPICommand->Write(0xad, param, sizeof(param));
waitForReady();
}
void SST25DeviceImpl::nextAAIWordProgram(int data)
{
char param[] = { (data & 0xff00) >> 8, data & 0xff };
_pSPICommand->Write(0xad, param, sizeof(param));
waitForReady();
}
void SST25DeviceImpl::fillAddress(char* pBuffer, int address)
{
*(pBuffer + 0) = (address & 0xff0000) >> 16;
*(pBuffer + 1) = (address & 0x00ff00) >> 8;
*(pBuffer + 2) = (address & 0x0000ff);
}
void SST25DeviceImpl::pageProgram(int address, const void* buffer)
{
_pSPICommand->SetMaxFrequency(_property.operationClkHz);
writeEnable();
char param[256 + 3];
fillAddress(param, address);
memcpy(param + 3, buffer, 256);
_pSPICommand->Write(0x02, param, sizeof(param));
waitForReady();
}
void SST25DeviceImpl::writePage(int address, const void* buffer, int length)
{
int pageSize = _property.pageSize;
int pageSizeMask = pageSize - 1;
int pageAddressMask = ~pageSizeMask;
if (length <= 0)
{
return;
}
const unsigned char* p = static_cast<const unsigned char*>(buffer);
if ((address & pageSizeMask) != 0)
{
int readLen = address & pageSizeMask;
int copyLen = pageSize - readLen;
if (copyLen > length)
{
copyLen = length;
}
char buf[pageSize];
int writeAddress = address & pageAddressMask;
Read(writeAddress, buf, readLen);
memcpy(&buf[address & pageSizeMask], buffer, copyLen);
pageProgram(writeAddress, buf);
p += readLen;
address += pageSize - readLen;
length -= copyLen;
}
while (length >= pageSize)
{
pageProgram(address, p);
address += pageSize;
p += pageSize;
length -= pageSize;
}
if (length != 0)
{
char buf[pageSize];
memcpy(buf, p, length);
memset(&buf[length], 0xff, pageSize - length);
pageProgram(address, buf);
}
}
void SST25DeviceImpl::writeBytes(int address, const void* buffer, int length)
{
const unsigned char* p = static_cast<const unsigned char*>(buffer);
while (length-- >= 0)
{
byteProgram(address++, *p++);
}
}
void SST25DeviceImpl::writeAAI(int address, const void* buffer, int length)
{
if (length <= 0)
{
return;
}
const unsigned char* p = static_cast<const unsigned char*>(buffer);
if (length < 2)
{
byteProgram(address, *p);
return;
}
beginAAIProgram(address, *p++);
while (--length != 0)
{
nextAAIProgram(*p++);
}
endAAIProgram();
}
void SST25DeviceImpl::writeAAIWord(int address, const void* buffer, int length)
{
if (length <= 0)
{
return;
}
const unsigned char* p = static_cast<const unsigned char*>(buffer);
if ((address & 0x1) != 0)
{
byteProgram(address++, *p++);
length--;
}
if (length < 4)
{
writeBytes(address, p, length);
return;
}
beginAAIWordProgram(address, (*p << 8) | *(p + 1));
address += length & ~0x1;
p += 2;
length -= 2;
do
{
nextAAIWordProgram((*p << 8) | *(p + 1));
p += 2;
length -= 2;
} while (length >= 2);
endAAIProgram();
if (length != 0)
{
byteProgram(address, *p);
}
}
