Skip to content

Commit

Permalink
✨ (is25lp): Add writeEnable
Browse files Browse the repository at this point in the history
  • Loading branch information
YannLocatelli committed Sep 25, 2021
1 parent 0ae1d64 commit d4c020d
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 7 deletions.
11 changes: 7 additions & 4 deletions drivers/CoreFlashMemory/include/CoreFlashMemoryIS25LP016D.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class CoreFlashMemoryIS25LP016D : public interface::FlashMemory
auto write(uint32_t address, lstd::span<uint8_t> tx_buffer) -> size_t final;

private:
auto enableWrite() -> bool;

interface::QSPI &_qspi;

spi_mode_t _spi_mode = SPIMode::Standard;
Expand All @@ -58,20 +60,21 @@ namespace command {
constexpr uint8_t read = 0x03;

constexpr uint8_t read_status = 0x05;

constexpr uint8_t write_enable = 0x06;
} // namespace command

namespace status_register {
constexpr uint8_t work_in_progress_mask = 0x01;
}
constexpr uint8_t work_in_progress_mask = 0x01;
constexpr uint8_t write_enable_latch_mask = 0x02;
} // namespace status_register

} // namespace flash_memory::is25lp016d

// ? IS25LP016D commands not used at the moment

// static constexpr uint8_t CMD_ERASE {0x20};
// static constexpr uint8_t CMD_WREN {0x6};
// static constexpr uint8_t CMD_RSTEN {0x66};
// static constexpr uint8_t CMD_RST {0x99};
// static constexpr uint8_t CMD_BIT_WEL {0x02};

#endif //_LEKA_OS_DRIVER_CORE_FLASH_MEMORY_IS25LP016D_H_
30 changes: 30 additions & 0 deletions drivers/CoreFlashMemory/source/CoreFlashMemoryIS25LP016D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#include "CoreFlashMemoryIS25LP016D.h"

#include "rtos/ThisThread.h"

using namespace std::chrono;

namespace leka {

void CoreFlashMemoryIS25LP016D::setSPIMode(spi_mode_t mode)
Expand Down Expand Up @@ -54,6 +58,29 @@ auto CoreFlashMemoryIS25LP016D::chipIsAvailable() -> bool
return false;
}

auto CoreFlashMemoryIS25LP016D::enableWrite() -> bool
{
std::array<uint8_t, 0> empty_tx_buffer;
std::array<uint8_t, 0> empty_rx_buffer;
std::array<uint8_t, flash_memory::is25lp016d::status_register_size> status_register {0xFF};

_qspi.sendCommand(flash_memory::is25lp016d::command::write_enable, -1, empty_tx_buffer, empty_rx_buffer);

while (!chipIsAvailable()) {
rtos::ThisThread::sleep_for(1ms);
}

auto bytes_written_read =
_qspi.sendCommand(flash_memory::is25lp016d::command::read_status, -1, empty_tx_buffer, status_register);

if (auto bytes_read = std::get<1>(bytes_written_read);
bytes_read == flash_memory::is25lp016d::status_register_size) {
auto write_enabled = status_register[0] & flash_memory::is25lp016d::status_register::write_enable_latch_mask;
return write_enabled;
}
return false;
}

auto CoreFlashMemoryIS25LP016D::read(uint32_t address, lstd::span<uint8_t> rx_buffer) -> size_t
{
if (address + rx_buffer.size() > flash_memory::is25lp016d::size) {
Expand All @@ -79,6 +106,9 @@ auto CoreFlashMemoryIS25LP016D::write(uint32_t address, lstd::span<uint8_t> tx_b
if (address + tx_buffer.size() > getSize()) {
return 0;
}
if (!enableWrite()) {
return 0;
}

auto bytes_write = _qspi.write(flash_memory::is25lp016d::command::write, -1, address, tx_buffer);

Expand Down
120 changes: 118 additions & 2 deletions drivers/CoreFlashMemory/tests/CoreFlashMemoryIS25LP016D_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using namespace leka;

using ::testing::_;
using ::testing::InSequence;
using ::testing::Return;

class CoreFlashMemoryIS25LP016DTest : public ::testing::Test
Expand Down Expand Up @@ -199,6 +200,116 @@ TEST_F(CoreFlashMemoryIS25LP016DTest, chipIsNotAvailableNoAnswer)
ASSERT_EQ(expected_is_available, actual_is_available);
}

TEST_F(CoreFlashMemoryIS25LP016DTest, enableWrite)
{
auto buffer = lstd::to_array<uint8_t>({0x61, 0x62, 0x63, 0x64, 0x65, 0x66}); // "abcdef"
size_t expected_bytes_written = buffer.size();

uint32_t address = 0x2A;
auto returned_buffer_read_written = std::tuple<size_t, size_t> {0x00, 0x01};
auto returned_value = lstd::to_array({flash_memory::is25lp016d::status_register::write_enable_latch_mask});

{
InSequence seq;

EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::write_enable, _, _, _)).Times(1);
EXPECT_CALL(qspimock,
sendCommand(flash_memory::is25lp016d::command::read_status, _, _, setArray(returned_value)))
.WillRepeatedly(Return(returned_buffer_read_written));
EXPECT_CALL(qspimock, write).WillOnce(Return(expected_bytes_written));
}

auto actual_bytes_written = flash_memory_is25lp.write(address, buffer);

ASSERT_EQ(expected_bytes_written, actual_bytes_written);
}

