[sw] flash_ctrl updates to support program resolution
- split an incoming programming request into required chunks
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/sw/device/lib/flash_ctrl.c b/sw/device/lib/flash_ctrl.c
index 598a12d..06c9421 100644
--- a/sw/device/lib/flash_ctrl.c
+++ b/sw/device/lib/flash_ctrl.c
@@ -7,6 +7,8 @@
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#define FLASH_CTRL0_BASE_ADDR TOP_EARLGREY_FLASH_CTRL_BASE_ADDR
+#define PROGRAM_RESOLUTION_WORDS \
+ (FLASH_CTRL_PARAM_REGBUSPGMRESBYTES / sizeof(uint32_t))
#define REG32(add) *((volatile uint32_t *)(add))
#define SETBIT(val, bit) (val | 1 << bit)
@@ -113,10 +115,38 @@
return get_clr_err();
}
+// The address is assumed to be aligned to uint32_t.
int flash_write(uint32_t addr, part_type_t part, const uint32_t *data,
uint32_t size) {
- // TODO: Breakdown into FIFO chunks if needed.
- return flash_write_internal(addr, part, data, size);
+ uint32_t window_offset = (addr / sizeof(uint32_t)) % PROGRAM_RESOLUTION_WORDS;
+ uint32_t max_words = PROGRAM_RESOLUTION_WORDS;
+
+ // If initial address isn't aligned, the delta is the max
+ // number of words that can be programmed.
+ max_words = PROGRAM_RESOLUTION_WORDS - window_offset;
+
+ // Loop through the amount of data to program.
+ uint32_t words_to_program = max_words;
+ uint32_t words_remaining = size;
+ uint32_t current_word = 0;
+ uint32_t err = 0;
+ while (words_remaining > 0) {
+ // Determine the number of words to program.
+ if (words_remaining < max_words) {
+ words_to_program = words_remaining;
+ } else {
+ words_to_program = max_words;
+ }
+ err |= flash_write_internal(addr + current_word * sizeof(uint32_t), part,
+ data, words_to_program);
+ current_word += words_to_program;
+ data += words_to_program;
+
+ // Increment remaining words and reset max words to program.
+ max_words = PROGRAM_RESOLUTION_WORDS;
+ words_remaining = size - current_word;
+ }
+ return err;
}
int flash_read(uint32_t addr, part_type_t part, uint32_t size, uint32_t *data) {