Skip to content

Commit

Permalink
target: Extract AT32F43x-specific flash handlers (and detection)
Browse files Browse the repository at this point in the history
* Create a separate translation unit src/target/at32f43x.c
  to implement flash operations differently (from stm32f1 or stm32f4)
* Move the at32f43_detect() here from src/target/stm32f1.c
  and tie it to new at32f43x_probe() instead
* Stub unimplemented operations with NULL pointers
  • Loading branch information
ALTracer authored and dragonmux committed Oct 29, 2023
1 parent dead511 commit bb12a29
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 89 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ SRC = \
adiv5.c \
adiv5_jtag.c \
adiv5_swd.c \
at32f43x.c \
command.c \
cortex.c \
cortexa.c \
Expand Down
175 changes: 175 additions & 0 deletions src/target/at32f43x.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2023 1BitSquared <[email protected]>
* Written by ALTracer <[email protected]>
*
* 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 3 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/>.
*/

/*
* This file implements AT32F43x target specific functions for detecting
* the device, providing the XML memory map and Flash memory programming.
*
* References:
* ARTERY doc - RM_AT32F435_437_EN_V2.04.pdf
* Reference manual - AT32F435/437 Series Reference Manual
*/

#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"

#define DBGMCU_IDCODE 0xe0042000U

#define AT32F4x_IDCODE_SERIES_MASK 0xfffff000U
#define AT32F4x_IDCODE_PART_MASK 0x00000fffU
#define AT32F43_SERIES_4K 0x70084000U
#define AT32F43_SERIES_2K 0x70083000U

static void at32f43_add_flash(target_s *const t, const uint32_t addr, const size_t length, const size_t blocksize,
const uint8_t base_sector, const uint8_t split)
{
if (length == 0)
return;

target_flash_s *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */
DEBUG_ERROR("calloc: failed in %s\n", __func__);
return;
}

f->start = addr;
f->length = length;
f->blocksize = blocksize;
f->erase = NULL;
f->write = NULL;
(void)base_sector;
(void)split;
f->writesize = 1024;
f->erased = 0xffU;
target_add_flash(t, f);
}

static bool at32f43_detect(target_s *target, const uint16_t part_id)
{
/*
* AT32F435 EOPB0 ZW/NZW split reconfiguration unsupported,
* assuming default split ZW=256 SRAM=384.
* AT32F437 also have a working "EMAC" (Ethernet MAC)
*/
uint32_t flash_size_bank1 = 0;
uint32_t flash_size_bank2 = 0;
uint32_t sector_size = 0;
switch (part_id) {
// 0x70084000U parts with 4KB sectors:
case 0x0540U: // LQFP144
case 0x0543U: // LQFP100
case 0x0546U: // LQFP64
case 0x0549U: // LQFP48
case 0x054cU: // QFN48
case 0x054fU: // LQFP144 w/Eth
case 0x0552U: // LQFP100 w/Eth
case 0x0555U: // LQFP64 w/Eth
// Flash (G): 4032 KB in 2 banks (2048+1984), 4KB per sector.
flash_size_bank1 = 2048U * 1024U;
flash_size_bank2 = 1984U * 1024U;
sector_size = 4096;
break;
case 0x0598U: // LQFP144
case 0x0599U: // LQFP100
case 0x059aU: // LQFP64
case 0x059bU: // LQFP48
case 0x059cU: // QFN48
case 0x059dU: // LQFP144 w/Eth
case 0x059eU: // LQFP100 w/Eth
case 0x059fU: // LQFP64 w/Eth
// Flash (D): 448 KB, only bank 1, 4KB per sector.
flash_size_bank1 = 448U * 1024U;
sector_size = 4096;
break;
// 0x70083000U parts with 2KB sectors:
case 0x0341U: // LQFP144
case 0x0344U: // LQFP100
case 0x0347U: // LQFP64
case 0x034aU: // LQFP48
case 0x034dU: // QFN48
case 0x0350U: // LQFP144 w/Eth
case 0x0353U: // LQFP100 w/Eth
case 0x0356U: // LQFP64 w/Eth
// Flash (M): 1024 KB in 2 banks (equal), 2KB per sector.
flash_size_bank1 = 512U * 1024U;
flash_size_bank2 = 512U * 1024U;
sector_size = 2048;
break;
case 0x0242U: // LQFP144
case 0x0245U: // LQFP100
case 0x0248U: // LQFP64
case 0x024bU: // LQFP48
case 0x024eU: // QFN48
case 0x0251U: // LQFP144 w/Eth
case 0x0254U: // LQFP100 w/Eth
case 0x0257U: // LQFP64 w/Eth
// Flash (C): 256 KB, only bank 1, 2KB per sector.
flash_size_bank1 = 256U * 1024U;
sector_size = 2048;
break;
default:
return false;
}
/*
* Arterytek F43x Flash controller has BLKERS (1<<3U).
* Block erase operates on 64 KB at once for all parts.
* Using here only sector erase (page erase) for compatibility.
*/
at32f43_add_flash(target, 0x08000000, flash_size_bank1, sector_size, 0, 0);
if (flash_size_bank2 > 0) {
const uint16_t base_sector = flash_size_bank1 / sector_size;
at32f43_add_flash(target, 0x08000000 + flash_size_bank1, flash_size_bank2, sector_size, base_sector, 0);
}

// SRAM1 (64KB) can be remapped to 0x10000000.
target_add_ram(target, 0x20000000, 64U * 1024U);
// SRAM2 (384-64=320 KB default).
target_add_ram(target, 0x20010000, 320U * 1024U);
/*
* SRAM total is adjustable between 128 KB and 512 KB (max).
* Out of 640 KB SRAM present on silicon, at least 128 KB are always
* dedicated to "zero-wait-state Flash". ZW region is limited by
* specific part flash capacity (for 256, 448 KB) or at 512 KB.
* AT32F435ZMT default EOPB0=0xffff05fa,
* EOPB[0:2]=0b010 for 384 KB SRAM + 256 KB zero-wait-state flash.
*/
target->driver = "AT32F435";
target->mass_erase = NULL;
return true;
}

