stlinkv2.py: merge Cortex-M0 support for FSM-55

This commit is contained in:
NIIBE Yutaka
2015-07-06 15:52:04 +09:00
parent 35c880fc0c
commit 9ba59de212
5 changed files with 109 additions and 42 deletions

View File

@@ -1,3 +1,19 @@
2015-07-06 Niibe Yutaka <gniibe@fsij.org>
Enhancement for FSM-55.
* tool/stlinkv2.py (stlinkv2.control_nrst): New.
(stlinkv2.get_rdp_key,has_spi_flash,has_protection): New.
(stlinkv2.get_core_id): Rename.
(stlinkv2.blank_check): Use self.flash_size.
(stlinkv2.start): Call control_nrst. Call get_core_id.
Distinguishing chip, and set rdp_key, flash_size and require_nrst.
(stlinkv2.flash_write): Use self.flash_block_size.
(main): Call control_nrst.
(prog_flash_write_body, prog_option_bytes_write_body)
(prog_blank_check_body): Support Cortex-M0.
(main): Call API V2 halt twice.
* tool/asm-thumb/*.S: Updated for Cortex-M0.
2015-06-30 Niibe Yutaka <gniibe@fsij.org>
* chopstx: Update.

View File

@@ -1,7 +1,7 @@
/* ARM Thumb Assembler code */
// arm-none-eabi-gcc -Wa,-amhls=blank_check.lst -c blank_check.S
.cpu cortex-m3
.cpu cortex-m0
.thumb
ldr r1, .START_ADDR
ldr r2, .END_ADDR

View File

@@ -8,11 +8,9 @@
#define FLASH_SR_OFFSET 0x0c
#define FLASH_CR_OFFSET 0x10
#define COUNT 0x1000
.cpu cortex-m3
.cpu cortex-m0
.thumb
movw r2, #COUNT
ldr r2, .SIZE
ldr r0, .SRC_ADDR
ldr r1, .TARGET_ADDR
ldr r4, .FLASH_BASE_ADDR
@@ -35,5 +33,6 @@
bkpt #0x00
.align 2
.FLASH_BASE_ADDR: .word 0x40022000
.SRC_ADDR: .word 0x20000038
.SRC_ADDR: .word 0x2000003C
.TARGET_ADDR: .word 0x08000000
.SIZE: .word 0x00000000

View File

