This is an automated email from Gerrit.

Michele Sardo ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/4226

-- gerrit

commit 7ca456cd7426e10df49138c15344607fd5b7a71a
Author: Michele Sardo <[email protected]>
Date:   Tue Sep 12 08:51:29 2017 +0200

    Added support for STMicroelectronics BlueNRG-1 and BlueNRG-2 SoC
    
    Added configuration files and flash loaders.
    
    Change-Id: I768eb3626f4e0eadb206bef90a867cc146fe8c75
    Signed-off-by: Michele Sardo <[email protected]>

diff --git a/contrib/loaders/flash/bluenrg-x/Makefile 
b/contrib/loaders/flash/bluenrg-x/Makefile
new file mode 100644
index 0000000..1a5cfc0
--- /dev/null
+++ b/contrib/loaders/flash/bluenrg-x/Makefile
@@ -0,0 +1,27 @@
+BIN2C = ../../../../src/helper/bin2char.sh
+
+CROSS_COMPILE ?= arm-none-eabi-
+
+CC=$(CROSS_COMPILE)gcc
+OBJCOPY=$(CROSS_COMPILE)objcopy
+OBJDUMP=$(CROSS_COMPILE)objdump
+
+CFLAGS =  -c -mthumb -mcpu=cortex-m0 -O3 -g
+
+all: bluenrg-x_write.inc
+
+.PHONY: clean
+
+.INTERMEDIATE: bluenrg-x_write.o
+
+%.o: %.c
+       $(CC) $(CFLAGS) -Wall -Wextra -Wa,-adhln=$*.lst $< -o $@
+
+%.bin: %.o
+       $(OBJCOPY) -Obinary $< $@
+
+%.inc: %.bin
+       $(BIN2C) < $< > $@
+
+clean:
+       -rm -f *.o *.lst *.bin *.inc
diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c 
b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
new file mode 100644
index 0000000..13a4c7d
--- /dev/null
+++ b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
@@ -0,0 +1,138 @@
+/* To be built with arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m0 -O3 
bluenrgx.c */
+/* Then postprocess output of command "arm-none-eabi-objdump -d bluenrgx.o" to 
make a C array of bytes */
+
+#include <stdint.h>
+
+/* Status Values ----------------------------------------------------------*/
+#define SUCCESS             0
+#define ERR_UNALIGNED       1
+#define ERR_INVALID_ADDRESS 2
+#define ERR_INVALID_TYPE    3
+#define ERR_WRITE_PROTECTED 4
+#define ERR_WRITE_FAILED    5
+#define ERR_ERASE_REQUIRED  6
+#define ERR_VERIFY_FAILED   7
+
+/* Flash Controller defines 
---------------------------------------------------*/
+#define FLASH_REG_COMMAND ((volatile uint32_t *)0x40100000)
+#define FLASH_REG_CONFIG  ((volatile uint32_t *)0x40100004)
+#define FLASH_REG_IRQSTAT ((volatile uint32_t *)0x40100008)
+#define FLASH_REG_IRQMASK ((volatile uint32_t *)0x4010000C)
+#define FLASH_REG_IRQRAW  ((volatile uint32_t *)0x40100010)
+#define FLASH_REG_ADDRESS ((volatile uint32_t *)0x40100018)
+#define FLASH_REG_UNLOCKM ((volatile uint32_t *)0x4010001C)
+#define FLASH_REG_UNLOCKL ((volatile uint32_t *)0x40100020)
+#define FLASH_REG_DATA0    ((volatile uint32_t *)0x40100040)
+#define FLASH_REG_DATA1    ((volatile uint32_t *)0x40100044)
+#define FLASH_REG_DATA2    ((volatile uint32_t *)0x40100048)
+#define FLASH_REG_DATA3    ((volatile uint32_t *)0x4010004C)
+#define FLASH_SIZE_REG 0x40100014
+
+#define MFB_MASS_ERASE 0x01
+#define MFB_PAGE_ERASE 0x02
+
+#define DO_ERASE  0x0100
+#define DO_VERIFY 0x0200
+#define FLASH_CMD_ERASE_PAGE 0x11
+#define FLASH_CMD_MASSERASE  0x22
+#define FLASH_CMD_WRITE      0x33
+#define FLASH_CMD_BURSTWRITE 0xCC
+#define FLASH_INT_CMDDONE    0x01
+#define MFB_BOTTOM          (0x10040000)
+#define MFB_SIZE_B          ((16 * (((*(uint32_t *) FLASH_SIZE_REG) + 1) >> 
12)) * 1024)
+#define MFB_SIZE_W          (MFB_SIZE_B/4)
+#define MFB_TOP             (MFB_BOTTOM+MFB_SIZE_B-1)
+#define MFB_PAGE_SIZE_B     (2048)
+#define MFB_PAGE_SIZE_W     (MFB_PAGE_SIZE_B/4)
+
+#define AREA_ERROR 0x01
+#define AREA_MFB   0x04
+
+#define FLASH_WORD_LEN       4
+
+typedef struct {
+       volatile uint8_t *wp;
+       uint8_t *rp;
+} work_area_t;
+
+/* Flash Commands --------------------------------------------------------*/
+static inline __attribute__((always_inline)) uint32_t flashWrite(uint32_t 
address, uint8_t **data,
+                                                                uint32_t 
writeLength)
+{
+       uint32_t index, flash_word[4];
+       uint8_t i;
+
+       *FLASH_REG_IRQMASK = 0;
+       for (index = 0; index < writeLength; index += (FLASH_WORD_LEN*4)) {
+               for (i = 0; i < 4; i++)
+                       flash_word[i] = (*(uint32_t *) (*data + i*4));
+
+               /* Clear the IRQ flags */
+               *FLASH_REG_IRQRAW = 0x0000003F;
+               /* Load the flash address to write */
+               *FLASH_REG_ADDRESS = (uint16_t)((address + index) >> 2);
+               /* Prepare and load the data to flash */
+               *FLASH_REG_DATA0 = flash_word[0];
+               *FLASH_REG_DATA1 = flash_word[1];
+               *FLASH_REG_DATA2 = flash_word[2];
+               *FLASH_REG_DATA3 = flash_word[3];
+               /* Flash write command */
+               *FLASH_REG_COMMAND = FLASH_CMD_BURSTWRITE;
+               /* Wait the end of the flash write command */
+               while ((*FLASH_REG_IRQRAW & FLASH_INT_CMDDONE) == 0)
+                       ;
+               /* Verify if the data is written in a correct way */
+
+               for (i = 0; i < 4; i++) {
+                       if (*((uint32_t *)(address + index + (i * 4))) != 
flash_word[i])
+                               return ERR_WRITE_FAILED;
+               }
+               *data += (FLASH_WORD_LEN * 4);
+       }
+
+       return SUCCESS;
+}
+
+__attribute__((naked)) __attribute__((noreturn)) void write(uint8_t 
*work_area_p,
+                                                           uint8_t *fifo_end,
+                                                           uint8_t 
*target_address,
+                                                           uint32_t count)
+{
+       uint32_t retval;
+       volatile work_area_t *work_area = (work_area_t *) work_area_p;
+       uint8_t *fifo_start = (uint8_t *) work_area->rp;
+
+       while (count) {
+               volatile int32_t fifo_linear_size;
+
+               /* Wait for some data in the FIFO */
+               while (work_area->rp == work_area->wp)
+                       ;
+               if (work_area->wp == 0) {
+                       /* Aborted by other party */
+                       break;
+               }
+               if (work_area->rp > work_area->wp) {
+                       fifo_linear_size = fifo_end-work_area->rp;
+               } else {
+                       fifo_linear_size = (work_area->wp - work_area->rp);
+                       if (fifo_linear_size < 0)
+                               fifo_linear_size = 0;
+               }
+               if (fifo_linear_size < 16) {
+                       /* We should never get here */
+                       continue;
+               }
+
+               retval = flashWrite((uint32_t) target_address, (uint8_t **) 
&work_area->rp, fifo_linear_size);
+               if (retval) {
+                       work_area->rp = (uint8_t *)retval;
+                       break;
+               }
+               target_address += fifo_linear_size;
+               if (work_area->rp >= fifo_end)
+                       work_area->rp = fifo_start;
+               count -= fifo_linear_size;
+       }
+       __asm("bkpt 0");
+}
diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc 
b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc
new file mode 100644
index 0000000..50421e2
--- /dev/null
+++ b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc
@@ -0,0 +1,20 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x07,0x00,0x06,0x93,0x43,0x68,0x42,0x4e,0x09,0x93,0x06,0x9b,0x08,0x91,0x07,0x92,
+0x00,0x2b,0x7b,0xd0,0x7a,0x68,0x3b,0x68,0x9a,0x42,0xfb,0xd0,0x3b,0x68,0x00,0x2b,
+0x74,0xd0,0x7a,0x68,0x3b,0x68,0x9a,0x42,0x63,0xd9,0x7b,0x68,0x08,0x9a,0xd3,0x1a,
+0x0b,0x93,0x0b,0x9b,0x0f,0x2b,0xed,0xdd,0x00,0x21,0x0b,0x9b,0x07,0x98,0x04,0x93,
+0x1a,0x1e,0x34,0x4b,0x19,0x60,0x43,0xd0,0x7b,0x68,0x01,0x22,0x05,0x93,0x19,0x00,
+0x31,0x4b,0x03,0x97,0x9c,0x46,0x31,0x4b,0x98,0x46,0x31,0x4b,0x9b,0x46,0x31,0x4b,
+0x9a,0x46,0x31,0x4b,0x99,0x46,0x8b,0x68,0x0c,0x68,0x01,0x93,0xcb,0x68,0x4d,0x68,
+0x02,0x93,0x3f,0x23,0x2d,0x4f,0x33,0x60,0x83,0x03,0x1b,0x0c,0x3b,0x60,0x67,0x46,
+0x3c,0x60,0x47,0x46,0x3d,0x60,0x5f,0x46,0x01,0x9b,0x3b,0x60,0x57,0x46,0x02,0x9b,
+0x3b,0x60,0xcc,0x27,0x4b,0x46,0x1f,0x60,0x01,0x9f,0x33,0x68,0x1a,0x42,0xfc,0xd0,
+0x03,0x68,0xa3,0x42,0x2f,0xd1,0x43,0x68,0xab,0x42,0x2c,0xd1,0x83,0x68,0x3c,0x00,
+0xbb,0x42,0x28,0xd1,0xc3,0x68,0x02,0x9c,0xa3,0x42,0x24,0xd1,0x03,0x9b,0x10,0x31,
+0x59,0x60,0x04,0x9c,0x05,0x9b,0x10,0x30,0xcb,0x1a,0x9c,0x42,0xcb,0xd8,0x03,0x9f,
+0x07,0x9a,0x0b,0x9b,0x94,0x46,0x9c,0x44,0x63,0x46,0x08,0x9a,0x07,0x93,0x7b,0x68,
+0x9a,0x42,0x01,0xd8,0x09,0x9b,0x7b,0x60,0x06,0x9a,0x0b,0x9b,0xd3,0x1a,0x06,0x93,
+0x8e,0xe7,0x3b,0x68,0x7a,0x68,0x9b,0x1a,0x0b,0x93,0x0b,0x9b,0x00,0x2b,0x98,0xda,
+0x00,0x23,0x0b,0x93,0x95,0xe7,0x05,0x23,0x03,0x9f,0x7b,0x60,0x00,0xbe,0xc0,0x46,
+0x10,0x00,0x10,0x40,0x0c,0x00,0x10,0x40,0x40,0x00,0x10,0x40,0x44,0x00,0x10,0x40,
+0x48,0x00,0x10,0x40,0x4c,0x00,0x10,0x40,0x00,0x00,0x10,0x40,0x18,0x00,0x10,0x40,
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 5a992fe..b4a037a 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -18,6 +18,7 @@ NOR_DRIVERS = \
        %D%/ath79.c \
        %D%/atsamv.c \
        %D%/avrf.c \
