commit 95c82cf7f408e4f6d27b59e1575bb02a36e29690
parent 7a6f4f31f17ce3b396051f59fdc4eee848528912
Author: Brian Swetland <swetland@frotz.net>
Date: Fri, 3 May 2019 15:08:49 -0700
agents: nrf528xx: add flash support for Nordic NRF528xx family
Diffstat:
3 files changed, 152 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -45,6 +45,7 @@ $(call agent, stm32f0xx, 0x20000400, M0)
$(call agent, lpc13xx, 0x10000400, M3)
$(call agent, lpc15xx, 0x02000400, M3)
$(call agent, cc13xx, 0x20000400, M3)
+$(call agent, nrf528xx, 0x20000400, M3)
# tool to pack the agents into a source file
SRCS := tools/mkbuiltins.c
diff --git a/agents/nrf528xx.c b/agents/nrf528xx.c
@@ -0,0 +1,127 @@
+// agents/nrf528xx.c
+//
+// Copyright 2019 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.
+
+#define LOADADDR 0x20000400
+
+#define FLASH_BASE 0x00000000
+
+#include <agent/flash.h>
+#include <fw/io.h>
+
+#define NVMC_READY 0x4001E400
+#define NVMC_CONFIG 0x4001E504
+#define NVMC_CONFIG_READ 0
+#define NVMC_CONFIG_WRITE 1
+#define NVMC_CONFIG_ERASE 2
+#define NVMC_ERASEPAGE 0x4001E508
+
+#define FICR_CODEPAGESIZE 0x10000010
+#define FICR_CODESIZE 0x10000014
+
+static unsigned FLASH_PAGE_SIZE = 1024;
+static unsigned FLASH_SIZE = 192 * 1024;
+
+int flash_agent_setup(flash_agent *agent) {
+
+ // TODO - validate part ID
+ if (0) {
+ // unknown part
+ return ERR_INVALID;
+ }
+
+ // check flash size
+ FLASH_PAGE_SIZE = readl(FICR_CODEPAGESIZE);
+ FLASH_SIZE = FLASH_PAGE_SIZE * readl(FICR_CODESIZE);
+
+ agent->flash_size = FLASH_SIZE;
+
+ return ERR_NONE;
+}
+
+int flash_agent_erase(u32 flash_addr, u32 length) {
+ int status = ERR_NONE;
+ if (flash_addr > FLASH_SIZE) {
+ return ERR_INVALID;
+ }
+ if (flash_addr & (FLASH_PAGE_SIZE - 1)) {
+ return ERR_ALIGNMENT;
+ }
+ writel(NVMC_CONFIG_ERASE, NVMC_CONFIG);
+ while (length > 0) {
+ if (length > FLASH_PAGE_SIZE) {
+ length -= FLASH_PAGE_SIZE;
+ } else {
+ length = 0;
+ }
+ writel(flash_addr, NVMC_ERASEPAGE);
+ while (readl(NVMC_READY) != 1) ;
+ for (unsigned n = 0; n < FLASH_PAGE_SIZE; n += 4) {
+ if (readl(flash_addr + n) != 0xFFFFFFFF) {
+ status = ERR_FAIL;
+ goto done;
+ }
+ }
+ flash_addr += FLASH_PAGE_SIZE;
+ }
+done:
+ writel(NVMC_CONFIG_READ, NVMC_CONFIG);
+ return status;
+}
+
+int flash_agent_write(u32 flash_addr, const void *_data, u32 length) {
+ int status = ERR_NONE;
+ const unsigned *data = _data;
+ if (flash_addr > FLASH_SIZE) {
+ return ERR_INVALID;
+ }
+ if ((flash_addr & 3) || (length & 3)) {
+ return ERR_ALIGNMENT;
+ }
+ writel(NVMC_CONFIG_WRITE, NVMC_CONFIG);
+ while (length > 0) {
+ writel(*data, flash_addr);
+ while (readl(NVMC_READY) != 1) ;
+ if (readl(flash_addr) != *data) {
+ status = ERR_FAIL;
+ goto done;
+ }
+ data++;
+ length -= 4;
+ flash_addr += 4;
+ }
+done:
+ writel(NVMC_CONFIG_READ, NVMC_CONFIG);
+ return status;
+}
+
+int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) {
+ return ERR_INVALID;
+}
+
+const flash_agent __attribute((section(".vectors"))) FlashAgent = {
+ .magic = AGENT_MAGIC,
+ .version = AGENT_VERSION,
+ .flags = 0,
+ .load_addr = LOADADDR,
+ .data_addr = LOADADDR + 0x400,
+ .data_size = 0x4000,
+ .flash_addr = FLASH_BASE,
+ .flash_size = 0,
+ .setup = flash_agent_setup,
+ .erase = flash_agent_erase,
+ .write = flash_agent_write,
+ .ioctl = flash_agent_ioctl,
+};
diff --git a/tools/builtins.c b/tools/builtins.c
@@ -151,6 +151,30 @@ static struct {
"\x6F\xF0\x02\x00\x10\xBD\x00\xBF\xA8\x01\x00\x10\x6F\xF0\x01\x00"
"\x70\x47\x00\x00"
},
+ { "agent-nrf528xx.bin", 340,
+ "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x00\x20"
+ "\x00\x08\x00\x20\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x41\x04\x00\x20\x71\x04\x00\x20\xED\x04\x00\x20\x69\x04\x00\x20"
+ "\x05\x4B\x1A\x68\x05\x4B\x1A\x60\x05\x4B\x1B\x68\x53\x43\x05\x4A"
+ "\xC3\x61\x13\x60\x00\x20\x70\x47\x10\x00\x00\x10\x4C\x05\x00\x20"
+ "\x14\x00\x00\x10\x50\x05\x00\x20\x6F\xF0\x01\x00\x70\x47\x00\x00"
+ "\x19\x4B\xF0\xB5\x1B\x68\x83\x42\x27\xD3\x18\x4B\x1A\x68\x01\x3A"
+ "\x02\x42\x25\xD1\x02\x24\x16\x4A\x16\x4E\x17\x4F\x14\x60\x19\xB9"
+ "\x08\x46\x00\x23\x13\x60\xF0\xBD\x1C\x68\x30\x60\x8C\x42\x2C\xBF"
+ "\x00\x21\x09\x1B\x3C\x68\x01\x2C\xFC\xD1\x00\x24\x1D\x68\xAC\x42"
+ "\x01\xD3\x28\x44\xEB\xE7\x50\xF8\x04\xE0\xBE\xF1\xFF\x3F\x01\xD1"
+ "\x04\x34\xF4\xE7\x4F\xF0\xFF\x30\xE3\xE7\x6F\xF0\x01\x00\xF0\xBD"
+ "\x6F\xF0\x02\x00\xF0\xBD\x00\xBF\x50\x05\x00\x20\x4C\x05\x00\x20"
+ "\x04\xE5\x01\x40\x08\xE5\x01\x40\x00\xE4\x01\x40\x14\x4B\xF0\xB5"
+ "\x1B\x68\x83\x42\x1E\xD3\x40\xEA\x02\x03\x9B\x07\x1D\xD1\x01\x23"
+ "\x10\x4D\x11\x4E\x2B\x60\x0B\x46\x44\x1A\xD0\x1A\x08\x18\x02\xD1"
+ "\x00\x23\x2B\x60\xF0\xBD\xE0\x18\x53\xF8\x04\x7B\x07\x60\x37\x68"
+ "\x01\x2F\xFC\xD1\x07\x68\x53\xF8\x04\x0C\x87\x42\xED\xD0\x4F\xF0"
+ "\xFF\x30\xED\xE7\x6F\xF0\x01\x00\xF0\xBD\x6F\xF0\x02\x00\xF0\xBD"
+ "\x50\x05\x00\x20\x04\xE5\x01\x40\x00\xE4\x01\x40\x00\x04\x00\x00"
+ "\x00\x00\x03\x00"
+ },
};
void *get_builtin_file(const char *name, size_t *sz) {