#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "buffer_utils.h"
#define MSP432E4_EEPROM_BASE 0x400af000U
#define MSP432E4_FLASH_CTRL_BASE 0x400fd000U
#define MSP432E4_SYS_CTRL_BASE 0x400fe000U
#define MSP432E4_SYS_CTRL_DID0 (MSP432E4_SYS_CTRL_BASE + 0x0000U)
#define MSP432E4_SYS_CTRL_DID0_CLASS_MASK 0xffff0000U
#define MSP432E4_SYS_CTRL_DID0_MSP432E4 0x180c0000U
#define MSP432E4_SYS_CTRL_DID0_VERSION_MAJ_SHIFT 8U
#define MSP432E4_SYS_CTRL_DID0_VERSION_MAJ_MASK 0xffU
#define MSP432E4_SYS_CTRL_DID0_VERSION_MIN_MASK 0xffU
#define MSP432E4_SYS_CTRL_DID1 (MSP432E4_SYS_CTRL_BASE + 0x0004U)
#define MSP432E4_SYS_CTRL_DID1_FAMILY_MASK 0xff000000U
#define MSP432E4_SYS_CTRL_DID1_MSP432E4 0x10000000U
#define MSP432E4_SYS_CTRL_DID1_PART_NUM_SHIFT 16U
#define MSP432E4_SYS_CTRL_DID1_PART_NUM_MASK 0xffU
#define MSP432E4_SYS_CTRL_DID1_PIN_COUNT_SHIFT 13U
#define MSP432E4_SYS_CTRL_DID1_PIN_COUNT_MASK 0x7U
#define MSP432E4_SYS_CTRL_DID1_TEMP_RANGE_SHIFT 5U
#define MSP432E4_SYS_CTRL_DID1_TEMP_RANGE_MASK 0x7U
#define MSP432E4_SYS_CTRL_DID1_PACKAGE_TYPE_SHIFT 3U
#define MSP432E4_SYS_CTRL_DID1_PACKAGE_TYPE_MASK 0x3U
#define MSP432E4_SYS_CTRL_BOOTCFG (MSP432E4_SYS_CTRL_BASE + 0x01d0U)
#define MSP432E4_SYS_CTRL_BOOTCFG_KEY (1U << 4U)
#define MSP432E4_FLASH_PERIPH_PROP (MSP432E4_FLASH_CTRL_BASE + 0x0fc0U)
#define MSP432E4_FLASH_SRAM_SIZE (MSP432E4_FLASH_CTRL_BASE + 0x0fc4U)
#define MSP432E4_FLASH_CTRL (MSP432E4_FLASH_CTRL_BASE + 0x0008U)
#define MSP432E4_FLASH_CTRL2 (MSP432E4_FLASH_CTRL_BASE + 0x0020U)
#define MSP432E4_FLASH_CTRL_WRITE (1U << 0U)
#define MSP432E4_FLASH_CTRL_ERASE (1U << 1U)
#define MSP432E4_FLASH_CTRL_MASS_ERASE (1U << 2U)
#define MSP432E4_FLASH_CTRL_COMMIT (1U << 3U)
#define MSP432E4_FLASH_FCRIS (MSP432E4_FLASH_CTRL_BASE + 0x000cU)
#define MSP432E4_FLASH_FLPEKEY (MSP432E4_FLASH_CTRL_BASE + 0x003cU)
#define MSP432E4_FLASH_ADDR (MSP432E4_FLASH_CTRL_BASE + 0x0000U)
#define MSP432E4_FLASH_DATA (MSP432E4_FLASH_CTRL_BASE + 0x0004U)
#define MSP432E4_EEPROM_SIZE (MSP432E4_EEPROM_BASE + 0x0000U)
#define MSP432E4_SRAM_BASE 0x20000000U
#define MSP432E4_FLASH_BASE 0x00000000U
#define MSP432E4_FLASH_WRITE_SIZE 4U
typedef struct msp432e4_flash {
target_flash_s target_flash;
uint16_t flash_key;
} msp432e4_flash_s;
static bool msp432e4_flash_erase(target_flash_s *flash, target_addr_t addr, size_t length);
static bool msp432e4_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t length);
static bool msp432e4_mass_erase(target_s *target);
static void msp432e4_add_flash(
target_s *const target, const uint32_t sector_size, const uint32_t base, const size_t length)
{
msp432e4_flash_s *const flash = calloc(1, sizeof(*flash));
if (flash == NULL) {
DEBUG_WARN("calloc: failed in %s\n", __func__);
return;
}
target_flash_s *target_flash = &flash->target_flash;
target_flash->start = base;
target_flash->length = length;
target_flash->blocksize = sector_size;
target_flash->writesize = MSP432E4_FLASH_WRITE_SIZE;
target_flash->erase = msp432e4_flash_erase;
target_flash->write = msp432e4_flash_write;
target_flash->erased = 0xff;
target_add_flash(target, target_flash);
if (target_mem_read32(target, MSP432E4_SYS_CTRL_BOOTCFG) & MSP432E4_SYS_CTRL_BOOTCFG_KEY)
flash->flash_key = 0xa442U;
else
flash->flash_key = (uint16_t)target_mem_read32(target, MSP432E4_FLASH_FLPEKEY);
}
bool msp432e4_probe(target_s *const target)
{
const uint32_t devid0 = target_mem_read32(target, MSP432E4_SYS_CTRL_DID0);
const uint32_t devid1 = target_mem_read32(target, MSP432E4_SYS_CTRL_DID1);
DEBUG_INFO("%s: Device ID %" PRIx32 ":%" PRIx32 "\n", __func__, devid0, devid1);
if ((devid0 & MSP432E4_SYS_CTRL_DID0_CLASS_MASK) != MSP432E4_SYS_CTRL_DID0_MSP432E4 ||
(devid1 & MSP432E4_SYS_CTRL_DID1_FAMILY_MASK) != MSP432E4_SYS_CTRL_DID1_MSP432E4)
return false;
DEBUG_TARGET("%s: Device version %x:%x, part ID %x, pin count %u, temperature grade %x, package type %x\n",
__func__, (devid0 >> MSP432E4_SYS_CTRL_DID0_VERSION_MAJ_SHIFT) & MSP432E4_SYS_CTRL_DID0_VERSION_MAJ_MASK,
devid0 & MSP432E4_SYS_CTRL_DID0_VERSION_MIN_MASK,
(devid1 >> MSP432E4_SYS_CTRL_DID1_PART_NUM_SHIFT) & MSP432E4_SYS_CTRL_DID1_PART_NUM_MASK,
(devid1 >> MSP432E4_SYS_CTRL_DID1_PIN_COUNT_SHIFT) & MSP432E4_SYS_CTRL_DID1_PIN_COUNT_MASK,
(devid1 >> MSP432E4_SYS_CTRL_DID1_TEMP_RANGE_SHIFT) & MSP432E4_SYS_CTRL_DID1_TEMP_RANGE_MASK,
(devid1 >> MSP432E4_SYS_CTRL_DID1_PACKAGE_TYPE_SHIFT) & MSP432E4_SYS_CTRL_DID1_PACKAGE_TYPE_MASK);
target->driver = "MSP432E4";
target->mass_erase = msp432e4_mass_erase;
const uint32_t sram_size = ((target_mem_read32(target, MSP432E4_FLASH_SRAM_SIZE) & 0xffffU) + 1U) * 256U;
target_add_ram(target, MSP432E4_SRAM_BASE, sram_size);
const uint32_t flash_props = target_mem_read32(target, MSP432E4_FLASH_PERIPH_PROP);
const uint32_t flash_size = ((flash_props & 0xffffU) + 1U) * 2048U;
const uint32_t flash_sector_size = (UINT32_C(1) << ((flash_props >> 16U) & 7U)) * 1024U;
msp432e4_add_flash(target, flash_sector_size, MSP432E4_FLASH_BASE, flash_size);
return true;
}
static bool msp432e4_flash_erase(target_flash_s *const target_flash, const target_addr_t addr, const size_t length)
{
(void)length;
target_s *const target = target_flash->t;
const msp432e4_flash_s *const flash = (msp432e4_flash_s *)target_flash;
target_mem_write32(target, MSP432E4_FLASH_ADDR, addr);
target_mem_write32(target, MSP432E4_FLASH_CTRL, (flash->flash_key << 16U) | MSP432E4_FLASH_CTRL_ERASE);
while (target_mem_read32(target, MSP432E4_FLASH_CTRL) & MSP432E4_FLASH_CTRL_ERASE)
continue;
return true;
}
static bool msp432e4_flash_write(
target_flash_s *const target_flash, target_addr_t dest, const void *const src, const size_t length)
{
(void)length;
target_s *const target = target_flash->t;
const msp432e4_flash_s *const flash = (msp432e4_flash_s *)target_flash;
target_mem_write32(target, MSP432E4_FLASH_ADDR, dest);
target_mem_write32(target, MSP432E4_FLASH_DATA, read_le4((const uint8_t *)src, 0));
target_mem_write32(target, MSP432E4_FLASH_CTRL, (flash->flash_key << 16U) | MSP432E4_FLASH_CTRL_WRITE);
while (target_mem_read32(target, MSP432E4_FLASH_CTRL) & MSP432E4_FLASH_CTRL_WRITE)
continue;
return true;
}
static bool msp432e4_mass_erase(target_s *const target)
{
const msp432e4_flash_s *const flash = (msp432e4_flash_s *)target->flash;
platform_timeout_s timeout;
platform_timeout_set(&timeout, 500);
target_mem_write32(target, MSP432E4_FLASH_CTRL, (flash->flash_key << 16U) | MSP432E4_FLASH_CTRL_MASS_ERASE);
while (target_mem_read32(target, MSP432E4_FLASH_CTRL) & MSP432E4_FLASH_CTRL_MASS_ERASE)
target_print_progress(&timeout);
return true;
}