flash/nor: add support for TI MSP432 devices
[openocd.git] / contrib / loaders / flash / msp432 / main_msp432p401x.c
diff --git a/contrib/loaders/flash/msp432/main_msp432p401x.c b/contrib/loaders/flash/msp432/main_msp432p401x.c
new file mode 100644 (file)
index 0000000..7992f11
--- /dev/null
@@ -0,0 +1,385 @@
+/******************************************************************************
+*
+* Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  Redistributions of source code must retain the above copyright
+*  notice, this list of conditions and the following disclaimer.
+*
+*  Redistributions in binary form must reproduce the above copyright
+*  notice, this list of conditions and the following disclaimer in the
+*  documentation and/or other materials provided with the
+*  distribution.
+*
+*  Neither the name of Texas Instruments Incorporated nor the names of
+*  its contributors may be used to endorse or promote products derived
+*  from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************/
+
+#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);
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)