commit deab0abef44cb4d541aa33789445a703c7ff8ddc
parent 75d7471794d036f2a4408d2517cb6be600e9bb98
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 15 Jun 2015 02:28:12 -0700
stm32f4xx: first cut at a flash agent for this family
Diffstat:
7 files changed, 169 insertions(+), 1 deletion(-)
diff --git a/agents/module.mk b/agents/module.mk
@@ -11,3 +11,8 @@ M_START := agents/lpc-header.o
 M_OBJS := agents/lpc-main.o
 $(call build-target-executable)
 
+M_NAME := agent-stm32f4xx
+M_CHIP := stm32f4xx-agt
+M_START := agents/stm-header.o
+M_OBJS := agents/stm-main.o
+$(call build-target-executable)
diff --git a/agents/stm-header.S b/agents/stm-header.S
@@ -0,0 +1,22 @@
+
+.section .vectors
+.syntax unified
+.globl _start
+
+_start:
+	.long 0x42776166	// magic
+	.long 0x00010000	// version
+	.long 0x00000000	// flags
+	.long _start
+	.long _start + 0x400	// data addr
+	.long 0x00008000	// data size
+	.long CONFIG_FLASHADDR	// flash addr
+	.long CONFIG_FLASHSIZE	// flash size
+	.long 0
+	.long 0
+	.long 0
+	.long 0
+	.long flash_agent_setup + 1
+	.long flash_agent_erase + 1
+	.long flash_agent_write + 1
+	.long flash_agent_ioctl + 1
diff --git a/agents/stm-main.c b/agents/stm-main.c
@@ -0,0 +1,128 @@
+// agents/stm-main.c
+//
+// Copyright 2015 Brian Swetland <swetland@frotz.net>
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <agent/flash.h>
+#include <fw/io.h>
+
+#define FLASH_BASE		0x40023C00
+#define FLASH_ACR		(FLASH_BASE + 0x00)
+
+#define FLASH_KEYR		(FLASH_BASE + 0x04)
+#define FLASH_KEYR_KEY1		0x45670123
+#define FLASH_KEYR_KEY2		0xCDEF89AB
+
+#define FLASH_SR		(FLASH_BASE + 0x0C)
+#define FLASH_SR_BSY		(1 << 16)
+#define FLASH_SR_PGSERR		(1 << 7) // sequence error
+#define FLASH_SR_PGPERR		(1 << 6) // parallelism error
+#define FLASH_SR_PGAERR		(1 << 5) // alignment error
+#define FLASH_SR_WRPERR		(1 << 4) // write-protect error
+#define FLASH_SR_OPERR		(1 << 1) // operation error
+#define FLASH_SR_ERRMASK	0xF2
+#define FLASH_SR_EOP		(1 << 0) // end of operation
+
+#define FLASH_CR		(FLASH_BASE + 0x10)
+#define FLASH_CR_LOCK		(1 << 31)
+#define FLASH_CR_ERRIE		(1 << 25) // error irq en
+#define FLASH_CR_EOPIE		(1 << 24) // end of op irq en
+#define FLASH_CR_STRT		(1 << 16) // start
+#define FLASH_CR_PSIZE_8	(0 << 8)
+#define FLASH_CR_PSIZE_16	(1 << 8)
+#define FLASH_CR_PSIZE_32	(2 << 8)
+#define FLASH_CR_PSIZE_64	(3 << 8)
+#define FLASH_CR_SNB(n)		(((n) & 15) << 3) // sector number
+#define FLASH_CR_MER		(1 << 2) // mass erase
+#define FLASH_CR_SER		(1 << 1) // sector erase
+#define FLASH_CR_PG		(1 << 0) // programming
+
+
+#define SECTORS 12
+
+static u32 sectors[SECTORS + 1] = {
+	0x00000000,
+	0x00004000,
+	0x00008000,
+	0x0000C000,
+	0x00010000,
+	0x00020000,
+	0x00040000,
+	0x00060000,
+	0x00080000,
+	0x000A0000,
+	0x000C0000,
+	0x000E0000,
+	0x00100000,
+};
+
+int flash_agent_setup(flash_agent *agent) {
+	writel(FLASH_KEYR_KEY1, FLASH_KEYR);
+	writel(FLASH_KEYR_KEY2, FLASH_KEYR);
+	if (readl(FLASH_CR) & FLASH_CR_LOCK) {
+		return ERR_FAIL;
+	} else {
+		return ERR_NONE;
+	}
+}
+
+int flash_agent_erase(u32 flash_addr, u32 length) {
+	u32 v;
+	int n;
+	for (n = 0; n < SECTORS; n++) {
+		if (flash_addr == sectors[n]) goto ok;
+	}
+	return ERR_ALIGNMENT;
+ok:
+	for (;;) {
+		writel(FLASH_CR_SER | FLASH_CR_SNB(n), FLASH_CR);
+		writel(FLASH_CR_STRT | FLASH_CR_SER | FLASH_CR_SNB(n), FLASH_CR);
+		while ((v = readl(FLASH_SR)) & FLASH_SR_BSY) ;
+		if (v & FLASH_SR_ERRMASK) {
+			return ERR_FAIL;
+		}
+		n++;
+		if (n == SECTORS) break;
+		if ((sectors[n] - flash_addr) >= length) break;
+	}
+	return ERR_NONE;
+}
+
+int flash_agent_write(u32 flash_addr, const void *_data, u32 length) {
+	const u32 *data = _data;
+	u32 v;
+	if ((flash_addr & 3) || (length & 3)) {
+		return ERR_ALIGNMENT;
+	}
+	writel(FLASH_CR_PG | FLASH_CR_PSIZE_32, FLASH_CR);
+	while (length > 0) {
+		writel(*data, flash_addr);
+		data++;
+		length -= 4;
+		flash_addr += 4;
+		while ((v = readl(FLASH_SR)) & FLASH_SR_BSY) ;
+		if (v & FLASH_SR_ERRMASK) {
+			writel(0, FLASH_CR);
+			return ERR_FAIL;
+		}
+	}
+	writel(0, FLASH_CR);
+	return ERR_NONE;
+}
+
+int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) {
+	return ERR_INVALID;
+}
+
+
diff --git a/arch/stm32f4xx/config.mk b/arch/stm32f4xx/config.mk
@@ -0,0 +1,13 @@
+
+#           name          arch      rambase    ramsize    flashbase  flashsize  linkscript
+$(call chip,stm32f4xx-rom,stm32f1xx,0x20000000,0x00020000,0x00000000,0x00100000,rom)
+$(call chip,stm32f4xx-ram,stm32f1xx,0x20000000,0x00020000,0x00000000,0x00000000,ram)
+$(call chip,stm32f4xx-agt,stm32f1xx,0x20000400,0x0001fc00,0x00000000,0x00100000,ram)
+
+
+ARCH_stm32f4xx_CFLAGS := -Iarch/stm32f4xx/include
+ARCH_stm32f4xx_CFLAGS += -Iarch/arm-cm3/include
+ARCH_stm32f4xx_CFLAGS += -DCONFIG_STACKTOP=0x20005000
+ARCH_stm32f4xx_START := arch/arm-cm3/start.o
+
+ARCH_stm32f4xx_OBJS :=
diff --git a/arch/stm32f4xx/include/arch/hardware.h b/arch/stm32f4xx/include/arch/hardware.h
diff --git a/arch/stm32f4xx/include/arch/irqs.h b/arch/stm32f4xx/include/arch/irqs.h
diff --git a/tools/module.mk b/tools/module.mk
@@ -10,7 +10,7 @@ M_OBJS += tools/usb.o
 M_OBJS += out/debugger-builtins.o
 $(call build-host-executable)
 
-AGENTS := out/agent-lpc13xx.bin out/agent-lpc15xx.bin
+AGENTS := out/agent-lpc13xx.bin out/agent-lpc15xx.bin out/agent-stm32f4xx.bin
 out/debugger-builtins.c: $(AGENTS) bin/mkbuiltins
 	@mkdir -p out
 	./bin/mkbuiltins $(AGENTS) > $@