Compare commits

..

1 Commits

Author SHA1 Message Date
d5bf59152f
ADuCM36x experimental support 2023-01-08 15:49:59 +01:00
4 changed files with 304 additions and 1 deletions

View File

@ -20,6 +20,7 @@ SRC = \
adiv5.c \
adiv5_jtagdp.c \
adiv5_swdp.c \
aducm36x.c \
command.c \
cortexa.c \
cortexm.c \
@ -65,7 +66,7 @@ SRC = \
include $(PLATFORM_DIR)/Makefile.inc
OPT_FLAGS ?= -Os
OPT_FLAGS ?= -Os -nolibc
CFLAGS += $(OPT_FLAGS)
LDFLAGS += $(OPT_FLAGS)

300
src/target/aducm36x.c Normal file
View File

@ -0,0 +1,300 @@
/***************************************************************************
* Copyright (C) 2023 by Christopher Are *
* c.are@jcsmith.fr *
***************************************************************************/
/***************************************************************************
* This version for ADuCM36x is largely based on the following flash *
* drivers: *
* - aducm360.c *
* Copyright (C) 2015 by Ivan Buliev *
* i.buliev@mikrosistemi.com *
* - aduc702x.c *
* Copyright (C) 2008 by Kevin McGuire *
* Copyright (C) 2008 by Marcel Wijlaars *
* Copyright (C) 2009 by Michael Ashton *
* and *
* - stm32f1x.c *
* Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* Copyright (C) 2008 by Spencer Oliver *
* spen@spen-soft.co.uk *
* *
* Copyright (C) 2011 by Andreas Fritiofson *
* andreas.fritiofson@gmail.com *
***************************************************************************/
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
#include "adiv5.h"
#define ADUCM36x_CPUID_ID 0x412FC231 // 41 = ARM; 2 = Revision; F = Always 0xF; C23 = Cortex-M3; 1 = Patch
#define ADUCM36x_SRAM_BASE 0x20000000
#define ADUCM36x_SRAM_SIZE 0x5FFFU // 8kB SRAM
#define ADUCM36x_FLASH_BASE 0x00000000
#define ADUCM36x_FLASH_SIZE 0x3FFFFU // 256kB
#define ADUCM36x_FLASH_CTRL 0x40002800
#define ADUCM36x_FLASH_FEESTA 0x0000
#define ADUCM36x_FLASH_FEECON0 0x0004
#define ADUCM36x_FLASH_FEECMD 0x0008
#define ADUCM36x_FLASH_FEEADR0L 0x0010
#define ADUCM36x_FLASH_FEEADR0H 0x0014
#define ADUCM36x_FLASH_FEEADR1L 0x0018
#define ADUCM36x_FLASH_FEEADR1H 0x001C
#define ADUCM36x_FLASH_FEEKEY 0x0020
#define ADUCM36x_FLASH_FEEPROL 0x0028
#define ADUCM36x_FLASH_FEEPROH 0x002C
#define ADUCM36x_FLASH_FEESIGL 0x0030
#define ADUCM36x_FLASH_FEESIGH 0x0034
#define ADUCM36x_FLASH_FEECON1 0x0038
#define ADUCM36x_FLASH_FEEADRAL 0x0048
#define ADUCM36x_FLASH_FEEADRAH 0x004C
#define ADUCM36x_FLASH_FEEAEN0 0x0078
#define ADUCM36x_FLASH_FEEAEN1 0x007C
#define ADUCM36x_FLASH_FEEAEN2 0x0080
#define ADUCM36x_FLASH_BLOCKSIZE 16384U
#define ADUCM36x_FLASH_PAGESIZE 2048U
#define ADUCM36x_FLASH_PAGE_MSK (0xFFFFFFFFu & ~(ADUCM36x_FLASH_PAGESIZE - 1U))
static bool aducm36x_attach(target *t);
static int aducm36x_flash_erase(struct target_flash *f, long unsigned int addr, unsigned int len);
static int aducm36x_flash_write(struct target_flash *f, long unsigned int dest, const void *src, unsigned int len);
static bool aducm36x_flash_mass_erase(target *t);
static bool aducm36x_page_erase(target *t, uint32_t paddr);
static bool aducm36x_check_flash_completion(target *t, unsigned int timeout_ms);
static bool aducm36x_set_write_enable(target *t, int enable);
static void aducm36x_flash_unlock(target *t);
static void aducm36x_add_flash(target *t) {
struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */
DEBUG_WARN("calloc: failed in %s\n", __func__);
return;
}
f->start = ADUCM36x_FLASH_BASE;
f->length = ADUCM36x_FLASH_SIZE;
f->blocksize = ADUCM36x_FLASH_BLOCKSIZE;
f->erase = aducm36x_flash_erase;
f->write = aducm36x_flash_write;
f->erased = 0xffU;
target_add_flash(t, f);
}
bool aducm36x_probe(target *t) {
/* Positively identify the target device somehow */
if (target_mem_read32(t, CORTEXM_CPUID) != ADUCM36x_CPUID_ID)
return false;
t->driver = "Analog Device - ADuCM36x";
//t->mass_erase = aducm36x_flash_mass_erase;
t->attach = aducm36x_attach;
return true;
}
static bool aducm36x_attach(target *t) {
if (!cortexm_attach(t))
return false;
/*
* Because we are in attach, which can be called multiple times for a device, we *must*
* free any existing map before rebuilding it. Failure to do so will result in unpredictable behaviour.
*/
target_mem_map_free(t);
aducm36x_add_flash(t);
target_add_ram(t, ADUCM36x_SRAM_BASE, ADUCM36x_SRAM_SIZE);
return true;
}
/* ----------------------------------------------------------------------- */
/*
* chip erase 2.4/ 21 ms
* page erase 2.4/ 21 ms
* page programm 0.9/ 12 ms
*/
static int aducm36x_flash_erase(struct target_flash *f, long unsigned int addr, unsigned int len) {
int32_t result = true;
target *t = f->t;
DEBUG_INFO("Erase addr 0x%08" PRIx32 " len 0x%" PRIx32 "\n", addr, (uint32_t)len);
if (addr & (f->blocksize - 1U)) {
DEBUG_WARN("Unaligned erase\n");
return false;
}
if ((addr < f->start) || (addr >= f->start + f->length)) {
DEBUG_WARN("Address is invalid\n");
return false;
}
addr -= f->start;
len = ALIGN(len, f->blocksize);
len = MIN(len, f->length - addr);
const bool full_erase = addr == f->start && len == f->length;
if (full_erase) {
aducm36x_flash_mass_erase(t);
} else {
while (len) {
result = aducm36x_page_erase(t, addr);
if (!result) {
DEBUG_WARN("Erase failed!\n");
break;
}
if (len >= ADUCM36x_FLASH_PAGESIZE) {
const uint32_t chunk = len & ADUCM36x_FLASH_PAGE_MSK;
len -= chunk;
addr += chunk;
} else {
len = 0;
}
}
}
return result;
}
static int aducm36x_flash_write(struct target_flash *f, long unsigned int dest, const void *src, unsigned int len) {
int32_t result = true;
target *t = f->t;
DEBUG_INFO("RP Write %08" PRIx32 " len 0x%" PRIx32 "\n", dest, (uint32_t)len);
if ((dest & 0xff) || (len & 0xff)) {
DEBUG_WARN("Unaligned erase\n");
return false;
}
dest -= f->start;
/* Clear any old status */
target_mem_read32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEESTA);
/* Enable the writing to the flash*/
aducm36x_set_write_enable(t, 1);
/* Unlock for writing */
aducm36x_flash_unlock(t);
/* Use generic CortexM write function to do the work */
cortexm_mem_write_sized(t, dest, src, len, ALIGN_WORD);
/* Check the result */
result = aducm36x_check_flash_completion(t, 50);
if (result != true) {
DEBUG_WARN("flash write failed at 0x%08" PRIx32, dest);
aducm36x_set_write_enable(t, 0);
}
return result;
}
static bool aducm36x_flash_mass_erase(target *t) {
bool result = true;
/* Clear any old status */
target_mem_read32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEESTA);
/* Enable the writing to the flash*/
aducm36x_set_write_enable(t, 1);
/* Unlock for writing */
aducm36x_flash_unlock(t);
/* Issue the 'MASSERASE' command */
target_mem_write32(t, ADUCM36x_FLASH_CTRL+ADUCM36x_FLASH_FEECMD, 0x00000003);
/* Check the result */
result = aducm36x_check_flash_completion(t, 3500);
if (result != true) {
DEBUG_WARN("mass erase failed.");
aducm36x_set_write_enable(t, 0);
}
return result;
}
static bool aducm36x_page_erase(target *t, uint32_t paddr) {
bool result = true;
/* Clear any old status */
target_mem_read32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEESTA);
/* Enable the writing to the flash*/
aducm36x_set_write_enable(t, 1);
/* Unlock for writing */
aducm36x_flash_unlock(t);
/* Write the sector address */
target_mem_write32(t, ADUCM36x_FLASH_CTRL+ADUCM36x_FLASH_FEEADR0L, paddr & 0xFFFF);
target_mem_write32(t, ADUCM36x_FLASH_CTRL+ADUCM36x_FLASH_FEEADR0H, (paddr>>16) & 0xFFFF);
/* Issue the 'ERASEPAGE' command */
target_mem_write32(t, ADUCM36x_FLASH_CTRL+ADUCM36x_FLASH_FEECMD, 0x00000001);
/* Check the result */
result = aducm36x_check_flash_completion(t, 50);
if (result != true) {
DEBUG_WARN("page erase failed at 0x%08" PRIx32, paddr);
aducm36x_set_write_enable(t, 0);
}
return result;
}
/* ----------------------------------------------------------------------- */
/* sets FEECON0 bit 2
* enable = 1 enables writes & erases, 0 disables them */
static bool aducm36x_set_write_enable(target *t, int enable) {
/* don't bother to preserve int enable bit here */
uint32_t value;
value = target_mem_read32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEECON0);
if (enable)
value |= 0x00000004;
else
value &= ~0x00000004;
target_mem_write32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEECON0, value);
return true;
}
/* ----------------------------------------------------------------------- */
/* wait up to timeout_ms for controller to not be busy,
* then check whether the command passed or failed. */
static bool aducm36x_check_flash_completion(target *t, unsigned int timeout_ms) {
uint32_t v = 1;
platform_timeout timeout;
platform_timeout_set(&timeout, timeout_ms);
while (1) {
v = target_mem_read32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEESTA);
if ((v & 0x00000001) == 0)
break;
if (platform_timeout_is_expired(&timeout))
break;
}
if (!(v & 0x00000004)) /* b2 */
return false;
return true;
}
static void aducm36x_flash_unlock(target *t)
{
target_mem_write32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEEKEY, 0x0000F456);
target_mem_write32(t, ADUCM36x_FLASH_CTRL + ADUCM36x_FLASH_FEEKEY, 0x0000F123);
}

View File

@ -462,6 +462,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
PROBE(ch32f1_probe);
PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */
PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */
PROBE(aducm36x_probe);
} else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */
PROBE(lpc11xx_probe); /* LPC24C11 */
PROBE(lpc43xx_probe);

View File

@ -198,4 +198,5 @@ bool efm32_probe(target *t);
bool msp432_probe(target *t);
bool ke04_probe(target *t);
bool rp_probe(target *t);
bool aducm36x_probe(target *t);
#endif