Skip to content

Commit 15ff9a8

Browse files
author
Cruz Monrreal
authored
Merge pull request #6864 from davidsaada/david_flashiap_unaligned_src
FlashIAP: Fix problem of programming source buffer not aligned to 4
2 parents e533b41 + 9cdecf4 commit 15ff9a8

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

TESTS/mbed_drivers/flashiap/main.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "utest/utest.h"
2323
#include "unity/unity.h"
2424
#include "greentea-client/test_env.h"
25+
#include <algorithm>
2526

2627
#include "mbed.h"
2728

@@ -48,10 +49,10 @@ void flashiap_program_test()
4849
TEST_ASSERT_NOT_EQUAL(0, sector_size);
4950
TEST_ASSERT_NOT_EQUAL(0, page_size);
5051
TEST_ASSERT_TRUE(sector_size % page_size == 0);
51-
const uint8_t test_value = 0xCE;
52-
uint8_t *data = new uint8_t[page_size];
53-
for (uint32_t i = 0; i < page_size; i++) {
54-
data[i] = test_value;
52+
uint32_t prog_size = std::max(page_size, (uint32_t)8);
53+
uint8_t *data = new uint8_t[prog_size + 2];
54+
for (uint32_t i = 0; i < prog_size + 2; i++) {
55+
data[i] = i;
5556
}
5657

5758
// the one before the last sector in the system
@@ -61,19 +62,29 @@ void flashiap_program_test()
6162
TEST_ASSERT_EQUAL_INT32(0, ret);
6263

6364

64-
for (uint32_t i = 0; i < sector_size / page_size; i++) {
65-
uint32_t page_addr = address + i * page_size;
66-
ret = flash_device.program(data, page_addr, page_size);
65+
for (uint32_t i = 0; i < sector_size / prog_size; i++) {
66+
uint32_t prog_addr = address + i * prog_size;
67+
ret = flash_device.program(data, prog_addr, prog_size);
6768
TEST_ASSERT_EQUAL_INT32(0, ret);
6869
}
6970

70-
uint8_t *data_flashed = new uint8_t[page_size];
71-
for (uint32_t i = 0; i < sector_size / page_size; i++) {
72-
uint32_t page_addr = address + i * page_size;
73-
ret = flash_device.read(data_flashed, page_addr, page_size);
71+
uint8_t *data_flashed = new uint8_t[prog_size];
72+
for (uint32_t i = 0; i < sector_size / prog_size; i++) {
73+
uint32_t page_addr = address + i * prog_size;
74+
ret = flash_device.read(data_flashed, page_addr, prog_size);
7475
TEST_ASSERT_EQUAL_INT32(0, ret);
75-
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, page_size);
76+
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, prog_size);
7677
}
78+
79+
// check programming of unaligned buffer and size
80+
ret = flash_device.erase(address, sector_size);
81+
TEST_ASSERT_EQUAL_INT32(0, ret);
82+
ret = flash_device.program(data + 2, address, prog_size);
83+
TEST_ASSERT_EQUAL_INT32(0, ret);
84+
ret = flash_device.read(data_flashed, address, prog_size - 1);
85+
TEST_ASSERT_EQUAL_INT32(0, ret);
86+
TEST_ASSERT_EQUAL_UINT8_ARRAY(data + 2, data_flashed, prog_size - 1);
87+
7788
delete[] data;
7889
delete[] data_flashed;
7990

drivers/FlashIAP.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,18 @@ int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
107107
_mutex->lock();
108108
while (size) {
109109
uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
110+
bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf);
110111
chunk = std::min(current_sector_size - (addr % current_sector_size), size);
111-
if (chunk < page_size) {
112+
// Need to use the internal page buffer in any of these two cases:
113+
// 1. Size is not page aligned
114+
// 2. Source buffer is not aligned to uint32_t. This is not supported by many targets (although
115+
// the pointer they accept is of uint8_t).
116+
if (unaligned_src || (chunk < page_size)) {
117+
chunk = std::min(chunk, page_size);
112118
memcpy(_page_buf, buf, chunk);
113-
memset(_page_buf + chunk, 0xFF, page_size - chunk);
119+
if (chunk < page_size) {
120+
memset(_page_buf + chunk, 0xFF, page_size - chunk);
121+
}
114122
prog_buf = _page_buf;
115123
prog_size = page_size;
116124
} else {

0 commit comments

Comments
 (0)