* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
-
.text
.syntax unified
.cpu cortex-m0
.thumb
/*
+Parameters
r0 - destination address
r1 - source address
- r2 - count
+ r2 - half pages
+ r3 - bytes per half page
+ r4 - flash base
+Variables
+ r0 - destination write pointer
+ r1 - source read pointer
+ r2 - source limit address
+ r3 - bytes per half page
+ r4 - flash base
+ r5 - pages left in current half page
+ r6 - temporary r/w
*/
+/* offsets of registers from flash reg base */
+#define STM32_FLASH_SR_OFFSET 0x18
+
.thumb_func
.global _start
_start:
- // r2 = source + count * 4
- lsls r2, r2, #2
- adds r2, r1, r2
+ // r2 = source + half pages * bytes per half page
+ muls r2, r2, r3
+ add r2, r1, r2
// Go to compare
- b test_done
+ b test_done
+write_half_page:
+ // initialize pages left in current half page
+ mov r5, r3
write_word:
// load word from address in r1 and increase r1 by 4
- ldmia r1!, {r3}
+ ldmia r1!, {r6}
// store word to address in r0 and increase r0 by 4
- stmia r0!, {r3}
+ stmia r0!, {r6}
+ // check for end of half page
+ subs r5, r5, #4
+ bne write_word
+wait_busy:
+ // read status register into r6, loop while bottom bit is set
+ ldr r6, [r4, #STM32_FLASH_SR_OFFSET]
+ lsls r6, r6, #31
+ bne wait_busy
test_done:
- // compare r1 and r2
+ // compare r1 and r2, loop if not equal
cmp r1, r2
- // loop if not equal
- bne write_word
+ bne write_half_page
// Set breakpoint to exit
- bkpt #0x00
-
+ bkpt #0x00
/* Autogenerated with ../../../../src/helper/bin2char.sh */
-0x92,0x00,0x8a,0x18,0x01,0xe0,0x08,0xc9,0x08,0xc0,0x91,0x42,0xfb,0xd1,0x00,0xbe,
+0x5a,0x43,0x0a,0x44,0x07,0xe0,0x1d,0x46,0x40,0xc9,0x40,0xc0,0x04,0x3d,0xfb,0xd1,
+0xa6,0x69,0xf6,0x07,0xfc,0xd1,0x91,0x42,0xf5,0xd1,0x00,0xbe,
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
uint32_t hp_nb = stm32lx_info->part_info.page_size / 2;
- uint32_t buffer_size = 16384;
+ uint32_t buffer_size = (16384 / hp_nb) * hp_nb; /* must be multiple of hp_nb */
struct working_area *write_algorithm;
struct working_area *source;
uint32_t address = bank->base + offset;
- struct reg_param reg_params[3];
+ struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
};
/* Make sure we're performing a half-page aligned write. */
+ if (offset % hp_nb) {
+ LOG_ERROR("The offset must be %" PRIu32 "B-aligned but it is %" PRIi32 "B)", hp_nb, offset);
+ return ERROR_FAIL;
+ }
if (count % hp_nb) {
LOG_ERROR("The byte count must be %" PRIu32 "B-aligned but count is %" PRIu32 "B)", hp_nb, count);
return ERROR_FAIL;
LOG_WARNING("no large enough working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ } else {
+ /* Make sure we're still asking for an integral number of half-pages */
+ buffer_size -= buffer_size % hp_nb;
}
}
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
+ init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
+ init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
/* Enable half-page write */
retval = stm32lx_enable_write_half_page(bank);
destroy_reg_param(®_params[0]);
destroy_reg_param(®_params[1]);
destroy_reg_param(®_params[2]);
+ destroy_reg_param(®_params[3]);
+ destroy_reg_param(®_params[4]);
return retval;
}
buf_set_u32(reg_params[0].value, 0, 32, address);
/* The source address of the copy (R1) */
buf_set_u32(reg_params[1].value, 0, 32, source->address);
- /* The length of the copy (R2) */
- buf_set_u32(reg_params[2].value, 0, 32, this_count / 4);
+ /* The number of half pages to copy (R2) */
+ buf_set_u32(reg_params[2].value, 0, 32, this_count / hp_nb);
+ /* The size in byes of a half page (R3) */
+ buf_set_u32(reg_params[3].value, 0, 32, hp_nb);
+ /* The flash base address (R4) */
+ buf_set_u32(reg_params[4].value, 0, 32, stm32lx_info->flash_base);
/* 5: Execute the bunch of code */
retval = target_run_algorithm(target, 0, NULL,
destroy_reg_param(®_params[0]);
destroy_reg_param(®_params[1]);
destroy_reg_param(®_params[2]);
+ destroy_reg_param(®_params[3]);
+ destroy_reg_param(®_params[4]);
return retval;
}