Began implementing SAM3-series flash programmer.
authorethereal <ethereal@ethv.net>
Sat, 8 Mar 2014 06:05:40 +0000 (23:05 -0700)
committerethereal <ethereal@ethv.net>
Sat, 8 Mar 2014 06:05:40 +0000 (23:05 -0700)
flash_specs [new file with mode: 0644]
programmer/.gitignore [new file with mode: 0644]
programmer/CMakeLists.txt [new file with mode: 0644]
programmer/Makefile [new file with mode: 0644]
programmer/src/CMakeLists.txt [new file with mode: 0644]
programmer/src/main.c [new file with mode: 0644]

diff --git a/flash_specs b/flash_specs
new file mode 100644 (file)
index 0000000..03815ad
--- /dev/null
@@ -0,0 +1,15 @@
+FL_ID:          0xf0711
+FL_SIZE:        0x20000
+FL_PAGE_SIZE:   0x100
+FL_NB_PLANE:    0x1
+FL_PLANE[0]:    0x20000
+FL_NB_LOCK:     0x8
+FL_LOCK[0]:     0x4000
+FL_LOCK[1]:     0x4000
+FL_LOCK[2]:     0x4000
+FL_LOCK[3]:     0x4000
+FL_LOCK[4]:     0x4000
+FL_LOCK[5]:     0x4000
+FL_LOCK[6]:     0x4000
+FL_LOCK[7]:     0x4000
+Extra word: 9
diff --git a/programmer/.gitignore b/programmer/.gitignore
new file mode 100644 (file)
index 0000000..c779f7e
--- /dev/null
@@ -0,0 +1,14 @@
+*~
+*.swp
+
+.vimrc
+.ycm*
+.gdb_history
+.clang_complete
+
+# Executable
+/programmer
+/build/
+core
+
+
diff --git a/programmer/CMakeLists.txt b/programmer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9164555
--- /dev/null
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.6)
+
+#set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/)
+
+project(programmer C CXX)
+
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
+
+add_subdirectory(src)
diff --git a/programmer/Makefile b/programmer/Makefile
new file mode 100644 (file)
index 0000000..0ac7f01
--- /dev/null
@@ -0,0 +1,16 @@
+.PHONY: all
+all:
+       $(MAKE) -C build
+
+.PHONY: redep
+redep:
+       mkdir -p build/ ; cd build/ ; cmake .. ; cd ..
+
+.PHONY: clean
+clean:
+       $(MAKE) -C build clean
+
+.PHONY: distclean
+distclean:
+       $(MAKE) -C build clean
+       rm -rf build
diff --git a/programmer/src/CMakeLists.txt b/programmer/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c75a587
--- /dev/null
@@ -0,0 +1,7 @@
+add_definitions(-Wextra -Wall -std=gnu99)
+
+aux_source_directory(. dotSources)
+
+add_executable(programmer ${dotSources})
+
+target_link_libraries(programmer m)
diff --git a/programmer/src/main.c b/programmer/src/main.c
new file mode 100644 (file)
index 0000000..27b8558
--- /dev/null
@@ -0,0 +1,109 @@
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define FLASH_BASE 0x400000
+#define PAGE_SIZE 0x100
+
+struct {
+    const char *serial_path;
+    int serial_fd;
+} state;
+
+static void pabort(const char *what) {
+    perror(what);
+    abort();
+}
+
+static void serial_init();
+static void serial_close();
+static void serial_send(const void *data, size_t bytes);
+
+static void program_page(uint32_t pageid, const void *data, uint32_t bytes);
+
+int main(int argc, char *argv[]) {
+    state.serial_path = "/dev/ttyAMA0";
+    serial_init();
+
+    int fd = open(argv[1], O_RDONLY);
+    size_t data_size = lseek(fd, 0, SEEK_END);
+    uint8_t *data = malloc(data_size);
+    lseek(fd, 0, SEEK_SET);
+    read(fd, data, data_size);
+    close(fd);
+
+    /*for(size_t i = 0x800; i < data_size; i ++) {
+        char buffer[32];
+        sprintf(buffer, "O%lx,%x#", offset + i, data[i]);
+
+        serial_send(buffer, strlen(buffer));
+    }*/
+
+    for(size_t i = 0; i < data_size; i += PAGE_SIZE) {
+        program_page(i/PAGE_SIZE, data + i, data_size-i);
+    }
+
+    serial_close();
+
+    return 0;
+}
+
+static void serial_init() {
+    state.serial_fd = open(state.serial_path, O_RDWR | O_NDELAY | O_NOCTTY);
+    if(state.serial_fd == -1) pabort("open");
+
+    struct termios options;
+       tcgetattr(state.serial_fd, &options);
+       options.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+       options.c_iflag = IGNPAR;
+       options.c_oflag = 0;
+       options.c_lflag = 0;
+       tcflush(state.serial_fd, TCIFLUSH);
+       tcsetattr(state.serial_fd, TCSANOW, &options);
+}
+
+static void serial_close() {
+    close(state.serial_fd);
+    state.serial_fd = -1;
+}
+
+static void serial_send(const void *data, size_t bytes) {
+    size_t off = 0;
+    while(off < bytes) {
+        int ret = write(state.serial_fd, (const uint8_t *)data + off, bytes-off);
+        if(ret < 0 && (errno != EAGAIN && errno != EWOULDBLOCK)) {
+            pabort("write");
+        }
+        else if(ret > 0) off += ret;
+    }
+}
+
+static void serial_recv(const void *data, size_t bytes) {
+    
+}
+
+#define FLASH_REG_BASE 0x400e0a00
+#define FLASH_REG_FMR FLASH_REG_BASE + 0x0
+#define FLASH_REG_FCR FLASH_REG_BASE + 0x4
+#define FLASH_REG_FSR FLASH_REG_BASE + 0x8
+#define FLASH_REG_FRR FLASH_REG_BASE + 0xc
+
+static void program_page(uint32_t pageid, const void *data, uint32_t bytes) {
+    // write into latch buffer
+    for(size_t i = 0; i < PAGE_SIZE && i < bytes; i ++) {
+        char buffer[32];
+        sprintf(buffer, "O%lx,%x#", FLASH_BASE + pageid*PAGE_SIZE + i, ((uint8_t *)data)[i]);
+
+        serial_send(buffer, strlen(buffer));
+    }
+
+    // send erase-and-write command
+    char buffer[32];
+    sprintf(buffer, "W%x,%x#", FLASH_REG_FMR, 0x5a000003 | (pageid<<8));
+    serial_send(buffer, strlen(buffer));
+}