Merge branch 'master' into from_upstream
This commit is contained in:
@@ -19,6 +19,7 @@ NOR_DRIVERS = \
|
||||
%D%/atsamv.c \
|
||||
%D%/avrf.c \
|
||||
%D%/bluenrg-x.c \
|
||||
%D%/cc3220sf.c \
|
||||
%D%/cfi.c \
|
||||
%D%/dsp5680xx_flash.c \
|
||||
%D%/efm32.c \
|
||||
@@ -43,6 +44,7 @@ NOR_DRIVERS = \
|
||||
%D%/ocl.c \
|
||||
%D%/pic32mx.c \
|
||||
%D%/psoc4.c \
|
||||
%D%/psoc5lp.c \
|
||||
%D%/psoc6.c \
|
||||
%D%/sim3x.c \
|
||||
%D%/spi.c \
|
||||
@@ -64,6 +66,7 @@ NOR_DRIVERS = \
|
||||
|
||||
NORHEADERS = \
|
||||
%D%/core.h \
|
||||
%D%/cc3220sf.h \
|
||||
%D%/cfi.h \
|
||||
%D%/driver.h \
|
||||
%D%/imp.h \
|
||||
|
||||
@@ -0,0 +1,529 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2017 by Texas Instruments, Inc. *
|
||||
* *
|
||||
* 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 2 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/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "imp.h"
|
||||
#include "cc3220sf.h"
|
||||
#include <helper/time_support.h>
|
||||
#include <target/algorithm.h>
|
||||
#include <target/armv7m.h>
|
||||
|
||||
#define FLASH_TIMEOUT 5000
|
||||
|
||||
struct cc3220sf_bank {
|
||||
bool probed;
|
||||
struct armv7m_algorithm armv7m_info;
|
||||
};
|
||||
|
||||
static int cc3220sf_mass_erase(struct flash_bank *bank)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
bool done;
|
||||
long long start_ms;
|
||||
long long elapsed_ms;
|
||||
uint32_t value;
|
||||
|
||||
int retval = ERROR_OK;
|
||||
|
||||
if (TARGET_HALTED != target->state) {
|
||||
LOG_ERROR("Target not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* Set starting address to erase to zero */
|
||||
retval = target_write_u32(target, FMA_REGISTER_ADDR, 0);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
/* Write the MERASE bit of the FMC register */
|
||||
retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_MERASE_VALUE);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
/* Poll the MERASE bit until the mass erase is complete */
|
||||
done = false;
|
||||
start_ms = timeval_ms();
|
||||
while (!done) {
|
||||
retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if ((value & FMC_MERASE_BIT) == 0) {
|
||||
/* Bit clears when mass erase is finished */
|
||||
done = true;
|
||||
} else {
|
||||
elapsed_ms = timeval_ms() - start_ms;
|
||||
if (elapsed_ms > 500)
|
||||
keep_alive();
|
||||
if (elapsed_ms > FLASH_TIMEOUT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
/* Mass erase timed out waiting for confirmation */
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command)
|
||||
{
|
||||
struct cc3220sf_bank *cc3220sf_bank;
|
||||
|
||||
if (CMD_ARGC < 6)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
cc3220sf_bank = malloc(sizeof(struct cc3220sf_bank));
|
||||
if (NULL == cc3220sf_bank)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* Initialize private flash information */
|
||||
cc3220sf_bank->probed = false;
|
||||
|
||||
/* Finish initialization of flash bank */
|
||||
bank->driver_priv = cc3220sf_bank;
|
||||
bank->next = NULL;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int cc3220sf_erase(struct flash_bank *bank, int first, int last)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
bool done;
|
||||
long long start_ms;
|
||||
long long elapsed_ms;
|
||||
uint32_t address;
|
||||
uint32_t value;
|
||||
|
||||
int retval = ERROR_OK;
|
||||
|
||||
if (TARGET_HALTED != target->state) {
|
||||
LOG_ERROR("Target not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* Do a mass erase if user requested all sectors of flash */
|
||||
if ((first == 0) && (last == (bank->num_sectors - 1))) {
|
||||
/* Request mass erase of flash */
|
||||
return cc3220sf_mass_erase(bank);
|
||||
}
|
||||
|
||||
/* Erase requested sectors one by one */
|
||||
for (int i = first; i <= last; i++) {
|
||||
|
||||
/* Determine address of sector to erase */
|
||||
address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE;
|
||||
|
||||
/* Set starting address to erase */
|
||||
retval = target_write_u32(target, FMA_REGISTER_ADDR, address);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
/* Write the ERASE bit of the FMC register */
|
||||
retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_ERASE_VALUE);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
/* Poll the ERASE bit until the erase is complete */
|
||||
done = false;
|
||||
start_ms = timeval_ms();
|
||||
while (!done) {
|
||||
retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if ((value & FMC_ERASE_BIT) == 0) {
|
||||
/* Bit clears when mass erase is finished */
|
||||
done = true;
|
||||
} else {
|
||||
elapsed_ms = timeval_ms() - start_ms;
|
||||
if (elapsed_ms > 500)
|
||||
keep_alive();
|
||||
if (elapsed_ms > FLASH_TIMEOUT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
/* Sector erase timed out waiting for confirmation */
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int cc3220sf_protect(struct flash_bank *bank, int set, int first,
|
||||
int last)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||
uint32_t offset, uint32_t count)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
|
||||
struct working_area *algo_working_area;
|
||||
struct working_area *buffer_working_area;
|
||||
struct reg_param reg_params[3];
|
||||
uint32_t algo_base_address;
|
||||
uint32_t algo_buffer_address;
|
||||
uint32_t algo_buffer_size;
|
||||
uint32_t address;
|
||||
uint32_t remaining;
|
||||
uint32_t words;
|
||||
uint32_t result;
|
||||
|
||||
int retval = ERROR_OK;
|
||||
|
||||
if (TARGET_HALTED != target->state) {
|
||||
LOG_ERROR("Target not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* Obtain working area to use for flash helper algorithm */
|
||||
retval = target_alloc_working_area(target, sizeof(cc3220sf_algo),
|
||||
&algo_working_area);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
/* Obtain working area to use for flash buffer */
|
||||
retval = target_alloc_working_area(target,
|
||||
target_get_working_area_avail(target), &buffer_working_area);
|
||||
if (ERROR_OK != retval) {
|
||||
target_free_working_area(target, algo_working_area);
|
||||
return retval;
|
||||
}
|
||||
|
||||
algo_base_address = algo_working_area->address;
|
||||
algo_buffer_address = buffer_working_area->address;
|
||||
algo_buffer_size = buffer_working_area->size;
|
||||
|
||||
/* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
|
||||
/* (algo runs more efficiently if it operates on 32 words at a time) */
|
||||
if (algo_buffer_size > 0x80)
|
||||
algo_buffer_size &= ~0x7f;
|
||||
|
||||
/* Write flash helper algorithm into target memory */
|
||||
retval = target_write_buffer(target, algo_base_address,
|
||||
sizeof(cc3220sf_algo), cc3220sf_algo);
|
||||
if (ERROR_OK != retval) {
|
||||
target_free_working_area(target, algo_working_area);
|
||||
target_free_working_area(target, buffer_working_area);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Initialize the ARMv7m specific info to run the algorithm */
|
||||
cc3220sf_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||
cc3220sf_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
|
||||
|
||||
/* Initialize register params for flash helper algorithm */
|
||||
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
|
||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
||||
init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
|
||||
|
||||
/* Prepare to write to flash */
|
||||
address = FLASH_BASE_ADDR + offset;
|
||||
remaining = count;
|
||||
|
||||
/* The flash hardware can only write complete words to flash. If
|
||||
* an unaligned address is passed in, we must do a read-modify-write
|
||||
* on a word with enough bytes to align the rest of the buffer. And
|
||||
* if less than a whole word remains at the end, we must also do a
|
||||
* read-modify-write on a final word to finish up.
|
||||
*/
|
||||
|
||||
/* Do one word write to align address on 32-bit boundary if needed */
|
||||
if (0 != (address & 0x3)) {
|
||||
uint8_t head[4];
|
||||
|
||||
/* Get starting offset for data to write (will be 1 to 3) */
|
||||
uint32_t head_offset = address & 0x03;
|
||||
|
||||
/* Get the aligned address to write this first word to */
|
||||
uint32_t head_address = address & 0xfffffffc;
|
||||
|
||||
/* Retrieve what is already in flash at the head address */
|
||||
retval = target_read_buffer(target, head_address, sizeof(head), head);
|
||||
|
||||
if (ERROR_OK == retval) {
|
||||
/* Substitute in the new data to write */
|
||||
while ((remaining > 0) && (head_offset < 4)) {
|
||||
head[head_offset] = *buffer;
|
||||
head_offset++;
|
||||
address++;
|
||||
buffer++;
|
||||
remaining--;
|
||||
}
|
||||
}
|
||||
|
||||
if (ERROR_OK == retval) {
|
||||
/* Helper parameters are passed in registers R0-R2 */
|
||||
/* Set start of data buffer, address to write to, and word count */
|
||||
buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, head_address);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, 1);
|
||||
|
||||
/* Write head value into buffer to flash */
|
||||
retval = target_write_buffer(target, algo_buffer_address,
|
||||
sizeof(head), head);
|
||||
}
|
||||
|
||||
if (ERROR_OK == retval) {
|
||||
/* Execute the flash helper algorithm */
|
||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||
algo_base_address, 0, FLASH_TIMEOUT,
|
||||
&cc3220sf_bank->armv7m_info);
|
||||
if (ERROR_OK != retval)
|
||||
LOG_ERROR("cc3220sf: Flash algorithm failed to run");
|
||||
|
||||
/* Check that the head value was written to flash */
|
||||
result = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
if (0 != result) {
|
||||
retval = ERROR_FAIL;
|
||||
LOG_ERROR("cc3220sf: Flash operation failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if there's data at end of buffer that isn't a full word */
|
||||
uint32_t tail_count = remaining & 0x03;
|
||||
/* Adjust remaining so it is a multiple of whole words */
|
||||
remaining -= tail_count;
|
||||
|
||||
while ((ERROR_OK == retval) && (remaining > 0)) {
|
||||
/* Set start of data buffer and address to write to */
|
||||
buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||
|
||||
/* Download data to write into memory buffer */
|
||||
if (remaining >= algo_buffer_size) {
|
||||
/* Fill up buffer with data to flash */
|
||||
retval = target_write_buffer(target, algo_buffer_address,
|
||||
algo_buffer_size, buffer);
|
||||
if (ERROR_OK != retval)
|
||||
break;
|
||||
|
||||
/* Count to write is in 32-bit words */
|
||||
words = algo_buffer_size / 4;
|
||||
|
||||
/* Bump variables to next data */
|
||||
address += algo_buffer_size;
|
||||
buffer += algo_buffer_size;
|
||||
remaining -= algo_buffer_size;
|
||||
} else {
|
||||
/* Fill buffer with what's left of the data */
|
||||
retval = target_write_buffer(target, algo_buffer_address,
|
||||
remaining, buffer);
|
||||
if (ERROR_OK != retval)
|
||||
break;
|
||||
|
||||
/* Calculate the final word count to write */
|
||||
words = remaining / 4;
|
||||
if (0 != (remaining % 4))
|
||||
words++;
|
||||
|
||||
/* Bump variables to any final data */
|
||||
address += remaining;
|
||||
buffer += remaining;
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
/* Set number of words to write */
|
||||
buf_set_u32(reg_params[2].value, 0, 32, words);
|
||||
|
||||
/* Execute the flash helper algorithm */
|
||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||
algo_base_address, 0, FLASH_TIMEOUT,
|
||||
&cc3220sf_bank->armv7m_info);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("cc3220sf: Flash algorithm failed to run");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that all words were written to flash */
|
||||
result = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
if (0 != result) {
|
||||
retval = ERROR_FAIL;
|
||||
LOG_ERROR("cc3220sf: Flash operation failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do one word write for any final bytes less than a full word */
|
||||
if ((ERROR_OK == retval) && (0 != tail_count)) {
|
||||
uint8_t tail[4];
|
||||
|
||||
/* Set starting byte offset for data to write */
|
||||
uint32_t tail_offset = 0;
|
||||
|
||||
/* Retrieve what is already in flash at the tail address */
|
||||
retval = target_read_buffer(target, address, sizeof(tail), tail);
|
||||
|
||||
if (ERROR_OK == retval) {
|
||||
/* Substitute in the new data to write */
|
||||
while (tail_count > 0) {
|
||||
tail[tail_offset] = *buffer;
|
||||
tail_offset++;
|
||||
buffer++;
|
||||
tail_count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (ERROR_OK == retval) {
|
||||
/* Set start of data buffer, address to write to, and word count */
|
||||
buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, 1);
|
||||
|
||||
/* Write tail value into buffer to flash */
|
||||
retval = target_write_buffer(target, algo_buffer_address,
|
||||
sizeof(tail), tail);
|
||||
}
|
||||
|
||||
if (ERROR_OK == retval) {
|
||||
/* Execute the flash helper algorithm */
|
||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||
algo_base_address, 0, FLASH_TIMEOUT,
|
||||
&cc3220sf_bank->armv7m_info);
|
||||
if (ERROR_OK != retval)
|
||||
LOG_ERROR("cc3220sf: Flash algorithm failed to run");
|
||||
|
||||
/* Check that the tail was written to flash */
|
||||
result = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
if (0 != result) {
|
||||
retval = ERROR_FAIL;
|
||||
LOG_ERROR("cc3220sf: Flash operation failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free resources */
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
destroy_reg_param(®_params[2]);
|
||||
target_free_working_area(target, algo_working_area);
|
||||
target_free_working_area(target, buffer_working_area);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int cc3220sf_probe(struct flash_bank *bank)
|
||||
{
|
||||
struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
|
||||
|
||||
uint32_t base;
|
||||
uint32_t size;
|
||||
int num_sectors;
|
||||
int bank_id;
|
||||
|
||||
bank_id = bank->bank_number;
|
||||
|
||||
if (0 == bank_id) {
|
||||
base = FLASH_BASE_ADDR;
|
||||
size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE;
|
||||
num_sectors = FLASH_NUM_SECTORS;
|
||||
} else {
|
||||
/* Invalid bank number somehow */
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (NULL != bank->sectors) {
|
||||
free(bank->sectors);
|
||||
bank->sectors = NULL;
|
||||
}
|
||||
|
||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
|
||||
if (NULL == bank->sectors)
|
||||
return ERROR_FAIL;
|
||||
|
||||
bank->base = base;
|
||||
bank->size = size;
|
||||
bank->write_start_alignment = 0;
|
||||
bank->write_end_alignment = 0;
|
||||
bank->num_sectors = num_sectors;
|
||||
|
||||
for (int i = 0; i < num_sectors; i++) {
|
||||
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
|
||||
bank->sectors[i].size = FLASH_SECTOR_SIZE;
|
||||
bank->sectors[i].is_erased = -1;
|
||||
bank->sectors[i].is_protected = 0;
|
||||
}
|
||||
|
||||
/* We've successfully recorded the stats on this flash bank */
|
||||
cc3220sf_bank->probed = true;
|
||||
|
||||
/* If we fall through to here, then all went well */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int cc3220sf_auto_probe(struct flash_bank *bank)
|
||||
{
|
||||
struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
|
||||
|
||||
int retval = ERROR_OK;
|
||||
|
||||
if (0 != bank->bank_number) {
|
||||
/* Invalid bank number somehow */
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (!cc3220sf_bank->probed)
|
||||
retval = cc3220sf_probe(bank);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int cc3220sf_protect_check(struct flash_bank *bank)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int cc3220sf_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||
{
|
||||
int printed;
|
||||
|
||||
printed = snprintf(buf, buf_size, "CC3220SF with 1MB internal flash\n");
|
||||
|
||||
if (printed >= buf_size)
|
||||
return ERROR_BUF_TOO_SMALL;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
struct flash_driver cc3220sf_flash = {
|
||||
.name = "cc3220sf",
|
||||
.flash_bank_command = cc3220sf_flash_bank_command,
|
||||
.erase = cc3220sf_erase,
|
||||
.protect = cc3220sf_protect,
|
||||
.write = cc3220sf_write,
|
||||
.read = default_flash_read,
|
||||
.probe = cc3220sf_probe,
|
||||
.auto_probe = cc3220sf_auto_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = cc3220sf_protect_check,
|
||||
.info = cc3220sf_info,
|
||||
.free_driver_priv = default_flash_free_driver_priv,
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2017 by Texas Instruments, Inc. *
|
||||
* *
|
||||
* 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 2 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/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_FLASH_NOR_CC3220SF_H
|
||||
#define OPENOCD_FLASH_NOR_CC3220SF_H
|
||||
|
||||
/* CC3220SF device types */
|
||||
#define CC3220_NO_TYPE 0 /* Device type not determined yet */
|
||||
#define CC3220_OTHER 1 /* CC3220 variant without flash */
|
||||
#define CC3220SF 2 /* CC3220SF variant with flash */
|
||||
|
||||
/* Flash parameters */
|
||||
#define FLASH_BASE_ADDR 0x01000000
|
||||
#define FLASH_SECTOR_SIZE 2048
|
||||
#define FLASH_NUM_SECTORS 512
|
||||
|
||||
/* CC2200SF flash registers */
|
||||
#define FMA_REGISTER_ADDR 0x400FD000
|
||||
#define FMC_REGISTER_ADDR 0x400FD008
|
||||
#define FMC_DEFAULT_VALUE 0xA4420000
|
||||
#define FMC_ERASE_BIT 0x00000002
|
||||
#define FMC_MERASE_BIT 0x00000004
|
||||
#define FMC_ERASE_VALUE (FMC_DEFAULT_VALUE | FMC_ERASE_BIT)
|
||||
#define FMC_MERASE_VALUE (FMC_DEFAULT_VALUE | FMC_MERASE_BIT)
|
||||
|
||||
/* Flash helper algorithm for CC3220SF */
|
||||
const uint8_t cc3220sf_algo[] = {
|
||||
#include "../../../contrib/loaders/flash/cc3220sf/cc3220sf.inc"
|
||||
};
|
||||
|
||||
#endif /* OPENOCD_FLASH_NOR_CC3220SF_H */
|
||||
+10
-2
@@ -188,9 +188,17 @@ void flash_free_all_banks(void)
|
||||
else
|
||||
LOG_WARNING("Flash driver of %s does not support free_driver_priv()", bank->name);
|
||||
|
||||
/* For 'virtual' flash driver bank->sectors and bank->prot_blocks pointers are copied from
|
||||
* master flash_bank structure. They point to memory locations allocated by master flash driver
|
||||
* so master driver is responsible for releasing them.
|
||||
* Avoid UB caused by double-free memory corruption if flash bank is 'virtual'. */
|
||||
|
||||
if (strcmp(bank->driver->name, "virtual") != 0) {
|
||||
free(bank->sectors);
|
||||
free(bank->prot_blocks);
|
||||
}
|
||||
|
||||
free(bank->name);
|
||||
free(bank->sectors);
|
||||
free(bank->prot_blocks);
|
||||
free(bank);
|
||||
bank = next;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ extern struct flash_driver ath79_flash;
|
||||
extern struct flash_driver atsamv_flash;
|
||||
extern struct flash_driver avr_flash;
|
||||
extern struct flash_driver bluenrgx_flash;
|
||||
extern struct flash_driver cc3220sf_flash;
|
||||
extern struct flash_driver cfi_flash;
|
||||
extern struct flash_driver dsp5680xx_flash;
|
||||
extern struct flash_driver efm32_flash;
|
||||
@@ -56,6 +57,9 @@ extern struct flash_driver numicro_flash;
|
||||
extern struct flash_driver ocl_flash;
|
||||
extern struct flash_driver pic32mx_flash;
|
||||
extern struct flash_driver psoc4_flash;
|
||||
extern struct flash_driver psoc5lp_flash;
|
||||
extern struct flash_driver psoc5lp_eeprom_flash;
|
||||
extern struct flash_driver psoc5lp_nvl_flash;
|
||||
extern struct flash_driver psoc6_flash;
|
||||
extern struct flash_driver sim3x_flash;
|
||||
extern struct flash_driver stellaris_flash;
|
||||
@@ -91,6 +95,7 @@ static struct flash_driver *flash_drivers[] = {
|
||||
&atsamv_flash,
|
||||
&avr_flash,
|
||||
&bluenrgx_flash,
|
||||
&cc3220sf_flash,
|
||||
&cfi_flash,
|
||||
&dsp5680xx_flash,
|
||||
&efm32_flash,
|
||||
@@ -115,6 +120,9 @@ static struct flash_driver *flash_drivers[] = {
|
||||
&ocl_flash,
|
||||
&pic32mx_flash,
|
||||
&psoc4_flash,
|
||||
&psoc5lp_flash,
|
||||
&psoc5lp_eeprom_flash,
|
||||
&psoc5lp_nvl_flash,
|
||||
&psoc6_flash,
|
||||
&sim3x_flash,
|
||||
&stellaris_flash,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,8 +46,13 @@ static void virtual_update_bank_info(struct flash_bank *bank)
|
||||
bank->bus_width = master_bank->bus_width;
|
||||
bank->erased_value = master_bank->erased_value;
|
||||
bank->default_padded_value = master_bank->default_padded_value;
|
||||
bank->write_start_alignment = master_bank->write_start_alignment;
|
||||
bank->write_end_alignment = master_bank->write_end_alignment;
|
||||
bank->minimal_write_gap = master_bank->minimal_write_gap;
|
||||
bank->num_sectors = master_bank->num_sectors;
|
||||
bank->sectors = master_bank->sectors;
|
||||
bank->num_prot_blocks = master_bank->num_prot_blocks;
|
||||
bank->prot_blocks = master_bank->prot_blocks;
|
||||
}
|
||||
|
||||
FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
|
||||
|
||||
Reference in New Issue
Block a user