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
};
/**
* @brief
*
*/
enum class ChunkSize
{
PAGE,
SECTOR,
BLOCK_32KB,
BLOCK_64KB
};
class W25Qxx
{
public:
@ -62,13 +74,18 @@ namespace sta
*/
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 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.
*/
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
@ -188,6 +205,8 @@ namespace sta
* @return uint8_t
*/
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:
/*
* Erase operations

View File

@ -57,8 +57,15 @@
#define W25QXX_INDIV_BLOCK_UNLOCK 0x39
#define W25QXX_READ_BLOCK_LOCK 0x3D
#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

View File

@ -1,8 +1,10 @@
#include <string.h>
#include <vector>
#include <sta/debug/assert.hpp>
#include <sta/debug/debug.hpp>
#include <sta/drivers/w25qxx.hpp>
#include <sta/lang.hpp>
namespace sta
@ -44,21 +46,47 @@ namespace sta
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 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;
uint8_t * page = new uint8_t[256];
uint8_t * buffer = new uint8_t[bytes];
while (left < right)
{
middle = (left + right) / 2 + 1;
readData(middle, page, 256);
middle = (left + right) / 2;
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
{
@ -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)
@ -145,9 +179,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 24),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -156,17 +190,18 @@ namespace sta
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(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)
{
STA_ASSERT(length <= W25QXX_PAGE_SIZE);
while (isBusy()) {}
if (!writeEnable())
@ -179,9 +214,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 24),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -190,15 +225,32 @@ namespace sta
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(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 */)
{
device_->beginTransmission();
@ -341,9 +393,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 24),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -352,8 +404,8 @@ namespace sta
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -377,9 +429,9 @@ namespace sta
if (addrMode_ == AddressMode::_32BIT)
{
uint8_t addrBuffer[4] = {
(uint8_t) (address << 24),
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 24),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -388,8 +440,8 @@ namespace sta
else
{
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -444,8 +496,8 @@ namespace sta
while (!isWriteEnabled()) {}
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};
@ -462,8 +514,8 @@ namespace sta
while (!isWriteEnabled()) {}
uint8_t addrBuffer[3] = {
(uint8_t) (address << 16),
(uint8_t) (address << 8),
(uint8_t) (address >> 16),
(uint8_t) (address >> 8),
(uint8_t) (address)
};