/* Identify AT32F43x "High Performance" line devices (Cortex-M4) */
bool at32f43x_probe(target_s *target)
{
// Artery clones use Cortex M4 cores
if ((target->cpuid & CORTEX_CPUID_PARTNO_MASK) != CORTEX_M4)
return false;

// Artery chips use the complete idcode word for identification
const uint32_t idcode = target_mem_read32(target, DBGMCU_IDCODE);
const uint32_t series = idcode & AT32F4x_IDCODE_SERIES_MASK;
const uint16_t part_id = idcode & AT32F4x_IDCODE_PART_MASK;

if (series == AT32F43_SERIES_4K || series == AT32F43_SERIES_2K)
return at32f43_detect(target, part_id);
return false;
}
1 change: 1 addition & 0 deletions src/target/cortexm.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ bool cortexm_probe(adiv5_access_port_s *ap)
PROBE(lpc546xx_probe);
PROBE(lpc43xx_probe);
PROBE(at32f40x_probe);
PROBE(at32f43x_probe); /* AT32F435 doesn't survive LPC40xx IAP */
PROBE(lpc40xx_probe);
PROBE(kinetis_probe); /* Older K-series */
PROBE(msp432e4_probe);
Expand Down
89 changes: 0 additions & 89 deletions src/target/stm32f1.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ static bool stm32f1_mass_erase(target_s *target);
#define AT32F4x_IDCODE_PART_MASK 0x00000fffU
#define AT32F41_SERIES 0x70030000U
#define AT32F40_SERIES 0x70050000U
#define AT32F43_SERIES_4K 0x70084000U
#define AT32F43_SERIES_2K 0x70083000U

#define DBGMCU_IDCODE_MM32L0 0x40013400U
#define DBGMCU_IDCODE_MM32F3 0x40007080U
Expand Down Expand Up @@ -258,91 +256,6 @@ static bool at32f41_detect(target_s *target, const uint16_t part_id)
return true;
}

