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@2:6f8ab876b516, 2011-03-02 (annotated)
- 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?
| User | Revision | Line number | New 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 "SST25DeviceImpl.h" |
| s_ain | 0:d0117f54a7ee | 4 | |
| s_ain | 2:6f8ab876b516 | 5 | const SST25DeviceImpl::DeviceProperty* SST25DeviceImpl::findMatchDevice(ISPICommand* pSPICommand) |
| s_ain | 0:d0117f54a7ee | 6 | { |
| s_ain | 0:d0117f54a7ee | 7 | int manufacturersId; |
| s_ain | 0:d0117f54a7ee | 8 | int deviceId; |
| s_ain | 2:6f8ab876b516 | 9 | readId(pSPICommand, 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 | 2:6f8ab876b516 | 59 | 50000000 |
| 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 | 2:6f8ab876b516 | 70 | 50000000 |
| 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 | 2:6f8ab876b516 | 81 | 50000000 |
| 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 | 2:6f8ab876b516 | 92 | 50000000 |
| 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 | 2:6f8ab876b516 | 103 | 50000000 |
| 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 | 2:6f8ab876b516 | 119 | bool SST25DeviceImpl::IsSupported(ISPICommand* pSPICommand) |
| s_ain | 0:d0117f54a7ee | 120 | { |
| s_ain | 2:6f8ab876b516 | 121 | return findMatchDevice(pSPICommand) != NULL; |
| s_ain | 0:d0117f54a7ee | 122 | } |
| s_ain | 0:d0117f54a7ee | 123 | |
| s_ain | 2:6f8ab876b516 | 124 | SST25DeviceImpl* SST25DeviceImpl::Create(ISPICommand* pSPICommand) |
| s_ain | 0:d0117f54a7ee | 125 | { |
| s_ain | 2:6f8ab876b516 | 126 | const DeviceProperty* property = findMatchDevice(pSPICommand); |
| 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 | 2:6f8ab876b516 | 131 | return new SST25DeviceImpl(pSPICommand, *property); |
| s_ain | 0:d0117f54a7ee | 132 | } |
| s_ain | 0:d0117f54a7ee | 133 | |
| s_ain | 2:6f8ab876b516 | 134 | SST25DeviceImpl::SST25DeviceImpl(ISPICommand* pSPICommand, const DeviceProperty& property) |
| s_ain | 2:6f8ab876b516 | 135 | : _pSPICommand(pSPICommand) |
| s_ain | 0:d0117f54a7ee | 136 | , _property(property) |
| s_ain | 0:d0117f54a7ee | 137 | { |
| s_ain | 2:6f8ab876b516 | 138 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 139 | } |
| s_ain | 0:d0117f54a7ee | 140 | |
| s_ain | 0:d0117f54a7ee | 141 | SST25DeviceImpl::~SST25DeviceImpl(void) |
| s_ain | 0:d0117f54a7ee | 142 | { |
| s_ain | 0:d0117f54a7ee | 143 | |
| s_ain | 0:d0117f54a7ee | 144 | } |
| s_ain | 0:d0117f54a7ee | 145 | |
| s_ain | 2:6f8ab876b516 | 146 | void SST25DeviceImpl::readId(ISPICommand* pSPICommand, int& manufacturersId, int& deviceId) |
| s_ain | 0:d0117f54a7ee | 147 | { |
| s_ain | 0:d0117f54a7ee | 148 | const static int DefaultOperationFrequency = 20000000; |
| s_ain | 2:6f8ab876b516 | 149 | pSPICommand->SetMaxFrequency(DefaultOperationFrequency); |
| s_ain | 0:d0117f54a7ee | 150 | |
| s_ain | 2:6f8ab876b516 | 151 | unsigned char read[2]; |
| s_ain | 2:6f8ab876b516 | 152 | char param[3]; |
| s_ain | 2:6f8ab876b516 | 153 | fillAddress(param, 0x000000); |
| s_ain | 2:6f8ab876b516 | 154 | pSPICommand->Read(0x90, param, sizeof(param), read, sizeof(read)); |
| s_ain | 2:6f8ab876b516 | 155 | manufacturersId = read[0]; |
| s_ain | 2:6f8ab876b516 | 156 | deviceId = read[1]; |
| s_ain | 0:d0117f54a7ee | 157 | } |
| s_ain | 0:d0117f54a7ee | 158 | |
| s_ain | 0:d0117f54a7ee | 159 | int SST25DeviceImpl::readStatusRegister(void) |
| s_ain | 0:d0117f54a7ee | 160 | { |
| s_ain | 2:6f8ab876b516 | 161 | unsigned char read; |
| s_ain | 2:6f8ab876b516 | 162 | _pSPICommand->Read(0x05, &read, 1); |
| s_ain | 2:6f8ab876b516 | 163 | return read; |
| s_ain | 0:d0117f54a7ee | 164 | } |
| s_ain | 0:d0117f54a7ee | 165 | |
| s_ain | 0:d0117f54a7ee | 166 | void SST25DeviceImpl::writeStatusRegister(int value) |
| s_ain | 0:d0117f54a7ee | 167 | { |
| s_ain | 2:6f8ab876b516 | 168 | _pSPICommand->Write(0x50); |
| s_ain | 0:d0117f54a7ee | 169 | |
| s_ain | 2:6f8ab876b516 | 170 | char vb = static_cast<char>(value); |
| s_ain | 2:6f8ab876b516 | 171 | _pSPICommand->Write(0x01, &vb, sizeof(vb)); |
| s_ain | 0:d0117f54a7ee | 172 | } |
| s_ain | 0:d0117f54a7ee | 173 | |
| s_ain | 0:d0117f54a7ee | 174 | void SST25DeviceImpl::writeEnable() |
| s_ain | 0:d0117f54a7ee | 175 | { |
| s_ain | 0:d0117f54a7ee | 176 | int status = readStatusRegister(); |
| s_ain | 0:d0117f54a7ee | 177 | status &= _property.blockProtectionMask; |
| s_ain | 0:d0117f54a7ee | 178 | writeStatusRegister(status); |
| s_ain | 2:6f8ab876b516 | 179 | _pSPICommand->Write(0x06); |
| s_ain | 0:d0117f54a7ee | 180 | } |
| s_ain | 0:d0117f54a7ee | 181 | |
| s_ain | 0:d0117f54a7ee | 182 | void SST25DeviceImpl::writeDisable() |
| s_ain | 0:d0117f54a7ee | 183 | { |
| s_ain | 2:6f8ab876b516 | 184 | _pSPICommand->Write(0x04); |
| s_ain | 0:d0117f54a7ee | 185 | } |
| s_ain | 0:d0117f54a7ee | 186 | |
| s_ain | 0:d0117f54a7ee | 187 | void SST25DeviceImpl::waitForReady() |
| s_ain | 0:d0117f54a7ee | 188 | { |
| s_ain | 0:d0117f54a7ee | 189 | while (readStatusRegister() & 0x01) |
| s_ain | 0:d0117f54a7ee | 190 | ; |
| s_ain | 0:d0117f54a7ee | 191 | } |
| s_ain | 0:d0117f54a7ee | 192 | |
| s_ain | 0:d0117f54a7ee | 193 | std::string SST25DeviceImpl::GetDeviceName(void) const |
| s_ain | 0:d0117f54a7ee | 194 | { |
| s_ain | 0:d0117f54a7ee | 195 | return _property.deviceName; |
| s_ain | 0:d0117f54a7ee | 196 | } |
| s_ain | 0:d0117f54a7ee | 197 | |
| s_ain | 0:d0117f54a7ee | 198 | int SST25DeviceImpl::GetCapacity(void) const |
| s_ain | 0:d0117f54a7ee | 199 | { |
| s_ain | 0:d0117f54a7ee | 200 | return _property.capacity; |
| s_ain | 0:d0117f54a7ee | 201 | } |
| s_ain | 0:d0117f54a7ee | 202 | |
| s_ain | 0:d0117f54a7ee | 203 | int SST25DeviceImpl::Read(int address, void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 204 | { |
| s_ain | 0:d0117f54a7ee | 205 | if (address >= GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 206 | { |
| s_ain | 0:d0117f54a7ee | 207 | return 0; |
| s_ain | 0:d0117f54a7ee | 208 | } |
| s_ain | 0:d0117f54a7ee | 209 | if (address + length > GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 210 | { |
| s_ain | 0:d0117f54a7ee | 211 | length = GetCapacity() - address; |
| s_ain | 0:d0117f54a7ee | 212 | } |
| s_ain | 0:d0117f54a7ee | 213 | if (length == 0) |
| s_ain | 0:d0117f54a7ee | 214 | { |
| s_ain | 0:d0117f54a7ee | 215 | return 0; |
| s_ain | 0:d0117f54a7ee | 216 | } |
| s_ain | 0:d0117f54a7ee | 217 | |
| s_ain | 2:6f8ab876b516 | 218 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 219 | |
| s_ain | 2:6f8ab876b516 | 220 | char param[] = { 0, 0, 0, 0xff }; |
| s_ain | 2:6f8ab876b516 | 221 | fillAddress(param, address); |
| s_ain | 2:6f8ab876b516 | 222 | _pSPICommand->Read(0x0b, param, sizeof(param), buffer, length); |
| s_ain | 0:d0117f54a7ee | 223 | return length; |
| s_ain | 0:d0117f54a7ee | 224 | } |
| s_ain | 0:d0117f54a7ee | 225 | |
| s_ain | 0:d0117f54a7ee | 226 | int SST25DeviceImpl::Write(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 227 | { |
| s_ain | 0:d0117f54a7ee | 228 | if (address >= GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 229 | { |
| s_ain | 0:d0117f54a7ee | 230 | return 0; |
| s_ain | 0:d0117f54a7ee | 231 | } |
| s_ain | 0:d0117f54a7ee | 232 | if (address + length > GetCapacity()) |
| s_ain | 0:d0117f54a7ee | 233 | { |
| s_ain | 0:d0117f54a7ee | 234 | length = GetCapacity() - address; |
| s_ain | 0:d0117f54a7ee | 235 | } |
| s_ain | 0:d0117f54a7ee | 236 | if (length == 0) |
| s_ain | 0:d0117f54a7ee | 237 | { |
| s_ain | 0:d0117f54a7ee | 238 | return 0; |
| s_ain | 0:d0117f54a7ee | 239 | } |
| s_ain | 0:d0117f54a7ee | 240 | (this->*_property.pfnWriter)(address, buffer, length); |
| s_ain | 0:d0117f54a7ee | 241 | return length; |
| s_ain | 0:d0117f54a7ee | 242 | } |
| s_ain | 0:d0117f54a7ee | 243 | |
| s_ain | 0:d0117f54a7ee | 244 | void SST25DeviceImpl::ChipErase() |
| s_ain | 0:d0117f54a7ee | 245 | { |
| s_ain | 2:6f8ab876b516 | 246 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 247 | |
| s_ain | 0:d0117f54a7ee | 248 | writeEnable(); |
| s_ain | 2:6f8ab876b516 | 249 | _pSPICommand->Write(0x60); |
| s_ain | 0:d0117f54a7ee | 250 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 251 | } |
| s_ain | 0:d0117f54a7ee | 252 | |
| s_ain | 0:d0117f54a7ee | 253 | void SST25DeviceImpl::byteProgram(int address, int value) |
| s_ain | 0:d0117f54a7ee | 254 | { |
| s_ain | 2:6f8ab876b516 | 255 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 256 | |
| s_ain | 0:d0117f54a7ee | 257 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 258 | |
| s_ain | 2:6f8ab876b516 | 259 | char param[] = { 0, 0, 0, value }; |
| s_ain | 2:6f8ab876b516 | 260 | fillAddress(param, address); |
| s_ain | 2:6f8ab876b516 | 261 | _pSPICommand->Write(0x02, param, sizeof(param)); |
| s_ain | 2:6f8ab876b516 | 262 | |
| s_ain | 0:d0117f54a7ee | 263 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 264 | } |
| s_ain | 0:d0117f54a7ee | 265 | |
| s_ain | 0:d0117f54a7ee | 266 | void SST25DeviceImpl::beginAAIProgram(int address, int data) |
| s_ain | 0:d0117f54a7ee | 267 | { |
| s_ain | 2:6f8ab876b516 | 268 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 269 | |
| s_ain | 0:d0117f54a7ee | 270 | writeEnable(); |
| s_ain | 2:6f8ab876b516 | 271 | |
| s_ain | 2:6f8ab876b516 | 272 | char param[] = { 0, 0, 0, data }; |
| s_ain | 2:6f8ab876b516 | 273 | fillAddress(param, address); |
| s_ain | 2:6f8ab876b516 | 274 | _pSPICommand->Write(0xaf, param, sizeof(param)); |
| s_ain | 0:d0117f54a7ee | 275 | |
| s_ain | 0:d0117f54a7ee | 276 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 277 | } |
| s_ain | 0:d0117f54a7ee | 278 | |
| s_ain | 0:d0117f54a7ee | 279 | void SST25DeviceImpl::nextAAIProgram(int data) |
| s_ain | 0:d0117f54a7ee | 280 | { |
| s_ain | 2:6f8ab876b516 | 281 | char param = static_cast<char>(data); |
| s_ain | 2:6f8ab876b516 | 282 | _pSPICommand->Write(0xaf, ¶m, 1); |
| s_ain | 2:6f8ab876b516 | 283 | |
| s_ain | 0:d0117f54a7ee | 284 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 285 | } |
| s_ain | 0:d0117f54a7ee | 286 | |
| s_ain | 0:d0117f54a7ee | 287 | void SST25DeviceImpl::endAAIProgram(void) |
| s_ain | 0:d0117f54a7ee | 288 | { |
| s_ain | 2:6f8ab876b516 | 289 | _pSPICommand->Write(0x04); |
| s_ain | 0:d0117f54a7ee | 290 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 291 | } |
| s_ain | 0:d0117f54a7ee | 292 | |
| s_ain | 0:d0117f54a7ee | 293 | void SST25DeviceImpl::beginAAIWordProgram(int address, int data) |
| s_ain | 0:d0117f54a7ee | 294 | { |
| s_ain | 2:6f8ab876b516 | 295 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 296 | |
| s_ain | 0:d0117f54a7ee | 297 | writeEnable(); |
| s_ain | 2:6f8ab876b516 | 298 | char param[] = { 0, 0, 0, (data & 0xff00) >> 8, data & 0xff }; |
| s_ain | 2:6f8ab876b516 | 299 | fillAddress(param, address); |
| s_ain | 2:6f8ab876b516 | 300 | _pSPICommand->Write(0xad, param, sizeof(param)); |
| s_ain | 0:d0117f54a7ee | 301 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 302 | } |
| s_ain | 0:d0117f54a7ee | 303 | |
| s_ain | 0:d0117f54a7ee | 304 | void SST25DeviceImpl::nextAAIWordProgram(int data) |
| s_ain | 0:d0117f54a7ee | 305 | { |
| s_ain | 2:6f8ab876b516 | 306 | char param[] = { (data & 0xff00) >> 8, data & 0xff }; |
| s_ain | 2:6f8ab876b516 | 307 | _pSPICommand->Write(0xad, param, sizeof(param)); |
| s_ain | 0:d0117f54a7ee | 308 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 309 | } |
| s_ain | 0:d0117f54a7ee | 310 | |
| s_ain | 2:6f8ab876b516 | 311 | void SST25DeviceImpl::fillAddress(char* pBuffer, int address) |
| s_ain | 0:d0117f54a7ee | 312 | { |
| s_ain | 2:6f8ab876b516 | 313 | *(pBuffer + 0) = (address & 0xff0000) >> 16; |
| s_ain | 2:6f8ab876b516 | 314 | *(pBuffer + 1) = (address & 0x00ff00) >> 8; |
| s_ain | 2:6f8ab876b516 | 315 | *(pBuffer + 2) = (address & 0x0000ff); |
| s_ain | 0:d0117f54a7ee | 316 | } |
| s_ain | 0:d0117f54a7ee | 317 | |
| s_ain | 0:d0117f54a7ee | 318 | void SST25DeviceImpl::pageProgram(int address, const void* buffer) |
| s_ain | 0:d0117f54a7ee | 319 | { |
| s_ain | 2:6f8ab876b516 | 320 | _pSPICommand->SetMaxFrequency(_property.operationClkHz); |
| s_ain | 0:d0117f54a7ee | 321 | |
| s_ain | 0:d0117f54a7ee | 322 | writeEnable(); |
| s_ain | 0:d0117f54a7ee | 323 | |
| s_ain | 2:6f8ab876b516 | 324 | char param[256 + 3]; |
| s_ain | 2:6f8ab876b516 | 325 | fillAddress(param, address); |
| s_ain | 2:6f8ab876b516 | 326 | memcpy(param + 3, buffer, 256); |
| s_ain | 2:6f8ab876b516 | 327 | _pSPICommand->Write(0x02, param, sizeof(param)); |
| s_ain | 2:6f8ab876b516 | 328 | |
| s_ain | 0:d0117f54a7ee | 329 | waitForReady(); |
| s_ain | 0:d0117f54a7ee | 330 | } |
| s_ain | 0:d0117f54a7ee | 331 | |
| s_ain | 0:d0117f54a7ee | 332 | void SST25DeviceImpl::writePage(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 333 | { |
| s_ain | 0:d0117f54a7ee | 334 | int pageSize = _property.pageSize; |
| s_ain | 0:d0117f54a7ee | 335 | int pageSizeMask = pageSize - 1; |
| s_ain | 0:d0117f54a7ee | 336 | int pageAddressMask = ~pageSizeMask; |
| s_ain | 0:d0117f54a7ee | 337 | |
| s_ain | 0:d0117f54a7ee | 338 | if (length <= 0) |
| s_ain | 0:d0117f54a7ee | 339 | { |
| s_ain | 0:d0117f54a7ee | 340 | return; |
| s_ain | 0:d0117f54a7ee | 341 | } |
| s_ain | 0:d0117f54a7ee | 342 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 343 | if ((address & pageSizeMask) != 0) |
| s_ain | 0:d0117f54a7ee | 344 | { |
| s_ain | 0:d0117f54a7ee | 345 | int readLen = address & pageSizeMask; |
| s_ain | 0:d0117f54a7ee | 346 | int copyLen = pageSize - readLen; |
| s_ain | 0:d0117f54a7ee | 347 | if (copyLen > length) |
| s_ain | 0:d0117f54a7ee | 348 | { |
| s_ain | 0:d0117f54a7ee | 349 | copyLen = length; |
| s_ain | 0:d0117f54a7ee | 350 | } |
| s_ain | 0:d0117f54a7ee | 351 | char buf[pageSize]; |
| s_ain | 0:d0117f54a7ee | 352 | int writeAddress = address & pageAddressMask; |
| s_ain | 0:d0117f54a7ee | 353 | Read(writeAddress, buf, readLen); |
| s_ain | 0:d0117f54a7ee | 354 | memcpy(&buf[address & pageSizeMask], buffer, copyLen); |
| s_ain | 0:d0117f54a7ee | 355 | pageProgram(writeAddress, buf); |
| s_ain | 0:d0117f54a7ee | 356 | p += readLen; |
| s_ain | 0:d0117f54a7ee | 357 | address += pageSize - readLen; |
| s_ain | 0:d0117f54a7ee | 358 | length -= copyLen; |
| s_ain | 0:d0117f54a7ee | 359 | } |
| s_ain | 0:d0117f54a7ee | 360 | while (length >= pageSize) |
| s_ain | 0:d0117f54a7ee | 361 | { |
| s_ain | 0:d0117f54a7ee | 362 | pageProgram(address, p); |
| s_ain | 0:d0117f54a7ee | 363 | address += pageSize; |
| s_ain | 0:d0117f54a7ee | 364 | p += pageSize; |
| s_ain | 0:d0117f54a7ee | 365 | length -= pageSize; |
| s_ain | 0:d0117f54a7ee | 366 | } |
| s_ain | 0:d0117f54a7ee | 367 | if (length != 0) |
| s_ain | 0:d0117f54a7ee | 368 | { |
| s_ain | 0:d0117f54a7ee | 369 | char buf[pageSize]; |
| s_ain | 0:d0117f54a7ee | 370 | memcpy(buf, p, length); |
| s_ain | 0:d0117f54a7ee | 371 | memset(&buf[length], 0xff, pageSize - length); |
| s_ain | 0:d0117f54a7ee | 372 | pageProgram(address, buf); |
| s_ain | 0:d0117f54a7ee | 373 | } |
| s_ain | 0:d0117f54a7ee | 374 | } |
| s_ain | 0:d0117f54a7ee | 375 | |
| s_ain | 0:d0117f54a7ee | 376 | void SST25DeviceImpl::writeBytes(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 377 | { |
| s_ain | 0:d0117f54a7ee | 378 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 379 | while (length-- >= 0) |
| s_ain | 0:d0117f54a7ee | 380 | { |
| s_ain | 0:d0117f54a7ee | 381 | byteProgram(address++, *p++); |
| s_ain | 0:d0117f54a7ee | 382 | } |
| s_ain | 0:d0117f54a7ee | 383 | } |
| s_ain | 0:d0117f54a7ee | 384 | |
| s_ain | 0:d0117f54a7ee | 385 | void SST25DeviceImpl::writeAAI(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 386 | { |
| s_ain | 0:d0117f54a7ee | 387 | if (length <= 0) |
| s_ain | 0:d0117f54a7ee | 388 | { |
| s_ain | 0:d0117f54a7ee | 389 | return; |
| s_ain | 0:d0117f54a7ee | 390 | } |
| s_ain | 0:d0117f54a7ee | 391 | |
| s_ain | 0:d0117f54a7ee | 392 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 393 | if (length < 2) |
| s_ain | 0:d0117f54a7ee | 394 | { |
| s_ain | 0:d0117f54a7ee | 395 | byteProgram(address, *p); |
| s_ain | 0:d0117f54a7ee | 396 | return; |
| s_ain | 0:d0117f54a7ee | 397 | } |
| s_ain | 0:d0117f54a7ee | 398 | |
| s_ain | 0:d0117f54a7ee | 399 | beginAAIProgram(address, *p++); |
| s_ain | 0:d0117f54a7ee | 400 | while (--length != 0) |
| s_ain | 0:d0117f54a7ee | 401 | { |
| s_ain | 0:d0117f54a7ee | 402 | nextAAIProgram(*p++); |
| s_ain | 0:d0117f54a7ee | 403 | } |
| s_ain | 0:d0117f54a7ee | 404 | endAAIProgram(); |
| s_ain | 0:d0117f54a7ee | 405 | } |
| s_ain | 0:d0117f54a7ee | 406 | |
| s_ain | 0:d0117f54a7ee | 407 | void SST25DeviceImpl::writeAAIWord(int address, const void* buffer, int length) |
| s_ain | 0:d0117f54a7ee | 408 | { |
| s_ain | 0:d0117f54a7ee | 409 | if (length <= 0) |
| s_ain | 0:d0117f54a7ee | 410 | { |
| s_ain | 0:d0117f54a7ee | 411 | return; |
| s_ain | 0:d0117f54a7ee | 412 | } |
| s_ain | 0:d0117f54a7ee | 413 | |
| s_ain | 0:d0117f54a7ee | 414 | const unsigned char* p = static_cast<const unsigned char*>(buffer); |
| s_ain | 0:d0117f54a7ee | 415 | if ((address & 0x1) != 0) |
| s_ain | 0:d0117f54a7ee | 416 | { |
| s_ain | 0:d0117f54a7ee | 417 | byteProgram(address++, *p++); |
| s_ain | 0:d0117f54a7ee | 418 | length--; |
| s_ain | 0:d0117f54a7ee | 419 | } |
| s_ain | 0:d0117f54a7ee | 420 | |
| s_ain | 0:d0117f54a7ee | 421 | if (length < 4) |
| s_ain | 0:d0117f54a7ee | 422 | { |
| s_ain | 0:d0117f54a7ee | 423 | writeBytes(address, p, length); |
| s_ain | 0:d0117f54a7ee | 424 | return; |
| s_ain | 0:d0117f54a7ee | 425 | } |
| s_ain | 0:d0117f54a7ee | 426 | |
| s_ain | 0:d0117f54a7ee | 427 | beginAAIWordProgram(address, (*p << 8) | *(p + 1)); |
| s_ain | 0:d0117f54a7ee | 428 | address += length & ~0x1; |
| s_ain | 0:d0117f54a7ee | 429 | p += 2; |
| s_ain | 0:d0117f54a7ee | 430 | length -= 2; |
| s_ain | 0:d0117f54a7ee | 431 | |
| s_ain | 0:d0117f54a7ee | 432 | do |
| s_ain | 0:d0117f54a7ee | 433 | { |
| s_ain | 0:d0117f54a7ee | 434 | nextAAIWordProgram((*p << 8) | *(p + 1)); |
| s_ain | 0:d0117f54a7ee | 435 | p += 2; |
| s_ain | 0:d0117f54a7ee | 436 | length -= 2; |
| s_ain | 0:d0117f54a7ee | 437 | } while (length >= 2); |
| s_ain | 0:d0117f54a7ee | 438 | endAAIProgram(); |
| s_ain | 0:d0117f54a7ee | 439 | |
| s_ain | 0:d0117f54a7ee | 440 | if (length != 0) |
| s_ain | 0:d0117f54a7ee | 441 | { |
| s_ain | 0:d0117f54a7ee | 442 | byteProgram(address, *p); |
| s_ain | 0:d0117f54a7ee | 443 | } |
| s_ain | 0:d0117f54a7ee | 444 | } |
