From 3c61c39b4434f56ebd5a1855e8972603d97da53a Mon Sep 17 00:00:00 2001 From: maak184 Date: Tue, 4 Apr 2023 15:35:27 -0300 Subject: [PATCH 1/2] Feat: Add support for EFR32FG23 (draft) --- src/target/adiv5.c | 7 +- src/target/efm32.c | 182 ++++++++++++++++++++++++++++---------- src/target/target_flash.c | 11 +-- 3 files changed, 146 insertions(+), 54 deletions(-) diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 164dc4e248c..8a069b1edfa 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -679,9 +679,10 @@ adiv5_access_port_s *adiv5_new_ap(adiv5_debug_port_s *dp, uint8_t apsel) if (!tmpap.idr) /* IDR Invalid */ return NULL; - tmpap.csw = adiv5_ap_read(&tmpap, ADIV5_AP_CSW); - tmpap.csw &= ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); - tmpap.csw |= ADIV5_AP_CSW_DBGSWENABLE; + //tmpap.csw = adiv5_ap_read(&tmpap, ADIV5_AP_CSW); + //tmpap.csw &= ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); + //tmpap.csw |= ADIV5_AP_CSW_DBGSWENABLE; + tmpap.csw = 0x23000012U; if (tmpap.csw & ADIV5_AP_CSW_TRINPROG) { DEBUG_WARN("AP %d: Transaction in progress. AP is not usable!\n", apsel); diff --git a/src/target/efm32.c b/src/target/efm32.c index 7e478f9a4a2..7bbfcd4a712 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -41,6 +41,8 @@ #include "target_internal.h" #include "cortexm.h" #include "adiv5.h" +#include "gdb_packet.h" +#include "exception.h" #define SRAM_BASE 0x20000000U #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(efm32_flash_write_stub), 4) @@ -49,10 +51,6 @@ static bool efm32_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) static bool efm32_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len); static bool efm32_mass_erase(target_s *t); -static const uint16_t efm32_flash_write_stub[] = { -#include "flashstub/efm32.stub" -}; - static bool efm32_cmd_serial(target_s *t, int argc, const char **argv); static bool efm32_cmd_efm_info(target_s *t, int argc, const char **argv); static bool efm32_cmd_bootloader(target_s *t, int argc, const char **argv); @@ -68,17 +66,17 @@ const command_s efm32_cmd_list[] = { /* Memory System Controller (MSC) Registers */ /* -------------------------------------------------------------------------- */ -#define EFM32_MSC_WRITECTRL(msc) (msc + 0x008U) -#define EFM32_MSC_WRITECMD(msc) (msc + 0x00cU) -#define EFM32_MSC_ADDRB(msc) (msc + 0x010U) -#define EFM32_MSC_WDATA(msc) (msc + 0x018U) -#define EFM32_MSC_STATUS(msc) (msc + 0x01cU) -#define EFM32_MSC_IF(msc) (msc + 0x030U) -#define EFM32_MSC_LOCK(msc) (msc + (msc == 0x400c0000U ? 0x3cU : 0x40U)) -#define EFM32_MSC_MASSLOCK(msc) (msc + 0x054U) +#define EFM32_MSC_WRITECTRL(msc) (msc + 0x00CU) //(msc + 0x008U) +#define EFM32_MSC_WRITECMD(msc) (msc + 0x010U) +#define EFM32_MSC_ADDRB(msc) (msc + 0x014U) +#define EFM32_MSC_WDATA(msc) (msc + 0x018U) +#define EFM32_MSC_STATUS(msc) (msc + 0x01CU) +#define EFM32_MSC_IF(msc) (msc + 0x020U) +#define EFM32_MSC_LOCK(msc) (msc + 0x03CU) +#define EFM32_MSC_MASSLOCK(msc) (msc + 0x040U) -#define EFM32_MSC_LOCK_LOCKKEY 0x1b71U -#define EFM32_MSC_MASSLOCK_LOCKKEY 0x631aU +#define EFM32_MSC_LOCK_LOCKKEY 0x7025U +#define EFM32_MSC_MASSLOCK_LOCKKEY 0x0000U #define EFM32_MSC_WRITECMD_LADDRIM (1U << 0U) #define EFM32_MSC_WRITECMD_ERASEPAGE (1U << 1U) @@ -103,6 +101,7 @@ const command_s efm32_cmd_list[] = { #define EFM32_LOCK_BITS (EFM32_INFO + 0x4000U) #define EFM32_V1_DI (EFM32_INFO + 0x8000U) #define EFM32_V2_DI (EFM32_INFO + 0x81b0U) +#define EFR32FG23_DI (EFM32_INFO + 0x8000U) /* -------------------------------------------------------------------------- */ /* Lock Bits (LB) */ @@ -255,7 +254,52 @@ const command_s efm32_cmd_list[] = { #define EFM32_V2_DI_OPA2CAL7 (EFM32_V2_DI + 0x1fcU) /* OPA2 Calibration Register for DRIVESTRENGTH 3, INCBW=0 */ /* top 24 bits of eui */ -#define EFM32_V2_DI_EUI_ENERGYMICRO 0xd0cf5e +#define EFM32_V2_DI_EUI_ENERGYMICRO 0x666d71 //0xd0cf5e + +/* -------------------------------------------------------------------------- */ +/* Device Information (DI) Area for EFR32FG23 */ +/* -------------------------------------------------------------------------- */ + +#define EFR32FG23_DI_INFO (EFR32FG23_DI + 0x000U) +#define EFR32FG23_DI_PART (EFR32FG23_DI + 0x004U) +#define EFR32FG23_DI_MEMINFO (EFR32FG23_DI + 0x008U) +#define EFR32FG23_DI_MSIZE (EFR32FG23_DI + 0x00cU) +#define EFR32FG23_DI_PKGINFO (EFR32FG23_DI + 0x010U) +#define EFR32FG23_DI_CUSTOMINFO (EFR32FG23_DI + 0x014U) +#define EFR32FG23_DI_SWFIX (EFR32FG23_DI + 0x018U) +#define EFR32FG23_DI_SWCAPA0 (EFR32FG23_DI + 0x01cU) +#define EFR32FG23_DI_SWCAPA1 (EFR32FG23_DI + 0x020U) +#define EFR32FG23_DI_EXTINFO (EFR32FG23_DI + 0x028U) +#define EFR32FG23_DI_EUI48L (EFR32FG23_DI + 0x040U) +#define EFR32FG23_DI_EUI48H (EFR32FG23_DI + 0x044U) +#define EFR32FG23_DI_EUI64L (EFR32FG23_DI + 0x048U) +#define EFR32FG23_DI_EUI64H (EFR32FG23_DI + 0x04CU) +#define EFR32FG23_DI_CALTEMP (EFR32FG23_DI + 0x050U) +#define EFR32FG23_DI_EMUTEMP (EFR32FG23_DI + 0x054U) +#define EFR32FG23_DI_HFRCODPLLCALn (EFR32FG23_DI + 0x058U) +#define EFR32FG23_DI_HFRCOEM23CALn (EFR32FG23_DI + 0x0A0U) +#define EFR32FG23_DI_MODULENAME0 (EFR32FG23_DI + 0x130U) +#define EFR32FG23_DI_MODULENAME1 (EFR32FG23_DI + 0x134U) +#define EFR32FG23_DI_MODULENAME2 (EFR32FG23_DI + 0x138U) +#define EFR32FG23_DI_MODULENAME3 (EFR32FG23_DI + 0x13CU) +#define EFR32FG23_DI_MODULENAME4 (EFR32FG23_DI + 0x140U) +#define EFR32FG23_DI_MODULENAME5 (EFR32FG23_DI + 0x144U) +#define EFR32FG23_DI_MODULENAME6 (EFR32FG23_DI + 0x148U) +#define EFR32FG23_DI_MODULEINFO (EFR32FG23_DI + 0x14CU) +#define EFR32FG23_DI_MODXOCAL (EFR32FG23_DI + 0x150U) +#define EFR32FG23_DI_HFXOCAL (EFR32FG23_DI + 0x17CU) +#define EFR32FG23_DI_IADC0GAIN0 (EFR32FG23_DI + 0x180U) +#define EFR32FG23_DI_IADC0GAIN1 (EFR32FG23_DI + 0x184U) +#define EFR32FG23_DI_IADC0OFFSETCAL0 (EFR32FG23_DI + 0x188U) +#define EFR32FG23_DI_IADC0NORMALOFFSETCAL0 (EFR32FG23_DI + 0x18CU) +#define EFR32FG23_DI_IADC0NORMALOFFSETCAL1 (EFR32FG23_DI + 0x190U) +#define EFR32FG23_DI_IADC0HISPDOFFSETCAL0 (EFR32FG23_DI + 0x194U) +#define EFR32FG23_DI_IADC0HISPDOFFSETCAL1 (EFR32FG23_DI + 0x198U) +#define EFR32FG23_DI_LEGACY (EFR32FG23_DI + 0x1FCU) +#define EFR32FG23_DI_RTHERM (EFR32FG23_DI + 0x25CU) + +/* top 24 bits of eui */ +#define EFR32FG23_DI_EUI_ENERGYMICRO 0xf4b3b1 /* -------------------------------------------------------------------------- */ /* Constants */ @@ -331,6 +375,10 @@ static const efm32_device_s efm32_devices[] = { {61, true, 2048, "EFR32FG14P", 0x400e0000, 2048, 16384, "Flex Gecko"}, {62, true, 2048, "EFR32FG14B", 0x400e0000, 2048, 16384, "Flex Gecko"}, {63, true, 2048, "EFR32FG14V", 0x400e0000, 2048, 16384, "Flex Gecko"}, + /* For EFR32xG23 devices */ + {0, true, 8192, "EFR32FG23", 0x40030000, 1024, 0, "Flex Gecko"}, + {3, true, 8192, "EFR32FG23", 0x40030000, 1024, 0, "Z-wave Gecko"}, + {5, true, 8192, "EFR32FG23", 0x40030000, 1024, 0, "Pearl Gecko"}, }; /* miscchip */ @@ -374,6 +422,11 @@ static const efm32_v2_di_tempgrade_s efm32_v2_di_tempgrades[] = { static uint64_t efm32_v1_read_eui64(target_s *t) { return ((uint64_t)target_mem_read32(t, EFM32_V1_DI_EUI64_1) << 32U) | target_mem_read32(t, EFM32_V1_DI_EUI64_0); +} + +static uint64_t efr32fg23_read_eui64(target_s *t) +{ + return ((uint64_t)target_mem_read32(t, EFR32FG23_DI_EUI64H) >> 8U); } /* Reads the Unique Number (DI V2 only) */ @@ -385,6 +438,14 @@ static uint64_t efm32_v2_read_unique(target_s *t, uint8_t di_version) return ((uint64_t)target_mem_read32(t, EFM32_V2_DI_UNIQUEH) << 32U) | target_mem_read32(t, EFM32_V2_DI_UNIQUEL); } +static uint64_t efr32fg23_read_unique(target_s *t, uint8_t di_version) +{ + if (di_version != 3) + return 0; + + return (((uint64_t)target_mem_read32(t, EFR32FG23_DI_EUI64H) & 0x000FU) << 32U ) | target_mem_read32(t, EFR32FG23_DI_EUI64L); +} + /* Reads the EFM32 flash size in kiB */ static uint16_t efm32_read_flash_size(target_s *t, uint8_t di_version) { @@ -393,6 +454,8 @@ static uint16_t efm32_read_flash_size(target_s *t, uint8_t di_version) return target_mem_read16(t, EFM32_V1_DI_MEM_INFO_FLASH); case 2: return target_mem_read32(t, EFM32_V2_DI_MSIZE) & 0xffffU; + case 3: + return target_mem_read16(t, EFR32FG23_DI_MSIZE); default: return 0; } @@ -406,6 +469,8 @@ static uint16_t efm32_read_ram_size(target_s *t, uint8_t di_version) return target_mem_read16(t, EFM32_V1_DI_MEM_INFO_RAM); case 2: return (target_mem_read32(t, EFM32_V2_DI_MSIZE) >> 16U) & 0xffffU; + case 3: + return (target_mem_read32(t, EFR32FG23_DI_MSIZE) >> 16U) & 0xffffU; default: return 0; } @@ -428,6 +493,9 @@ static uint32_t efm32_flash_page_size(target_s *t, uint8_t di_version) case 2U: mem_info_page_size = (target_mem_read32(t, EFM32_V2_DI_MEMINFO) >> 24U) & 0xffU; break; + case 3U: + mem_info_page_size = target_mem_read8(t, EFR32FG23_DI_MEMINFO); + break; default: return 0; } @@ -443,6 +511,8 @@ static uint16_t efm32_read_part_number(target_s *t, uint8_t di_version) return target_mem_read8(t, EFM32_V1_DI_PART_NUMBER); case 2: return target_mem_read32(t, EFM32_V2_DI_PART) & 0xffffU; + case 3: + return target_mem_read32(t, EFR32FG23_DI_PART) & 0xffffU; default: return 0; } @@ -456,6 +526,8 @@ static uint8_t efm32_read_part_family(target_s *t, uint8_t di_version) return target_mem_read8(t, EFM32_V1_DI_PART_FAMILY); case 2: return (target_mem_read32(t, EFM32_V2_DI_PART) >> 16U) & 0xffU; + case 3: + return (target_mem_read32(t, EFR32FG23_DI_PART) >> 23U) & 0x3fU; default: return 0; } @@ -498,7 +570,7 @@ static void efm32_add_flash(target_s *t, target_addr_t addr, size_t length, size { target_flash_s *f = calloc(1, sizeof(*f)); if (!f) { /* calloc failed: heap exhaustion */ - DEBUG_WARN("calloc: failed in %s\n", __func__); + gdb_outf("calloc: failed !!\n"); return; } @@ -514,6 +586,8 @@ static void efm32_add_flash(target_s *t, target_addr_t addr, size_t length, size /* Lookup device */ static efm32_device_s const *efm32_get_device(target_s *t, uint8_t di_version) { + if(di_version == 0) return NULL; + uint8_t part_family = efm32_read_part_family(t, di_version); /* Search for family */ @@ -538,17 +612,25 @@ bool efm32_probe(target_s *t) { /* Check if the OUI in the EUI is silabs or energymicro. * Use this to identify the Device Identification (DI) version */ + uint8_t di_version = 1; - uint64_t oui24 = ((efm32_v1_read_eui64(t) >> 40U) & 0xffffffU); + uint32_t oui24 = ((efm32_v1_read_eui64(t) >> 40U) & 0xffffffU); if (oui24 == EFM32_V1_DI_EUI_SILABS) { /* Device Identification (DI) version 1 */ di_version = 1; } else if (oui24 == EFM32_V2_DI_EUI_ENERGYMICRO) { /* Device Identification (DI) version 2 */ di_version = 2; + } else if (oui24 == EFR32FG23_DI_EUI_ENERGYMICRO) { + /* Device Identification (DI) for EFR32FG23 */ + di_version = 3; } else { + uint32_t oui24 = (uint32_t)(efr32fg23_read_eui64(t) & 0xffffffU); + if (oui24 == EFR32FG23_DI_EUI_ENERGYMICRO || oui24 == 0x8000C0U){ + di_version = 3; + } /* Unknown OUI - assume version 1 */ - di_version = 1; + else di_version = 0; } /* Read the part family, and reject if unknown */ @@ -556,6 +638,8 @@ bool efm32_probe(target_s *t) if (!device) return false; + t->attach = cortexm_attach; + t->detach = cortexm_detach; t->mass_erase = efm32_mass_erase; uint16_t part_number = efm32_read_part_number(t, di_version); @@ -566,7 +650,12 @@ bool efm32_probe(target_s *t) uint32_t ram_size = ram_kib * 0x400U; uint32_t flash_page_size = device->flash_page_size; + efm32_priv_s *priv_storage = calloc(1, sizeof(*priv_storage)); + if (!priv_storage) { /* calloc failed: heap exhaustion */ + gdb_outf("calloc: failed!"); + return false; + } t->target_storage = (void *)priv_storage; priv_storage->di_version = di_version; @@ -578,10 +667,9 @@ bool efm32_probe(target_s *t) /* Setup Target */ t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; t->driver = priv_storage->efm32_variant_string; - tc_printf(t, "flash size %u page size %u\n", flash_size, flash_page_size); target_add_ram(t, SRAM_BASE, ram_size); - efm32_add_flash(t, 0x00000000, flash_size, flash_page_size); + efm32_add_flash(t, 0x08000000, flash_size, flash_page_size); if (device->user_data_size) { /* optional User Data (UD) section */ efm32_add_flash(t, 0x0fe00000, device->user_data_size, flash_page_size); } @@ -589,6 +677,8 @@ bool efm32_probe(target_s *t) efm32_add_flash(t, 0x0fe10000, device->bootloader_size, flash_page_size); } + target_mem_write32(t, 0x40008064U, 0xFFFFFFFFU); + target_mem_write32(t, 0x40008068U, 0x1FFFFFFFU); target_add_commands(t, efm32_cmd_list, "EFM32"); return true; @@ -605,16 +695,16 @@ static bool efm32_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) uint32_t msc = priv_storage->device->msc_addr; + /* Set WREN bit to enable MSC write and erase functionality */ + target_mem_write32(t, EFM32_MSC_WRITECTRL(msc), 1); + /* Unlock */ target_mem_write32(t, EFM32_MSC_LOCK(msc), EFM32_MSC_LOCK_LOCKKEY); - /* Set WREN bit to enable MSC write and erase functionality */ - target_mem_write32(t, EFM32_MSC_WRITECTRL(msc), 1); while (len) { /* Write address of first word in row to erase it */ target_mem_write32(t, EFM32_MSC_ADDRB(msc), addr); - target_mem_write32(t, EFM32_MSC_WRITECMD(msc), EFM32_MSC_WRITECMD_LADDRIM); /* Issue the erase command */ target_mem_write32(t, EFM32_MSC_WRITECMD(msc), EFM32_MSC_WRITECMD_ERASEPAGE); @@ -631,35 +721,29 @@ static bool efm32_flash_erase(target_flash_s *f, target_addr_t addr, size_t len) else len = 0; } - return true; } /* Write flash page by page */ static bool efm32_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len) { - (void)len; - target_s *t = f->t; efm32_priv_s *priv_storage = (efm32_priv_s *)t->target_storage; - if (!priv_storage || !priv_storage->device) + if (!priv_storage || !priv_storage->device){ return false; + } + uint32_t msc = priv_storage->device->msc_addr; - /* Write flashloader */ - target_mem_write(t, SRAM_BASE, efm32_flash_write_stub, sizeof(efm32_flash_write_stub)); - /* Write Buffer */ - target_mem_write(t, STUB_BUFFER_BASE, src, len); - /* Run flashloader */ - const bool ret = cortexm_run_stub(t, SRAM_BASE, dest, STUB_BUFFER_BASE, len, priv_storage->device->msc_addr) == 0; + target_mem_write32(t, EFM32_MSC_WRITECTRL(msc), 1); + target_mem_write32(t, EFM32_MSC_LOCK(msc), EFM32_MSC_LOCK_LOCKKEY); + + for (size_t i = 0; i < len; i+=4){ + target_mem_write32(t, EFM32_MSC_ADDRB(msc), (uint32_t)((uint32_t)dest + (uint32_t)i)); + target_mem_write32(t, EFM32_MSC_WDATA(msc), *(uint32_t*)((uint8_t*)src + (uintptr_t)i)); + } -#ifdef ENABLE_DEBUG - /* Check the MSC_IF */ - uint32_t msc = priv_storage->device->msc_addr; - uint32_t msc_if = target_mem_read32(t, EFM32_MSC_IF(msc)); - DEBUG_INFO("EFM32: Flash write done MSC_IF=%08" PRIx32 "\n", msc_if); -#endif - return ret; + return true; } /* Uses the MSC ERASEMAIN0/1 command to erase the entire flash */ @@ -683,7 +767,7 @@ static bool efm32_mass_erase(target_s *t) target_mem_write32(t, EFM32_MSC_WRITECTRL(msc), 1); /* Unlock mass erase */ - target_mem_write32(t, EFM32_MSC_MASSLOCK(msc), EFM32_MSC_MASSLOCK_LOCKKEY); + target_mem_write32(t, EFM32_MSC_LOCK(msc), EFM32_MSC_LOCK_LOCKKEY); /* Erase operation */ target_mem_write32(t, EFM32_MSC_WRITECMD(msc), EFM32_MSC_WRITECMD_ERASEMAIN0); @@ -710,9 +794,6 @@ static bool efm32_mass_erase(target_s *t) } } - /* Relock mass erase */ - target_mem_write32(t, EFM32_MSC_MASSLOCK(msc), 0); - return true; } @@ -740,6 +821,11 @@ static bool efm32_cmd_serial(target_s *t, int argc, const char **argv) unique = efm32_v2_read_unique(t, di_version); break; + case 3: + /* Read unique number */ + unique = efr32fg23_read_unique(t, di_version); + break; + default: tc_printf(t, "Bad DI version %hhu! This driver doesn't know about this DI version\n", di_version); return false; @@ -772,6 +858,10 @@ static bool efm32_cmd_efm_info(target_s *t, int argc, const char **argv) tc_printf(t, "DI version 2 (energy micro remix?) base 0x%08" PRIx32 "\n\n", EFM32_V2_DI); break; + case 3: + tc_printf(t, "DI version EFR32xG23 base 0x%08" PRIx32 "\n\n", EFR32FG23_DI); + break; + default: tc_printf(t, "Bad DI version %hhu! This driver doesn't know about this DI version\n", di_version); return false; @@ -959,7 +1049,7 @@ bool efm32_aap_probe(adiv5_access_port_s *ap) efm32_aap_priv_s *priv_storage = calloc(1, sizeof(*priv_storage)); sprintf(priv_storage->aap_driver_string, "EFM32 Authentication Access Port rev.%hu", aap_revision); t->driver = priv_storage->aap_driver_string; - t->regs_size = 0; + t->regs_size = 4; return true; } @@ -996,4 +1086,4 @@ static bool efm32_aap_mass_erase(target_s *t) DEBUG_INFO("EFM32: AAP STATUS=%08" PRIx32 "\n", status); return true; -} +} \ No newline at end of file diff --git a/src/target/target_flash.c b/src/target/target_flash.c index 9ee31aa9d59..8508e0f48e4 100644 --- a/src/target/target_flash.c +++ b/src/target/target_flash.c @@ -37,6 +37,7 @@ #include "general.h" #include "target_internal.h" +#include "gdb_packet.h" target_flash_s *target_flash_for_addr(target_s *t, uint32_t addr) { @@ -55,10 +56,10 @@ static bool target_enter_flash_mode(target_s *t) bool ret = true; if (t->enter_flash_mode) ret = t->enter_flash_mode(t); - else + //else /* Reset target on flash command */ /* This saves us if we're interrupted in IRQ context */ - target_reset(t); + // target_reset(t); if (ret == true) t->flash_mode = true; @@ -188,10 +189,10 @@ static bool flash_buffered_flush(target_flash_s *f) const uint8_t *src = f->buf + (aligned_addr - f->buf_addr_base); uint32_t len = f->buf_addr_high - aligned_addr; - - for (size_t offset = 0; offset < len; offset += f->writesize) + + for (size_t offset = 0; offset < len; offset += f->writesize){ ret &= f->write(f, aligned_addr + offset, src + offset, f->writesize); - + } f->buf_addr_base = UINT32_MAX; f->buf_addr_low = UINT32_MAX; f->buf_addr_high = 0; From 9860592a7103e203b7e5f8edb9adc20cfa876486 Mon Sep 17 00:00:00 2001 From: Marcelo Felix Carlos <79105582+maak184@users.noreply.github.com> Date: Wed, 19 Apr 2023 14:50:54 -0300 Subject: [PATCH 2/2] fix: identify any revision of efr32xG23 processor --- src/target/efm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/efm32.c b/src/target/efm32.c index 7bbfcd4a712..12f709bb040 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -630,7 +630,7 @@ bool efm32_probe(target_s *t) di_version = 3; } /* Unknown OUI - assume version 1 */ - else di_version = 0; + else di_version = 3; } /* Read the part family, and reject if unknown */