Skip to content

Commit

Permalink
Fix FlashIAP test failure
Browse files Browse the repository at this point in the history
  • Loading branch information
multiplemonomials committed Jan 24, 2025
1 parent f7d1aef commit a208924
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ cmake_install.cmake
CMakeFiles/
cmake_build/
Testing/
cmake-variants.yaml
CMakeUserPresets.json

# CLion
cmake-build-*/
28 changes: 17 additions & 11 deletions drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,11 @@ void flashiap_timing_test()
std::chrono::microseconds curr_time{};
std::chrono::microseconds avg_erase_time{};
unsigned int num_write_sizes;
unsigned int byte_usec_ratio;
float byte_sec_ratio;
std::chrono::microseconds max_erase_time(0), min_erase_time(-1);
const unsigned int max_writes = 128;
const unsigned int max_write_sizes = 6;
const unsigned int max_byte_usec_ratio = 200;
const unsigned int max_byte_sec_ratio = 200000000;

uint32_t page_size = flash_device.get_page_size();
uint32_t write_size = page_size;
Expand Down Expand Up @@ -294,28 +294,34 @@ void flashiap_timing_test()
}
timer.reset();
ret = flash_device.program(buf, address, write_size);

if(ret)
{
printf("Failed programming %" PRIu32 " bytes at address 0x%" PRIx32 "\n!", write_size, address);
TEST_FAIL();
}

curr_time = timer.elapsed_time();
avg_write_time += curr_time;
TEST_ASSERT_EQUAL_INT32(0, ret);
max_write_time = us_max(max_write_time, curr_time);
min_write_time = us_min(min_write_time, curr_time);
address += write_size;
}
delete[] buf;
avg_write_time /= num_writes;
byte_usec_ratio = write_size / avg_write_time.count();
utest_printf("Write size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64 " (usec), rate %10u bytes/usec\n",
write_size, avg_write_time.count(), min_write_time.count(), max_write_time.count(), byte_usec_ratio);
TEST_ASSERT(byte_usec_ratio < max_byte_usec_ratio);
byte_sec_ratio = write_size / std::chrono::duration_cast<std::chrono::duration<float>>(avg_write_time).count();
utest_printf("Write size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64 " (usec), rate %.01f bytes/sec\n",
write_size, avg_write_time.count(), min_write_time.count(), max_write_time.count(), byte_sec_ratio);
TEST_ASSERT(byte_sec_ratio < max_byte_sec_ratio);
write_size *= 4;
}

if (num_write_sizes) {
avg_erase_time /= num_write_sizes;
byte_usec_ratio = sector_size / avg_erase_time.count();
utest_printf("\nErase size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64" (usec), rate %10u bytes/usec\n\n",
sector_size, avg_erase_time.count(), min_erase_time.count(), max_erase_time.count(), byte_usec_ratio);
TEST_ASSERT(byte_usec_ratio < max_byte_usec_ratio);
byte_sec_ratio = sector_size / std::chrono::duration_cast<std::chrono::duration<float>>(avg_erase_time).count();
utest_printf("\nErase size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64" (usec), rate %.01f bytes/sec\n\n",
sector_size, avg_erase_time.count(), min_erase_time.count(), max_erase_time.count(), byte_sec_ratio);
TEST_ASSERT(byte_sec_ratio < max_byte_sec_ratio);
}

ret = flash_device.deinit();
Expand Down
17 changes: 14 additions & 3 deletions targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "cmsis.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

#define MEMMAP (*((volatile unsigned long *) 0x400FC040))

Expand Down Expand Up @@ -122,10 +124,18 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
// On LPC1768, the first RAM bank starts at 0x1000000, so anywhere below that has to be flash.
// The IAP firmware does not support flash to flash copies, so if the source data is in flash
// it must be buffered in RAM.
bool isFlashToFlashCopy = (ptrdiff_t)(data) < 0x10000000;
// Additionally, there seems to be an issue where the IAP ROM won't operate if a source page to be copied
// crosses the boundary between AHBSRAM0 and AHBSRAM1
const bool startsInAHBSRAM1 = ((uint32_t)data) >= MBED_CONFIGURED_RAM_BANK_IRAM2_START && ((uint32_t)data) < (MBED_CONFIGURED_RAM_BANK_IRAM2_START + 16384);
const bool endsInAHBSRAM2 = startsInAHBSRAM1 && ((((uint32_t)data) + size) >= MBED_CONFIGURED_RAM_BANK_IRAM2_START + 16384);
const bool sourceAddressPageAligned = (((uint32_t)data) % pageSize) == 0;
bool mustBuffer = ((ptrdiff_t)(data) < MBED_CONFIGURED_RAM_BANK_IRAM1_START) || (startsInAHBSRAM1 && endsInAHBSRAM2 && !sourceAddressPageAligned);

// printf("Flash program: flash address = 0x%" PRIx32 ", source data = 0x%" PRIx32 ", size = 0x%" PRIx32 ", startsInAHBSRAM1 = %d, endsInAHBSRAM2=%d, mustBuffer=%d\n",
// address, (ptrdiff_t)data, size, !!startsInAHBSRAM1, !!endsInAHBSRAM2, !!mustBuffer);

// check word boundary
if (isFlashToFlashCopy) {
if (mustBuffer) {
// always malloc outside critical section
tempBuffer = malloc(pageSize);
if (tempBuffer == 0) {
Expand All @@ -140,7 +150,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
for(size_t pageIdx = 0; pageIdx < (size / pageSize); ++pageIdx)
{
uint8_t * pageSourceAddr = source + (pageIdx * pageSize);
if (isFlashToFlashCopy) {
if (mustBuffer) {
memcpy(tempBuffer, pageSourceAddr, pageSize);
pageSourceAddr = tempBuffer;
}
Expand All @@ -166,6 +176,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
IAP_Call (&IAP.cmd, &IAP.stat); // Call IAP Command
if (IAP.stat) {
core_util_critical_section_exit();
//printf("IAP copy failed, address=0x%lx, pageSourceAddr=0x%lx, pageSize=%u\n", address, pageSourceAddr, pageSize);
return -1; // Command Failed
}

Expand Down

0 comments on commit a208924

Please sign in to comment.