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
Diff: SST25DeviceImpl.cpp
- Revision:
- 0:d0117f54a7ee
- Child:
- 1:385965a14c7c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SST25DeviceImpl.cpp Tue Mar 01 15:44:13 2011 +0000
@@ -0,0 +1,478 @@
+#include "ISPI.h"
+#include <string.h>
+#include "SST25DeviceImpl.h"
+
+const SST25DeviceImpl::DeviceProperty* SST25DeviceImpl::findMatchDevice(ISPI* pSPI)
+{
+ int manufacturersId;
+ int deviceId;
+ readId(pSPI, 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,
+ 46000000
+ },
+ },
+ //SST25xF080B 8MBit (1MByte)
+ { 0xbf, 0x8e,
+ {
+ "SST25xF080B",
+ 8192 * 1024 / 8,
+ 0xe3,
+ 1,
+ &SST25DeviceImpl::writeAAIWord,
+ 46000000
+ },
+ },
+ //SST25xF016B 16MBit (2MByte)
+ { 0xbf, 0x41,
+ {
+ "SST25xF016B",
+ 16384 * 1024 / 8,
+ 0xe3,
+ 1,
+ &SST25DeviceImpl::writeAAIWord,
+ 46000000
+ },
+ },
+ //SST25xF032B 32MBit (4MByte)
+ { 0xbf, 0x4a,
+ {
+ "SST25xF032B",
+ 32768 * 1024 / 8,
+ 0xc3,
+ 1,
+ &SST25DeviceImpl::writeAAIWord,
+ 46000000
+ },
+ },
+ //SST25xF064C 64MBit (8MByte)
+ { 0xbf, 0x4b,
+ {
+ "SST25xF064C",
+ 65536 * 1024 / 8,
+ 0xc3,
+ 256,
+ &SST25DeviceImpl::writePage,
+ 46000000
+ },
+ }
+ };
+ 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(ISPI* pSPI)
+{
+ return findMatchDevice(pSPI) != NULL;
+}
+
+SST25DeviceImpl* SST25DeviceImpl::Create(ISPI* pSPI)
+{
+ const DeviceProperty* property = findMatchDevice(pSPI);
+ if (property == NULL)
+ {
+ return NULL;
+ }
+ return new SST25DeviceImpl(pSPI, *property);
+}
+
+SST25DeviceImpl::SST25DeviceImpl(ISPI* pSPI, const DeviceProperty& property)
+ : _pSPI(pSPI)
+ , _property(property)
+{
+ _pSPI->ChangeCS(ISPI::High);
+ _pSPI->SetFrequency(_property.operationClkHz);
+}
+
+SST25DeviceImpl::~SST25DeviceImpl(void)
+{
+
+}
+
+void SST25DeviceImpl::readId(ISPI* pSPI, int& manufacturersId, int& deviceId)
+{
+ const static int DefaultOperationFrequency = 20000000;
+ pSPI->SetFrequency(DefaultOperationFrequency);
+
+ pSPI->ChangeCS(ISPI::Low);
+ pSPI->Write(0x90);
+ pSPI->Write(0x00);
+ pSPI->Write(0x00);
+ pSPI->Write(0x00);
+ manufacturersId = pSPI->Read();
+ deviceId = pSPI->Read();
+ pSPI->ChangeCS(ISPI::High);
+}
+
+int SST25DeviceImpl::readStatusRegister(void)
+{
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x05);
+ int result = _pSPI->Read();
+ _pSPI->ChangeCS(ISPI::High);
+ return result;
+}
+
+void SST25DeviceImpl::writeStatusRegister(int value)
+{
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x50);
+ _pSPI->ChangeCS(ISPI::High);
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x01);
+ _pSPI->Write(value);
+ _pSPI->ChangeCS(ISPI::High);
+}
+
+void SST25DeviceImpl::writeEnable()
+{
+ int status = readStatusRegister();
+ status &= _property.blockProtectionMask;
+ writeStatusRegister(status);
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x06);
+ _pSPI->ChangeCS(ISPI::High);
+}
+
+void SST25DeviceImpl::writeDisable()
+{
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x04);
+ _pSPI->ChangeCS(ISPI::High);
+}
+
+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;
+ }
+
+ _pSPI->SetFrequency(_property.operationClkHz);
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x0b);
+ writeAddress(address);
+ _pSPI->Write(0xff);
+ _pSPI->Read(buffer, length);
+ _pSPI->ChangeCS(ISPI::High);
+ 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()
+{
+ _pSPI->SetFrequency(_property.operationClkHz);
+
+ writeEnable();
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x60);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::byteProgram(int address, int value)
+{
+ _pSPI->SetFrequency(_property.operationClkHz);
+
+ writeEnable();
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x02);
+ writeAddress(address);
+ _pSPI->Write(value);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::beginAAIProgram(int address, int data)
+{
+ _pSPI->SetFrequency(_property.operationClkHz);
+
+ writeEnable();
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0xaf);
+ writeAddress(address);
+ _pSPI->Write(data);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::nextAAIProgram(int data)
+{
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0xaf);
+ _pSPI->Write(data);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::endAAIProgram(void)
+{
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x04);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::beginAAIWordProgram(int address, int data)
+{
+ _pSPI->SetFrequency(_property.operationClkHz);
+
+ writeEnable();
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0xad);
+ writeAddress(address);
+ _pSPI->Write((data & 0xff00) >> 8);
+ _pSPI->Write(data & 0xff);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::nextAAIWordProgram(int data)
+{
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0xad);
+ _pSPI->Write((data & 0xff00) >> 8);
+ _pSPI->Write(data & 0xff);
+ _pSPI->ChangeCS(ISPI::High);
+ waitForReady();
+}
+
+void SST25DeviceImpl::writeAddress(int address)
+{
+ _pSPI->Write((address & 0xff0000) >> 16);
+ _pSPI->Write((address & 0xff00) >> 8);
+ _pSPI->Write(address & 0xff);
+}
+
+void SST25DeviceImpl::pageProgram(int address, const void* buffer)
+{
+ _pSPI->SetFrequency(_property.operationClkHz);
+
+ const unsigned char* p = static_cast<const unsigned char*>(buffer);
+
+ writeEnable();
+
+ _pSPI->ChangeCS(ISPI::Low);
+ _pSPI->Write(0x02);
+ writeAddress(address);
+ _pSPI->Write(p, 256);
+ _pSPI->ChangeCS(ISPI::High);
+ 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);
+ }
+}
