Skip to content

Commit 374d605

Browse files
authored
Merge pull request #575 from rizlik/pic32_fixes
Pic32c: fix unaligned read, always check flash done after flash operations
2 parents dea8b4e + 1151f5f commit 374d605

File tree

2 files changed

+78
-21
lines changed

2 files changed

+78
-21
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: 38 additions & 20 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,23 +171,26 @@ 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);
186186
pic32_fcw_wait_complete();
187187
err = pic32_get_errs();
188188
pic32_last_err = err;
189-
err &= ~FCW_INTFLAG_DONE_BIT;
189+
if (!(err & FCW_INTFLAG_DONE_BIT)) {
190+
err = -1;
191+
} else {
192+
err &= ~FCW_INTFLAG_DONE_BIT;
193+
}
190194
pic32_clear_errs();
191195
return err;
192196
}
@@ -201,14 +205,6 @@ static uint32_t pic32_addr_dqword_align(uint32_t addr)
201205
return (addr & ~0x1F);
202206
}
203207

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-
212208
static int pic32_fcw_erase_sector(uint32_t addr)
213209
{
214210
uint32_t err;
@@ -218,9 +214,13 @@ static int pic32_fcw_erase_sector(uint32_t addr)
218214
pic32_fcw_start_op(FCW_OP_ERASE_SECTOR);
219215
pic32_fcw_wait_complete();
220216
err = pic32_get_errs();
221-
pic32_clear_errs();
222217
pic32_last_err = err;
223-
err &= ~FCW_INTFLAG_DONE_BIT;
218+
if (!(err & FCW_INTFLAG_DONE_BIT)) {
219+
err = -1;
220+
} else {
221+
err &= ~FCW_INTFLAG_DONE_BIT;
222+
}
223+
pic32_clear_errs();
224224
return err;
225225
}
226226

@@ -239,7 +239,8 @@ static uint8_t pic32_mask_zeros(uint8_t programmed, uint8_t to_program)
239239

240240
int pic32_flash_write(uint32_t address, const uint8_t *data, int len)
241241
{
242-
uint8_t buff[FCW_WRITE_SIZE], curr[FCW_WRITE_SIZE];
242+
uint32_t buff[FCW_WRITE_WORD_SIZE], curr[FCW_WRITE_WORD_SIZE];
243+
uint8_t *p_buff, *p_curr;
243244
uint32_t _addr;
244245
uint8_t i;
245246
int ret;
@@ -256,11 +257,13 @@ int pic32_flash_write(uint32_t address, const uint8_t *data, int len)
256257
* is at least WOLFBOOT_SECTOR_SIZE, an erase was already performed,
257258
* so we can write data directly.
258259
*/
259-
pic32_copy_dqword(curr, _addr);
260-
memset(buff, 0xff, FCW_WRITE_SIZE);
260+
memcpy(curr, (uint8_t*)(uintptr_t)_addr, sizeof(curr));
261+
memset(buff, 0xff, sizeof(buff));
261262
i = address - _addr;
263+
p_curr = (uint8_t*)curr;
264+
p_buff = (uint8_t*)buff;
262265
for (; i < FCW_WRITE_SIZE && len > 0; i++, len--) {
263-
buff[i] = pic32_mask_zeros(curr[i], *data);
266+
p_buff[i] = pic32_mask_zeros(p_curr[i], *data);
264267
data++;
265268
address++;
266269
}
@@ -269,7 +272,15 @@ int pic32_flash_write(uint32_t address, const uint8_t *data, int len)
269272
return ret;
270273
continue;
271274
}
272-
ret = pic32_write_dqword_aligned(address, data);
275+
276+
/* move data in aligned buffer */
277+
if (!pic32_addr_is_dqword_aligned((uint32_t)(uintptr_t)data)) {
278+
memcpy(buff, data, sizeof(buff));
279+
ret = pic32_write_dqword_aligned(address, buff);
280+
} else {
281+
ret = pic32_write_dqword_aligned(address, (uint32_t*)data);
282+
}
283+
273284
if (ret != 0)
274285
return ret;
275286
address += FCW_WRITE_SIZE;
@@ -406,6 +417,7 @@ int hal_flash_test_align(void);
406417
int hal_flash_test_write_once(void);
407418
int hal_flash_test(void);
408419
int hal_flash_test_dualbank(void);
420+
int hal_flash_test_unaligned_src(void);
409421
void pic32_flash_test(void)
410422
{
411423
int ret;
@@ -419,6 +431,12 @@ void pic32_flash_test(void)
419431
ret = hal_flash_test_write_once();
420432
if (ret != 0)
421433
wolfBoot_panic();
434+
/* enable unaligned access fault for testing */
435+
ret = *(volatile uint32_t*)0xE000ED14;
436+
*(volatile uint32_t*)0xE000ED14 = ret | 8;
437+
ret = hal_flash_test_unaligned_src();
438+
if (ret != 0)
439+
wolfBoot_panic();
422440
#ifdef DUALBANK_SWAP
423441
ret = hal_flash_test_dualbank();
424442
if (ret != 0)

0 commit comments

Comments
 (0)