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@1:385965a14c7c, 2011-03-02 (annotated)
- 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?
| User | Revision | Line number | New 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 "SST25DeviceImpl.h" |
| s_ain | 0:d0117f54a7ee | 4 | |
| s_ain | 0:d0117f54a7ee | 5 | const SST25DeviceImpl::DeviceProperty* SST25DeviceImpl::findMatchDevice(ISPI* pSPI) |
| s_ain | 0:d0117f54a7ee | 6 | { |
| s_ain | 0:d0117f54a7ee | 7 | int manufacturersId; |
| s_ain | 0:d0117f54a7ee | 8 | int deviceId; |
| s_ain | 0:d0117f54a7ee | 9 | readId(pSPI, manufacturersId, deviceId); |
| s_ain | 0:d0117f54a7ee | 10 | |
| s_ain | 0:d0117f54a7ee | 11 | struct SupportedDevice |
| s_ain | 0:d0117f54a7ee | 12 | { |
| s_ain | 0:d0117f54a7ee | 13 | int manufacturersId; |
| s_ain | 0:d0117f54a7ee | 14 | int deviceId; |
| s_ain | 0:d0117f54a7ee | 15 | DeviceProperty property; |
| s_ain | 0:d0117f54a7ee | 16 | } static const supportedDevices[] = |
| s_ain | 0:d0117f54a7ee | 17 | { |
| s_ain | 0:d0117f54a7ee | 18 | //SST25xF512A 512KBit (64KByte) |
| s_ain | 0:d0117f54a7ee | 19 | { 0xbf, 0x48, |
| s_ain | 0:d0117f54a7ee | 20 | { |
| s_ain | 0:d0117f54a7ee | 21 | "SST25xF512A", |
| s_ain | 0:d0117f54a7ee | 22 | 512 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 23 | 0xf3, |
| s_ain | 0:d0117f54a7ee | 24 | 1, |
| s_ain | 0:d0117f54a7ee | 25 | &SST25DeviceImpl::writeAAI, |
| s_ain | 0:d0117f54a7ee | 26 | 33000000 |
| s_ain | 0:d0117f54a7ee | 27 | }, |
| s_ain | 0:d0117f54a7ee | 28 | }, |
| s_ain | 0:d0117f54a7ee | 29 | //SST25xF010A 1MBit (128KByte) |
| s_ain | 0:d0117f54a7ee | 30 | { 0xbf, 0x49, |
| s_ain | 0:d0117f54a7ee | 31 | { |
| s_ain | 0:d0117f54a7ee | 32 | "SST25xF010A", |
| s_ain | 0:d0117f54a7ee | 33 | 1024 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 34 | 0xf3, |
| s_ain | 0:d0117f54a7ee | 35 | 1, |
| s_ain | 0:d0117f54a7ee | 36 | &SST25DeviceImpl::writeAAI, |
| s_ain | 0:d0117f54a7ee | 37 | 33000000 |
| s_ain | 0:d0117f54a7ee | 38 | }, |
| s_ain | 0:d0117f54a7ee | 39 | }, |
| s_ain | 0:d0117f54a7ee | 40 | //SST25xF020A 2MBit (256KByte) |
| s_ain | 0:d0117f54a7ee | 41 | { 0xbf, 0x43, |
| s_ain | 0:d0117f54a7ee | 42 | { |
| s_ain | 0:d0117f54a7ee | 43 | "SST25xF020A", |
| s_ain | 0:d0117f54a7ee | 44 | 2048 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 45 | 0xf3, |
| s_ain | 0:d0117f54a7ee | 46 | 1, |
| s_ain | 0:d0117f54a7ee | 47 | &SST25DeviceImpl::writeAAI, |
| s_ain | 0:d0117f54a7ee | 48 | 33000000 |
| s_ain | 0:d0117f54a7ee | 49 | }, |
| s_ain | 0:d0117f54a7ee | 50 | }, |
| s_ain | 0:d0117f54a7ee | 51 | //SST25xF040B 4MBit (512KByte) |
| s_ain | 0:d0117f54a7ee | 52 | { 0xbf, 0x8d, |
| s_ain | 0:d0117f54a7ee | 53 | { |
| s_ain | 0:d0117f54a7ee | 54 | "SST25xF040B", |
| s_ain | 0:d0117f54a7ee | 55 | 4096 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 56 | 0xe3, |
| s_ain | 0:d0117f54a7ee | 57 | 1, |
| s_ain | 0:d0117f54a7ee | 58 | &SST25DeviceImpl::writeAAIWord, |
| s_ain | 0:d0117f54a7ee | 59 | 46000000 |
| s_ain | 0:d0117f54a7ee | 60 | }, |
| s_ain | 0:d0117f54a7ee | 61 | }, |
| s_ain | 0:d0117f54a7ee | 62 | //SST25xF080B 8MBit (1MByte) |
| s_ain | 0:d0117f54a7ee | 63 | { 0xbf, 0x8e, |
| s_ain | 0:d0117f54a7ee | 64 | { |
| s_ain | 0:d0117f54a7ee | 65 | "SST25xF080B", |
| s_ain | 0:d0117f54a7ee | 66 | 8192 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 67 | 0xe3, |
| s_ain | 0:d0117f54a7ee | 68 | 1, |
| s_ain | 0:d0117f54a7ee | 69 | &SST25DeviceImpl::writeAAIWord, |
| s_ain | 0:d0117f54a7ee | 70 | 46000000 |
| s_ain | 0:d0117f54a7ee | 71 | }, |
| s_ain | 0:d0117f54a7ee | 72 | }, |
| s_ain | 0:d0117f54a7ee | 73 | //SST25xF016B 16MBit (2MByte) |
| s_ain | 0:d0117f54a7ee | 74 | { 0xbf, 0x41, |
| s_ain | 0:d0117f54a7ee | 75 | { |
| s_ain | 0:d0117f54a7ee | 76 | "SST25xF016B", |
| s_ain | 0:d0117f54a7ee | 77 | 16384 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 78 | 0xe3, |
| s_ain | 0:d0117f54a7ee | 79 | 1, |
| s_ain | 0:d0117f54a7ee | 80 | &SST25DeviceImpl::writeAAIWord, |
| s_ain | 0:d0117f54a7ee | 81 | 46000000 |
| s_ain | 0:d0117f54a7ee | 82 | }, |
| s_ain | 0:d0117f54a7ee | 83 | }, |
| s_ain | 0:d0117f54a7ee | 84 | //SST25xF032B 32MBit (4MByte) |
| s_ain | 0:d0117f54a7ee | 85 | { 0xbf, 0x4a, |
| s_ain | 0:d0117f54a7ee | 86 | { |
| s_ain | 0:d0117f54a7ee | 87 | "SST25xF032B", |
| s_ain | 0:d0117f54a7ee | 88 | 32768 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 89 | 0xc3, |
| s_ain | 0:d0117f54a7ee | 90 | 1, |
| s_ain | 0:d0117f54a7ee | 91 | &SST25DeviceImpl::writeAAIWord, |
| s_ain | 0:d0117f54a7ee | 92 | 46000000 |
| s_ain | 0:d0117f54a7ee | 93 | }, |
| s_ain | 0:d0117f54a7ee | 94 | }, |
| s_ain | 0:d0117f54a7ee | 95 | //SST25xF064C 64MBit (8MByte) |
| s_ain | 0:d0117f54a7ee | 96 | { 0xbf, 0x4b, |
| s_ain | 0:d0117f54a7ee | 97 | { |
| s_ain | 0:d0117f54a7ee | 98 | "SST25xF064C", |
| s_ain | 0:d0117f54a7ee | 99 | 65536 * 1024 / 8, |
| s_ain | 0:d0117f54a7ee | 100 | 0xc3, |
| s_ain | 0:d0117f54a7ee | 101 | 256, |
| s_ain | 0:d0117f54a7ee | 102 | &SST25DeviceImpl::writePage, |
| s_ain | 0:d0117f54a7ee | 103 | 46000000 |
| s_ain | 0:d0117f54a7ee | 104 | }, |
| s_ain | 0:d0117f54a7ee | 105 | } |
| s_ain | 0:d0117f54a7ee | 106 | }; |
| s_ain | 0:d0117f54a7ee | 107 | int count = sizeof(supportedDevices) / sizeof(supportedDevices[0]); |
| s_ain | 0:d0117f54a7ee | 108 | for (int i = 0; i < count; ++i) |
| s_ain | 0:d0117f54a7ee | 109 | { |
| s_ain | 0:d0117f54a7ee | 110 | const SupportedDevice& device = supportedDevices[i]; |
| s_ain | 0:d0117f54a7ee | 111 | if (device.manufacturersId == manufacturersId && device.deviceId == deviceId) |
| s_ain | 0:d0117f54a7ee | 112 | { |
| s_ain | 0:d0117f54a7ee | 113 | return &device.property; |
| s_ain | 0:d0117f54a7ee | 114 | } |
| s_ain | 0:d0117f54a7ee | 115 | } |
| s_ain | 0:d0117f54a7ee | 116 | return NULL; |
| s_ain | 0:d0117f54a7ee | 117 | } |
| s_ain | 0:d0117f54a7ee | 118 | |
| s_ain | 0:d0117f54a7ee | 119 | bool SST25DeviceImpl::IsSupported(ISPI* pSPI) |
| s_ain | 0:d0117f54a7ee | 120 | { |
| s_ain | 0:d0117f54a7ee | 121 | return findMatchDevice(pSPI) != NULL; |
| s_ain | 0:d0117f54a7ee | 122 | } |
| s_ain | 0:d0117f54a7ee | 123 | |
| s_ain | 0:d0117f54a7ee | 124 | SST25DeviceImpl* SST25DeviceImpl::Create(ISPI* pSPI) |
| s_ain | 0:d0117f54a7ee | 125 | { |
| s_ain | 0:d0117f54a7ee | 126 | const DeviceProperty* property = findMatchDevice(pSPI); |
| s_ain | 0:d0117f54a7ee | 127 | if (property == NULL) |
| s_ain | 0:d0117f54a7ee | 128 | { |
| s_ain | 0:d0117f54a7ee | 129 | return NULL; |
| s_ain | 0:d0117f54a7ee | 130 | } |
| s_ain | 0:d0117f54a7ee | 131 | return new SST25DeviceImpl(pSPI, *property); |
| s_ain | 0:d0117f54a7ee | 132 | } |
| s_ain | 0:d0117f54a7ee | 133 | |
| s_ain | 0:d0117f54a7ee | 134 | SST25DeviceImpl::SST25DeviceImpl(ISPI* pSPI, const DeviceProperty& property) |
| s_ain | 0:d0117f54a7ee | 135 | : _pSPI(pSPI) |
| s_ain | 0:d0117f54a7ee | 136 | , _property(property) |
| s_ain | 0:d0117f54a7ee | 137 | { |
| s_ain | 0:d0117f54a7ee | 138 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 139 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 140 | } |
| s_ain | 0:d0117f54a7ee | 141 | |
| s_ain | 0:d0117f54a7ee | 142 | SST25DeviceImpl::~SST25DeviceImpl(void) |
| s_ain | 0:d0117f54a7ee | 143 | { |
| s_ain | 0:d0117f54a7ee | 144 | |
| s_ain | 0:d0117f54a7ee | 145 | } |
| s_ain | 0:d0117f54a7ee | 146 | |
| s_ain | 0:d0117f54a7ee | 147 | void SST25DeviceImpl::readId(ISPI* pSPI, int& manufacturersId, int& deviceId) |
| s_ain | 0:d0117f54a7ee | 148 | { |
| s_ain | 0:d0117f54a7ee | 149 | const static int DefaultOperationFrequency = 20000000; |
| s_ain | 0:d0117f54a7ee | 150 | pSPI->SetFrequency(DefaultOperationFrequency); |
| s_ain | 0:d0117f54a7ee | 151 | |
| s_ain | 0:d0117f54a7ee | 152 | pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 153 | pSPI->Write(0x90); |
| s_ain | 0:d0117f54a7ee | 154 | pSPI->Write(0x00); |
| s_ain | 0:d0117f54a7ee | 155 | pSPI->Write(0x00); |
| s_ain | 0:d0117f54a7ee | 156 | pSPI->Write(0x00); |
| s_ain | 0:d0117f54a7ee | 157 | manufacturersId = pSPI->Read(); |
| s_ain | 0:d0117f54a7ee | 158 | deviceId = pSPI->Read(); |
| s_ain | 0:d0117f54a7ee | 159 | pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 160 | } |
| s_ain | 0:d0117f54a7ee | 161 | |
| s_ain | 0:d0117f54a7ee | 162 | int SST25DeviceImpl::readStatusRegister(void) |
| s_ain | 0:d0117f54a7ee | 163 | { |
| s_ain | 0:d0117f54a7ee | 164 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 165 | _pSPI->Write(0x05); |
| s_ain | 0:d0117f54a7ee | 166 | int result = _pSPI->Read(); |
| s_ain | 0:d0117f54a7ee | 167 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 168 | return result; |
| s_ain | 0:d0117f54a7ee | 169 | } |
| s_ain | 0:d0117f54a7ee | 170 | |
| s_ain | 0:d0117f54a7ee | 171 | void SST25DeviceImpl::writeStatusRegister(int value) |
| s_ain | 0:d0117f54a7ee | 172 | { |
| s_ain | 0:d0117f54a7ee | 173 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 174 | _pSPI->Write(0x50); |
| s_ain | 0:d0117f54a7ee | 175 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 176 | |
| s_ain | 0:d0117f54a7ee | 177 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 178 | _pSPI->Write(0x01); |
| s_ain | 0:d0117f54a7ee | 179 | _pSPI->Write(value); |
| s_ain | 0:d0117f54a7ee | 180 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 181 | } |
| s_ain | 0:d0117f54a7ee | 182 | |
| s_ain | 0:d0117f54a7ee | 183 | void SST25DeviceImpl::writeEnable() |
| s_ain | 0:d0117f54a7ee | 184 | { |
| s_ain | 0:d0117f54a7ee | 185 | int status = readStatusRegister(); |
| s_ain | 0:d0117f54a7ee | 186 | status &= _property.blockProtectionMask; |
| s_ain | 0:d0117f54a7ee | 187 | writeStatusRegister(status); |
| s_ain | 0:d0117f54a7ee | 188 | |
| s_ain | 0:d0117f54a7ee | 189 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 190 | _pSPI->Write(0x06); |
| s_ain | 0:d0117f54a7ee | 191 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 192 | } |
| s_ain | 0:d0117f54a7ee | 193 | |
| s_ain | 0:d0117f54a7ee | 194 | void SST25DeviceImpl::writeDisable() |
| s_ain | 0:d0117f54a7ee | 195 | { |
| s_ain | 0:d0117f54a7ee | 196 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 197 | _pSPI->Write(0x04); |
| s_ain | 0:d0117f54a7ee | 198 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 199 | } |
| s_ain | 0:d0117f54a7ee | 200 | |
| s_ain | 0:d0117f54a7ee | 201 | void SST25DeviceImpl::waitForReady() |
| s_ain | 0:d0117f54a7ee | 202 | { |
| s_ain | 0:d0117f54a7ee | 203 | while (readStatusRegister() & 0x01) |
| s_ain | 0:d0117f54a7ee | 204 | ; |
| s_ain | 0:d0117f54a7ee | 205 | } |
| s_ain | 0:d0117f54a7ee | 206 | |
| s_ain | 0:d0117f54a7ee | 207 | std::string SST25DeviceImpl::GetDeviceName(void) const |
| s_ain | 0:d0117f54a7ee | 208 | { |
| s_ain | 0:d0117f54a7ee | 209 | return _property.deviceName; |
| s_ain | 0:d0117f54a7ee | 210 | } |
| s_ain | 0:d0117f54a7ee | 211 | |
| s_ain | 0:d0117f54a7ee | 212 | int SST25DeviceImpl::GetCapacity(void) const |
| s_ain | 0:d0117f54a7ee | 213 | { |
| s_ain | 0:d0117f54a7ee | 214 | return _property.capacity; |
| s_ain | 0:d0117f54a7ee | 215 | } |
| s_ain | 0:d0117f54a7ee | 216 | |
| s_ain | 0:d0117f54a7ee | 217 | int SST25DeviceImpl::Read(int address, void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 218 | { |
| s_ain | 0:d0117f54a7ee | 219 | if (address >= GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 220 | { |
| s_ain | 0:d0117f54a7ee | 221 | return 0; |
| s_ain | 0:d0117f54a7ee | 222 | } |
| s_ain | 0:d0117f54a7ee | 223 | if (address + length > GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 224 | { |
| s_ain | 0:d0117f54a7ee | 225 | length = GetCapacity() - address; |
| s_ain | 0:d0117f54a7ee | 226 | } |
| s_ain | 0:d0117f54a7ee | 227 | if (length == 0) |
| s_ain | 0:d0117f54a7ee | 228 | { |
| s_ain | 0:d0117f54a7ee | 229 | return 0; |
| s_ain | 0:d0117f54a7ee | 230 | } |
| s_ain | 0:d0117f54a7ee | 231 | |
| s_ain | 0:d0117f54a7ee | 232 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 233 | |
| s_ain | 0:d0117f54a7ee | 234 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 235 | _pSPI->Write(0x0b); |
| s_ain | 0:d0117f54a7ee | 236 | writeAddress(address); |
| s_ain | 0:d0117f54a7ee | 237 | _pSPI->Write(0xff); |
| s_ain | 0:d0117f54a7ee | 238 | _pSPI->Read(buffer, length); |
| s_ain | 0:d0117f54a7ee | 239 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 240 | return length; |
| s_ain | 0:d0117f54a7ee | 241 | } |
| s_ain | 0:d0117f54a7ee | 242 | |
| s_ain | 0:d0117f54a7ee | 243 | int SST25DeviceImpl::Write(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 244 | { |
| s_ain | 0:d0117f54a7ee | 245 | if (address >= GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 246 | { |
| s_ain | 0:d0117f54a7ee | 247 | return 0; |
| s_ain | 0:d0117f54a7ee | 248 | } |
| s_ain | 0:d0117f54a7ee | 249 | if (address + length > GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 250 | { |
| s_ain | 0:d0117f54a7ee | 251 | length = GetCapacity() - address; |
| s_ain | 0:d0117f54a7ee | 252 | } |
| s_ain | 0:d0117f54a7ee | 253 | if (length == 0) |
| s_ain | 0:d0117f54a7ee | 254 | { |
| s_ain | 0:d0117f54a7ee | 255 | return 0; |
| s_ain | 0:d0117f54a7ee | 256 | } |
| s_ain | 0:d0117f54a7ee | 257 | (this->*_property.pfnWriter)(address, buffer, length); |
| s_ain | 0:d0117f54a7ee | 258 | return length; |
| s_ain | 0:d0117f54a7ee | 259 | } |
| s_ain | 0:d0117f54a7ee | 260 | |
| s_ain | 0:d0117f54a7ee | 261 | void SST25DeviceImpl::ChipErase() |
| s_ain | 0:d0117f54a7ee | 262 | { |
| s_ain | 0:d0117f54a7ee | 263 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 264 | |
| s_ain | 0:d0117f54a7ee | 265 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 266 | |
| s_ain | 0:d0117f54a7ee | 267 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 268 | _pSPI->Write(0x60); |
| s_ain | 0:d0117f54a7ee | 269 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 270 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 271 | } |
| s_ain | 0:d0117f54a7ee | 272 | |
| s_ain | 0:d0117f54a7ee | 273 | void SST25DeviceImpl::byteProgram(int address, int value) |
| s_ain | 0:d0117f54a7ee | 274 | { |
| s_ain | 0:d0117f54a7ee | 275 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 276 | |
| s_ain | 0:d0117f54a7ee | 277 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 278 | |
| s_ain | 0:d0117f54a7ee | 279 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 280 | _pSPI->Write(0x02); |
| s_ain | 0:d0117f54a7ee | 281 | writeAddress(address); |
| s_ain | 0:d0117f54a7ee | 282 | _pSPI->Write(value); |
| s_ain | 0:d0117f54a7ee | 283 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 284 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 285 | } |
| s_ain | 0:d0117f54a7ee | 286 | |
| s_ain | 0:d0117f54a7ee | 287 | void SST25DeviceImpl::beginAAIProgram(int address, int data) |
| s_ain | 0:d0117f54a7ee | 288 | { |
| s_ain | 0:d0117f54a7ee | 289 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 290 | |
| s_ain | 0:d0117f54a7ee | 291 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 292 | |
| s_ain | 0:d0117f54a7ee | 293 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 294 | _pSPI->Write(0xaf); |
| s_ain | 0:d0117f54a7ee | 295 | writeAddress(address); |
| s_ain | 0:d0117f54a7ee | 296 | _pSPI->Write(data); |
| s_ain | 0:d0117f54a7ee | 297 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 298 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 299 | } |
| s_ain | 0:d0117f54a7ee | 300 | |
| s_ain | 0:d0117f54a7ee | 301 | void SST25DeviceImpl::nextAAIProgram(int data) |
| s_ain | 0:d0117f54a7ee | 302 | { |
| s_ain | 0:d0117f54a7ee | 303 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 304 | _pSPI->Write(0xaf); |
| s_ain | 0:d0117f54a7ee | 305 | _pSPI->Write(data); |
| s_ain | 0:d0117f54a7ee | 306 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 307 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 308 | } |
| s_ain | 0:d0117f54a7ee | 309 | |
| s_ain | 0:d0117f54a7ee | 310 | void SST25DeviceImpl::endAAIProgram(void) |
| s_ain | 0:d0117f54a7ee | 311 | { |
| s_ain | 0:d0117f54a7ee | 312 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 313 | _pSPI->Write(0x04); |
| s_ain | 0:d0117f54a7ee | 314 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 315 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 316 | } |
| s_ain | 0:d0117f54a7ee | 317 | |
| s_ain | 0:d0117f54a7ee | 318 | void SST25DeviceImpl::beginAAIWordProgram(int address, int data) |
| s_ain | 0:d0117f54a7ee | 319 | { |
| s_ain | 0:d0117f54a7ee | 320 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 321 | |
| s_ain | 0:d0117f54a7ee | 322 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 323 | |
| s_ain | 0:d0117f54a7ee | 324 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 325 | _pSPI->Write(0xad); |
| s_ain | 0:d0117f54a7ee | 326 | writeAddress(address); |
| s_ain | 0:d0117f54a7ee | 327 | _pSPI->Write((data & 0xff00) >> 8); |
| s_ain | 0:d0117f54a7ee | 328 | _pSPI->Write(data & 0xff); |
| s_ain | 0:d0117f54a7ee | 329 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 330 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 331 | } |
| s_ain | 0:d0117f54a7ee | 332 | |
| s_ain | 0:d0117f54a7ee | 333 | void SST25DeviceImpl::nextAAIWordProgram(int data) |
| s_ain | 0:d0117f54a7ee | 334 | { |
| s_ain | 0:d0117f54a7ee | 335 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 336 | _pSPI->Write(0xad); |
| s_ain | 0:d0117f54a7ee | 337 | _pSPI->Write((data & 0xff00) >> 8); |
| s_ain | 0:d0117f54a7ee | 338 | _pSPI->Write(data & 0xff); |
| s_ain | 0:d0117f54a7ee | 339 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 340 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 341 | } |
| s_ain | 0:d0117f54a7ee | 342 | |
| s_ain | 0:d0117f54a7ee | 343 | void SST25DeviceImpl::writeAddress(int address) |
| s_ain | 0:d0117f54a7ee | 344 | { |
| s_ain | 0:d0117f54a7ee | 345 | _pSPI->Write((address & 0xff0000) >> 16); |
| s_ain | 0:d0117f54a7ee | 346 | _pSPI->Write((address & 0xff00) >> 8); |
| s_ain | 0:d0117f54a7ee | 347 | _pSPI->Write(address & 0xff); |
| s_ain | 0:d0117f54a7ee | 348 | } |
| s_ain | 0:d0117f54a7ee | 349 | |
| s_ain | 0:d0117f54a7ee | 350 | void SST25DeviceImpl::pageProgram(int address, const void* buffer) |
| s_ain | 0:d0117f54a7ee | 351 | { |
| s_ain | 0:d0117f54a7ee | 352 | _pSPI->SetFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 353 | |
| s_ain | 0:d0117f54a7ee | 354 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 355 | |
| s_ain | 0:d0117f54a7ee | 356 | _pSPI->ChangeCS(ISPI::Low); |
| s_ain | 0:d0117f54a7ee | 357 | _pSPI->Write(0x02); |
| s_ain | 0:d0117f54a7ee | 358 | writeAddress(address); |
| s_ain | 1:385965a14c7c | 359 | _pSPI->Write(buffer, 256); |
| s_ain | 0:d0117f54a7ee | 360 | _pSPI->ChangeCS(ISPI::High); |
| s_ain | 0:d0117f54a7ee | 361 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 362 | } |
| s_ain | 0:d0117f54a7ee | 363 | |
| s_ain | 0:d0117f54a7ee | 364 | void SST25DeviceImpl::writePage(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 365 | { |
| s_ain | 0:d0117f54a7ee | 366 | int pageSize = _property.pageSize; |
| s_ain | 0:d0117f54a7ee | 367 | int pageSizeMask = pageSize - 1; |
| s_ain | 0:d0117f54a7ee | 368 | int pageAddressMask = ~pageSizeMask; |
| s_ain | 0:d0117f54a7ee | 369 | |
| s_ain | 0:d0117f54a7ee | 370 | if (length <= 0) |
| s_ain | 0:d0117f54a7ee | 371 | { |
| s_ain | 0:d0117f54a7ee | 372 | return; |
| s_ain | 0:d0117f54a7ee | 373 | } |
| s_ain | 0:d0117f54a7ee | 374 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 375 | if ((address & pageSizeMask) != 0) |
| s_ain | 0:d0117f54a7ee | 376 | { |
| s_ain | 0:d0117f54a7ee | 377 | int readLen = address & pageSizeMask; |
| s_ain | 0:d0117f54a7ee | 378 | int copyLen = pageSize - readLen; |
| s_ain | 0:d0117f54a7ee | 379 | if (copyLen > length) |
| s_ain | 0:d0117f54a7ee | 380 | { |
| s_ain | 0:d0117f54a7ee | 381 | copyLen = length; |
| s_ain | 0:d0117f54a7ee | 382 | } |
| s_ain | 0:d0117f54a7ee | 383 | char buf[pageSize]; |
| s_ain | 0:d0117f54a7ee | 384 | int writeAddress = address & pageAddressMask; |
| s_ain | 0:d0117f54a7ee | 385 | Read(writeAddress, buf, readLen); |
| s_ain | 0:d0117f54a7ee | 386 | memcpy(&buf[address & pageSizeMask], buffer, copyLen); |
| s_ain | 0:d0117f54a7ee | 387 | pageProgram(writeAddress, buf); |
| s_ain | 0:d0117f54a7ee | 388 | p += readLen; |
| s_ain | 0:d0117f54a7ee | 389 | address += pageSize - readLen; |
| s_ain | 0:d0117f54a7ee | 390 | length -= copyLen; |
| s_ain | 0:d0117f54a7ee | 391 | } |
| s_ain | 0:d0117f54a7ee | 392 | while (length >= pageSize) |
| s_ain | 0:d0117f54a7ee | 393 | { |
| s_ain | 0:d0117f54a7ee | 394 | pageProgram(address, p); |
| s_ain | 0:d0117f54a7ee | 395 | address += pageSize; |
| s_ain | 0:d0117f54a7ee | 396 | p += pageSize; |
| s_ain | 0:d0117f54a7ee | 397 | length -= pageSize; |
| s_ain | 0:d0117f54a7ee | 398 | } |
| s_ain | 0:d0117f54a7ee | 399 | if (length != 0) |
| s_ain | 0:d0117f54a7ee | 400 | { |
| s_ain | 0:d0117f54a7ee | 401 | char buf[pageSize]; |
| s_ain | 0:d0117f54a7ee | 402 | memcpy(buf, p, length); |
| s_ain | 0:d0117f54a7ee | 403 | memset(&buf[length], 0xff, pageSize - length); |
| s_ain | 0:d0117f54a7ee | 404 | pageProgram(address, buf); |
| s_ain | 0:d0117f54a7ee | 405 | } |
| s_ain | 0:d0117f54a7ee | 406 | } |
| s_ain | 0:d0117f54a7ee | 407 | |
| s_ain | 0:d0117f54a7ee | 408 | void SST25DeviceImpl::writeBytes(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 409 | { |
| s_ain | 0:d0117f54a7ee | 410 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 411 | while (length-- >= 0) |
| s_ain | 0:d0117f54a7ee | 412 | { |
| s_ain | 0:d0117f54a7ee | 413 | byteProgram(address++, *p++); |
| s_ain | 0:d0117f54a7ee | 414 | } |
| s_ain | 0:d0117f54a7ee | 415 | } |
| s_ain | 0:d0117f54a7ee | 416 | |
| s_ain | 0:d0117f54a7ee | 417 | void SST25DeviceImpl::writeAAI(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 418 | { |
| s_ain | 0:d0117f54a7ee | 419 | if (length <= 0) |
| s_ain | 0:d0117f54a7ee | 420 | { |
| s_ain | 0:d0117f54a7ee | 421 | return; |
| s_ain | 0:d0117f54a7ee | 422 | } |
| s_ain | 0:d0117f54a7ee | 423 | |
| s_ain | 0:d0117f54a7ee | 424 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 425 | if (length < 2) |
| s_ain | 0:d0117f54a7ee | 426 | { |
| s_ain | 0:d0117f54a7ee | 427 | byteProgram(address, *p); |
| s_ain | 0:d0117f54a7ee | 428 | return; |
| s_ain | 0:d0117f54a7ee | 429 | } |
| s_ain | 0:d0117f54a7ee | 430 | |
| s_ain | 0:d0117f54a7ee | 431 | beginAAIProgram(address, *p++); |
| s_ain | 0:d0117f54a7ee | 432 | while (--length != 0) |
| s_ain | 0:d0117f54a7ee | 433 | { |
| s_ain | 0:d0117f54a7ee | 434 | nextAAIProgram(*p++); |
| s_ain | 0:d0117f54a7ee | 435 | } |
| s_ain | 0:d0117f54a7ee | 436 | endAAIProgram(); |
| s_ain | 0:d0117f54a7ee | 437 | } |
| s_ain | 0:d0117f54a7ee | 438 | |
| s_ain | 0:d0117f54a7ee | 439 | void SST25DeviceImpl::writeAAIWord(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 440 | { |
| s_ain | 0:d0117f54a7ee | 441 | if (length <= 0) |
| s_ain | 0:d0117f54a7ee | 442 | { |
| s_ain | 0:d0117f54a7ee | 443 | return; |
| s_ain | 0:d0117f54a7ee | 444 | } |
| s_ain | 0:d0117f54a7ee | 445 | |
| s_ain | 0:d0117f54a7ee | 446 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 447 | if ((address & 0x1) != 0) |
| s_ain | 0:d0117f54a7ee | 448 | { |
| s_ain | 0:d0117f54a7ee | 449 | byteProgram(address++, *p++); |
| s_ain | 0:d0117f54a7ee | 450 | length--; |
| s_ain | 0:d0117f54a7ee | 451 | } |
| s_ain | 0:d0117f54a7ee | 452 | |
| s_ain | 0:d0117f54a7ee | 453 | if (length < 4) |
| s_ain | 0:d0117f54a7ee | 454 | { |
| s_ain | 0:d0117f54a7ee | 455 | writeBytes(address, p, length); |
| s_ain | 0:d0117f54a7ee | 456 | return; |
| s_ain | 0:d0117f54a7ee | 457 | } |
| s_ain | 0:d0117f54a7ee | 458 | |
| s_ain | 0:d0117f54a7ee | 459 | beginAAIWordProgram(address, (*p << 8) | *(p + 1)); |
| s_ain | 0:d0117f54a7ee | 460 | address += length & ~0x1; |
| s_ain | 0:d0117f54a7ee | 461 | p += 2; |
| s_ain | 0:d0117f54a7ee | 462 | length -= 2; |
| s_ain | 0:d0117f54a7ee | 463 | |
| s_ain | 0:d0117f54a7ee | 464 | do |
| s_ain | 0:d0117f54a7ee | 465 | { |
| s_ain | 0:d0117f54a7ee | 466 | nextAAIWordProgram((*p << 8) | *(p + 1)); |
| s_ain | 0:d0117f54a7ee | 467 | p += 2; |
| s_ain | 0:d0117f54a7ee | 468 | length -= 2; |
| s_ain | 0:d0117f54a7ee | 469 | } while (length >= 2); |
| s_ain | 0:d0117f54a7ee | 470 | endAAIProgram(); |
| s_ain | 0:d0117f54a7ee | 471 | |
| s_ain | 0:d0117f54a7ee | 472 | if (length != 0) |
| s_ain | 0:d0117f54a7ee | 473 | { |
| s_ain | 0:d0117f54a7ee | 474 | byteProgram(address, *p); |
| s_ain | 0:d0117f54a7ee | 475 | } |
| s_ain | 0:d0117f54a7ee | 476 | } |
