mirror of
git://git.code.sf.net/p/openocd/code
synced 2025-07-19 10:08:37 +10:00
Replace the BSD-3-Clause boilerplate with the SPDX tag. Add the SPDX tag and the copyright to two makefiles that were added by TI with the other files in their respective folder. The SPDX tag on files *.c is incorrect, as it should use the C99 single line comment using '//'. But current checkpatch doesn't allow C99 comments, so keep using standard C comments, by now. Change-Id: I3ad1b2dbdb6054b74dcc26e394c9223ba0427caf Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: https://review.openocd.org/c/openocd/+/7158 Tested-by: jenkins
360 lines
9.6 KiB
C
360 lines
9.6 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "driverlib.h"
|
|
|
|
#include "MSP432P4_FlashLibIf.h"
|
|
|
|
/* Number of erase repeats until timeout */
|
|
#define FLASH_MAX_REPEATS 5
|
|
|
|
/* Local prototypes */
|
|
void msp432_flash_init(void);
|
|
void msp432_flash_mass_erase(void);
|
|
void msp432_flash_sector_erase(void);
|
|
void msp432_flash_write(void);
|
|
void msp432_flash_continous_write(void);
|
|
void msp432_flash_exit(void);
|
|
void unlock_flash_sectors(void);
|
|
void unlock_all_flash_sectors(void);
|
|
void lock_all_flash_sectors(void);
|
|
void __cs_set_dco_frequency_range(uint32_t dco_freq);
|
|
static bool program_device(void *src, void *dest, uint32_t length);
|
|
|
|
struct backup_params {
|
|
uint32_t BANK0_WAIT_RESTORE;
|
|
uint32_t BANK1_WAIT_RESTORE;
|
|
uint32_t CS_DC0_FREQ_RESTORE;
|
|
uint8_t VCORE_LEVEL_RESTORE;
|
|
uint8_t PCM_VCORE_LEVEL_RESTORE;
|
|
};
|
|
|
|
#define BACKUP_PARAMS ((struct backup_params *) 0x20000180)
|
|
|
|
/* Main with trampoline */
|
|
int main(void)
|
|
{
|
|
/* Halt watchdog */
|
|
MAP_WDT_A_HOLD_TIMER();
|
|
|
|
/* Disable interrupts */
|
|
cpu_cpsid();
|
|
|
|
while (1) {
|
|
switch (FLASH_LOADER->FLASH_FUNCTION) {
|
|
case FLASH_INIT:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
|
|
msp432_flash_init();
|
|
FLASH_LOADER->FLASH_FUNCTION = 0;
|
|
break;
|
|
case FLASH_MASS_ERASE:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
|
|
msp432_flash_mass_erase();
|
|
FLASH_LOADER->FLASH_FUNCTION = 0;
|
|
break;
|
|
case FLASH_SECTOR_ERASE:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
|
|
msp432_flash_sector_erase();
|
|
FLASH_LOADER->FLASH_FUNCTION = 0;
|
|
break;
|
|
case FLASH_PROGRAM:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
|
|
msp432_flash_write();
|
|
FLASH_LOADER->FLASH_FUNCTION = 0;
|
|
break;
|
|
case FLASH_CONTINUOUS_PROGRAM:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
|
|
msp432_flash_continous_write();
|
|
FLASH_LOADER->FLASH_FUNCTION = 0;
|
|
break;
|
|
case FLASH_EXIT:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
|
|
msp432_flash_exit();
|
|
FLASH_LOADER->FLASH_FUNCTION = 0;
|
|
break;
|
|
case FLASH_NO_COMMAND:
|
|
break;
|
|
default:
|
|
FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Initialize flash */
|
|
void msp432_flash_init(void)
|
|
{
|
|
bool success = false;
|
|
|
|
/* Point to vector table in RAM */
|
|
SCB->VTOR = (uint32_t)0x01000000;
|
|
|
|
/* backup system parameters */
|
|
BACKUP_PARAMS->BANK0_WAIT_RESTORE =
|
|
MAP_FLASH_CTL_GET_WAIT_STATE(FLASH_BANK0);
|
|
BACKUP_PARAMS->BANK1_WAIT_RESTORE =
|
|
MAP_FLASH_CTL_GET_WAIT_STATE(FLASH_BANK1);
|
|
BACKUP_PARAMS->VCORE_LEVEL_RESTORE = MAP_PCM_GET_CORE_VOLTAGE_LEVEL();
|
|
BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE = MAP_PCM_GET_POWER_STATE();
|
|
BACKUP_PARAMS->CS_DC0_FREQ_RESTORE = CS->CTL0 & CS_CTL0_DCORSEL_MASK;
|
|
|
|
/* set parameters for flashing */
|
|
success = MAP_PCM_SET_POWER_STATE(PCM_AM_LDO_VCORE0);
|
|
|
|
/* Set Flash wait states to 2 */
|
|
MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK0, 2);
|
|
MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK1, 2);
|
|
|
|
/* Set CPU speed to 24MHz */
|
|
__cs_set_dco_frequency_range(CS_DCO_FREQUENCY_24);
|
|
|
|
if (!success) {
|
|
/* Indicate failed power switch */
|
|
FLASH_LOADER->RETURN_CODE = FLASH_POWER_ERROR;
|
|
} else
|
|
FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
|
|
}
|
|
|
|
/* Erase entire flash */
|
|
void msp432_flash_mass_erase(void)
|
|
{
|
|
bool success = false;
|
|
|
|
/* Allow flash writes */
|
|
unlock_flash_sectors();
|
|
|
|
/* Allow some mass erase repeats before timeout with error */
|
|
int erase_repeats = FLASH_MAX_REPEATS;
|
|
while (!success && (erase_repeats > 0)) {
|
|
/* Mass erase with post-verify */
|
|
success = MAP_FLASH_CTL_PERFORM_MASS_ERASE();
|
|
erase_repeats--;
|
|
}
|
|
|
|
if (erase_repeats == 0)
|
|
FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR;
|
|
else
|
|
FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
|
|
|
|
/* Block flash writes */
|
|
lock_all_flash_sectors();
|
|
}
|
|
|
|
/* Erase one flash sector */
|
|
void msp432_flash_sector_erase(void)
|
|
{
|
|
bool success = false;
|
|
|
|
/* Allow flash writes */
|
|
unlock_all_flash_sectors();
|
|
|
|
/* Allow some sector erase repeats before timeout with error */
|
|
int erase_repeats = FLASH_MAX_REPEATS;
|
|
while (!success && (erase_repeats > 0)) {
|
|
/* Sector erase with post-verify */
|
|
success = MAP_FLASH_CTL_ERASE_SECTOR(FLASH_LOADER->DST_ADDRESS);
|
|
erase_repeats--;
|
|
}
|
|
|
|
if (erase_repeats == 0)
|
|
FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
|
|
else
|
|
FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
|
|
|
|
/* Block flash writes */
|
|
lock_all_flash_sectors();
|
|
}
|
|
|
|
/* Write data to flash with the help of DriverLib */
|
|
void msp432_flash_write(void)
|
|
{
|
|
bool success = false;
|
|
|
|
/* Allow flash writes */
|
|
unlock_all_flash_sectors();
|
|
|
|
while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY))
|
|
;
|
|
|
|
FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
|
|
|
|
/* Program memory */
|
|
success = program_device((uint32_t *)RAM_LOADER_BUFFER1,
|
|
(void *)FLASH_LOADER->DST_ADDRESS, FLASH_LOADER->SRC_LENGTH);
|
|
|
|
FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
|
|
~(BUFFER_ACTIVE | BUFFER_DATA_READY);
|
|
|
|
/* Block flash writes */
|
|
lock_all_flash_sectors();
|
|
|
|
if (!success)
|
|
FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
|
|
else
|
|
FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
|
|
}
|
|
|
|
/* Write data to flash with the help of DriverLib with auto-increment */
|
|
void msp432_flash_continous_write(void)
|
|
{
|
|
bool buffer1_in_use = false;
|
|
bool buffer2_in_use = false;
|
|
uint32_t *src_address = NULL;
|
|
bool success = false;
|
|
|
|
uint32_t bytes_to_write = FLASH_LOADER->SRC_LENGTH;
|
|
uint32_t write_package = 0;
|
|
uint32_t start_addr = FLASH_LOADER->DST_ADDRESS;
|
|
|
|
while (bytes_to_write > 0) {
|
|
if (bytes_to_write > SRC_LENGTH_MAX) {
|
|
write_package = SRC_LENGTH_MAX;
|
|
bytes_to_write -= write_package;
|
|
} else {
|
|
write_package = bytes_to_write;
|
|
bytes_to_write -= write_package;
|
|
}
|
|
unlock_all_flash_sectors();
|
|
|
|
while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) &&
|
|
!(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY))
|
|
;
|
|
|
|
if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) {
|
|
FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE;
|
|
src_address = (uint32_t *)RAM_LOADER_BUFFER1;
|
|
buffer1_in_use = true;
|
|
} else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) {
|
|
FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE;
|
|
src_address = (uint32_t *)RAM_LOADER_BUFFER2;
|
|
buffer2_in_use = true;
|
|
}
|
|
if (buffer1_in_use || buffer2_in_use) {
|
|
success = program_device(src_address,
|
|
(void *)start_addr, write_package);
|
|
|
|
if (buffer1_in_use)
|
|
P6->OUT &= ~BIT4; /* Program from B1 */
|
|
else if (buffer2_in_use)
|
|
P3->OUT &= ~BIT6; /* Program from B1 */
|
|
|
|
start_addr += write_package;
|
|
}
|
|
if (buffer1_in_use) {
|
|
FLASH_LOADER->BUFFER1_STATUS_REGISTER &=
|
|
~(BUFFER_ACTIVE | BUFFER_DATA_READY);
|
|
buffer1_in_use = false;
|
|
} else if (buffer2_in_use) {
|
|
FLASH_LOADER->BUFFER2_STATUS_REGISTER &=
|
|
~(BUFFER_ACTIVE | BUFFER_DATA_READY);
|
|
buffer2_in_use = false;
|
|
}
|
|
/* Block flash writes */
|
|
lock_all_flash_sectors();
|
|
|
|
if (!success) {
|
|
FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
if (success)
|
|
FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
|
|
}
|
|
|
|
/* Unlock Main/Info Flash sectors */
|
|
void unlock_flash_sectors(void)
|
|
{
|
|
if (FLASH_LOADER->ERASE_PARAM & ERASE_MAIN) {
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0,
|
|
0xFFFFFFFF);
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1,
|
|
0xFFFFFFFF);
|
|
}
|
|
if (FLASH_LOADER->ERASE_PARAM & ERASE_INFO) {
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0,
|
|
FLASH_SECTOR0 | FLASH_SECTOR1);
|
|
if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY)
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1,
|
|
FLASH_SECTOR0 | FLASH_SECTOR1);
|
|
}
|
|
}
|
|
|
|
/* Unlock All Flash sectors */
|
|
void unlock_all_flash_sectors(void)
|
|
{
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, 0xFFFFFFFF);
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, 0xFFFFFFFF);
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0,
|
|
FLASH_SECTOR0 | FLASH_SECTOR1);
|
|
if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY)
|
|
MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1,
|
|
FLASH_SECTOR0 | FLASH_SECTOR1);
|
|
}
|
|
|
|
|
|
/* Lock all Flash sectors */
|
|
void lock_all_flash_sectors(void)
|
|
{
|
|
MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, 0xFFFFFFFF);
|
|
MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, 0xFFFFFFFF);
|
|
MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0,
|
|
FLASH_SECTOR0 | FLASH_SECTOR1);
|
|
MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1,
|
|
FLASH_SECTOR0 | FLASH_SECTOR1);
|
|
}
|
|
|
|
|
|
/* Force DCO frequency range */
|
|
void __cs_set_dco_frequency_range(uint32_t dco_freq)
|
|
{
|
|
/* Unlocking the CS Module */
|
|
CS->KEY = CS_KEY_VAL;
|
|
|
|
/* Resetting Tuning Parameters and Setting the frequency */
|
|
CS->CTL0 = (CS->CTL0 & ~CS_CTL0_DCORSEL_MASK) | dco_freq;
|
|
|
|
/* Locking the CS Module */
|
|
CS->KEY = 0;
|
|
}
|
|
|
|
/* Exit flash programming */
|
|
void msp432_flash_exit(void)
|
|
{
|
|
bool success = false;
|
|
|
|
/* Restore modified registers, in reverse order */
|
|
__cs_set_dco_frequency_range(CS_DCO_FREQUENCY_3);
|
|
|
|
MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK0,
|
|
BACKUP_PARAMS->BANK0_WAIT_RESTORE);
|
|
MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK1,
|
|
BACKUP_PARAMS->BANK1_WAIT_RESTORE);
|
|
|
|
success = MAP_PCM_SET_POWER_STATE(BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE);
|
|
|
|
success &= MAP_PCM_SET_CORE_VOLTAGE_LEVEL(
|
|
BACKUP_PARAMS->VCORE_LEVEL_RESTORE);
|
|
|
|
__cs_set_dco_frequency_range(BACKUP_PARAMS->CS_DC0_FREQ_RESTORE);
|
|
|
|
/* Point to vector table in Flash */
|
|
SCB->VTOR = (uint32_t)0x00000000;
|
|
|
|
if (!success)
|
|
FLASH_LOADER->RETURN_CODE = FLASH_ERROR;
|
|
else
|
|
FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS;
|
|
}
|
|
|
|
static bool program_device(void *src, void *dest, uint32_t length)
|
|
{
|
|
return MAP_FLASH_CTL_PROGRAM_MEMORY(src, dest, length);
|
|
}
|