+       %D%/bluenrg-x.c \
        %D%/cfi.c \
        %D%/dsp5680xx_flash.c \
        %D%/efm32.c \
diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c
new file mode 100644
index 0000000..604397e
--- /dev/null
+++ b/src/flash/nor/bluenrg-x.c
@@ -0,0 +1,556 @@
+/***************************************************************************
+ *   Copyright (C) 2017 by Michele Sardo                                   *
+ *   [email protected]                                                    *
+ *                                                                         *
+ *   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 <target/algorithm.h>
+#include <target/armv7m.h>
+#include <target/cortex_m.h>
+#include "imp.h"
+
+#define FLASH_SIZE_REG       (0x40100014)
+#define DIE_ID_REG           (0x4090001C)
+#define JTAG_IDCODE_REG      (0x40900028)
+#define BLUENRG2_IDCODE      (0x0200A041)
+#define FLASH_BASE           (0x10040000)
+#define FLASH_PAGE_SIZE      (2048)
+#define FLASH_REG_COMMAND    (0x40100000)
+#define FLASH_REG_IRQRAW     (0x40100010)
+#define FLASH_REG_ADDRESS    (0x40100018)
+#define FLASH_REG_DATA       (0x40100040)
+#define FLASH_CMD_ERASE_PAGE 0x11
+#define FLASH_CMD_MASSERASE  0x22
+#define FLASH_CMD_WRITE      0x33
+#define FLASH_CMD_BURSTWRITE 0xCC
+#define FLASH_INT_CMDDONE    0x01
+#define FLASH_WORD_LEN       4
+
+struct bluenrgx_flash_bank {
+       int probed;
+       uint32_t idcode;
+       uint32_t die_id;
+};
+
+static int bluenrgx_protect_check(struct flash_bank *bank)
+{
+       /* Nothing to do. Protection is only handled in SW. */
+       return ERROR_OK;
+}
+
+/* flash_bank bluenrg-x 0 0 0 0 <target#> */
+FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
+{
+       struct bluenrgx_flash_bank *bluenrgx_info;
+       /* Create the bank structure */
+       bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
+
+       /* Check allocation */
+       if (bluenrgx_info == NULL) {
+               LOG_ERROR("failed to allocate bank structure");
+               return ERROR_FAIL;
+       }
+
+       bank->driver_priv = bluenrgx_info;
+
+       bluenrgx_info->probed = 0;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       return ERROR_OK;
+}
+
+static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
+{
+       int retval = ERROR_OK;
+       struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
+       int num_sectors = (last - first + 1);
+       int mass_erase = (num_sectors == bank->num_sectors);
+       struct target *target = bank->target;
+       uint32_t address, command;
+
+       /* check preconditions */
+       if (bluenrgx_info->probed == 0)
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       /* Disable blue module */
+       if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
+               LOG_ERROR("Blue disable failed");
+               return ERROR_FAIL;
+       }
+
+       if (mass_erase) {
+               command = FLASH_CMD_MASSERASE;
+               address = bank->base;
+               if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != 
ERROR_OK) {
+                       LOG_ERROR("Register write failed");
+                       return ERROR_FAIL;
+               }
+
+               if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) 
!= ERROR_OK) {
+                       LOG_ERROR("Register write failed");
+                       return ERROR_FAIL;
+               }
+
+               if (target_write_u32(target, FLASH_REG_COMMAND, command) != 
ERROR_OK) {
+                       LOG_ERROR("Register write failed");
+                       return ERROR_FAIL;
+               }
+
+               for (int i = 0; i < 100; i++) {
+                       uint32_t value;
+                       if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
+                               LOG_ERROR("Register write failed");
+                               return ERROR_FAIL;
+                       }
+                       if (value & FLASH_INT_CMDDONE)
+                               break;
+                       if (i == 99) {
+                               LOG_ERROR("Mass erase command failed 
(timeout)");
+                               retval = ERROR_FAIL;
+                       }
+               }
+
+       } else {
+               command = FLASH_CMD_ERASE_PAGE;
+               for (int i = first; i <= last; i++) {
+                       address = bank->base+i*FLASH_PAGE_SIZE;
+
+                       if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != 
ERROR_OK) {
+                               LOG_ERROR("Register write failed");
+                               return ERROR_FAIL;
+                       }
+
+                       if (target_write_u32(target, FLASH_REG_ADDRESS, address 
>> 2) != ERROR_OK) {
+                               LOG_ERROR("Register write failed");
+                               return ERROR_FAIL;
+                       }
+
+                       if (target_write_u32(target, FLASH_REG_COMMAND, 
command) != ERROR_OK) {
+                               LOG_ERROR("Failed");
+                               return ERROR_FAIL;
+                       }
+
+                       for (int j = 0; j < 100; j++) {
+                               uint32_t value;
+                               if (target_read_u32(target, FLASH_REG_IRQRAW, 
&value)) {
+                                       LOG_ERROR("Register write failed");
+                                       return ERROR_FAIL;
+                               }
+                               if (value & FLASH_INT_CMDDONE)
+                                       break;
+                               if (j == 99) {
+                                       LOG_ERROR("Erase command failed 
(timeout)");
+                                       retval = ERROR_FAIL;
+                               }
+                       }
+               }
+       }
+
+       return retval;
+
+}
+
+static int bluenrgx_protect(struct flash_bank *bank, int set, int first, int 
last)
+{
+       /* Protection is only handled in software: no hardware write protection
+          available in BlueNRG-x devices */
+       int sector;
+
+       for (sector = first; sector <= last; sector++)
+               bank->sectors[sector].is_protected = set;
+       return ERROR_OK;
+}
+static int bluenrgx_write_word(struct target *target, uint32_t address_base, 
uint32_t *values, uint32_t count)
+{
+       int retval = ERROR_OK;
+
+       retval = target_write_u32(target, FLASH_REG_IRQRAW, 0x3f);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Register write failed, error code: %d", retval);
+               return retval;
+       }
+
+       for (uint32_t i = 0; i < count; i++) {
+               uint32_t address = address_base + i * FLASH_WORD_LEN;
+               uint32_t read_back;
+
+               retval = target_write_u32(target, FLASH_REG_ADDRESS, address >> 
2);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Register write failed, error code: %d", 
retval);
+                       return retval;
+               }
+
+               retval = target_write_u32(target, FLASH_REG_DATA, values[i]);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Register write failed, error code: %d", 
retval);
+                       return retval;
+               }
+
+               retval = target_write_u32(target, FLASH_REG_COMMAND, 
FLASH_CMD_WRITE);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Register write failed, error code: %d", 
retval);
+                       return retval;
+               }
+
+               for (int j = 0; j < 100; j++) {
+                       uint32_t reg_value;
+                       retval = target_read_u32(target, FLASH_REG_IRQRAW, 
&reg_value);
+
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Register read failed, error code: 
%d", retval);
+                               return retval;
+                       }
+
+                       if (reg_value & FLASH_INT_CMDDONE)
+                               break;
+
+                       if (j == 99) {
+                               LOG_ERROR("Write command failed (timeout)");
+                               return ERROR_FAIL;
+                       }
+               }
+
+               retval = target_read_u32(target, address, &read_back);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Flash read failed, error code: %d", retval);
+                       return retval;
+               }
+
+               if (read_back != values[i]) {
+                       LOG_ERROR("Comparison failed: expected: %08x, got 
%08x", values[i], read_back);
+                       return ERROR_FAIL;
+               }
+       }
+       return retval;
+}
+
+static int bluenrgx_write_bytes(struct target *target, uint32_t address_base, 
uint8_t *buffer, uint32_t count)
+{
+       int retval = ERROR_OK;
+       uint8_t *new_buffer = NULL;
+       uint32_t pre_bytes = 0, post_bytes = 0, pre_word, post_word, 
pre_address, post_address;
+
+       if (address_base & 3) {
+               pre_bytes = address_base & 3;
+               pre_address = address_base - pre_bytes;
+       }
+
+       if ((count + pre_bytes) & 3) {
+               post_bytes = ((count + pre_bytes + 3) & ~3) - (count + 
pre_bytes);
+               post_address = (address_base + count) & ~3;
+       }
+
+       if (pre_bytes || post_bytes) {
+               uint32_t old_count = count;
+
+               count = old_count + pre_bytes + post_bytes;
+
+               new_buffer = malloc(count);
+
+               if (new_buffer == NULL) {
+                       LOG_ERROR("odd number of bytes to write and no memory "
+                                 "for padding buffer");
+                       return ERROR_FAIL;
+               }
+
+               LOG_INFO("Requested number of bytes to write and/or address not 
word aligned (%" PRIu32 "), extending to %"
+                        PRIu32 " ", old_count, count);
+
+               if (pre_bytes) {
+                       if (target_read_u32(target, pre_address, &pre_word)) {
+                               LOG_ERROR("Memory read failed");
+                               return ERROR_FAIL;
+                       }
+
+               }
+
+               if (post_bytes) {
+                       if (target_read_u32(target, post_address, &post_word)) {
+                               LOG_ERROR("Memory read failed");
+                               return ERROR_FAIL;
+                       }
+
+               }
+
+               memcpy(new_buffer, &pre_word, pre_bytes);
+               memcpy((new_buffer+((pre_bytes+old_count) & ~3)), &post_word, 
4);
+               memcpy(new_buffer+pre_bytes, buffer, old_count);
+               buffer = new_buffer;
+       }
+
+       retval = bluenrgx_write_word(target, address_base - pre_bytes, 
(uint32_t *) buffer, count/4);
+
+       if (new_buffer)
+               free(new_buffer);
+
+       return retval;
+}
+
+static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
+                         uint32_t offset, uint32_t count)
+{
+       struct target *target = bank->target;
+       uint32_t buffer_size = 16384 + 8;
+       struct working_area *write_algorithm;
+       struct working_area *write_algorithm_sp;
+       struct working_area *source;
+       uint32_t address = bank->base + offset;
+       struct reg_param reg_params[5];
+       struct armv7m_algorithm armv7m_info;
+       int retval = ERROR_OK;
+       uint32_t pre_size = 0, fast_size = 0, post_size = 0;
+       uint32_t pre_offset = 0, fast_offset = 0, post_offset = 0;
+
+       /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
+        * hints how to generate the data!
+        */
+       static const uint8_t bluenrgx_flash_write_code[] = {
+#include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
+       };
+
+       if ((offset + count) > bank->size) {
+               LOG_ERROR("Requested write past beyond of flash size: 
(offset+count) = %d, size=%d",
+                         (offset + count),
+                         bank->size);
+               return ERROR_FLASH_DST_OUT_OF_BANK;
+       }
+
+       if (bank->target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* We are good here and we need to compute pre_size, fast_size, 
post_size */
+       pre_size  = MIN(count, ((offset+0xF) & ~0xF) - offset);
+       pre_offset = offset;
+       fast_size = 16*((count - pre_size) / 16);
+       fast_offset = offset + pre_size;
+       post_size = (count-pre_size-fast_size) % 16;
+       post_offset = fast_offset + fast_size;
+
+       LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size, pre_offset);
+       LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size, fast_offset);
+       LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size, post_offset);
+
+       /* Program initial chunk not 16 bytes aligned */
+       retval = bluenrgx_write_bytes(target, bank->base+pre_offset, (uint8_t 
*) buffer, pre_size);
+       if (retval) {
+               LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
+               return ERROR_FAIL;
+       }
+
+       /* Program chunk 16 bytes aligned in fast mode */
+       if (fast_size) {
+
+               if (target_alloc_working_area(target, 
sizeof(bluenrgx_flash_write_code),
+                                             &write_algorithm) != ERROR_OK) {
+                       LOG_WARNING("no working area available, can't do block 
memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+
+               retval = target_write_buffer(target, write_algorithm->address,
+                                            sizeof(bluenrgx_flash_write_code),
+                                            bluenrgx_flash_write_code);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* memory buffer */
+               if (target_alloc_working_area(target, buffer_size, &source)) {
+                       LOG_WARNING("no large enough working area available");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+
+               /* Stack pointer area */
+               if (target_alloc_working_area(target, 64,
+                                             &write_algorithm_sp) != ERROR_OK) 
{
+                       LOG_DEBUG("no working area for write code stack 
pointer");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+
+               armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+               armv7m_info.core_mode = ARM_MODE_THREAD;
+
+               init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
+               init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+               init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+               init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
+               init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
+
+               /* FIFO start address (first two words used for write and read 
pointers) */
+               buf_set_u32(reg_params[0].value, 0, 32, source->address);
+               /* FIFO end address (first two words used for write and read 
pointers) */
+               buf_set_u32(reg_params[1].value, 0, 32, source->address + 
source->size);
+               /* Flash memory address */
+               buf_set_u32(reg_params[2].value, 0, 32, address+pre_size);
+               /* Number of bytes */
+               buf_set_u32(reg_params[3].value, 0, 32, fast_size);
+               /* Stack pointer for program working area */
+               buf_set_u32(reg_params[4].value, 0, 32, 
write_algorithm_sp->address);
+
+               LOG_DEBUG("source->address = %08lx", source->address);
+               LOG_DEBUG("source->address+ source->size = %08lx", 
source->address+source->size);
+               LOG_DEBUG("write_algorithm_sp->address = %08lx", 
write_algorithm_sp->address);
+               LOG_DEBUG("address = %08x", address+pre_size);
+               LOG_DEBUG("count = %08x", count);
+
+               retval = target_run_flash_async_algorithm(target,
+                                                         buffer+pre_size,
+                                                         fast_size/16,
+                                                         16, /* Block size: we 
write in block of 16 bytes to enjoy burstwrite speed */
+                                                         0,
+                                                         NULL,
+                                                         5,
+                                                         reg_params,
+                                                         source->address,
+                                                         source->size,
+                                                         
write_algorithm->address,
+                                                         0,
+                                                         &armv7m_info);
+
+               if (retval == ERROR_FLASH_OPERATION_FAILED) {
+                       LOG_ERROR("error executing bluenrg-x flash write 
algorithm");
+
+                       uint32_t error = buf_get_u32(reg_params[0].value, 0, 
32);
+
+                       if (error != 0)
+                               LOG_ERROR("flash write failed = %08" PRIx32, 
error);
+               }
+               if (retval == ERROR_OK) {
+                       uint32_t rp;
+                       /* Read back rp and check that is valid */
+                       retval = target_read_u32(target, source->address+4, 
&rp);
+                       if (retval == ERROR_OK) {
+                               if ((rp < source->address+8) || (rp > 
(source->address + source->size))) {
+                                       LOG_ERROR("flash write failed = %08" 
PRIx32, rp);
+                                       retval = ERROR_FLASH_OPERATION_FAILED;
+                               }
+                       }
+               }
+               target_free_working_area(target, source);
+               target_free_working_area(target, write_algorithm);
+               target_free_working_area(target, write_algorithm_sp);
+
+               destroy_reg_param(&reg_params[0]);
+               destroy_reg_param(&reg_params[1]);
+               destroy_reg_param(&reg_params[2]);
+               destroy_reg_param(&reg_params[3]);
+               destroy_reg_param(&reg_params[4]);
+       }
+
+       /* Program chunk at end, not addressable by fast burst write algorithm 
*/
+       retval = bluenrgx_write_bytes(target, bank->base+post_offset, (uint8_t 
*) (buffer+pre_size+fast_size), post_size);
+       if (retval) {
+               LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
+               return ERROR_FAIL;
+       }
+       return retval;
+}
+
+static int bluenrgx_probe(struct flash_bank *bank)
+{
+       struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
+       uint32_t idcode, size_info, die_id;
+       int i;
+       int retval = target_read_u32(bank->target, JTAG_IDCODE_REG, &idcode);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = target_read_u32(bank->target, FLASH_SIZE_REG, &size_info);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = target_read_u32(bank->target, DIE_ID_REG, &die_id);
+       if (retval != ERROR_OK)
+               return retval;
+
+       bank->size = (size_info + 1) * 4;
+       bank->base = FLASH_BASE;
+       bank->num_sectors = bank->size/FLASH_PAGE_SIZE;
+       bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * 
bank->num_sectors);
+
+       for (i = 0; i < bank->num_sectors; i++) {
+               bank->sectors[i].offset = i * FLASH_PAGE_SIZE;
+               bank->sectors[i].size = FLASH_PAGE_SIZE;
+               bank->sectors[i].is_erased = -1;
+               bank->sectors[i].is_protected = 0;
+       }
+
+       bluenrgx_info->probed = 1;
+       bluenrgx_info->die_id = die_id;
+       bluenrgx_info->idcode = idcode;
+       return ERROR_OK;
+}
+
+static int bluenrgx_auto_probe(struct flash_bank *bank)
+{
+       struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
+
+       if (bluenrgx_info->probed)
+               return ERROR_OK;
+
+       return bluenrgx_probe(bank);
+}
+
+/* This method must return a string displaying information about the bank */
+static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+       struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
+       int mask_number, cut_number;
+       char *part_name;
+
+       if (!bluenrgx_info->probed) {
+               int retval = bluenrgx_probe(bank);
+               if (retval != ERROR_OK) {
+                       snprintf(buf, buf_size,
+                                "Unable to find bank information.");
+                       return retval;
+               }
+       }
+
+       if (bluenrgx_info->idcode == BLUENRG2_IDCODE)
+               part_name = "BLUENRG-2";
+       else
+               part_name = "BLUENRG-1";
+
+       mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
+       cut_number = bluenrgx_info->die_id & 0xF;
+
+       snprintf(buf, buf_size,
+                "%s - Rev: %d.%d", part_name, mask_number, cut_number);
+       return ERROR_OK;
+}
+
+struct flash_driver bluenrgx_flash = {
+       .name = "bluenrg-x",
+       .flash_bank_command = bluenrgx_flash_bank_command,
+       .erase = bluenrgx_erase,
+       .protect = bluenrgx_protect,
+       .write = bluenrgx_write,
+       .read = default_flash_read,
+       .probe = bluenrgx_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = bluenrgx_protect_check,
+       .auto_probe = bluenrgx_auto_probe,
+       .info = bluenrgx_get_info,
+};
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 4ad1d92..35deeb2 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -31,6 +31,7 @@ extern struct flash_driver at91samd_flash;
 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 cfi_flash;
 extern struct flash_driver dsp5680xx_flash;
 extern struct flash_driver efm32_flash;
@@ -84,6 +85,7 @@ static struct flash_driver *flash_drivers[] = {
        &ath79_flash,
        &atsamv_flash,
        &avr_flash,
+       &bluenrgx_flash,
        &cfi_flash,
        &dsp5680xx_flash,
        &efm32_flash,
diff --git a/tcl/board/steval-idb007v1.cfg b/tcl/board/steval-idb007v1.cfg
new file mode 100644
index 0000000..24dbd1e
--- /dev/null
+++ b/tcl/board/steval-idb007v1.cfg
@@ -0,0 +1,4 @@
+# This is an evaluation board with a single BlueNRG-1 chip.
+# 
http://www.st.com/content/st_com/en/products/evaluation-tools/solution-evaluation-tools/communication-and-connectivity-solution-eval-boards/steval-idb008v1.html
+set CHIPNAME bluenrg-1
+source [find target/bluenrg-x.cfg]
diff --git a/tcl/board/steval-idb008v1.cfg b/tcl/board/steval-idb008v1.cfg
new file mode 100644
index 0000000..3e9d0e5
--- /dev/null
+++ b/tcl/board/steval-idb008v1.cfg
@@ -0,0 +1,4 @@
+# This is an evaluation board with a single BlueNRG-2 chip.
+# 
http://www.st.com/content/st_com/en/products/evaluation-tools/solution-evaluation-tools/communication-and-connectivity-solution-eval-boards/steval-idb007v1.html
+set CHIPNAME bluenrg-2
+source [find target/bluenrg-x.cfg]
diff --git a/tcl/target/bluenrg-x.cfg b/tcl/target/bluenrg-x.cfg
new file mode 100644
index 0000000..3ae5108
--- /dev/null
+++ b/tcl/target/bluenrg-x.cfg
@@ -0,0 +1,73 @@
+#
+# bluenrg-1/2 devices support only SWD transports.
+#
+
+source [find target/swj-dp.tcl]
+
+if { [info exists CHIPNAME] } {
+   set _CHIPNAME $CHIPNAME
+} else {
+   set _CHIPNAME bluenrg-1
+}
+
+set _ENDIAN little
+
+# Work-area is a space in RAM used for flash programming
+# By default use 24kB-256bytes
+if { [info exists WORKAREASIZE] } {
+   set _WORKAREASIZE $WORKAREASIZE
+} else {
+   set _WORKAREASIZE 0x5F00
+}
+
+adapter_khz 4000
+
+if { [info exists CPUTAPID] } {
+   set _CPUTAPID $CPUTAPID
+} else {
+   set _CPUTAPID 0x0bb11477
+}
+
+swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
+
+set _TARGETNAME $_CHIPNAME.cpu
+set WDOG_VALUE 0
+set WDOG_VALUE_SET 0
+
+target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position 
$_TARGETNAME
+
+$_TARGETNAME configure -work-area-phys 0x20000100 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+# flash size will be probed
+set _FLASHNAME $_CHIPNAME.flash
+flash bank $_FLASHNAME bluenrg-x 0 0 0 0 $_TARGETNAME
+
+# In BlueNRG-X reset pin is actually a shutdown (power-off), so define reset 
as none
+reset_config none
+
+if {![using_hla]} {
+   # if srst is not fitted use SYSRESETREQ to
+   # perform a soft reset
+   cortex_m reset_config sysresetreq
+}
+
+$_TARGETNAME configure -event halted {
+       global WDOG_VALUE
+       global WDOG_VALUE_SET
+       # Stop watchdog during halt, if enabled
+       mem2array value 32 0x40700008 1
+       set WDOG_VALUE [expr ($value(0))]
+       if [expr ($value(0) & (1 << 1))] {
+               set WDOG_VALUE_SET 1
+               mww 0x40700008 [expr ($value(0) & 0xFFFFFFFD)]
+       }
+}
+$_TARGETNAME configure -event resumed {
+       global WDOG_VALUE
+       global WDOG_VALUE_SET
+       if [expr $WDOG_VALUE_SET] {
+               # Restore watchdog enable value after resume
+               mww 0x40700008 $WDOG_VALUE
+               set WDOG_VALUE_SET 0
+       }
+}

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to