Merge pull request #6864 from davidsaada/david_flashiap_unaligned_src

FlashIAP: Fix problem of programming source buffer not aligned to 4
pull/6480/head
Cruz Monrreal 2018-05-14 10:35:38 -05:00 committed by GitHub
commit 15ff9a8bf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 14 deletions

View File

@ -22,6 +22,7 @@
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include <algorithm>
#include "mbed.h"
@ -48,10 +49,10 @@ void flashiap_program_test()
TEST_ASSERT_NOT_EQUAL(0, sector_size);
TEST_ASSERT_NOT_EQUAL(0, page_size);
TEST_ASSERT_TRUE(sector_size % page_size == 0);
const uint8_t test_value = 0xCE;
uint8_t *data = new uint8_t[page_size];
for (uint32_t i = 0; i < page_size; i++) {
data[i] = test_value;
uint32_t prog_size = std::max(page_size, (uint32_t)8);
uint8_t *data = new uint8_t[prog_size + 2];
for (uint32_t i = 0; i < prog_size + 2; i++) {
data[i] = i;
}
// the one before the last sector in the system
@ -61,19 +62,29 @@ void flashiap_program_test()
TEST_ASSERT_EQUAL_INT32(0, ret);
for (uint32_t i = 0; i < sector_size / page_size; i++) {
uint32_t page_addr = address + i * page_size;
ret = flash_device.program(data, page_addr, page_size);
for (uint32_t i = 0; i < sector_size / prog_size; i++) {
uint32_t prog_addr = address + i * prog_size;
ret = flash_device.program(data, prog_addr, prog_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
}
uint8_t *data_flashed = new uint8_t[page_size];
for (uint32_t i = 0; i < sector_size / page_size; i++) {
uint32_t page_addr = address + i * page_size;
ret = flash_device.read(data_flashed, page_addr, page_size);
uint8_t *data_flashed = new uint8_t[prog_size];
for (uint32_t i = 0; i < sector_size / prog_size; i++) {
uint32_t page_addr = address + i * prog_size;
ret = flash_device.read(data_flashed, page_addr, prog_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, page_size);
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, prog_size);
}
// check programming of unaligned buffer and size
ret = flash_device.erase(address, sector_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
ret = flash_device.program(data + 2, address, prog_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
ret = flash_device.read(data_flashed, address, prog_size - 1);
TEST_ASSERT_EQUAL_INT32(0, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY(data + 2, data_flashed, prog_size - 1);
delete[] data;
delete[] data_flashed;

View File

@ -107,10 +107,18 @@ int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
_mutex->lock();
while (size) {
uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf);
chunk = std::min(current_sector_size - (addr % current_sector_size), size);
if (chunk < page_size) {
// Need to use the internal page buffer in any of these two cases:
// 1. Size is not page aligned
// 2. Source buffer is not aligned to uint32_t. This is not supported by many targets (although
// the pointer they accept is of uint8_t).
if (unaligned_src || (chunk < page_size)) {
chunk = std::min(chunk, page_size);
memcpy(_page_buf, buf, chunk);
memset(_page_buf + chunk, 0xFF, page_size - chunk);
if (chunk < page_size) {
memset(_page_buf + chunk, 0xFF, page_size - chunk);
}
prog_buf = _page_buf;
prog_size = page_size;
} else {