summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien <damien.p.george@gmail.com>2013-10-18 23:44:05 +0100
committerDamien <damien.p.george@gmail.com>2013-10-18 23:44:05 +0100
commit995b8aabb1ee786a4070d6d8392750ff878d53fa (patch)
tree94a997dc8a4e6e89d048786fb6812a12bc99f4b8
parent5ac1b2efbd5dfb2a62fe984dc9dc8a7127fb5e82 (diff)
downloadmicropython-995b8aabb1ee786a4070d6d8392750ff878d53fa.tar.gz
micropython-995b8aabb1ee786a4070d6d8392750ff878d53fa.zip
Partially implement proper flash storage.
-rw-r--r--stm/Makefile13
-rw-r--r--stm/flash.c128
-rw-r--r--stm/flash.h2
-rw-r--r--stm/led.c47
-rw-r--r--stm/led.h9
-rw-r--r--stm/main.c111
-rw-r--r--stm/malloc0.c2
-rw-r--r--stm/stm32f405.ld8
-rw-r--r--stm/storage.c142
-rw-r--r--stm/storage.h4
10 files changed, 325 insertions, 141 deletions
diff --git a/stm/Makefile b/stm/Makefile
index ee1453da69..e2f6dba900 100644
--- a/stm/Makefile
+++ b/stm/Makefile
@@ -14,7 +14,9 @@ SRC_C = \
main.c \
printf.c \
system_stm32f4xx.c \
+ led.c \
flash.c \
+ storage.c \
string0.c \
malloc0.c \
stm32fxxx_it.c \
@@ -84,11 +86,14 @@ OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(PY_O) $(SRC_FATFS:.
all: $(BUILD) $(BUILD)/flash.dfu
-$(BUILD)/flash.dfu: $(BUILD)/flash.bin
- python2 ~/stm/dfu/dfu.py -b 0x08000000:$< $@
+$(BUILD)/flash.dfu: $(BUILD)/flash0.bin $(BUILD)/flash1.bin
+ python2 ~/stm/dfu/dfu.py -b 0x08000000:$(BUILD)/flash0.bin -b 0x08020000:$(BUILD)/flash1.bin $@
-$(BUILD)/flash.bin: $(BUILD)/flash.elf
- arm-none-eabi-objcopy -O binary -j .isr_vector -j .text -j .data $^ $@
+$(BUILD)/flash0.bin: $(BUILD)/flash.elf
+ arm-none-eabi-objcopy -O binary -j .isr_vector $^ $@
+
+$(BUILD)/flash1.bin: $(BUILD)/flash.elf
+ arm-none-eabi-objcopy -O binary -j .text -j .data $^ $@
$(BUILD)/flash.elf: $(OBJ)
$(LD) $(LDFLAGS) -o $@ $(OBJ)
diff --git a/stm/flash.c b/stm/flash.c
index 15dcea9f04..24dd3a1dcc 100644
--- a/stm/flash.c
+++ b/stm/flash.c
@@ -1,5 +1,7 @@
+#include <stdio.h>
#include <stm32f4xx.h>
#include <stm32f4xx_flash.h>
+#include "flash.h"
/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
@@ -15,7 +17,73 @@
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
-static uint32_t GetSector(uint32_t Address);
+static const uint32_t flash_info_table[26] = {
+ ADDR_FLASH_SECTOR_0, FLASH_Sector_0,
+ ADDR_FLASH_SECTOR_1, FLASH_Sector_1,
+ ADDR_FLASH_SECTOR_2, FLASH_Sector_2,
+ ADDR_FLASH_SECTOR_3, FLASH_Sector_3,
+ ADDR_FLASH_SECTOR_4, FLASH_Sector_4,
+ ADDR_FLASH_SECTOR_5, FLASH_Sector_5,
+ ADDR_FLASH_SECTOR_6, FLASH_Sector_6,
+ ADDR_FLASH_SECTOR_7, FLASH_Sector_7,
+ ADDR_FLASH_SECTOR_8, FLASH_Sector_8,
+ ADDR_FLASH_SECTOR_9, FLASH_Sector_9,
+ ADDR_FLASH_SECTOR_10, FLASH_Sector_10,
+ ADDR_FLASH_SECTOR_11, FLASH_Sector_11,
+ ADDR_FLASH_SECTOR_11 + 0x20000, 0,
+};
+
+uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) {
+ if (addr >= flash_info_table[0]) {
+ for (int i = 0; i < 24; i += 2) {
+ if (addr < flash_info_table[i + 2]) {
+ if (start_addr != NULL) {
+ *start_addr = flash_info_table[i];
+ }
+ if (size != NULL) {
+ *size = flash_info_table[i + 2] - flash_info_table[i];
+ }
+ return flash_info_table[i + 1];
+ }
+ }
+ }
+ return 0;
+}
+
+#if 0
+/**
+ * @brief Gets the sector of a given address
+ * @param None
+ * @retval The sector of a given address
+ */
+uint32_t flash_get_sector(uint32_t addr) {
+ if ((addr < ADDR_FLASH_SECTOR_1) && (addr >= ADDR_FLASH_SECTOR_0)) {
+ return FLASH_Sector_0;
+ } else if ((addr < ADDR_FLASH_SECTOR_2) && (addr >= ADDR_FLASH_SECTOR_1)) {
+ return FLASH_Sector_1;
+ } else if ((addr < ADDR_FLASH_SECTOR_3) && (addr >= ADDR_FLASH_SECTOR_2)) {
+ return FLASH_Sector_2;
+ } else if ((addr < ADDR_FLASH_SECTOR_4) && (addr >= ADDR_FLASH_SECTOR_3)) {
+ return FLASH_Sector_3;
+ } else if ((addr < ADDR_FLASH_SECTOR_5) && (addr >= ADDR_FLASH_SECTOR_4)) {
+ return FLASH_Sector_4;
+ } else if ((addr < ADDR_FLASH_SECTOR_6) && (addr >= ADDR_FLASH_SECTOR_5)) {
+ return FLASH_Sector_5;
+ } else if ((addr < ADDR_FLASH_SECTOR_7) && (addr >= ADDR_FLASH_SECTOR_6)) {
+ return FLASH_Sector_6;
+ } else if ((addr < ADDR_FLASH_SECTOR_8) && (addr >= ADDR_FLASH_SECTOR_7)) {
+ return FLASH_Sector_7;
+ } else if ((addr < ADDR_FLASH_SECTOR_9) && (addr >= ADDR_FLASH_SECTOR_8)) {
+ return FLASH_Sector_8;
+ } else if ((addr < ADDR_FLASH_SECTOR_10) && (addr >= ADDR_FLASH_SECTOR_9)) {
+ return FLASH_Sector_9;
+ } else if ((addr < ADDR_FLASH_SECTOR_11) && (addr >= ADDR_FLASH_SECTOR_10)) {
+ return FLASH_Sector_10;
+ } else {
+ return FLASH_Sector_11;
+ }
+}
+#endif
void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
// unlock
@@ -26,7 +94,7 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32)
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
// Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word
- if (FLASH_EraseSector(GetSector(flash_dest), VoltageRange_3) != FLASH_COMPLETE) {
+ if (FLASH_EraseSector(flash_get_sector_info(flash_dest, NULL, NULL), VoltageRange_3) != FLASH_COMPLETE) {
/* Error occurred while sector erase.
User can add here some code to deal with this error */
return;
@@ -51,59 +119,3 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32)
// lock
FLASH_Lock();
}
-
-/**
- * @brief Gets the sector of a given address
- * @param None
- * @retval The sector of a given address
- */
-static uint32_t GetSector(uint32_t Address)
-{
- uint32_t sector = 0;
-
- if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
- {
- sector = FLASH_Sector_0;
- }
- else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
- {
- sector = FLASH_Sector_1;
- }
- else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
- {
- sector = FLASH_Sector_2;
- }
- else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
- {
- sector = FLASH_Sector_3;
- }
- else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
- {
- sector = FLASH_Sector_4;
- }
- else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
- {
- sector = FLASH_Sector_5;
- }
- else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
- {
- sector = FLASH_Sector_6;
- }
- else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
- {
- sector = FLASH_Sector_7;
- }
- else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
- {
- sector = FLASH_Sector_8;
- }
- else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
- {
- sector = FLASH_Sector_9;
- }
- else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
- {
- sector = FLASH_Sector_10;
- }
- return sector;
-}
diff --git a/stm/flash.h b/stm/flash.h
new file mode 100644
index 0000000000..33d31df7a6
--- /dev/null
+++ b/stm/flash.h
@@ -0,0 +1,2 @@
+uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size);
+void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32);
diff --git a/stm/led.c b/stm/led.c
new file mode 100644
index 0000000000..a6255540f3
--- /dev/null
+++ b/stm/led.c
@@ -0,0 +1,47 @@
+#include <stm32f4xx.h>
+#include <stm32f4xx_gpio.h>
+#include "led.h"
+
+#define PYB_LED_R_PORT (GPIOA)
+#define PYB_LED_R1_PIN (GPIO_Pin_8)
+#define PYB_LED_R2_PIN (GPIO_Pin_10)
+#define PYB_LED_G_PORT (GPIOC)
+#define PYB_LED_G1_PIN (GPIO_Pin_4)
+#define PYB_LED_G2_PIN (GPIO_Pin_5)
+
+void led_init() {
+ // set the output high (so LED is off)
+ PYB_LED_R_PORT->BSRRL = PYB_LED_R1_PIN;
+ PYB_LED_R_PORT->BSRRL = PYB_LED_R2_PIN;
+ PYB_LED_G_PORT->BSRRL = PYB_LED_G1_PIN;
+ PYB_LED_G_PORT->BSRRL = PYB_LED_G2_PIN;
+ // make them open drain outputs
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = PYB_LED_R1_PIN | PYB_LED_R2_PIN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_Init(PYB_LED_R_PORT, &GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Pin = PYB_LED_G1_PIN | PYB_LED_G2_PIN;
+ GPIO_Init(PYB_LED_G_PORT, &GPIO_InitStructure);
+}
+
+void led_state(pyb_led_t led, int state) {
+ GPIO_TypeDef *port;
+ uint32_t pin;
+ switch (led) {
+ case PYB_LED_R1: port = PYB_LED_R_PORT; pin = PYB_LED_R1_PIN; break;
+ case PYB_LED_R2: port = PYB_LED_R_PORT; pin = PYB_LED_R2_PIN; break;
+ case PYB_LED_G1: port = PYB_LED_G_PORT; pin = PYB_LED_G1_PIN; break;
+ case PYB_LED_G2: port = PYB_LED_G_PORT; pin = PYB_LED_G2_PIN; break;
+ default: return;
+ }
+ if (state == 0) {
+ // LED off, output is high
+ port->BSRRL = pin;
+ } else {
+ // LED on, output is low
+ port->BSRRH = pin;
+ }
+}
diff --git a/stm/led.h b/stm/led.h
new file mode 100644
index 0000000000..aba00133de
--- /dev/null
+++ b/stm/led.h
@@ -0,0 +1,9 @@
+typedef enum {
+ PYB_LED_R1 = 0,
+ PYB_LED_R2 = 1,
+ PYB_LED_G1 = 2,
+ PYB_LED_G2 = 3,
+} pyb_led_t;
+
+void led_init();
+void led_state(pyb_led_t led, int state);
diff --git a/stm/main.c b/stm/main.c
index a45a90c5ec..1e973cf0e6 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -2,6 +2,9 @@
#include <stm32f4xx_rcc.h>
#include "std.h"
+#include "misc.h"
+#include "led.h"
+#include "storage.h"
#include "font_petme128_8x8.h"
void delay_ms(int ms);
@@ -32,13 +35,6 @@ void gpio_init() {
RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOAEN;
}
-#define PYB_LEDR_PORT (GPIOA)
-#define PYB_LEDR1_PORT_NUM (8)
-#define PYB_LEDR2_PORT_NUM (10)
-#define PYB_LEDG_PORT (GPIOC)
-#define PYB_LEDG1_PORT_NUM (4)
-#define PYB_LEDG2_PORT_NUM (5)
-
void gpio_pin_init(GPIO_TypeDef *gpio, uint32_t pin, uint32_t moder, uint32_t otyper, uint32_t ospeedr, uint32_t pupdr) {
set_bits(&gpio->MODER, 2 * pin, 3, moder);
set_bits(&gpio->OTYPER, pin, 1, otyper);
@@ -163,37 +159,6 @@ static void mma_stop() {
I2C1->CR1 |= I2C_CR1_STOP;
}
-void led_init() {
- // set the output high (so LED is off)
- PYB_LEDR_PORT->BSRRL = 1 << PYB_LEDR1_PORT_NUM;
- PYB_LEDR_PORT->BSRRL = 1 << PYB_LEDR2_PORT_NUM;
- PYB_LEDG_PORT->BSRRL = 1 << PYB_LEDG1_PORT_NUM;
- PYB_LEDG_PORT->BSRRL = 1 << PYB_LEDG2_PORT_NUM;
- // make it an open drain output
- gpio_pin_init(PYB_LEDR_PORT, PYB_LEDR1_PORT_NUM, 1, 1, 0, 0);
- gpio_pin_init(PYB_LEDR_PORT, PYB_LEDR2_PORT_NUM, 1, 1, 0, 0);
- gpio_pin_init(PYB_LEDG_PORT, PYB_LEDG1_PORT_NUM, 1, 1, 0, 0);
- gpio_pin_init(PYB_LEDG_PORT, PYB_LEDG2_PORT_NUM, 1, 1, 0, 0);
-}
-
-static void led_state(uint32_t led_port, int s) {
- if (s == 0) {
- // LED off, output is high
- if (led_port == PYB_LEDR1_PORT_NUM || led_port == PYB_LEDR2_PORT_NUM) {
- PYB_LEDR_PORT->BSRRL = 1 << led_port;
- } else {
- PYB_LEDG_PORT->BSRRL = 1 << led_port;
- }
- } else {
- // LED on, output is low
- if (led_port == PYB_LEDR1_PORT_NUM || led_port == PYB_LEDR2_PORT_NUM) {
- PYB_LEDR_PORT->BSRRH = 1 << led_port;
- } else {
- PYB_LEDG_PORT->BSRRH = 1 << led_port;
- }
- }
-}
-
#define PYB_USRSW_PORT (GPIOA)
#define PYB_USRSW_PORT_NUM (13)
@@ -402,11 +367,11 @@ void __fatal_error(const char *msg) {
lcd_print_strn(msg, strlen(msg));
for (;;) {
- led_state(PYB_LEDR1_PORT_NUM, 1);
- led_state(PYB_LEDR2_PORT_NUM, 0);
+ led_state(PYB_LED_R1, 1);
+ led_state(PYB_LED_R2, 0);
delay_ms(150);
- led_state(PYB_LEDR1_PORT_NUM, 0);
- led_state(PYB_LEDR2_PORT_NUM, 1);
+ led_state(PYB_LED_R1, 0);
+ led_state(PYB_LED_R2, 1);
delay_ms(150);
}
}
@@ -424,7 +389,7 @@ py_obj_t pyb_delay(py_obj_t count) {
}
py_obj_t pyb_led(py_obj_t state) {
- led_state(PYB_LEDG1_PORT_NUM, rt_is_true(state));
+ led_state(PYB_LED_G1, rt_is_true(state));
return state;
}
@@ -471,12 +436,8 @@ void nlr_test() {
}
*/
-int dummy_bss;
-
int main() {
- int dummy;
-
- // should disable JTAG
+ // TODO disable JTAG
qstr_init();
rt_init();
@@ -485,25 +446,26 @@ int main() {
led_init();
sw_init();
lcd_init();
+ storage_init();
// print a message
printf(" micro py board\n");
// flash to indicate we are alive!
for (int i = 0; i < 2; i++) {
- led_state(PYB_LEDR1_PORT_NUM, 1);
- led_state(PYB_LEDR2_PORT_NUM, 0);
+ led_state(PYB_LED_R1, 1);
+ led_state(PYB_LED_R2, 0);
delay_ms(100);
- led_state(PYB_LEDR1_PORT_NUM, 0);
- led_state(PYB_LEDR2_PORT_NUM, 1);
+ led_state(PYB_LED_R1, 0);
+ led_state(PYB_LED_R2, 1);
delay_ms(100);
}
// turn LEDs off
- led_state(PYB_LEDR1_PORT_NUM, 0);
- led_state(PYB_LEDR2_PORT_NUM, 0);
- led_state(PYB_LEDG1_PORT_NUM, 0);
- led_state(PYB_LEDG2_PORT_NUM, 0);
+ led_state(PYB_LED_R1, 0);
+ led_state(PYB_LED_R2, 0);
+ led_state(PYB_LED_G1, 0);
+ led_state(PYB_LED_G2, 0);
// get and print clock speeds
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
@@ -522,10 +484,12 @@ int main() {
usb_init();
}
+ /*
+ // to print info about memory
for (;;) {
- led_state(PYB_LEDG1_PORT_NUM, 1);
+ led_state(PYB_LED_G1, 1);
delay_ms(100);
- led_state(PYB_LEDG1_PORT_NUM, 0);
+ led_state(PYB_LED_G1, 0);
extern void *_sidata;
extern void *_sdata;
extern void *_edata;
@@ -543,14 +507,11 @@ int main() {
printf("_estack=%p\n", &_estack);
printf("_etext=%p\n", &_etext);
printf("_heap_start=%p\n", &_heap_start);
- printf("&dummy=%p\n", &dummy);
- printf("&dummy_bss=%p\n", &dummy_bss);
- printf("dummy_bss=%x\n", dummy_bss);
- //printf("sizeof(int)=%d\n", sizeof(int)); // 4
delay_ms(1000);
}
delay_ms(500);
}
+ */
//printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init
//delay_ms(1000);
@@ -662,7 +623,7 @@ int main() {
printf("pars;al=%u\n", m_get_total_bytes_allocated());
delay_ms(1000);
//parse_node_show(pn, 0);
- py_compile(pn);
+ py_compile(pn, false);
printf("comp;al=%u\n", m_get_total_bytes_allocated());
delay_ms(1000);
@@ -677,9 +638,9 @@ int main() {
py_obj_t module_fun = rt_make_function_from_id(1);
// flash once
- led_state(PYB_LEDG1_PORT_NUM, 1);
+ led_state(PYB_LED_G1, 1);
delay_ms(100);
- led_state(PYB_LEDG1_PORT_NUM, 0);
+ led_state(PYB_LED_G1, 0);
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
@@ -696,9 +657,9 @@ int main() {
}
// flash once
- led_state(PYB_LEDG1_PORT_NUM, 1);
+ led_state(PYB_LED_G1, 1);
delay_ms(100);
- led_state(PYB_LEDG1_PORT_NUM, 0);
+ led_state(PYB_LED_G1, 0);
delay_ms(1000);
printf("nalloc=%u\n", m_get_total_bytes_allocated());
@@ -710,13 +671,13 @@ int main() {
// benchmark C version of impl02.py
if (0) {
- led_state(PYB_LEDG1_PORT_NUM, 1);
+ led_state(PYB_LED_G1, 1);
delay_ms(100);
- led_state(PYB_LEDG1_PORT_NUM, 0);
+ led_state(PYB_LED_G1, 0);
impl02_c_version();
- led_state(PYB_LEDG1_PORT_NUM, 1);
+ led_state(PYB_LED_G1, 1);
delay_ms(100);
- led_state(PYB_LEDG1_PORT_NUM, 0);
+ led_state(PYB_LED_G1, 0);
}
// MMA testing
@@ -834,8 +795,8 @@ int main() {
for (;;) {
delay_ms(10);
if (sw_get()) {
- led_state(PYB_LEDR1_PORT_NUM, 1);
- led_state(PYB_LEDG1_PORT_NUM, 0);
+ led_state(PYB_LED_R1, 1);
+ led_state(PYB_LED_G1, 0);
i = 1 - i;
if (i) {
printf(" angel %05x.\n", n);
@@ -846,8 +807,8 @@ int main() {
}
n += 1;
} else {
- led_state(PYB_LEDR1_PORT_NUM, 0);
- led_state(PYB_LEDG1_PORT_NUM, 1);
+ led_state(PYB_LED_R1, 0);
+ led_state(PYB_LED_G1, 1);
}
}
diff --git a/stm/malloc0.c b/stm/malloc0.c
index 1b45846e6f..fc0267911d 100644
--- a/stm/malloc0.c
+++ b/stm/malloc0.c
@@ -6,7 +6,7 @@ static uint32_t mem = 0;
void *malloc(size_t n) {
if (mem == 0) {
extern uint32_t _heap_start;
- mem = &_heap_start; // need to use big ram block so we can execute code from it (is it true that we can't execute from CCM?)
+ mem = (uint32_t)&_heap_start; // need to use big ram block so we can execute code from it (is it true that we can't execute from CCM?)
}
void *ptr = (void*)mem;
mem = (mem + n + 3) & (~3);
diff --git a/stm/stm32f405.ld b/stm/stm32f405.ld
index cca49bfbd2..5dfa8c145d 100644
--- a/stm/stm32f405.ld
+++ b/stm/stm32f405.ld
@@ -5,7 +5,9 @@
/* Specify the memory areas */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x100000 /* 1 MiB */
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x100000 /* entire flash, 1 MiB */
+ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 0x004000 /* sector 0, 16 KiB */
+ FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 0x020000 /* sector 5, 128 KiB */
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 0x010000 /* 64 KiB */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */
}
@@ -27,7 +29,7 @@ SECTIONS
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
- } >FLASH
+ } >FLASH_ISR
/* The program code and other data goes into FLASH */
.text :
@@ -43,7 +45,7 @@ SECTIONS
. = ALIGN(4);
_etext = .; /* define a global symbol at end of code */
_sidata = _etext; /* This is used by the startup in order to initialize the .data secion */
- } >FLASH
+ } >FLASH_TEXT
/*
.ARM.extab :
diff --git a/stm/storage.c b/stm/storage.c
new file mode 100644
index 0000000000..56ade79773
--- /dev/null
+++ b/stm/storage.c
@@ -0,0 +1,142 @@
+#include <stdint.h>
+#include "std.h"
+
+#include "misc.h"
+#include "led.h"
+#include "flash.h"
+#include "storage.h"
+
+#define BLOCK_SIZE (512)
+#define CACHE_MEM_START_ADDR (0x10000000) // CCM data RAM, 64k
+#define FLASH_PART1_START_BLOCK (0x100)
+#define FLASH_PART1_NUM_BLOCKS (224) // 16k+16k+16k+64k=112k
+#define FLASH_MEM_START_ADDR (0x08004000) // sector 1, 16k
+
+static bool is_initialised = false;
+static uint32_t cache_flash_sector_id;
+static uint32_t cache_flash_sector_start;
+static uint32_t cache_flash_sector_size;
+static bool cache_dirty;
+
+static void cache_flush() {
+ if (cache_dirty) {
+ // sync the cache RAM buffer by writing it to the flash page
+ flash_write(cache_flash_sector_start, (const uint32_t*)CACHE_MEM_START_ADDR, cache_flash_sector_size / 4);
+ cache_dirty = false;
+ // indicate a clean cache with LED off
+ led_state(PYB_LED_R1, 0);
+ }
+}
+
+static uint8_t *cache_get_addr_for_write(uint32_t flash_addr) {
+ uint32_t flash_sector_start;
+ uint32_t flash_sector_size;
+ uint32_t flash_sector_id = flash_get_sector_info(flash_addr, &flash_sector_start, &flash_sector_size);
+ if (cache_flash_sector_id != flash_sector_id) {
+ cache_flush();
+ memcpy((void*)CACHE_MEM_START_ADDR, (const void*)flash_sector_start, flash_sector_size);
+ cache_flash_sector_id = flash_sector_id;
+ cache_flash_sector_start = flash_sector_start;
+ cache_flash_sector_size = flash_sector_size;
+ }
+ cache_dirty = true;
+ // indicate a dirty cache with LED on
+ led_state(PYB_LED_R1, 1);
+ return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
+}
+
+void storage_init() {
+ cache_flash_sector_id = 0;
+ cache_dirty = false;
+ is_initialised = true;
+}
+
+void storage_flush() {
+ cache_flush();
+}
+
+static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) {
+ buf[0] = boot;
+
+ if (num_blocks == 0) {
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ } else {
+ buf[1] = 0xff;
+ buf[2] = 0xff;
+ buf[3] = 0xff;
+ }
+
+ buf[4] = type;
+
+ if (num_blocks == 0) {
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+ } else {
+ buf[5] = 0xff;
+ buf[6] = 0xff;
+ buf[7] = 0xff;
+ }
+
+ buf[8] = start_block;
+ buf[9] = start_block >> 8;
+ buf[10] = start_block >> 16;
+ buf[11] = start_block >> 24;
+
+ buf[12] = num_blocks;
+ buf[13] = num_blocks >> 8;
+ buf[14] = num_blocks >> 16;
+ buf[15] = num_blocks >> 24;
+}
+
+bool storage_read_block(uint8_t *dest, uint32_t block) {
+ //printf("RD %u\n", block);
+ if (block == 0) {
+ // fake the MBR so we can decide on our own partition table
+
+ for (int i = 0; i < 446; i++) {
+ dest[i] = 0;
+ }
+
+ build_partition(dest + 446, 0, 0x01 /* FAT12 */, FLASH_PART1_START_BLOCK, FLASH_PART1_NUM_BLOCKS);
+ build_partition(dest + 462, 0, 0, 0, 0);
+ build_partition(dest + 478, 0, 0, 0, 0);
+ build_partition(dest + 494, 0, 0, 0, 0);
+
+ dest[510] = 0x55;
+ dest[511] = 0xaa;
+
+ return true;
+
+ } else if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
+ // non-MBR block, just copy straight from flash
+ uint8_t *src = (uint8_t*)FLASH_MEM_START_ADDR + (block - FLASH_PART1_START_BLOCK) * BLOCK_SIZE;
+ memcpy(dest, src, BLOCK_SIZE);
+ return true;
+
+ } else {
+ // bad block number
+ return false;
+ }
+}
+
+bool storage_write_block(const uint8_t *src, uint32_t block) {
+ //printf("WR %u\n", block);
+ if (block == 0) {
+ // can't write MBR, but pretend we did
+ return true;
+
+ } else if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
+ // non-MBR block, copy to cache
+ uint32_t flash_addr = FLASH_MEM_START_ADDR + (block - FLASH_PART1_START_BLOCK) * BLOCK_SIZE;
+ uint8_t *dest = cache_get_addr_for_write(flash_addr);
+ memcpy(dest, src, BLOCK_SIZE);
+ return true;
+
+ } else {
+ // bad block number
+ return false;
+ }
+}
diff --git a/stm/storage.h b/stm/storage.h
new file mode 100644
index 0000000000..542329e4ba
--- /dev/null
+++ b/stm/storage.h
@@ -0,0 +1,4 @@
+void storage_init();
+void storage_flush();
+bool storage_read_block(uint8_t *dest, uint32_t block);
+bool storage_write_block(const uint8_t *src, uint32_t block);