- return 0;
-}
-
-static void lock_flash(struct stlink_libsg* sl) {
- /* write to 1 only. reset by hw at unlock sequence */
-
- const uint32_t n = read_flash_cr(sl) | (1 << FLASH_CR_LOCK);
-
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_pg(struct stlink_libsg* sl) {
- const uint32_t n = 1 << FLASH_CR_PG;
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) clear_flash_cr_pg(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_per(struct stlink_libsg* sl) {
- const uint32_t n = 1 << FLASH_CR_PER;
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) clear_flash_cr_per(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PER);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_mer(struct stlink_libsg* sl) {
- const uint32_t n = 1 << FLASH_CR_MER;
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) clear_flash_cr_mer(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_MER);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_strt(struct stlink_libsg* sl) {
- /* assume come on the flash_cr_per path */
- const uint32_t n = (1 << FLASH_CR_PER) | (1 << FLASH_CR_STRT);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static inline uint32_t read_flash_acr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_ACR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline uint32_t read_flash_sr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_SR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline unsigned int is_flash_busy(struct stlink_libsg* sl) {
- return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
-}
-
-static void wait_flash_busy(struct stlink_libsg* sl) {
- /* todo: add some delays here */
- while (is_flash_busy(sl))
- ;
-}
-
-static inline unsigned int is_flash_eop(struct stlink_libsg* sl) {
- return read_flash_sr(sl) & (1 << FLASH_SR_EOP);
-}
-
-static void __attribute__((unused)) clear_flash_sr_eop(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_sr(sl) & ~(1 << FLASH_SR_EOP);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_SR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) wait_flash_eop(struct stlink_libsg* sl) {
- /* todo: add some delays here */
- while (is_flash_eop(sl) == 0)
- ;
-}
-
-static inline void write_flash_ar(struct stlink_libsg* sl, uint32_t n) {
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_AR, sizeof (uint32_t));
-}
-
-#if 0 /* todo */
-
-static void disable_flash_read_protection(struct stlink* sl) {
- /* erase the option byte area */
- /* rdp = 0x00a5; */
- /* reset */
-}
-#endif /* todo */
-
-#if 0 /* not working */
-
-static int write_flash_mem16
-(struct stlink* sl, uint32_t addr, uint16_t val) {
- /* half word writes */
- if (addr % 2) return -1;
-
- /* unlock if locked */
- unlock_flash_if(sl);
-
- /* set flash programming chosen bit */
- set_flash_cr_pg(sl);
-
- write_uint16(sl->q_buf, val);
- stlink_write_mem16(sl, addr, 2);
-
- /* wait for non business */
- wait_flash_busy(sl);
-
- lock_flash(sl);
-
- /* check the programmed value back */
- stlink_read_mem16(sl, addr, 2);
- if (*(const uint16_t*) sl->q_buf != val) {
- /* values differ at i * sizeof(uint16_t) */
- return -1;
- }
-
- /* success */
- return 0;
-}
-#endif /* not working */
-
-int stlink_erase_flash_page(struct stlink_libsg* sl, stm32_addr_t page) {
- /* page an addr in the page to erase */
-
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
-
- /* unlock if locked */
- unlock_flash_if(sl);
-
- /* set the page erase bit */
- set_flash_cr_per(sl);
-
- /* select the page to erase */
- write_flash_ar(sl, page);
-
- /* start erase operation, reset by hw with bsy bit */
- set_flash_cr_strt(sl);
-
- /* wait for completion */
- wait_flash_busy(sl);
-
- /* relock the flash */
- lock_flash(sl);
-
- /* todo: verify the erased page */
-
- return 0;
-}
-
-int stlink_erase_flash_mass(struct stlink_libsg* sl) {
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
-
- /* unlock if locked */
- unlock_flash_if(sl);
-
- /* set the mass erase bit */
- set_flash_cr_mer(sl);
-
- /* start erase operation, reset by hw with bsy bit */
- set_flash_cr_strt(sl);
-
- /* wait for completion */
- wait_flash_busy(sl);
-
- /* relock the flash */
- lock_flash(sl);
-
- /* todo: verify the erased memory */
-
- return 0;
-}
-
-static unsigned int is_core_halted(struct stlink_libsg* sl) {
- /* return non zero if core is halted */
- stlink_status(sl);
- return sl->q_buf[0] == STLINK_CORE_HALTED;
-}
-
-static int write_loader_to_sram
-(struct stlink* sl, stm32_addr_t* addr, size_t* size) {
- /* from openocd, contrib/loaders/flash/stm32.s */
- static const uint8_t loader_code[] ={
- 0x08, 0x4c, /* ldr r4, STM32_FLASH_BASE */
- 0x1c, 0x44, /* add r4, r3 */
- /* write_half_word: */
- 0x01, 0x23, /* movs r3, #0x01 */
- 0x23, 0x61, /* str r3, [r4, #STM32_FLASH_CR_OFFSET] */
- 0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
- 0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
- /* busy: */
- 0xe3, 0x68, /* ldr r3, [r4, #STM32_FLASH_SR_OFFSET] */
- 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
- 0xfb, 0xd0, /* beq busy */
- 0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
- 0x01, 0xd1, /* bne exit */
- 0x01, 0x3a, /* subs r2, r2, #0x01 */
- 0xf0, 0xd1, /* bne write_half_word */
- /* exit: */
- 0x00, 0xbe, /* bkpt #0x00 */
- 0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */
- };
-
- memcpy(sl->q_buf, loader_code, sizeof (loader_code));
- stlink_write_mem32(sl, sl->sram_base, sizeof (loader_code));
-
- *addr = sl->sram_base;
- *size = sizeof (loader_code);
-
- /* success */
- return 0;
-}
-
-
-int init_flash_loader(stlink_t *stl, flash_loader_t* fl) {
- struct stlink_libsg* sl = stl->backend_data;
- size_t size;
-
- /* allocate the loader in sram */
- if (write_loader_to_sram(sl, &fl->loader_addr, &size) == -1) {
- fprintf(stderr, "write_loader_to_sram() == -1\n");
- return -1;
- }
-
- /* allocate a one page buffer in sram right after loader */
- fl->buf_addr = fl->loader_addr + size;
-
- return 0;