Added support for STMicroelectronics BlueNRG-1 and BlueNRG-2 SoC

Added configuration files and flash loaders.

Change-Id: I768eb3626f4e0eadb206bef90a867cc146fe8c75
Signed-off-by: Michele Sardo <msmttchr@gmail.com>
Reviewed-on: http://openocd.zylin.com/4226
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
Michele Sardo
2017-09-12 08:51:29 +02:00
committed by Tomas Vanek
parent 8f1f912a7d
commit cb2f21bf36
10 changed files with 834 additions and 0 deletions

View File

@@ -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

View File

@@ -0,0 +1,132 @@
/* 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)
;
*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 != SUCCESS) {
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");
}

View File

@@ -0,0 +1,18 @@
/* Autogenerated with ../../../../src/helper/bin2char.sh */
0x05,0x93,0x43,0x68,0x05,0x00,0x07,0x93,0x05,0x9b,0x06,0x91,0x03,0x92,0x35,0x4c,
0x00,0x2b,0x5c,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0xfb,0xd0,0x2b,0x68,0x00,0x2b,
0x55,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0x52,0xd9,0x6b,0x68,0x06,0x9a,0xd3,0x1a,
0x09,0x93,0x09,0x9b,0x0f,0x2b,0xed,0xdd,0x00,0x21,0x09,0x9b,0x04,0x93,0x1a,0x1e,
0x29,0x4b,0x19,0x60,0x32,0xd0,0x29,0x4b,0x00,0x20,0x98,0x46,0x28,0x4b,0x6a,0x68,
0x9c,0x46,0x28,0x4b,0x28,0x4e,0x9b,0x46,0x28,0x4b,0x9a,0x46,0x28,0x4b,0x99,0x46,
0x01,0x23,0x51,0x68,0x17,0x68,0x00,0x91,0x91,0x68,0x01,0x91,0xd1,0x68,0x02,0x91,
0x3f,0x21,0x21,0x60,0x03,0x99,0x09,0x18,0x89,0x03,0x09,0x0c,0x31,0x60,0x41,0x46,
0x0f,0x60,0x67,0x46,0x00,0x99,0x39,0x60,0x5f,0x46,0x01,0x99,0x39,0x60,0x57,0x46,
0x02,0x99,0x39,0x60,0x49,0x46,0xcc,0x27,0x0f,0x60,0x21,0x68,0x0b,0x42,0xfc,0xd0,
0x04,0x99,0x10,0x32,0x10,0x30,0x6a,0x60,0x81,0x42,0xda,0xd8,0x03,0x9a,0x09,0x9b,
0x94,0x46,0x9c,0x44,0x63,0x46,0x06,0x9a,0x03,0x93,0x6b,0x68,0x9a,0x42,0x01,0xd8,
0x07,0x9b,0x6b,0x60,0x05,0x9a,0x09,0x9b,0xd3,0x1a,0x05,0x93,0xa2,0xd1,0x00,0xbe,
0x2b,0x68,0x6a,0x68,0x9b,0x1a,0x09,0x93,0x09,0x9b,0x00,0x2b,0xa9,0xda,0x00,0x23,
0x09,0x93,0xa6,0xe7,0x10,0x00,0x10,0x40,0x0c,0x00,0x10,0x40,0x40,0x00,0x10,0x40,
0x44,0x00,0x10,0x40,0x48,0x00,0x10,0x40,0x18,0x00,0x10,0x40,0x4c,0x00,0x10,0x40,
0x00,0x00,0x10,0x40,

View File

@@ -5344,6 +5344,30 @@ The AVR 8-bit microcontrollers from Atmel integrate flash memory.
@comment - defines mass_erase ... pointless given flash_erase_address
@end deffn
@deffn {Flash Driver} bluenrg-x
STMicroelectronics BlueNRG-1 and BlueNRG-2 Bluetooth low energy wireless system-on-chip. They include ARM Cortex-M0 core and internal flash memory.
The driver automatically recognizes these chips using
the chip identification registers, and autoconfigures itself.
@example
flash bank $_FLASHNAME bluenrg-x 0 0 0 0 $_TARGETNAME
@end example
Note that when users ask to erase all the sectors of the flash, a mass erase command is used which is faster than erasing
each single sector one by one.
@example
flash erase_sector 0 0 79 # It will perform a mass erase on BlueNRG-1
@end example
@example
flash erase_sector 0 0 127 # It will perform a mass erase on BlueNRG-2
@end example
Triggering a mass erase is also useful when users want to disable readout protection.
@end deffn
@deffn {Flash Driver} efm32
All members of the EFM32 microcontroller family from Energy Micro include
internal flash and use ARM Cortex-M3 cores. The driver automatically recognizes

View File

@@ -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 \

549
src/flash/nor/bluenrg-x.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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;
@@ -88,6 +89,7 @@ static struct flash_driver *flash_drivers[] = {
&ath79_flash,
&atsamv_flash,
&avr_flash,
&bluenrgx_flash,
&cfi_flash,
&dsp5680xx_flash,
&efm32_flash,

View File

@@ -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]

View File

@@ -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]

73
tcl/target/bluenrg-x.cfg Normal file
View File

@@ -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
}
}