@@ -7,11 +7,9 @@
#define FLASH_SR_OFFSET 0x0c
#define FLASH_CR_OFFSET 0x10
#define OB_RDP_UNLOCK 0x00a5
.cpu cortex-m3
.cpu cortex-m0
.thumb
movw r0, #OB_RDP_UNLOCK
ldr r0, .OPTION_BYTES
ldr r1, .TARGET_ADDR
ldr r2, .FLASH_BASE_ADDR
mov r3, #FLASH_CR_OPTPG
@@ -21,9 +19,16 @@
1: ldr r0, [r2, #FLASH_SR_OFFSET]
tst r0, r4
bne 1b
add r1, #2
mov r0, #255
strh r0, [r1]
2: ldr r0, [r2, #FLASH_SR_OFFSET]
tst r0, r4
bne 2b
mov r0, #0
str r0, [r2, #FLASH_CR_OFFSET]
bkpt #0x00
.align 2
.FLASH_BASE_ADDR: .word 0x40022000
.TARGET_ADDR: .word 0x1FFFF800
.OPTION_BYTES: .word 0x00000000

View File

@@ -3,7 +3,7 @@
"""
stlinkv2.py - a tool to control ST-Link/V2
Copyright (C) 2012, 2013 Free Software Initiative of Japan
Copyright (C) 2012, 2013, 2015 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -31,11 +31,17 @@ from colorama import init as colorama_init, Fore, Back, Style
# Assumes only single ST-Link/V2 device is attached to computer.
CORE_ID_CORTEX_M3=0x1ba01477
CORE_ID_CORTEX_M0=0x0bb11477
CHIP_ID_STM32F103=0x20036410
GPIOA=0x40010800
GPIOB=0x40010C00
OPTION_BYTES_ADDR=0x1ffff800
RDP_KEY=0x00a5 # Unlock readprotection
RDP_KEY_F1=0x00a5 # Unlock readprotection
RDP_KEY_F0=0x00aa # Unlock readprotection
FLASH_BASE_ADDR=0x40022000
FLASH_KEYR= FLASH_BASE_ADDR+0x04
@@ -62,44 +68,45 @@ FLASH_CR_STRT= 0x0040
FLASH_CR_LOCK= 0x0080
FLASH_CR_OPTWRE= 0x0200
FLASH_SIZE_F1=0x20000 # 128KiB
FLASH_SIZE_F0=0x4000 # 16KiB
SPI1= 0x40013000
def uint32(v):
return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
## HERE comes: "movw r2,#SIZE" instruction
prog_flash_write_body = "\x0A\x48" + "\x0B\x49" + \
"\x08\x4C" + "\x01\x25" + "\x14\x26" + "\x00\x27" + "\x25\x61" + \
prog_flash_write_body = "\x0D\x4A" + "\x0B\x48" + "\x0B\x49" + \
"\x09\x4C" + "\x01\x25" + "\x14\x26" + "\x00\x27" + "\x25\x61" + \
"\xC3\x5B" + "\xCB\x53" + "\xE3\x68" + "\x2B\x42" + "\xFC\xD1" + \
"\x33\x42" + "\x02\xD1" + "\x02\x37" + "\x97\x42" + "\xF5\xD1" + \
"\x00\x27" + "\x27\x61" + "\x00\xBE" + "\x00\x20\x02\x40" + \
"\x38\x00\x00\x20"
# .SRC_ADDR: 0x20000038
"\x00\x27" + "\x27\x61" + "\x00\xBE" + "\xC0\x46" + "\x00\x20\x02\x40" + \
"\x3C\x00\x00\x20"
# .SRC_ADDR: 0x2000003C
## HERE comes: target_addr in 4-byte
# .TARGET_ADDR
## HERE comes: size in 4-byte
# .SIZE
def gen_prog_flash_write(addr,size):
return pack("<BBBB", (0x40 | (size&0xf000)>>12), (0xf2 | (size&0x0800)>>9),
(size & 0x00ff), (0x02 | ((size&0x0700) >> 4))) + \
prog_flash_write_body + pack("<I", addr)
return prog_flash_write_body + pack("<I", addr) + pack("<I", size)
## HERE comes: "movw r0,#VAL" instruction
prog_option_bytes_write_body = "\x06\x49" + "\x05\x4A" + "\x10\x23" + \
"\x01\x24" + "\x13\x61" + "\x08\x80" + "\xD0\x68" + "\x20\x42" + \
"\xFC\xD1" + "\x00\x20" + "\x10\x61" + "\x00\xBE" + "\x00\x20\x02\x40"
prog_option_bytes_write_body = "\x0B\x48" + "\x0A\x49" + "\x08\x4A" + \
"\x10\x23" + "\x01\x24" + "\x13\x61" + "\x08\x80" + "\xD0\x68" + \
"\x20\x42" + "\xFC\xD1" + "\x02\x31" + "\xFF\x20" + "\x08\x80" + \
"\xD0\x68" + "\x20\x42" + "\xFC\xD1" + "\x00\x20" + "\x10\x61" + \
"\x00\xBE" + "\xC0\x46" + "\x00\x20\x02\x40"
## HERE comes: target_addr in 4-byte
# .TARGET_ADDR
## HERE comes: option_bytes in 4-byte
# .OPTION_BYTES
def gen_prog_option_bytes_write(addr,val):
return pack("<BBBB", (0x40 | (val&0xf000)>>12), (0xf2 | (val&0x0800)>>9),
(val & 0x00ff), (0x00 | ((val&0x0700) >> 4))) + \
prog_option_bytes_write_body + pack("<I", addr)
return prog_option_bytes_write_body + pack("<I", addr) + pack("<I", val)
prog_blank_check_body = "\x04\x49" + "\x05\x4A" + "\x08\x68" + "\x01\x30" + \
"\x02\xD1" + "\x04\x31" + "\x91\x42" + "\xF9\xD1" + "\x00\xBE" + \
"\x00\xBF" + "\x00\x00\x00\x08"
"\xC0\x46" + "\x00\x00\x00\x08"
## HERE comes: end_addr in 4-byte
# .END_ADDR
@@ -108,7 +115,8 @@ def gen_prog_blank_check(size):
SRAM_ADDRESS=0x20000000
BLOCK_SIZE=16384 # Should be less than (20KiB - 0x0038)
FLASH_BLOCK_SIZE_F1=16384 # Should be less than (20KiB - 0x0038)
FLASH_BLOCK_SIZE_F0=2048 # Should be less than (4KiB - 0x0038)
BLOCK_WRITE_TIMEOUT=80 # Increase this when you increase BLOCK_SIZE
@@ -219,11 +227,14 @@ class stlinkv2(object):
def write_debug_reg(self, addr, value):
return self.execute_get("\xf2\x35" + pack('<II', addr, value), 2)
def control_nrst(self, value):
return self.execute_get("\xf2\x3c" + pack('<B', value), 2)
def run(self):
v = self.execute_get("\xf2\x09\x00", 2)
return (v[1] << 8) + v[0]
def core_id(self):
def get_core_id(self):
v = self.execute_get("\xf2\x22\x00", 4)
return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
@@ -309,7 +320,7 @@ class stlinkv2(object):
return (self.read_memory_u32(FLASH_OBR) & 0x0002) != 0
def blank_check(self):
prog = gen_prog_blank_check(0x20000) # 128KiB XXX: table lookup???
prog = gen_prog_blank_check(self.flash_size)
self.write_memory(SRAM_ADDRESS, prog)
self.write_reg(15, SRAM_ADDRESS)
self.run()
@@ -398,8 +409,8 @@ class stlinkv2(object):
off = 0
while True:
if len(data[off:]) > BLOCK_SIZE:
size = BLOCK_SIZE
if len(data[off:]) > self.flash_block_size:
size = self.flash_block_size
self.flash_write_internal(addr, data, off, size)
off = off + size
addr = addr + size
@@ -467,6 +478,7 @@ class stlinkv2(object):
self.exit_from_dfu()
new_mode = self.stl_mode()
print "Change ST-Link/V2 mode %04x -> %04x" % (mode, new_mode)
self.control_nrst(2)
self.enter_swd()
s = self.get_status()
if s != 0x0080:
@@ -483,6 +495,38 @@ class stlinkv2(object):
if mode != 2:
raise ValueError("Failed to switch debug mode.", mode)
self.core_id = self.get_core_id()
if self.core_id == CORE_ID_CORTEX_M3:
self.chip_id = self.read_memory_u32(0xE0042000)
elif self.core_id == CORE_ID_CORTEX_M0:
self.chip_id = 0
else:
raise ValueError("Unknown core ID", self.core_id)
if self.chip_id == CHIP_ID_STM32F103:
self.rdp_key = RDP_KEY_F1
self.flash_size = FLASH_SIZE_F1
self.flash_block_size = FLASH_BLOCK_SIZE_F1
self.require_nrst = False
self.external_spi_flash = True
self.protection_feature = True
else:
self.rdp_key = RDP_KEY_F0
self.flash_size = FLASH_SIZE_F0
self.flash_block_size = FLASH_BLOCK_SIZE_F0
self.require_nrst = True
self.external_spi_flash = False
self.protection_feature = False
return (self.core_id, self.chip_id)
def get_rdp_key(self):
return self.rdp_key
def has_spi_flash(self):
return self.external_spi_flash
def has_protection(self):
return self.protection_feature
USB_VENDOR_ST=0x0483 # 0x0483 SGS Thomson Microelectronics
USB_VENDOR_STLINKV2=0x3748 # 0x3748 ST-LINK/V2
@@ -538,9 +582,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
raise ValueError("No ST-Link/V2 device found.", None)
print "ST-Link/V2 version info: %d %d %d" % stl.version()
stl.start()
core_id = stl.core_id()
chip_id = stl.read_memory_u32(0xE0042000)
(core_id, chip_id) = stl.start()
# FST-01 chip id: 0x20036410
print "CORE: %08x, CHIP_ID: %08x" % (core_id, chip_id)
@@ -553,11 +595,13 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
option_bytes = stl.option_bytes_read()
print "Option bytes: %08x" % option_bytes
if (option_bytes & 0xff) == RDP_KEY:
rdp_key = stl.get_rdp_key()
if (option_bytes & 0xff) == rdp_key:
ob_protection_enable = False
else:
ob_protection_enable = True
stl.control_nrst(2)
stl.enter_debug()
status = stl.get_status()
if status != 0x0081:
@@ -565,6 +609,8 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
# DCB_DHCSR DBGKEY|C_HALT|C_DEBUGEN
stl.write_debug_reg(0xE000EDF0, 0xA05F0003)
status = stl.get_status()
stl.write_debug_reg(0xE000EDF0, 0xA05F0003)
status = stl.get_status()
if status != 0x0081:
raise ValueError("Status of core is not halt.", status)
@@ -602,14 +648,14 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
stl.reset_sys()
stl.option_bytes_erase()
stl.reset_sys()
stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY)
stl.option_bytes_write(OPTION_BYTES_ADDR,rdp_key)
stl.usb_disconnect()
time.sleep(0.100)
stl.finish_gpio()
print "Flash ROM read protection disabled. Reset the board, now."
return 0
if spi_flash_check:
if spi_flash_check and stl.has_spi_flash():
stl.spi_flash_init()
id = stl.spi_flash_read_id()
print "SPI Flash ROM ID: %06x" % id
@@ -646,12 +692,13 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
off = off + blk_size
compare(data, data_received)
if not no_protect:
if not no_protect and stl.has_protection():
print "PROTECT"
stl.option_bytes_erase()
print "Flash ROM read protection enabled. Reset the board to enable protection."
if reset_after_successful_write:
stl.control_nrst(2)
stl.usb_disconnect()
stl.reset_sys()
stl.run()