static bool at32f43_detect(target_s *target, const uint16_t part_id)
{
/* AT32F435 EOPB0 ZW/NZW split reconfiguration unsupported,
* assuming default split ZW=256 SRAM=384.
* AT32F437 also have a working "EMAC" (Ethernet MAC)
*/
uint32_t flash_size_kb = 0;
uint32_t sector_size = 0;
switch (part_id) {
// 0x70084000U parts with 4KB sectors:
case 0x0540U: // LQFP144
case 0x0543U: // LQFP100
case 0x0546U: // LQFP64
case 0x0549U: // LQFP48
case 0x054cU: // QFN48
case 0x054fU: // LQFP144 w/Eth
case 0x0552U: // LQFP100 w/Eth
case 0x0555U: // LQFP64 w/Eth
// Flash (G): 4032 KB in 2 banks (2048+1984), 4KB per sector.
flash_size_kb = 4032;
sector_size = 4096;
break;
case 0x0598U: // LQFP144
case 0x0599U: // LQFP100
case 0x059aU: // LQFP64
case 0x059bU: // LQFP48
case 0x059cU: // QFN48
case 0x059dU: // LQFP144 w/Eth
case 0x059eU: // LQFP100 w/Eth
case 0x059fU: // LQFP64 w/Eth
// Flash (D): 448 KB, only bank 1, 4KB per sector.
flash_size_kb = 448;
sector_size = 4096;
break;
// 0x70083000U parts with 2KB sectors:
case 0x0341U: // LQFP144
case 0x0344U: // LQFP100
case 0x0347U: // LQFP64
case 0x034aU: // LQFP48
case 0x034dU: // QFN48
case 0x0350U: // LQFP144 w/Eth
case 0x0353U: // LQFP100 w/Eth
case 0x0356U: // LQFP64 w/Eth
// Flash (M): 1024 KB in 2 banks (equal), 2KB per sector.
flash_size_kb = 1024;
sector_size = 2048;
break;
case 0x0242U: // LQFP144
case 0x0245U: // LQFP100
case 0x0248U: // LQFP64
case 0x024bU: // LQFP48
case 0x024eU: // QFN48
case 0x0251U: // LQFP144 w/Eth
case 0x0254U: // LQFP100 w/Eth
case 0x0257U: // LQFP64 w/Eth
// Flash (C): 256 KB, only bank 1, 2KB per sector.
flash_size_kb = 256;
sector_size = 2048;
break;
default:
return false;
}
/*
* Arterytek F43x Flash controller has BLKERS (1<<3U).
* Block erase operates on 64 KB at once for all parts.
* Using here only sector erase (page erase) for compatibility.
*/
stm32f1_add_flash(target, 0x08000000, flash_size_kb * 1024U, sector_size);
// SRAM1 (64KB) can be remapped to 0x10000000.
target_add_ram(target, 0x20000000, 64U * 1024U);
// SRAM2 (384-64=320 KB default).
target_add_ram(target, 0x20010000, 320U * 1024U);
/*
* SRAM total is adjustable between 128 KB and 512 KB (max).
* Out of 640 KB SRAM present on silicon, at least 128 KB are always
* dedicated to "zero-wait-state Flash". ZW region is limited by
* specific part flash capacity (for 256, 448 KB) or at 512 KB.
* AT32F435ZMT default EOPB0=0xffff05fa,
* EOPB[0:2]=0b010 for 384 KB SRAM + 256 KB zero-wait-state flash.
*/
target->driver = "AT32F435";
target->mass_erase = stm32f1_mass_erase;
return true;
}

/* Identify AT32F40x "Mainstream" line devices (Cortex-M4) */
bool at32f40x_probe(target_s *target)
{
Expand All @@ -359,8 +272,6 @@ bool at32f40x_probe(target_s *target)
return at32f40_detect(target, part_id);
if (series == AT32F41_SERIES)
return at32f41_detect(target, part_id);
if (series == AT32F43_SERIES_4K || series == AT32F43_SERIES_2K)
return at32f43_detect(target, part_id);
return false;
}

Expand Down
1 change: 1 addition & 0 deletions src/target/target_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ bool lpc55_dmap_probe(adiv5_access_port_s *ap);

bool ch32f1_probe(target_s *target); // will catch all the clones
bool at32f40x_probe(target_s *target); // STM32 clones from Artery
bool at32f43x_probe(target_s *target);
bool mm32l0xx_probe(target_s *target);
bool mm32f3xx_probe(target_s *target);
bool gd32f1_probe(target_s *target);
Expand Down

0 comments on commit bb12a29

Please sign in to comment.