TEST_F(CoreFlashMemoryIS25LP016DTest, enableWriteFailChipNotYetAvailable)
{
auto buffer = lstd::to_array<uint8_t>({0x61, 0x62, 0x63, 0x64, 0x65, 0x66}); // "abcdef"
size_t expected_bytes_written = buffer.size();

uint32_t address = 0x2A;
auto returned_buffer_read_written = std::tuple<size_t, size_t> {0x00, 0x01};
auto returned_value = lstd::to_array({flash_memory::is25lp016d::status_register::write_enable_latch_mask &
~flash_memory::is25lp016d::status_register::work_in_progress_mask});
auto returned_value_chip_not_available =
lstd::to_array({flash_memory::is25lp016d::status_register::work_in_progress_mask});

{
InSequence seq;

EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::write_enable, _, _, _)).Times(1);
EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::read_status, _, _,
setArray(returned_value_chip_not_available)))
.WillOnce(Return(returned_buffer_read_written));
EXPECT_CALL(qspimock,
sendCommand(flash_memory::is25lp016d::command::read_status, _, _, setArray(returned_value)))
.WillRepeatedly(Return(returned_buffer_read_written));
EXPECT_CALL(qspimock, write).WillOnce(Return(expected_bytes_written));
}

auto actual_bytes_written = flash_memory_is25lp.write(address, buffer);

ASSERT_EQ(expected_bytes_written, actual_bytes_written);
}

TEST_F(CoreFlashMemoryIS25LP016DTest, enableWriteFail)
{
auto buffer = lstd::to_array<uint8_t>({0x61, 0x62, 0x63, 0x64, 0x65, 0x66}); // "abcdef"
size_t expected_bytes_written = 0;

uint32_t address = 0x2A;
auto returned_buffer_read_written = std::tuple<size_t, size_t> {0x00, 0x01};
auto returned_value = lstd::to_array({~flash_memory::is25lp016d::status_register::write_enable_latch_mask &
~flash_memory::is25lp016d::status_register::work_in_progress_mask});

{
InSequence seq;

EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::write_enable, _, _, _)).Times(1);
EXPECT_CALL(qspimock,
sendCommand(flash_memory::is25lp016d::command::read_status, _, _, setArray(returned_value)))
.WillRepeatedly(Return(returned_buffer_read_written));
EXPECT_CALL(qspimock, write).Times(0);
}

auto actual_bytes_written = flash_memory_is25lp.write(address, buffer);

ASSERT_EQ(expected_bytes_written, actual_bytes_written);
}

TEST_F(CoreFlashMemoryIS25LP016DTest, enableWriteFailNoReading)
{
auto buffer = lstd::to_array<uint8_t>({0x61, 0x62, 0x63, 0x64, 0x65, 0x66}); // "abcdef"
size_t expected_bytes_written = 0;

uint32_t address = 0x2A;
auto returned_buffer_read_written_chip_available = std::tuple<size_t, size_t> {0x00, 0x01};
auto returned_buffer_read_written = std::tuple<size_t, size_t> {0x00, 0x00};
auto returned_value = lstd::to_array({flash_memory::is25lp016d::status_register::write_enable_latch_mask &
~flash_memory::is25lp016d::status_register::work_in_progress_mask});
auto returned_value_chip_available =
lstd::to_array({~flash_memory::is25lp016d::status_register::work_in_progress_mask});

{
InSequence seq;

EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::write_enable, _, _, _)).Times(1);
EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::read_status, _, _,
setArray(returned_value_chip_available)))
.WillOnce(Return(returned_buffer_read_written_chip_available));
EXPECT_CALL(qspimock,
sendCommand(flash_memory::is25lp016d::command::read_status, _, _, setArray(returned_value)))
.WillRepeatedly(Return(returned_buffer_read_written));
EXPECT_CALL(qspimock, write).Times(0);
}

auto actual_bytes_written = flash_memory_is25lp.write(address, buffer);

ASSERT_EQ(expected_bytes_written, actual_bytes_written);
}

TEST_F(CoreFlashMemoryIS25LP016DTest, read)
{
const size_t bytes_to_read = 0x10;
Expand Down Expand Up @@ -232,9 +343,14 @@ TEST_F(CoreFlashMemoryIS25LP016DTest, write)
{
auto buffer = lstd::to_array<uint8_t>({0x61, 0x62, 0x63, 0x64, 0x65, 0x66}); // "abcdef"

uint32_t address = 0x2A;
size_t expected_bytes_write = 0x10;
uint32_t address = 0x2A;
size_t expected_bytes_write = 0x10;
auto returned_buffer_read_written = std::tuple<size_t, size_t> {0x00, 0x01};
auto returned_value = lstd::to_array({flash_memory::is25lp016d::status_register::write_enable_latch_mask});

EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::write_enable, _, _, _)).Times(1);
EXPECT_CALL(qspimock, sendCommand(flash_memory::is25lp016d::command::read_status, _, _, setArray(returned_value)))
.WillRepeatedly(Return(returned_buffer_read_written));
EXPECT_CALL(qspimock, write(flash_memory::is25lp016d::command::write, _, address, compareArray(buffer)))
.WillOnce(Return(expected_bytes_write));

Expand Down
3 changes: 2 additions & 1 deletion spikes/lk_flash_memory/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ auto main() -> int

rtos::ThisThread::sleep_for(1s);

coreis25lp.write(address, data);
auto bytes_written = coreis25lp.write(address, data);
log_info("Content write at 0x%x (%dB): %s", address, bytes_written, data);

auto bytes_read = coreis25lp.read(address, buffer);
log_info("Content read at 0x%x (%dB): %s", address, bytes_read, buffer);
Expand Down

0 comments on commit d4c020d

Please sign in to comment.