target: split target flash functions into seperate file
This commit is contained in:
parent
3d3dd21d48
commit
520be57e3d
|
@ -62,6 +62,7 @@ SRC = \
|
||||||
stm32l4.c \
|
stm32l4.c \
|
||||||
stm32g0.c \
|
stm32g0.c \
|
||||||
target.c \
|
target.c \
|
||||||
|
target_flash.c \
|
||||||
target_probe.c
|
target_probe.c
|
||||||
|
|
||||||
include $(PLATFORM_DIR)/Makefile.inc
|
include $(PLATFORM_DIR)/Makefile.inc
|
||||||
|
|
|
@ -29,9 +29,6 @@ target *target_list = NULL;
|
||||||
|
|
||||||
#define STDOUT_READ_BUF_SIZE 64
|
#define STDOUT_READ_BUF_SIZE 64
|
||||||
|
|
||||||
static int target_flash_write_buffered(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
|
||||||
static int target_flash_done_buffered(target_flash_s *f);
|
|
||||||
|
|
||||||
static bool target_cmd_mass_erase(target *t, int argc, const char **argv);
|
static bool target_cmd_mass_erase(target *t, int argc, const char **argv);
|
||||||
static bool target_cmd_range_erase(target *t, int argc, const char **argv);
|
static bool target_cmd_range_erase(target *t, int argc, const char **argv);
|
||||||
|
|
||||||
|
@ -255,122 +252,6 @@ bool target_mem_map(target *t, char *tmp, size_t len)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_flash_s *target_flash_for_addr(target *t, uint32_t addr)
|
|
||||||
{
|
|
||||||
for (target_flash_s *f = t->flash; f; f = f->next)
|
|
||||||
if ((f->start <= addr) &&
|
|
||||||
(addr < (f->start + f->length)))
|
|
||||||
return f;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int target_flash_erase(target *t, target_addr_t addr, size_t len)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
while (len) {
|
|
||||||
target_flash_s *f = target_flash_for_addr(t, addr);
|
|
||||||
if (!f) {
|
|
||||||
DEBUG_WARN("Requested address is outside the valid range 0x%06" PRIx32 "\n", addr);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const target_addr_t local_start_addr = addr & ~(f->blocksize - 1U);
|
|
||||||
const target_addr_t local_end_addr = local_start_addr + f->blocksize;
|
|
||||||
|
|
||||||
ret |= f->erase(f, local_start_addr, f->blocksize);
|
|
||||||
|
|
||||||
len -= MIN(local_end_addr - addr, len);
|
|
||||||
addr = local_end_addr;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int target_flash_write(target *t, target_addr_t dest, const void *src, size_t len)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
while (len) {
|
|
||||||
target_flash_s *f = target_flash_for_addr(t, dest);
|
|
||||||
if (!f)
|
|
||||||
return 1;
|
|
||||||
size_t tmptarget = MIN(dest + len, f->start + f->length);
|
|
||||||
size_t tmplen = tmptarget - dest;
|
|
||||||
ret |= target_flash_write_buffered(f, dest, src, tmplen);
|
|
||||||
dest += tmplen;
|
|
||||||
src += tmplen;
|
|
||||||
len -= tmplen;
|
|
||||||
/* If the current chunk of Flash is now full from this operation
|
|
||||||
* then finish operations on the Flash chunk and free the internal buffer.
|
|
||||||
*/
|
|
||||||
if (dest == f->start + f->length)
|
|
||||||
ret |= target_flash_done_buffered(f);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int target_flash_done(target *t)
|
|
||||||
{
|
|
||||||
for (target_flash_s *f = t->flash; f; f = f->next) {
|
|
||||||
int tmp = target_flash_done_buffered(f);
|
|
||||||
if (tmp)
|
|
||||||
return tmp;
|
|
||||||
if (f->done) {
|
|
||||||
tmp = f->done(f);
|
|
||||||
if (tmp)
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int target_flash_write_buffered(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (f->buf == NULL) {
|
|
||||||
/* Allocate flash sector buffer */
|
|
||||||
f->buf = malloc(f->writesize);
|
|
||||||
if (!f->buf) { /* malloc failed: heap exhaustion */
|
|
||||||
DEBUG_WARN("malloc: failed in %s\n", __func__);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
f->buf_addr = -1;
|
|
||||||
}
|
|
||||||
while (len) {
|
|
||||||
uint32_t offset = dest % f->writesize;
|
|
||||||
uint32_t base = dest - offset;
|
|
||||||
if (base != f->buf_addr) {
|
|
||||||
if (f->buf_addr != (uint32_t)-1) {
|
|
||||||
/* Write sector to flash if valid */
|
|
||||||
ret |= f->write(f, f->buf_addr, f->buf, f->writesize);
|
|
||||||
}
|
|
||||||
/* Setup buffer for a new sector */
|
|
||||||
f->buf_addr = base;
|
|
||||||
memset(f->buf, f->erased, f->writesize);
|
|
||||||
}
|
|
||||||
/* Copy chunk into sector buffer */
|
|
||||||
size_t sectlen = MIN(f->writesize - offset, len);
|
|
||||||
memcpy(f->buf + offset, src, sectlen);
|
|
||||||
dest += sectlen;
|
|
||||||
src += sectlen;
|
|
||||||
len -= sectlen;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int target_flash_done_buffered(target_flash_s *f)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
if ((f->buf != NULL) && (f->buf_addr != (uint32_t)-1)) {
|
|
||||||
/* Write sector to flash if valid */
|
|
||||||
ret = f->write(f, f->buf_addr, f->buf, f->writesize);
|
|
||||||
f->buf_addr = -1;
|
|
||||||
free(f->buf);
|
|
||||||
f->buf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void target_print_progress(platform_timeout *const timeout)
|
void target_print_progress(platform_timeout *const timeout)
|
||||||
{
|
{
|
||||||
if (platform_timeout_is_expired(timeout)) {
|
if (platform_timeout_is_expired(timeout)) {
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 1BitSquared <info@1bitsquared.com>
|
||||||
|
* Written by Rafael Silva <perigoso@riseup.net>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file implements target flash interaction routines.
|
||||||
|
* Provides functionality for buffered flash operations
|
||||||
|
* It depends on target flash implementations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "target_internal.h"
|
||||||
|
|
||||||
|
static int target_flash_write_buffered(target_flash_s *f, target_addr_t dest, const void *src, size_t len);
|
||||||
|
static int target_flash_done_buffered(target_flash_s *f);
|
||||||
|
|
||||||
|
target_flash_s *target_flash_for_addr(target *t, uint32_t addr)
|
||||||
|
{
|
||||||
|
for (target_flash_s *f = t->flash; f; f = f->next)
|
||||||
|
if ((f->start <= addr) && (addr < (f->start + f->length)))
|
||||||
|
return f;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int target_flash_erase(target *t, target_addr_t addr, size_t len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
while (len) {
|
||||||
|
target_flash_s *f = target_flash_for_addr(t, addr);
|
||||||
|
if (!f) {
|
||||||
|
DEBUG_WARN("Requested address is outside the valid range 0x%06" PRIx32 "\n", addr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const target_addr_t local_start_addr = addr & ~(f->blocksize - 1U);
|
||||||
|
const target_addr_t local_end_addr = local_start_addr + f->blocksize;
|
||||||
|
|
||||||
|
ret |= f->erase(f, local_start_addr, f->blocksize);
|
||||||
|
|
||||||
|
len -= MIN(local_end_addr - addr, len);
|
||||||
|
addr = local_end_addr;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int target_flash_write(target *t, target_addr_t dest, const void *src, size_t len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
while (len) {
|
||||||
|
target_flash_s *f = target_flash_for_addr(t, dest);
|
||||||
|
if (!f)
|
||||||
|
return 1;
|
||||||
|
size_t tmptarget = MIN(dest + len, f->start + f->length);
|
||||||
|
size_t tmplen = tmptarget - dest;
|
||||||
|
ret |= target_flash_write_buffered(f, dest, src, tmplen);
|
||||||
|
dest += tmplen;
|
||||||
|
src += tmplen;
|
||||||
|
len -= tmplen;
|
||||||
|
/* If the current chunk of Flash is now full from this operation
|
||||||
|
* then finish operations on the Flash chunk and free the internal buffer.
|
||||||
|
*/
|
||||||
|
if (dest == f->start + f->length)
|
||||||
|
ret |= target_flash_done_buffered(f);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int target_flash_done(target *t)
|
||||||
|
{
|
||||||
|
for (target_flash_s *f = t->flash; f; f = f->next) {
|
||||||
|
int tmp = target_flash_done_buffered(f);
|
||||||
|
if (tmp)
|
||||||
|
return tmp;
|
||||||
|
if (f->done) {
|
||||||
|
tmp = f->done(f);
|
||||||
|
if (tmp)
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int target_flash_write_buffered(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (f->buf == NULL) {
|
||||||
|
/* Allocate flash sector buffer */
|
||||||
|
f->buf = malloc(f->writesize);
|
||||||
|
if (!f->buf) { /* malloc failed: heap exhaustion */
|
||||||
|
DEBUG_WARN("malloc: failed in %s\n", __func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
f->buf_addr = -1;
|
||||||
|
}
|
||||||
|
while (len) {
|
||||||
|
uint32_t offset = dest % f->writesize;
|
||||||
|
uint32_t base = dest - offset;
|
||||||
|
if (base != f->buf_addr) {
|
||||||
|
if (f->buf_addr != (uint32_t)-1) {
|
||||||
|
/* Write sector to flash if valid */
|
||||||
|
ret |= f->write(f, f->buf_addr, f->buf, f->writesize);
|
||||||
|
}
|
||||||
|
/* Setup buffer for a new sector */
|
||||||
|
f->buf_addr = base;
|
||||||
|
memset(f->buf, f->erased, f->writesize);
|
||||||
|
}
|
||||||
|
/* Copy chunk into sector buffer */
|
||||||
|
size_t sectlen = MIN(f->writesize - offset, len);
|
||||||
|
memcpy(f->buf + offset, src, sectlen);
|
||||||
|
dest += sectlen;
|
||||||
|
src += sectlen;
|
||||||
|
len -= sectlen;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int target_flash_done_buffered(target_flash_s *f)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if ((f->buf != NULL) && (f->buf_addr != (uint32_t)-1)) {
|
||||||
|
/* Write sector to flash if valid */
|
||||||
|
ret = f->write(f, f->buf_addr, f->buf, f->writesize);
|
||||||
|
f->buf_addr = -1;
|
||||||
|
free(f->buf);
|
||||||
|
f->buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
Loading…
Reference in New Issue