From 995b8aabb1ee786a4070d6d8392750ff878d53fa Mon Sep 17 00:00:00 2001 From: Damien Date: Fri, 18 Oct 2013 23:44:05 +0100 Subject: [PATCH] Partially implement proper flash storage. --- stm/Makefile | 13 +++-- stm/flash.c | 128 +++++++++++++++++++++++------------------- stm/flash.h | 2 + stm/led.c | 47 ++++++++++++++++ stm/led.h | 9 +++ stm/main.c | 111 ++++++++++++------------------------ stm/malloc0.c | 2 +- stm/stm32f405.ld | 8 ++- stm/storage.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++ stm/storage.h | 4 ++ 10 files changed, 325 insertions(+), 141 deletions(-) create mode 100644 stm/flash.h create mode 100644 stm/led.c create mode 100644 stm/led.h create mode 100644 stm/storage.c create mode 100644 stm/storage.h 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 #include #include +#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 +#include +#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 #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 +#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);