summaryrefslogtreecommitdiff
path: root/fw/fe310/phone/flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/fe310/phone/flash.c')
-rw-r--r--fw/fe310/phone/flash.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/fw/fe310/phone/flash.c b/fw/fe310/phone/flash.c
new file mode 100644
index 0000000..e78576a
--- /dev/null
+++ b/fw/fe310/phone/flash.c
@@ -0,0 +1,160 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <encoding.h>
+#include <platform.h>
+
+#include <eos.h>
+
+#include <soc/timer.h>
+#include <dev/flash.h>
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+#include "app/status.h"
+
+#include "flash.h"
+
+static const uint8_t magic[] =
+ {0x2D, 0xC0, 0x3B, 0x5F, 0xEA, 0xE3, 0x1A, 0x3A, 0x83, 0x11, 0x6A, 0x33, 0x98, 0x46, 0x1C, 0x47};
+
+#define ACK 0x05
+#define NACK 0x0A
+#define BLK_SIZE 256
+
+__attribute__ ((section (".itim")))
+static uint32_t crc32x(unsigned char *buf, size_t len, uint32_t crc) {
+ int i;
+
+ crc = ~crc;
+ while (len--) {
+ crc ^= *buf++;
+ for (i=0; i<8; i++) {
+ uint32_t t = ~((crc & 1) - 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & t);
+ }
+ }
+
+ return ~crc;
+}
+
+__attribute__ ((section (".itim")))
+void flash_write(void) {
+ volatile uint32_t r;
+ uint32_t crc32, crc32_b;
+ uint32_t addr;
+ uint8_t buf[BLK_SIZE + 2 * sizeof(uint32_t)];
+ int i;
+
+ clear_csr(mstatus, MSTATUS_MIE);
+ SPI0_REG(SPI_REG_FCTRL) = 0;
+ SPI0_REG(SPI_REG_FMT) &= ~SPI_FMT_DIR(SPI_DIR_TX);
+
+ do {
+ for (i=0; i<sizeof(buf); i++) {
+ while ((r = UART0_REG(UART_REG_RXFIFO)) & 0x80000000);
+ buf[i] = r;
+ }
+
+ addr = 0;
+ addr |= (uint32_t)buf[0] << 24;
+ addr |= (uint32_t)buf[1] << 16;
+ addr |= (uint32_t)buf[2] << 8;
+ addr |= (uint32_t)buf[3];
+
+ crc32_b = 0;
+ crc32_b |= (uint32_t)buf[BLK_SIZE + 4] << 24;
+ crc32_b |= (uint32_t)buf[BLK_SIZE + 5] << 16;
+ crc32_b |= (uint32_t)buf[BLK_SIZE + 6] << 8;
+ crc32_b |= (uint32_t)buf[BLK_SIZE + 7];
+ crc32 = crc32x(buf, BLK_SIZE + sizeof(uint32_t), 0xffffffff);
+ if (crc32 != crc32_b) {
+ *buf = NACK;
+ goto write_rep;
+ }
+
+ if (addr != -1) {
+ if (addr % 4096 == 0) {
+ eos_flash_wren();
+ eos_flash_ser(addr);
+ eos_flash_wip();
+ }
+ eos_flash_wren();
+ eos_flash_pp(addr, buf + sizeof(uint32_t));
+ eos_flash_wip();
+ }
+ *buf = ACK;
+write_rep:
+ while (UART0_REG(UART_REG_TXFIFO) & 0x80000000);
+ UART0_REG(UART_REG_TXFIFO) = *buf;
+ } while (addr != -1);
+
+ while(1);
+}
+
+void flash_write_init(void) {
+ volatile uint32_t r;
+ uint8_t buf[sizeof(magic)];
+ int i;
+
+ while (!(UART0_REG(UART_REG_RXFIFO) & 0x80000000));
+ app_status_set_msg("READY!");
+ eve_window_root_draw(app_root());
+
+ for (i=0; i<sizeof(magic); i++) {
+ while ((r = UART0_REG(UART_REG_RXFIFO)) & 0x80000000);
+ buf[i] = r;
+ }
+ if (memcmp(buf, magic, sizeof(magic)) == 0) {
+ *buf = ACK;
+ app_status_set_msg("FLASH START");
+ } else {
+ *buf = NACK;
+ app_status_set_msg("FLASH FAIL");
+ }
+ eve_window_root_draw(app_root());
+
+ while (UART0_REG(UART_REG_TXFIFO) & 0x80000000);
+ UART0_REG(UART_REG_TXFIFO) = *buf;
+}
+
+int flash_app(EVEWindow *window, EVEViewStack *stack) {
+ EVEFormSpec spec[] = {
+ APP_SPACERW(1,1),
+ };
+ EVEPage *page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), flash_uievt, flash_close);
+ if (page == NULL) return EVE_ERR_NOMEM;
+
+ return EVE_OK;
+}
+
+int flash_uievt(EVEPage *page, uint16_t evt, void *param) {
+ int ret = 0;
+
+ switch (evt) {
+ case EVE_UIEVT_GEST_TOUCH: {
+ flash_write_init();
+ flash_write();
+ break;
+ }
+
+ default: {
+ ret = eve_form_uievt(page, evt, param);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void flash_close(EVEPage *page) {
+ eve_form_destroy(page);
+}