Tested with MKE04Z8VTG4, MKE02Z64VLC4 and MKE02Z64VLD2. Change-Id: I606e32a2746a3b96d3e50f3656ba78d40c41c1ea Signed-off-by: Ivan Meleca <ivan@artekit.eu> Reviewed-on: http://openocd.zylin.com/3380 Tested-by: jenkins Reviewed-by: Tomas Vanek <vanekt@fbl.cz>tags/v0.10.0-rc1
@@ -0,0 +1,19 @@ | |||
BIN2C = ../../../../src/helper/bin2char.sh | |||
ARM_CROSS_COMPILE ?= arm-none-eabi- | |||
ARM_AS ?= $(ARM_CROSS_COMPILE)as | |||
ARM_OBJCOPY ?= $(ARM_CROSS_COMPILE)objcopy | |||
arm: kinetis_ke_flash.inc kinetis_ke_watchdog.inc | |||
kinetis_ke_%.elf: kinetis_ke_%.s | |||
$(ARM_AS) $< -o $@ | |||
kinetis_ke_%.bin: kinetis_ke_%.elf | |||
$(ARM_OBJCOPY) -Obinary $< $@ | |||
kinetis_ke_%.inc: kinetis_ke_%.bin | |||
$(BIN2C) < $< > $@ | |||
clean: | |||
-rm -f *.elf *.bin *.inc |
@@ -0,0 +1,15 @@ | |||
/* Autogenerated with ../../../../src/helper/bin2char.sh */ | |||
0x16,0x68,0x00,0x2e,0xfe,0xd0,0x55,0x68,0xb5,0x42,0xf9,0xd0,0x2f,0x4e,0x30,0x27, | |||
0x37,0x70,0x2f,0x4e,0x00,0x27,0x37,0x70,0x2e,0x4e,0x06,0x27,0x37,0x70,0x07,0x0c, | |||
0x2d,0x4e,0x37,0x70,0x2a,0x4e,0x01,0x27,0x37,0x70,0xc7,0xb2,0x2a,0x4e,0x37,0x70, | |||
0x07,0x0a,0x28,0x4e,0x37,0x70,0x26,0x4e,0x02,0x27,0x37,0x70,0x6f,0x78,0x25,0x4e, | |||
0x37,0x70,0x2f,0x78,0x24,0x4e,0x37,0x70,0x21,0x4e,0x03,0x27,0x37,0x70,0xef,0x78, | |||
0x20,0x4e,0x37,0x70,0xaf,0x78,0x20,0x4e,0x37,0x70,0x01,0x39,0x04,0x30,0x04,0x35, | |||
0x9d,0x42,0x01,0xd3,0x15,0x1c,0x08,0x35,0x00,0x29,0x1b,0xd0,0x16,0x68,0xae,0x42, | |||
0x18,0xd0,0x17,0x4e,0x04,0x27,0x37,0x70,0x6f,0x78,0x16,0x4e,0x37,0x70,0x2f,0x78, | |||
0x15,0x4e,0x37,0x70,0x12,0x4e,0x05,0x27,0x37,0x70,0xef,0x78,0x11,0x4e,0x37,0x70, | |||
0xaf,0x78,0x11,0x4e,0x37,0x70,0x01,0x39,0x04,0x30,0x04,0x35,0x9d,0x42,0x01,0xd3, | |||
0x15,0x1c,0x08,0x35,0x09,0x4e,0x80,0x27,0x37,0x70,0x08,0x4e,0x36,0x78,0x3e,0x42, | |||
0xfb,0xd0,0x30,0x27,0x3e,0x42,0x04,0xd1,0x00,0x26,0x55,0x60,0x00,0x29,0x02,0xd0, | |||
0x9e,0xe7,0x00,0x20,0x50,0x60,0x30,0x1c,0x00,0xbe,0xc0,0x46,0x00,0x00,0x00,0x00, | |||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
@@ -0,0 +1,184 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2015 by Ivan Meleca * | |||
* ivan@artekit.eu * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
/* Params: | |||
* r0 = flash destination address, status | |||
* r1 = longword count | |||
* r2 = workarea start address | |||
* r3 = workarea end address | |||
*/ | |||
.text | |||
.cpu cortex-m0plus | |||
.code 16 | |||
.thumb_func | |||
.align 2 | |||
/* r5 = rp | |||
* r6 = wp, tmp | |||
* r7 = tmp | |||
*/ | |||
wait_fifo: | |||
ldr r6, [r2, #0] /* read wp */ | |||
cmp r6, #0 /* abort if wp == 0 */ | |||
beq exit | |||
ldr r5, [r2, #4] /* read rp */ | |||
cmp r5, r6 /* wait until rp != wp */ | |||
beq wait_fifo | |||
ldr r6, fstat /* Clear error flags */ | |||
mov r7, #48 | |||
strb r7, [r6] | |||
ldr r6, fccobix /* FCCOBIX = 0 */ | |||
mov r7, #0 | |||
strb r7, [r6] | |||
ldr r6, fccobhi /* Program FLASH command */ | |||
mov r7, #6 /* FCCOBHI = 6 */ | |||
strb r7, [r6] | |||
lsr r7, r0, #16 /* FCCOBLO = flash destination address >> 16 */ | |||
ldr r6, fccoblo | |||
strb r7, [r6] | |||
ldr r6, fccobix /* Index for lower byte address bits[15:0] */ | |||
mov r7, #1 | |||
strb r7, [r6] /* FCCOBIX = 1*/ | |||
uxtb r7, r0 /* Memory address bits[15:0] */ | |||
ldr r6, fccoblo | |||
strb r7, [r6] /* FCCOBLO = flash destination address */ | |||
lsr r7, r0, #8 | |||
ldr r6, fccobhi | |||
strb r7, [r6] /* FCCOBHI = flash destination address >> 8 */ | |||
ldr r6, fccobix /* FCCOBIX = 2 */ | |||
mov r7, #2 | |||
strb r7, [r6] | |||
ldrb r7, [r5, #1] /* FCCOBHI = rp >> 8 */ | |||
ldr r6, fccobhi | |||
strb r7, [r6] | |||
ldrb r7, [r5] /* FCCOBLO = rp */ | |||
ldr r6, fccoblo | |||
strb r7, [r6] | |||
ldr r6, fccobix /* FCCOBIX = 3 */ | |||
mov r7, #3 | |||
strb r7, [r6] | |||
ldrb r7, [r5, #3] /* FCCOBHI = rp >> 24 */ | |||
ldr r6, fccobhi | |||
strb r7, [r6] | |||
ldrb r7, [r5, #2] /* FCCOBLO = rp >> 16 */ | |||
ldr r6, fccoblo | |||
strb r7, [r6] | |||
sub r1, r1, #1 /* Two words (4 bytes) queued, decrement counter */ | |||
add r0, r0, #4 /* flash address += 4 */ | |||
add r5, r5, #4 /* rp += 4 */ | |||
cmp r5, r3 /* Wrap? */ | |||
bcc no_wrap | |||
mov r5, r2 | |||
add r5, r5, #8 | |||
no_wrap: | |||
cmp r1, #0 /* Done? */ | |||
beq execute | |||
ldr r6, [r2, #0] /* read wp */ | |||
cmp r6, r5 | |||
beq execute /* execute if rp == wp */ | |||
ldr r6, fccobix /* FCCOBIX = 4 */ | |||
mov r7, #4 | |||
strb r7, [r6] | |||
ldrb r7, [r5, #1] /* FCCOBHI = rp >> 8 */ | |||
ldr r6, fccobhi | |||
strb r7, [r6] | |||
ldrb r7, [r5] /* FCCOBLO = rp */ | |||
ldr r6, fccoblo | |||
strb r7, [r6] | |||
ldr r6, fccobix /* FCCOBIX = 5 */ | |||
mov r7, #5 | |||
strb r7, [r6] | |||
ldrb r7, [r5, #3] /* FCCOBHI = rp >> 24 */ | |||
ldr r6, fccobhi | |||
strb r7, [r6] | |||
ldrb r7, [r5, #2] /* FCCOBLO = rp >> 16 */ | |||
ldr r6, fccoblo | |||
strb r7, [r6] | |||
sub r1, r1, #1 /* Two words (4 bytes) queued, decrement counter */ | |||
add r0, r0, #4 /* flash address += 4 */ | |||
add r5, r5, #4 /* rp += 4 */ | |||
cmp r5, r3 /* Wrap? */ | |||
bcc execute | |||
mov r5, r2 | |||
add r5, r5, #8 | |||
execute: | |||
ldr r6, fstat /* Launch the command */ | |||
mov r7, #128 | |||
strb r7, [r6] | |||
wait_busy: | |||
ldr r6, fstat | |||
ldrb r6, [r6] /* Wait until finished */ | |||
tst r6, r7 | |||
beq wait_busy | |||
mov r7, #48 /* Check error */ | |||
tst r6, r7 | |||
bne error | |||
mov r6, #0 /* Clear error */ | |||
str r5, [r2, #4] /* Store rp */ | |||
cmp r1, #0 /* Done? */ | |||
beq done | |||
b wait_fifo | |||
error: | |||
mov r0, #0 | |||
str r0, [r2, #4] /* set rp = 0 on error */ | |||
done: | |||
mov r0, r6 /* Set result code */ | |||
bkpt #0 | |||
.align 2 | |||
fstat: | |||
.word 0 | |||
fccobix: | |||
.word 0 | |||
fccobhi: | |||
.word 0 | |||
fccoblo: | |||
.word 0 |
@@ -0,0 +1,4 @@ | |||
/* Autogenerated with ../../../../src/helper/bin2char.sh */ | |||
0x07,0x4b,0x7f,0x22,0x1d,0x78,0x5c,0x78,0x2a,0x40,0x06,0x4d,0x98,0x88,0xd9,0x88, | |||
0x5d,0x80,0x05,0x4d,0x5d,0x80,0x5c,0x70,0x98,0x80,0xd9,0x80,0x1a,0x70,0x00,0xbe, | |||
0x00,0x20,0x05,0x40,0xc5,0x20,0x00,0x00,0xd9,0x28,0x00,0x00, |
@@ -0,0 +1,47 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2015 by Ivan Meleca * | |||
* ivan@artekit.eu * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
.text | |||
.cpu cortex-m0plus | |||
.code 16 | |||
.thumb_func | |||
.align 2 | |||
ldr r3, wdog_cs1 | |||
mov r2, #127 | |||
ldrb r5, [r3] | |||
ldrb r4, [r3, #1] | |||
and r2, r5 | |||
ldr r5, unlock1 | |||
ldrh r0, [r3, #4] | |||
ldrh r1, [r3, #6] | |||
strh r5, [r3, #2] | |||
ldr r5, unlock2 | |||
strh r5, [r3, #2] | |||
strb r4, [r3, #1] | |||
strh r0, [r3, #4] | |||
strh r1, [r3, #6] | |||
strb r2, [r3] | |||
bkpt #0 | |||
.align 2 | |||
wdog_cs1: | |||
.word 0x40052000 // Watchdog Control and Status Register 1 | |||
unlock1: | |||
.word 0x20C5 // 1st unlock word | |||
unlock2: | |||
.word 0x28D9 // 2nd unlock word |
@@ -5248,6 +5248,33 @@ Command disables watchdog timer. | |||
@end deffn | |||
@end deffn | |||
@deffn {Flash Driver} kinetis_ke | |||
@cindex kinetis_ke | |||
KE members of the Kinetis microcontroller family from Freescale include | |||
internal flash and use ARM Cortex M0+. The driver automatically recognizes | |||
the KE family and sub-family using the chip identification register, and | |||
autoconfigures itself. | |||
@example | |||
flash bank $_FLASHNAME kinetis_ke 0 0 0 0 $_TARGETNAME | |||
@end example | |||
@deffn Command {kinetis_ke mdm check_security} | |||
Checks status of device security lock. Used internally in examine-end event. | |||
@end deffn | |||
@deffn Command {kinetis_ke mdm mass_erase} | |||
Issues a complete Flash erase via the MDM-AP. | |||
This can be used to erase a chip back to its factory state. | |||
Command removes security lock from a device (use of SRST highly recommended). | |||
It does not require the processor to be halted. | |||
@end deffn | |||
@deffn Command {kinetis_ke disable_wdog} | |||
Command disables watchdog timer. | |||
@end deffn | |||
@end deffn | |||
@deffn {Flash Driver} fm4 | |||
All members of the FM4 microcontroller family from Spansion (formerly Fujitsu) | |||
include internal flash and use ARM Cortex-M4 cores. | |||
@@ -46,6 +46,7 @@ NOR_DRIVERS = \ | |||
fm4.c \ | |||
dsp5680xx_flash.c \ | |||
kinetis.c \ | |||
kinetis_ke.c \ | |||
numicro.c \ | |||
nrf51.c \ | |||
mrvlqspi.c \ | |||
@@ -55,6 +55,7 @@ extern struct flash_driver dsp5680xx_flash; | |||
extern struct flash_driver fm3_flash; | |||
extern struct flash_driver fm4_flash; | |||
extern struct flash_driver kinetis_flash; | |||
extern struct flash_driver kinetis_ke_flash; | |||
extern struct flash_driver efm32_flash; | |||
extern struct flash_driver mdr_flash; | |||
extern struct flash_driver numicro_flash; | |||
@@ -104,6 +105,7 @@ static struct flash_driver *flash_drivers[] = { | |||
&fm4_flash, | |||
&dsp5680xx_flash, | |||
&kinetis_flash, | |||
&kinetis_ke_flash, | |||
&efm32_flash, | |||
&mdr_flash, | |||
&numicro_flash, | |||
@@ -0,0 +1,6 @@ | |||
# | |||
# Freescale Kinetis KE02 devices | |||
# | |||
set CHIPNAME ke02 | |||
source [find target/kex.cfg] |
@@ -0,0 +1,6 @@ | |||
# | |||
# Freescale Kinetis KE04 devices | |||
# | |||
set CHIPNAME ke04 | |||
source [find target/kex.cfg] |
@@ -0,0 +1,6 @@ | |||
# | |||
# Freescale Kinetis KE06 devices | |||
# | |||
set CHIPNAME ke06 | |||
source [find target/kex.cfg] |
@@ -0,0 +1,58 @@ | |||
# | |||
# Freescale Kinetis KE series devices | |||
# | |||
source [find target/swj-dp.tcl] | |||
if { [info exists CHIPNAME] } { | |||
set _CHIPNAME $CHIPNAME | |||
} else { | |||
set _CHIPNAME ke | |||
} | |||
# Work-area is a space in RAM used for flash programming | |||
# By default use 1kB | |||
if { [info exists WORKAREASIZE] } { | |||
set _WORKAREASIZE $WORKAREASIZE | |||
} else { | |||
set _WORKAREASIZE 0x400 | |||
} | |||
if { [info exists CPUTAPID] } { | |||
set _CPUTAPID $CPUTAPID | |||
} else { | |||
if { [using_jtag] } { | |||
set _CPUTAPID 0x4ba00477 | |||
} { | |||
set _CPUTAPID 0x2ba01477 | |||
} | |||
} | |||
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID | |||
set _TARGETNAME $_CHIPNAME.cpu | |||
target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu | |||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 | |||
set _FLASHNAME $_CHIPNAME.flash | |||
flash bank $_FLASHNAME kinetis_ke 0 0 0 0 $_TARGETNAME | |||
adapter_khz 1000 | |||
reset_config srst_nogate | |||
if {![using_hla]} { | |||
# It is important that "kinetis_ke mdm check_security" is called for | |||
# 'examine-end' event and not 'eximine-start'. Calling it in 'examine-start' | |||
# causes "kinetis_ke mdm check_security" to fail the first time openocd | |||
# calls it when it tries to connect after the CPU has been power-cycled. | |||
$_CHIPNAME.cpu configure -event examine-end { | |||
kinetis_ke mdm check_security | |||
} | |||
# if srst is not fitted use SYSRESETREQ to | |||
# perform a soft reset | |||
cortex_m reset_config sysresetreq | |||
} |