Address mode updating works as intended, successful chip erase, read and write

This commit is contained in:
dario
2024-02-19 11:28:28 +01:00
parent ebbcd79fb9
commit b28e15daff
3 changed files with 225 additions and 80 deletions

View File

@@ -8,20 +8,56 @@
namespace sta
{
W25Qxx::W25Qxx(SPIDevice * device)
W25Qxx::W25Qxx(SPIDevice * device, AddressMode addrMode /* = AddressMode::_24BIT */)
: device_{device},
state_{ChipState::NORMAL}
state_{ChipState::POWERED_DOWN},
addrMode_{addrMode}
{
STA_ASSERT(device != nullptr);
}
uint8_t W25Qxx::init()
{
// Check if the chip returns the correct device id.
if (getManufacturerID() != W25QXX_DEVICE_ID_RESULT)
{
return 0;
}
// If requested, tell the flash chip to use 32 bit addresses.
if (addrMode_ == AddressMode::_32BIT)
{
if (!setAddressMode(AddressMode::_32BIT))
{
return 0;
}
}
if (!releasePowerDown())
{
return 0;
}
return 1;
}
uint8_t W25Qxx::setAddressMode(AddressMode addrMode)
{
busWrite(W25QXX_4_BYTE_ADDR_ENABLE);
while (isBusy()) {}
return getAddressMode() == addrMode;
}
AddressMode W25Qxx::getAddressMode()
{
uint8_t status;
readStatusRegister(3, &status);
return status && 0x01 == 0x01 ? AddressMode::_32BIT : AddressMode::_24BIT;
}
uint8_t W25Qxx::getChipID()
{
uint8_t buffer[4];
@@ -35,7 +71,7 @@ namespace sta
uint8_t dummy[3] = {0, 0, 0};
uint8_t id;
busRead(W25QXX_JEDEC_ID, &id, 1, dummy, 3);
busRead(W25QXX_DEVICE_ID, &id, 1, dummy, 3);
return id;
}
@@ -45,8 +81,6 @@ namespace sta
uint8_t dummy[4];
uint8_t id[8];
STA_DEBUG_PRINTLN("Before crash?");
busRead(W25QXX_READ_UNIQUE_ID, id, 8, dummy, 4);
uint64_t id_complete = 0;
@@ -64,41 +98,75 @@ namespace sta
uint8_t status = 0;
readStatusRegister(1, &status);
return (0x01 & status) == 0x01;
return (0x01 && status) == 0x01;
}
uint8_t W25Qxx::readData(Address32 addr, uint8_t * buffer, size_t length, bool fast /* = true */)
uint8_t W25Qxx::readData(uint32_t address, uint8_t * buffer, size_t length, bool fast /* = true */)
{
device_->beginTransmission();
uint8_t instruction = fast ? W25QXX_FAST_READ : W25QXX_FAST_READ;
device_->transfer(&instruction, 1);
uint8_t instruction = fast ? W25QXX_FAST_READ : W25QXX_READ;
// In fast mode we have to send a 8 dummy clock cycles first.
if (fast)
{
uint8_t dummy = 0;
device_->transfer(&dummy, 1);
// TODO
}
device_->transfer(addr.buffer, sizeof(addr));
device_->receive(buffer, length);
device_->endTransmission();
while (isBusy()) {}
return 1;
// Depending on address mode, send 3 bytes or 4 bytes.
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
return busRead(instruction, buffer, length, addrBuffer, 4);
}
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
return busRead(instruction, buffer, length, addrBuffer, 4);
}
}
uint8_t W25Qxx::pageProgram(Address32 addr, uint8_t * buffer, size_t length)
uint8_t W25Qxx::pageProgram(uint32_t address, uint8_t * buffer, size_t length)
{
while (isBusy()) {}
if (!writeEnable())
{
return 0;
}
// TODO: sizeof(addr)-1 doesn't work for 24 bit addresses.
return busWrite(W25QXX_PAGE_PROGAM, buffer, length, addr.page, sizeof(addr)-1);
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
// TODO: Does this reset the writeEnable bit?
return busWrite(W25QXX_PAGE_PROGAM, buffer, length, addrBuffer, 4);
}
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
return busWrite(W25QXX_PAGE_PROGAM, buffer, length, addrBuffer, 4);
}
}
uint8_t W25Qxx::busWrite(uint8_t instruction, const uint8_t * data /* = nullptr */, size_t length /* = 0 */, uint8_t * arguments /* = nullptr */, size_t arg_length /* = 0 */)
@@ -114,8 +182,11 @@ namespace sta
device_->transfer(arguments, arg_length);
}
// Send the actual data bytes.
device_->transfer(data, length);
// If necessary, send the actual data bytes.
if (data != nullptr && length != 0)
{
device_->transfer(data, length);
}
device_->endTransmission();
@@ -126,13 +197,9 @@ namespace sta
{
device_->beginTransmission();
STA_DEBUG_PRINTLN("MAYBE HERE?");
// Send the instruction.
device_->transfer(instruction);
STA_DEBUG_PRINTLN("OR HERE?");
// If requested, send argument bytes before receiving the actual data.
if (arguments != nullptr && arg_length != 0)
{
@@ -144,8 +211,6 @@ namespace sta
device_->endTransmission();
STA_DEBUG_PRINTLN("STILL ALIVE?");
return 1;
}
@@ -221,34 +286,73 @@ namespace sta
bool W25Qxx::isWriteEnabled()
{
return true; // TODO
}
uint8_t W25Qxx::sectorErase(Address32 address)
uint8_t W25Qxx::sectorErase(uint32_t address)
{
if (!writeEnable())
{
return 0;
}
return busWrite(W25QXX_SECTOR_ERASE, address.buffer, sizeof(address));
}
uint8_t W25Qxx::blockErase(Address32 address, BlockSize blockSize)
{
if (!writeEnable())
if (addrMode_ == AddressMode::_32BIT)
{
return 0;
}
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
if (blockSize == BlockSize::_32KB)
{
return busWrite(W25QXX_BLOCK_ERASE_32_KB, address.buffer, sizeof(address));
return busWrite(W25QXX_SECTOR_ERASE, addrBuffer, 4);
}
else
{
return busWrite(W25QXX_BLOCK_ERASE_64_KB, address.buffer, sizeof(address));
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
return busWrite(W25QXX_SECTOR_ERASE, addrBuffer, 3);
}
return 1;
}
uint8_t W25Qxx::blockErase(uint32_t address, BlockSize blockSize)
{
if (!writeEnable())
{
return 0;
}
uint8_t instruction = blockSize == BlockSize::_32KB ? W25QXX_BLOCK_ERASE_32_KB : W25QXX_BLOCK_ERASE_64_KB;
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
return busWrite(instruction, addrBuffer, 4);
}
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address)
};
return busWrite(instruction, addrBuffer, 3);
}
return 1;
}
uint8_t W25Qxx::chipErase()
@@ -285,4 +389,4 @@ namespace sta
return 0;
}
} // namespace sta
} // namespace sta