ch32f1: formatting cleanup to bring things closer to inline with the rest of the codebase

This commit is contained in:
dragonmux 2022-06-22 14:14:59 -04:00 committed by Piotr Esden-Tempski
parent 9aba7ecce2
commit 08a8988462
1 changed files with 67 additions and 84 deletions

View File

@ -18,12 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* This file implements CH32F1xx target specific functions. /* This file implements CH32F1xx target specific functions.
The ch32 flash is rather slow so this code is using the so called fast mode (ch32 specific). The ch32 flash is rather slow so this code is using the so called fast mode (ch32 specific).
128 bytes are copied to a write buffer, then the write buffer is committed to flash 128 bytes are copied to a write buffer, then the write buffer is committed to flash
/!\ There is some sort of bus stall/bus arbitration going on that does NOT work when /!\ There is some sort of bus stall/bus arbitration going on that does NOT work when
programmed through SWD/jtag programmed through SWD/jtag
The workaround is to wait a few cycles before filling the write buffer. This is performed by reading the flash a few times The workaround is to wait a few cycles before filling the write buffer. This is performed by reading the flash a few times
*/ */
@ -32,21 +32,12 @@
#include "target_internal.h" #include "target_internal.h"
#include "cortexm.h" #include "cortexm.h"
#if PC_HOSTED == 1
#define DEBUG_CH DEBUG_INFO
#define ERROR_CH DEBUG_WARN
#else
#define DEBUG_CH(...) {} //DEBUG_WARN //(...) {}
#define ERROR_CH DEBUG_WARN //DEBUG_WARN
#endif
extern const struct command_s stm32f1_cmd_list[]; // Reuse stm32f1 stuff extern const struct command_s stm32f1_cmd_list[]; // Reuse stm32f1 stuff
static int ch32f1_flash_erase(struct target_flash *f, static int ch32f1_flash_erase(struct target_flash *f,
target_addr addr, size_t len); target_addr addr, size_t len);
static int ch32f1_flash_write(struct target_flash *f, static int ch32f1_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len); target_addr dest, const void *src, size_t len);
// these are common with stm32f1/gd32f1/... // these are common with stm32f1/gd32f1/...
#define FPEC_BASE 0x40022000 #define FPEC_BASE 0x40022000
@ -76,9 +67,6 @@ extern const struct command_s stm32f1_cmd_list[]; // Reuse stm32f1 stuff
#define FLASH_SR_EOP (1<<5) // End of programming #define FLASH_SR_EOP (1<<5) // End of programming
#define FLASH_BEGIN_ADDRESS_CH32 0x8000000 #define FLASH_BEGIN_ADDRESS_CH32 0x8000000
/** /**
\fn ch32f1_add_flash \fn ch32f1_add_flash
\brief "fast" flash driver for CH32F10x chips \brief "fast" flash driver for CH32F10x chips
@ -104,7 +92,7 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era
#define WAIT_BUSY() do { \ #define WAIT_BUSY() do { \
sr = target_mem_read32(t, FLASH_SR); \ sr = target_mem_read32(t, FLASH_SR); \
if(target_check_error(t)) { \ if(target_check_error(t)) { \
ERROR_CH("ch32f1 flash write: comm error\n"); \ DEBUG_WARN("ch32f1 flash write: comm error\n"); \
return -1; \ return -1; \
} \ } \
} while (sr & FLASH_SR_BSY); } while (sr & FLASH_SR_BSY);
@ -112,7 +100,7 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era
#define WAIT_EOP() do { \ #define WAIT_EOP() do { \
sr = target_mem_read32(t, FLASH_SR); \ sr = target_mem_read32(t, FLASH_SR); \
if(target_check_error(t)) { \ if(target_check_error(t)) { \
ERROR_CH("ch32f1 flash write: comm error\n"); \ DEBUG_WARN("ch32f1 flash write: comm error\n"); \
return -1; \ return -1; \
} \ } \
} while (!(sr & FLASH_SR_EOP)); } while (!(sr & FLASH_SR_EOP));
@ -120,18 +108,18 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era
#define CLEAR_EOP() target_mem_write32(t, FLASH_SR,FLASH_SR_EOP) #define CLEAR_EOP() target_mem_write32(t, FLASH_SR,FLASH_SR_EOP)
#define SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \ #define SET_CR(bit) { ct = target_mem_read32(t, FLASH_CR); \
ct|=(bit); \ ct |= (bit); \
target_mem_write32(t, FLASH_CR, ct);} target_mem_write32(t, FLASH_CR, ct);}
#define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \ #define CLEAR_CR(bit) {ct = target_mem_read32(t, FLASH_CR); \
ct&=~(bit); \ ct &= ~(bit); \
target_mem_write32(t, FLASH_CR, ct);} target_mem_write32(t, FLASH_CR, ct);}
// Which one is the right value ? // Which one is the right value ?
#define MAGIC_WORD 0x100 #define MAGIC_WORD 0x100
// #define MAGIC_WORD 0x1000 // #define MAGIC_WORD 0x1000
#define MAGIC(adr) { magic=target_mem_read32(t,(adr) ^ MAGIC_WORD); \ #define MAGIC(adr) { magic = target_mem_read32(t,(adr) ^ MAGIC_WORD); \
target_mem_write32(t, FLASH_MAGIC , magic); } target_mem_write32(t, FLASH_MAGIC , magic); }
/** /**
@ -140,7 +128,7 @@ static void ch32f1_add_flash(target *t, uint32_t addr, size_t length, size_t era
*/ */
static int ch32f1_flash_unlock(target *t) static int ch32f1_flash_unlock(target *t)
{ {
DEBUG_CH("CH32: flash unlock \n"); DEBUG_INFO("CH32: flash unlock \n");
target_mem_write32(t, FLASH_KEYR , KEY1); target_mem_write32(t, FLASH_KEYR , KEY1);
target_mem_write32(t, FLASH_KEYR , KEY2); target_mem_write32(t, FLASH_KEYR , KEY2);
@ -148,16 +136,17 @@ static int ch32f1_flash_unlock(target *t)
target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY1); target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY1);
target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY2); target_mem_write32(t, FLASH_MODEKEYR_CH32 , KEY2);
uint32_t cr = target_mem_read32(t, FLASH_CR); uint32_t cr = target_mem_read32(t, FLASH_CR);
if (cr & FLASH_CR_FLOCK_CH32){ if (cr & FLASH_CR_FLOCK_CH32) {
ERROR_CH("Fast unlock failed, cr: 0x%08" PRIx32 "\n", cr); DEBUG_WARN("Fast unlock failed, cr: 0x%08" PRIx32 "\n", cr);
return -1; return -1;
} }
return 0; return 0;
} }
static int ch32f1_flash_lock(target *t) static int ch32f1_flash_lock(target *t)
{ {
volatile uint32_t ct; volatile uint32_t ct;
DEBUG_CH("CH32: flash lock \n"); DEBUG_INFO("CH32: flash lock \n");
SET_CR(FLASH_CR_LOCK); SET_CR(FLASH_CR_LOCK);
return 0; return 0;
} }
@ -166,28 +155,24 @@ static int ch32f1_flash_lock(target *t)
\brief identify the ch32f1 chip \brief identify the ch32f1 chip
Actually grab all cortex m3 with designer = arm not caught earlier... Actually grab all cortex m3 with designer = arm not caught earlier...
*/ */
bool ch32f1_probe(target *t) bool ch32f1_probe(target *t)
{ {
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3)
if ((t->cpuid & CPUID_PARTNO_MASK) != CORTEX_M3 || t->idcode != 0x410) // only ch32f103
return false; return false;
if(t->idcode !=0x410) { // only ch32f103
return false;
}
// try to flock // try to flock
ch32f1_flash_lock(t); ch32f1_flash_lock(t);
// if this fails it is not a CH32 chip // if this fails it is not a CH32 chip
if(ch32f1_flash_unlock(t)) { if (ch32f1_flash_unlock(t))
return false; return false;
}
uint32_t signature = target_mem_read32(t, FLASHSIZE); uint32_t signature = target_mem_read32(t, FLASHSIZE);
uint32_t flashSize = signature & 0xFFFF; uint32_t flashSize = signature & 0xFFFF;
target_add_ram(t, 0x20000000, 0x5000); target_add_ram(t, 0x20000000, 0x5000);
ch32f1_add_flash(t, FLASH_BEGIN_ADDRESS_CH32, flashSize*1024, 128); ch32f1_add_flash(t, FLASH_BEGIN_ADDRESS_CH32, flashSize * 1024, 128);
target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD/VL-LD/VL-MD"); target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD/VL-LD/VL-MD");
t->driver = "CH32F1 medium density (stm32f1 clone)"; t->driver = "CH32F1 medium density (stm32f1 clone)";
return true; return true;
@ -196,26 +181,26 @@ bool ch32f1_probe(target *t)
\fn ch32f1_flash_erase \fn ch32f1_flash_erase
\brief fast erase of CH32 \brief fast erase of CH32
*/ */
int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len) int ch32f1_flash_erase(struct target_flash *f, target_addr addr, size_t len)
{ {
volatile uint32_t ct, sr, magic; volatile uint32_t ct, sr, magic;
target *t = f->t; target *t = f->t;
DEBUG_CH("CH32: flash erase \n"); DEBUG_INFO("CH32: flash erase \n");
if (ch32f1_flash_unlock(t)) { if (ch32f1_flash_unlock(t)) {
ERROR_CH("CH32: Unlock failed\n"); DEBUG_WARN("CH32: Unlock failed\n");
return -1; return -1;
} }
// Fast Erase 128 bytes pages (ch32 mode) // Fast Erase 128 bytes pages (ch32 mode)
while(len) { while (len) {
SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER SET_CR(FLASH_CR_FTER_CH32);// CH32 PAGE_ER
/* write address to FMA */ /* write address to FMA */
target_mem_write32(t, FLASH_AR , addr); target_mem_write32(t, FLASH_AR, addr);
/* Flash page erase start instruction */ /* Flash page erase start instruction */
SET_CR( FLASH_CR_STRT ); SET_CR(FLASH_CR_STRT);
WAIT_EOP(); WAIT_EOP();
CLEAR_EOP(); CLEAR_EOP();
CLEAR_CR( FLASH_CR_STRT ); CLEAR_CR(FLASH_CR_STRT);
// Magic // Magic
MAGIC(addr); MAGIC(addr);
if (len > 128) if (len > 128)
@ -226,8 +211,8 @@ int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len)
} }
sr = target_mem_read32(t, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
ch32f1_flash_lock(t); ch32f1_flash_lock(t);
if ((sr & SR_ERROR_MASK)) { if (sr & SR_ERROR_MASK) {
ERROR_CH("ch32f1 flash erase error 0x%" PRIx32 "\n", sr); DEBUG_WARN("ch32f1 flash erase error 0x%" PRIx32 "\n", sr);
return -1; return -1;
} }
return 0; return 0;
@ -241,13 +226,13 @@ int ch32f1_flash_erase (struct target_flash *f, target_addr addr, size_t len)
NB: Just reading fff is not enough as it could be a transient previous operation value NB: Just reading fff is not enough as it could be a transient previous operation value
*/ */
static bool ch32f1_wait_flash_ready(target *t, uint32_t adr) static bool ch32f1_wait_flash_ready(target *t, uint32_t addr)
{ {
uint32_t ff; uint32_t ff = 0;
for (int i = 0; i < 32; i++) for (size_t i = 0; i < 32; i++)
ff = target_mem_read32(t, adr); ff = target_mem_read32(t, addr);
if (ff != 0xffffffffUL) { if (ff != 0xffffffffUL) {
ERROR_CH("ch32f1 Not erased properly at %" PRIx32 " or flash access issue\n", adr); DEBUG_WARN("ch32f1 Not erased properly at %" PRIx32 " or flash access issue\n", addr);
return false; return false;
} }
return true; return true;
@ -257,22 +242,22 @@ static bool ch32f1_wait_flash_ready(target *t, uint32_t adr)
\brief fast flash for ch32. Load 128 bytes chunk and then flash them \brief fast flash for ch32. Load 128 bytes chunk and then flash them
*/ */
static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t offset) static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t offset)
{ {
volatile uint32_t ct, sr, magic; volatile uint32_t ct, sr, magic;
const uint32_t *ss = (const uint32_t *)(src+offset); const uint32_t *ss = (const uint32_t *)(src+offset);
uint32_t dd = dest+offset; uint32_t dd = dest + offset;
SET_CR(FLASH_CR_FTPG_CH32); SET_CR(FLASH_CR_FTPG_CH32);
target_mem_write32(t, dd+0,ss[0]); target_mem_write32(t, dd + 0, ss[0]);
target_mem_write32(t, dd+4,ss[1]); target_mem_write32(t, dd + 4, ss[1]);
target_mem_write32(t, dd+8,ss[2]); target_mem_write32(t, dd + 8, ss[2]);
target_mem_write32(t, dd+12,ss[3]); target_mem_write32(t, dd + 12, ss[3]);
SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */ SET_CR(FLASH_CR_BUF_LOAD_CH32); /* BUF LOAD */
WAIT_EOP(); WAIT_EOP();
CLEAR_EOP(); CLEAR_EOP();
CLEAR_CR(FLASH_CR_FTPG_CH32); CLEAR_CR(FLASH_CR_FTPG_CH32);
MAGIC((dest+offset)); MAGIC(dest + offset);
return 0; return 0;
} }
/** /**
@ -281,7 +266,7 @@ static int ch32f1_upload(target *t, uint32_t dest, const void *src, uint32_t of
*/ */
int ch32f1_buffer_clear(target *t) int ch32f1_buffer_clear(target *t)
{ {
volatile uint32_t ct,sr; volatile uint32_t ct, sr;
SET_CR(FLASH_CR_FTPG_CH32); // Fast page program 4- SET_CR(FLASH_CR_FTPG_CH32); // Fast page program 4-
SET_CR(FLASH_CR_BUF_RESET_CH32); // BUF_RESET 5- SET_CR(FLASH_CR_BUF_RESET_CH32); // BUF_RESET 5-
WAIT_BUSY(); // 6- WAIT_BUSY(); // 6-
@ -294,21 +279,21 @@ int ch32f1_buffer_clear(target *t)
*/ */
static int ch32f1_flash_write(struct target_flash *f, static int ch32f1_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len) target_addr dest, const void *src, size_t len)
{ {
volatile uint32_t ct, sr, magic; volatile uint32_t ct, sr, magic;
target *t = f->t; target *t = f->t;
size_t length = len; size_t length = len;
#ifdef CH32_VERIFY #ifdef CH32_VERIFY
target_addr orgDest=dest; target_addr org_dest = dest;
const void *orgSrc=src; const void *org_src = src;
#endif #endif
DEBUG_CH("CH32: flash write 0x%x ,size=%d\n",dest,len); DEBUG_INFO("CH32: flash write 0x%x ,size=%d\n", dest, len);
while(length > 0) while (length > 0)
{ {
if(ch32f1_flash_unlock(t)) { if (ch32f1_flash_unlock(t)) {
ERROR_CH("ch32f1 cannot fast unlock\n"); DEBUG_WARN("ch32f1 cannot fast unlock\n");
return -1; return -1;
} }
WAIT_BUSY(); WAIT_BUSY();
@ -316,12 +301,12 @@ static int ch32f1_flash_write(struct target_flash *f,
// Buffer reset... // Buffer reset...
ch32f1_buffer_clear(t); ch32f1_buffer_clear(t);
// Load 128 bytes to buffer // Load 128 bytes to buffer
if(!ch32f1_wait_flash_ready(t,dest)) { if (!ch32f1_wait_flash_ready(t,dest))
return -1; return -1;
}
for(int i = 0; i < 8; i++) { for (size_t i = 0; i < 8; i++) {
if(ch32f1_upload(t,dest,src, 16*i)) { if (ch32f1_upload(t, dest, src, i * 16U)) {
ERROR_CH("Cannot upload to buffer\n"); DEBUG_WARN("Cannot upload to buffer\n");
return -1; return -1;
} }
} }
@ -333,10 +318,10 @@ static int ch32f1_flash_write(struct target_flash *f,
CLEAR_EOP(); CLEAR_EOP();
CLEAR_CR(FLASH_CR_FTPG_CH32); CLEAR_CR(FLASH_CR_FTPG_CH32);
MAGIC((dest)); MAGIC(dest);
// next // next
if(length > 128) if (length > 128)
length -=128; length -=128;
else else
length = 0; length = 0;
@ -345,24 +330,23 @@ static int ch32f1_flash_write(struct target_flash *f,
sr = target_mem_read32(t, FLASH_SR); // 13 sr = target_mem_read32(t, FLASH_SR); // 13
ch32f1_flash_lock(t); ch32f1_flash_lock(t);
if ((sr & SR_ERROR_MASK) ) { if (sr & SR_ERROR_MASK) {
ERROR_CH("ch32f1 flash write error 0x%" PRIx32 "\n", sr); DEBUG_WARN("ch32f1 flash write error 0x%" PRIx32 "\n", sr);
return -1; return -1;
} }
} }
#ifdef CH32_VERIFY #ifdef CH32_VERIFY
DEBUG_CH("Verifying\n"); DEBUG_INFO("Verifying\n");
size_t i = 0; for (size_t i = 0; i < len; i += 4)
for(i = 0; i < len; i+= 4)
{ {
uint32_t mem=target_mem_read32(t, orgDest+i); const uint32_t expected = *(uint32_t *)(org_src + i);
uint32_t mem2=*(uint32_t *)(orgSrc+i); const uint32_t actual = target_mem_read32(t, org_dest + i);
if(mem!=mem2) if (expected != actual)
{ {
ERROR_CH(">>>>write mistmatch at address 0x%x\n",orgDest+i); DEBUG_WARN(">>>>write mistmatch at address 0x%x\n", org_dest + i);
ERROR_CH(">>>>expected 0x%x\n",mem2); DEBUG_WARN(">>>>expected: 0x%x\n", expected);
ERROR_CH(">>>>flash 0x%x\n",mem); DEBUG_WARN(">>>> actual: 0x%x\n", actual);
return -1; return -1;
} }
} }
@ -370,4 +354,3 @@ static int ch32f1_flash_write(struct target_flash *f,
return 0; return 0;
} }
// EOF