riscv-openocd-wch/src/flash/nor/wchriscv.c
2022-03-29 17:01:37 +08:00

180 lines
5.0 KiB
C
Executable File

/***************************************************************************
* WCH RISC-V mcu :CH32V103X CH32V20X CH32V30X CH56X CH57X CH58X *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* 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, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
extern int wlink_erase(void);
extern unsigned char riscvchip;
extern int wlink_reset();
extern int wlink_write(const uint8_t *buffer, uint32_t offset, uint32_t count);
extern int noloadflag;
struct ch32vx_options
{
uint8_t rdp;
uint8_t user;
uint16_t data;
uint32_t protection;
};
struct ch32vx_flash_bank
{
struct ch32vx_options option_bytes;
int ppage_size;
int probed;
bool has_dual_banks;
bool can_load_options;
uint32_t register_base;
uint8_t default_rdp;
int user_data_offset;
int option_offset;
uint32_t user_bank_size;
};
FLASH_BANK_COMMAND_HANDLER(ch32vx_flash_bank_command)
{
struct ch32vx_flash_bank *ch32vx_info;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
ch32vx_info = malloc(sizeof(struct ch32vx_flash_bank));
bank->driver_priv = ch32vx_info;
ch32vx_info->probed = 0;
ch32vx_info->has_dual_banks = false;
ch32vx_info->can_load_options = false;
ch32vx_info->user_bank_size = bank->size;
return ERROR_OK;
}
static int ch32vx_erase(struct flash_bank *bank, int first, int last)
{
if(noloadflag)
return ERROR_OK;
wlink_reset();
int ret = wlink_erase();
target_halt(bank->target);
if (ret)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int ch32vx_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
if(noloadflag)
return ERROR_OK;
int ret = wlink_write(buffer, offset, count);
if(riscvchip==0x03)
wlink_reset();
return ret;
}
static int ch32vx_get_device_id(struct flash_bank *bank, uint32_t *device_id)
{
struct target *target = bank->target;
int retval = target_read_u32(target, 0x1ffff7e8, device_id);
if (retval != ERROR_OK)
return retval;
return ERROR_OK;
}
static int ch32vx_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb)
{
struct target *target = bank->target;
int retval = target_read_u16(target, 0x1ffff7e0, flash_size_in_kb);
if (retval != ERROR_OK)
return retval;
return ERROR_OK;
}
static int ch32vx_probe(struct flash_bank *bank)
{
struct ch32vx_flash_bank *ch32vx_info = bank->driver_priv;
uint16_t delfault_max_flash_size=512;
uint16_t flash_size_in_kb;
uint32_t device_id;
int page_size;
uint32_t base_address = 0x00000000;
uint32_t rid = 0;
ch32vx_info->probed = 0;
/* read ch32 device id register */
int retval = ch32vx_get_device_id(bank, &device_id);
if (retval != ERROR_OK)
return retval;
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
page_size = 1024;
ch32vx_info->ppage_size = 4;
/* get flash size from target. */
retval = ch32vx_get_flash_size(bank, &flash_size_in_kb);
if(flash_size_in_kb)
LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
else
flash_size_in_kb=delfault_max_flash_size;
// /* calculate numbers of pages */
int num_pages = flash_size_in_kb * 1024 / page_size;
bank->base = base_address;
bank->size = (num_pages * page_size);
bank->num_sectors = num_pages;
bank->sectors = alloc_block_array(0, page_size, num_pages);
ch32vx_info->probed = 1;
return ERROR_OK;
}
static int ch32vx_auto_probe(struct flash_bank *bank)
{
struct ch32vx_flash_bank *ch32vx_info = bank->driver_priv;
if (ch32vx_info->probed)
return ERROR_OK;
return ch32vx_probe(bank);
}
static const struct command_registration ch32vx_command_handlers[] = {
{
.name = "wch_riscv",
.mode = COMMAND_ANY,
.help = "wch_riscv flash command group",
.usage = "",
},
COMMAND_REGISTRATION_DONE};
const struct flash_driver wch_riscv_flash = {
.name = "wch_riscv",
.commands = ch32vx_command_handlers,
.flash_bank_command = ch32vx_flash_bank_command,
.erase = ch32vx_erase,
.write = ch32vx_write,
.read = default_flash_read,
.probe = ch32vx_probe,
.auto_probe = ch32vx_auto_probe,
.erase_check = default_flash_blank_check,
.free_driver_priv = default_flash_free_driver_priv,
};