Updated binary search and addressing

This commit is contained in:
dario 2024-05-23 21:56:25 +02:00
parent 0c749626eb
commit aea0b1c262
3 changed files with 115 additions and 37 deletions

View File

@ -39,6 +39,18 @@ namespace sta
_32BIT _32BIT
}; };
/**
* @brief
*
*/
enum class ChunkSize
{
PAGE,
SECTOR,
BLOCK_32KB,
BLOCK_64KB
};
class W25Qxx class W25Qxx
{ {
public: public:
@ -62,13 +74,18 @@ namespace sta
*/ */
uint8_t init(); uint8_t init();
uint32_t getChunkBytes(ChunkSize size);
/** /**
* @brief Find the last page satisfying the given criterion. Uses a binary search to find this page. * @brief Find the first memory section not satisfying a given criterion using a binary search.
*
* @note This function assume that there is a page n such that every page before n satisfies the criterion, while every page after that doesn't
* *
* @param criterion A function evaluating the criterion on a page. * @param criterion A function evaluating the criterion on a page.
* @param size The size of the memory section. Has to be one of the predefined sizes.
* @return uint32_t The last address such that the criterion is satisfied. * @return uint32_t The last address such that the criterion is satisfied.
*/ */
uint32_t findLastPage(std::function<bool(uint8_t*)> criterion); uint32_t findLast(std::function<bool(uint8_t*)> criterion, ChunkSize size);
/** /**
* @brief Set the Address Mode object * @brief Set the Address Mode object
@ -188,6 +205,8 @@ namespace sta
* @return uint8_t * @return uint8_t
*/ */
uint8_t pageProgram(uint32_t address, uint8_t * buffer, size_t length); uint8_t pageProgram(uint32_t address, uint8_t * buffer, size_t length);
uint8_t sectorProgram(uint32_t address, uint8_t * buffer, size_t length);
public: public:
/* /*
* Erase operations * Erase operations

View File

@ -57,8 +57,15 @@
#define W25QXX_INDIV_BLOCK_UNLOCK 0x39 #define W25QXX_INDIV_BLOCK_UNLOCK 0x39
#define W25QXX_READ_BLOCK_LOCK 0x3D #define W25QXX_READ_BLOCK_LOCK 0x3D
#define W25QXX_DEVICE_ID_RESULT 0xEF #define W25QXX_DEVICE_ID_RESULT 0xEF
#define W25QXX_PAGE_SIZE 0x100
#define W25QXX_SECTOR_SIZE 0x1000
#define W25QXX_BLOCK_32_KB_SIZE 0x8000
#define W25QXX_BLOCK_64_KB_SIZE 0xF000
#define W25QXX_24B_MEM_SIZE 0xFFFFFF
#define W25QXX_32B_MEM_SIZE 0xFFFFFFFF
#endif // STA_SENSORS_W25QXX_DEFS_HPP #endif // STA_SENSORS_W25QXX_DEFS_HPP

View File

@ -1,8 +1,10 @@
#include <string.h> #include <string.h>
#include <vector>
#include <sta/debug/assert.hpp> #include <sta/debug/assert.hpp>
#include <sta/debug/debug.hpp> #include <sta/debug/debug.hpp>
#include <sta/drivers/w25qxx.hpp> #include <sta/drivers/w25qxx.hpp>
#include <sta/lang.hpp>
namespace sta namespace sta
@ -44,21 +46,47 @@ namespace sta
return 1; return 1;
} }
uint32_t W25Qxx::findLastPage(std::function<bool(uint8_t*)> criterion) uint32_t W25Qxx::getChunkBytes(ChunkSize size)
{ {
switch (size)
{
case ChunkSize::PAGE:
return W25QXX_PAGE_SIZE;
case ChunkSize::SECTOR:
return W25QXX_SECTOR_SIZE;
case ChunkSize::BLOCK_32KB:
return W25QXX_BLOCK_32_KB_SIZE;
case ChunkSize::BLOCK_64KB:
return W25QXX_BLOCK_64_KB_SIZE;
default:
STA_UNREACHABLE();
break;
}
}
uint32_t W25Qxx::findLast(std::function<bool(uint8_t*)> criterion, ChunkSize size)
{
uint32_t bytes = getChunkBytes(size);
uint32_t left = 0; uint32_t left = 0;
uint32_t right = 0xFFFFFFFF & (addrMode_ == AddressMode::_32BIT ? 0xFFFFFFFF : 0x00FFFFFF); uint32_t right = (addrMode_ == AddressMode::_32BIT ? W25QXX_32B_MEM_SIZE : W25QXX_24B_MEM_SIZE) / bytes;
uint32_t middle; uint32_t middle;
uint8_t * page = new uint8_t[256];
uint8_t * buffer = new uint8_t[bytes];
while (left < right) while (left < right)
{ {
middle = (left + right) / 2 + 1; middle = (left + right) / 2;
readData(middle, page, 256); readData(middle * bytes, buffer, bytes);
STA_DEBUG_PRINTF("Left %d Middle %d Right %d\n", left, middle, right);
if (criterion(page)) if (criterion(buffer))
{ {
left = middle; left = middle+1;
} }
else else
{ {
@ -66,7 +94,13 @@ namespace sta
} }
} }
return middle; readData(middle * bytes, buffer, bytes);
if (!criterion(buffer))
middle -= 1;
delete[] buffer;
return middle * bytes;
} }
uint8_t W25Qxx::setAddressMode(AddressMode addrMode) uint8_t W25Qxx::setAddressMode(AddressMode addrMode)
@ -145,9 +179,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT) if (addrMode_ == AddressMode::_32BIT)
{ {
uint8_t addrBuffer[4] = { uint8_t addrBuffer[4] = {
(uint8_t) (address << 24), (uint8_t) (address >> 24),
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -156,17 +190,18 @@ namespace sta
else else
{ {
uint8_t addrBuffer[3] = { uint8_t addrBuffer[3] = {
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
return busRead(instruction, buffer, length, addrBuffer, 4); return busRead(instruction, buffer, length, addrBuffer, 3);
} }
} }
uint8_t W25Qxx::pageProgram(uint32_t address, uint8_t * buffer, size_t length) uint8_t W25Qxx::pageProgram(uint32_t address, uint8_t * buffer, size_t length)
{ {
STA_ASSERT(length <= W25QXX_PAGE_SIZE);
while (isBusy()) {} while (isBusy()) {}
if (!writeEnable()) if (!writeEnable())
@ -179,9 +214,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT) if (addrMode_ == AddressMode::_32BIT)
{ {
uint8_t addrBuffer[4] = { uint8_t addrBuffer[4] = {
(uint8_t) (address << 24), (uint8_t) (address >> 24),
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -190,15 +225,32 @@ namespace sta
else else
{ {
uint8_t addrBuffer[3] = { uint8_t addrBuffer[3] = {
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
return busWrite(W25QXX_PAGE_PROGAM, buffer, length, addrBuffer, 4); return busWrite(W25QXX_PAGE_PROGAM, buffer, length, addrBuffer, 3);
} }
} }
uint8_t W25Qxx::sectorProgram(uint32_t address, uint8_t * buffer, size_t length)
{
STA_ASSERT(length <= W25QXX_SECTOR_SIZE);
uint32_t nPages = length / W25QXX_PAGE_SIZE;
uint32_t remainder = length % W25QXX_PAGE_SIZE;
uint8_t rslt = 1;
for (uint8_t i = 0; i < nPages; i++)
rslt &= pageProgram(address + i * W25QXX_PAGE_SIZE, buffer + i * W25QXX_PAGE_SIZE, W25QXX_PAGE_SIZE);
rslt &= pageProgram(address + nPages * W25QXX_PAGE_SIZE, buffer + nPages * W25QXX_PAGE_SIZE, remainder);
return rslt;
}
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 */, uint32_t delayCsHigh /*= 0 */) 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 */, uint32_t delayCsHigh /*= 0 */)
{ {
device_->beginTransmission(); device_->beginTransmission();
@ -341,9 +393,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT) if (addrMode_ == AddressMode::_32BIT)
{ {
uint8_t addrBuffer[4] = { uint8_t addrBuffer[4] = {
(uint8_t) (address << 24), (uint8_t) (address >> 24),
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -352,8 +404,8 @@ namespace sta
else else
{ {
uint8_t addrBuffer[3] = { uint8_t addrBuffer[3] = {
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -377,9 +429,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT) if (addrMode_ == AddressMode::_32BIT)
{ {
uint8_t addrBuffer[4] = { uint8_t addrBuffer[4] = {
(uint8_t) (address << 24), (uint8_t) (address >> 24),
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -388,8 +440,8 @@ namespace sta
else else
{ {
uint8_t addrBuffer[3] = { uint8_t addrBuffer[3] = {
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -444,8 +496,8 @@ namespace sta
while (!isWriteEnabled()) {} while (!isWriteEnabled()) {}
uint8_t addrBuffer[3] = { uint8_t addrBuffer[3] = {
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };
@ -462,8 +514,8 @@ namespace sta
while (!isWriteEnabled()) {} while (!isWriteEnabled()) {}
uint8_t addrBuffer[3] = { uint8_t addrBuffer[3] = {
(uint8_t) (address << 16), (uint8_t) (address >> 16),
(uint8_t) (address << 8), (uint8_t) (address >> 8),
(uint8_t) (address) (uint8_t) (address)
}; };