mirror of
https://git.intern.spaceteamaachen.de/ALPAKA/driver-w25qxxx.git
synced 2025-08-01 20:21:53 +00:00
Updated binary search and addressing
This commit is contained in:
parent
0c749626eb
commit
aea0b1c262
@ -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
|
||||
|
@ -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
|
||||
|
120
src/w25qxx.cpp
120
src/w25qxx.cpp
@ -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)
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user