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