Skip to content

Commit 3a5bffa

Browse files
committed
pic32c: fix buffer alignment issues in flash driver
1 parent dea8b4e commit 3a5bffa

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

hal/hal.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,46 @@ int hal_flash_test_align(void)
178178
wolfBoot_printf("Unaligned write test passed\n");
179179
return 0;
180180
}
181-
#endif
181+
182+
int hal_flash_test_unaligned_src(void)
183+
{
184+
uint32_t src[9];
185+
unsigned int i;
186+
uint8_t *ptr;
187+
int ret;
188+
189+
/* force unaligned pointer */
190+
ptr = (uint8_t*)(uintptr_t)src;
191+
ptr++;
192+
193+
for (i = 0; i < sizeof(src); i++) {
194+
ptr[i] = i & 0xff;
195+
}
196+
197+
hal_flash_unlock();
198+
ret = hal_flash_erase(TEST_ADDRESS, TEST_SZ);
199+
hal_flash_lock();
200+
if (ret != 0) {
201+
wolfBoot_printf("Erase Sector failed: Ret %d\n", ret);
202+
return -1;
203+
}
204+
205+
hal_flash_unlock();
206+
ret = hal_flash_write(TEST_ADDRESS, ptr, sizeof(src) - 1);
207+
hal_flash_lock();
208+
if (ret != 0) {
209+
wolfBoot_printf("writing for unaligned source failed: Ret %d\n", ret);
210+
return -1;
211+
}
212+
if (memcmp(ptr, (uint8_t*)TEST_ADDRESS, sizeof(src) - 1) != 0) {
213+
wolfBoot_printf("unaligned source verification failed\n");
214+
return -1;
215+
}
216+
217+
return 0;
218+
}
219+
220+
#endif /* TEST_FLASH_READONLY */
182221

183222
/* This test can be run only if swapping the flash do not reboot the board */
184223
#if defined(DUALBANK_SWAP) && !defined(TEST_FLASH_READONLY)

hal/pic32c.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#define FCW_MUTEX_LOCK_MASK 0x1
7777

7878
#define FCW_WRITE_SIZE (4 * 8)
79+
#define FCW_WRITE_WORD_SIZE (8)
7980
static uint32_t pic32_last_err = 0;
8081

8182
#define OSCCTRL_STATUS (*(volatile uint32_t *)(OSCCTRL_BASE + 0x10U))
@@ -170,16 +171,15 @@ static void pic32_fcw_wait_complete(void)
170171
while (FCW_STATUS & FCW_BUSY_MASK) {}
171172
}
172173

173-
static int pic32_write_dqword_aligned(uint32_t addr, const uint8_t *data)
174+
static int pic32_write_dqword_aligned(uint32_t addr, const uint32_t *data)
174175
{
175-
uint32_t i;
176-
uint32_t *_data = (uint32_t *)data;
177176
uint32_t err;
177+
uint32_t i;
178178

179179
pic32_fcw_wait_complete();
180180
FCW_ADDR = addr;
181181
for (i = 0; i < 8; i++) {
182-
FCW_DATA[i] = _data[i];
182+
FCW_DATA[i] = data[i];
183183
}
184184
FCW_KEY = FCW_UNLOCK_WRKEY;
185185
pic32_fcw_start_op(FCW_OP_QUAD_DOUBLE_WORD_WRITE);
@@ -201,14 +201,6 @@ static uint32_t pic32_addr_dqword_align(uint32_t addr)
201201
return (addr & ~0x1F);
202202
}
203203

204-
static void pic32_copy_dqword(uint8_t *dst, uint32_t addr)
205-
{
206-
int i;
207-
for (i = 0; i < FCW_WRITE_SIZE; i++) {
208-
dst[i] = *(volatile uint8_t *)(addr + i);
209-
}
210-
}
211-
212204
static int pic32_fcw_erase_sector(uint32_t addr)
213205
{
214206
uint32_t err;
@@ -239,7 +231,8 @@ static uint8_t pic32_mask_zeros(uint8_t programmed, uint8_t to_program)
239231

240232
int pic32_flash_write(uint32_t address, const uint8_t *data, int len)
241233
{
242-
uint8_t buff[FCW_WRITE_SIZE], curr[FCW_WRITE_SIZE];
234+
uint32_t buff[FCW_WRITE_WORD_SIZE], curr[FCW_WRITE_WORD_SIZE];
235+
uint8_t *p_buff, *p_curr;
243236
uint32_t _addr;
244237
uint8_t i;
245238
int ret;
@@ -256,11 +249,13 @@ int pic32_flash_write(uint32_t address, const uint8_t *data, int len)
256249
* is at least WOLFBOOT_SECTOR_SIZE, an erase was already performed,
257250
* so we can write data directly.
258251
*/
259-
pic32_copy_dqword(curr, _addr);
260-
memset(buff, 0xff, FCW_WRITE_SIZE);
252+
memcpy(curr, (uint8_t*)(uintptr_t)_addr, sizeof(curr));
253+
memset(buff, 0xff, sizeof(buff));
261254
i = address - _addr;
255+
p_curr = (uint8_t*)curr;
256+
p_buff = (uint8_t*)buff;
262257
for (; i < FCW_WRITE_SIZE && len > 0; i++, len--) {
263-
buff[i] = pic32_mask_zeros(curr[i], *data);
258+
p_buff[i] = pic32_mask_zeros(p_curr[i], *data);
264259
data++;
265260
address++;
266261
}
@@ -269,7 +264,15 @@ int pic32_flash_write(uint32_t address, const uint8_t *data, int len)
269264
return ret;
270265
continue;
271266
}
272-
ret = pic32_write_dqword_aligned(address, data);
267+
268+
/* move data in aligned buffer */
269+
if (!pic32_addr_is_dqword_aligned((uint32_t)(uintptr_t)data)) {
270+
memcpy(buff, data, sizeof(buff));
271+
ret = pic32_write_dqword_aligned(address, buff);
272+
} else {
273+
ret = pic32_write_dqword_aligned(address, (uint32_t*)data);
274+
}
275+
273276
if (ret != 0)
274277
return ret;
275278
address += FCW_WRITE_SIZE;
@@ -406,6 +409,7 @@ int hal_flash_test_align(void);
406409
int hal_flash_test_write_once(void);
407410
int hal_flash_test(void);
408411
int hal_flash_test_dualbank(void);
412+
int hal_flash_test_unaligned_src(void);
409413
void pic32_flash_test(void)
410414
{
411415
int ret;
@@ -419,6 +423,12 @@ void pic32_flash_test(void)
419423
ret = hal_flash_test_write_once();
420424
if (ret != 0)
421425
wolfBoot_panic();
426+
/* enable unaligned access fault for testing */
427+
ret = *(volatile uint32_t*)0xE000ED14;
428+
*(volatile uint32_t*)0xE000ED14 = ret | 8;
429+
ret = hal_flash_test_unaligned_src();
430+
if (ret != 0)
431+
wolfBoot_panic();
422432
#ifdef DUALBANK_SWAP
423433
ret = hal_flash_test_dualbank();
424434
if (ret != 0)

0 commit comments

Comments
 (0)