You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2022/09/14 16:10:54 UTC
[mynewt-core] 01/02: pic32: Relax flash write restrictions
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 1df46ed06d239de6f8777d07832796719868b0ac
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue Sep 13 00:03:16 2022 +0200
pic32: Relax flash write restrictions
Function pic32mz_flash_write() required source data to be 4 bytes
aligned. This alignment is not followed in fcb that can request writes
from odd addresses and that result in crash when *data is used with
odd address.
Now for unaligned source pointer function copies fragments of source
buffer to correctly aligned buffer on stack.
If num_bytes was not multiply of 4 function also did not write anything.
Calls from FCB can write single byte of CRC and this should be allowed
here.
---
hw/mcu/microchip/pic32mz/src/hal_flash.c | 45 +++++++++++++++++++++++++-------
1 file changed, 36 insertions(+), 9 deletions(-)
diff --git a/hw/mcu/microchip/pic32mz/src/hal_flash.c b/hw/mcu/microchip/pic32mz/src/hal_flash.c
index de15f5a96..507947734 100644
--- a/hw/mcu/microchip/pic32mz/src/hal_flash.c
+++ b/hw/mcu/microchip/pic32mz/src/hal_flash.c
@@ -104,23 +104,47 @@ pic32mz_flash_read(const struct hal_flash *dev, uint32_t address,
return 0;
}
+/**
+ * Function returns address to 4 byte aligned data
+ * @param src pointer to source data
+ * @param aligned_buffer address of aligned buffer to use in case src in unaligned
+ * @param aligned_buffer_size size of aligned buffer in bytes
+ * @param num_bytes number of bytes to provide.
+ * @return src if it is 4 byte aligned otherwise aligned_buffer
+ */
+const uint32_t *
+aligned_ptr(const void *src, uint32_t *aligned_buffer, uint32_t aligned_buffer_size, uint32_t num_bytes)
+{
+ if (((uint32_t)src & 3) == 0) {
+ /* Source is aligned, there is no need to copy data */
+ return (const uint32_t *)src;
+ }
+ if (num_bytes > aligned_buffer_size) {
+ num_bytes = aligned_buffer_size;
+ }
+ memcpy(aligned_buffer, src, num_bytes);
+ return aligned_buffer;
+}
+
static int
pic32mz_flash_write(const struct hal_flash *dev, uint32_t address,
const void *src, uint32_t num_bytes)
{
(void)dev;
- const uint32_t *data = (const uint32_t*)src;
- uint32_t word;
+ const uint32_t *data;
+ uint32_t aligned_data[4];
- if (num_bytes & (WORD_SIZE - 1) || (address & 3)) {
+ if ((address & 3)) {
return -1;
}
/* Write flash by word until the next quadword boundary is reached */
while (address & (QUADWORD_SIZE -1) && num_bytes >= WORD_SIZE) {
+ data = aligned_ptr(src, aligned_data, sizeof(aligned_data), num_bytes);
NVMADDR = address;
address += WORD_SIZE;
- NVMDATA0 = *data++;
+ src += WORD_SIZE;
+ NVMDATA0 = *data;
if (flash_do_op(WORD_PROGRAM)) {
return -1;
@@ -129,14 +153,15 @@ pic32mz_flash_write(const struct hal_flash *dev, uint32_t address,
}
while (num_bytes >= QUADWORD_SIZE) {
+ data = aligned_ptr(src, aligned_data, sizeof(aligned_data), num_bytes);
NVMADDR = address;
address += QUADWORD_SIZE;
+ src += QUADWORD_SIZE;
NVMDATA0 = data[0];
NVMDATA1 = data[1];
NVMDATA2 = data[2];
NVMDATA3 = data[3];
- data += 4;
if (flash_do_op(QUADWORD_PROGRAM)) {
return -1;
@@ -145,9 +170,11 @@ pic32mz_flash_write(const struct hal_flash *dev, uint32_t address,
}
while (num_bytes >= WORD_SIZE) {
+ data = aligned_ptr(src, aligned_data, sizeof(aligned_data), num_bytes);
NVMADDR = address;
address += WORD_SIZE;
- NVMDATA0 = *data++;
+ src += WORD_SIZE;
+ NVMDATA0 = *data;
if (flash_do_op(WORD_PROGRAM)) {
return -1;
@@ -155,11 +182,11 @@ pic32mz_flash_write(const struct hal_flash *dev, uint32_t address,
num_bytes -= WORD_SIZE;
}
if (num_bytes > 0) {
- memcpy(&word, data, num_bytes);
- pic32mz_flash_read(dev, address + num_bytes, ((uint8_t *)&word) + num_bytes, WORD_SIZE - num_bytes);
+ aligned_data[0] = 0xFFFFFFFF;
+ memcpy(aligned_data, src, num_bytes);
NVMADDR = address;
- NVMDATA0 = word;
+ NVMDATA0 = aligned_data[0];
if (flash_do_op(WORD_PROGRAM)) {
return -1;