Partially implement proper flash storage.

This commit is contained in:
Damien 2013-10-18 23:44:05 +01:00
parent 5ac1b2efbd
commit 995b8aabb1
10 changed files with 325 additions and 141 deletions

View File

@ -14,7 +14,9 @@ SRC_C = \
main.c \ main.c \
printf.c \ printf.c \
system_stm32f4xx.c \ system_stm32f4xx.c \
led.c \
flash.c \ flash.c \
storage.c \
string0.c \ string0.c \
malloc0.c \ malloc0.c \
stm32fxxx_it.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 all: $(BUILD) $(BUILD)/flash.dfu
$(BUILD)/flash.dfu: $(BUILD)/flash.bin $(BUILD)/flash.dfu: $(BUILD)/flash0.bin $(BUILD)/flash1.bin
python2 ~/stm/dfu/dfu.py -b 0x08000000:$< $@ python2 ~/stm/dfu/dfu.py -b 0x08000000:$(BUILD)/flash0.bin -b 0x08020000:$(BUILD)/flash1.bin $@
$(BUILD)/flash.bin: $(BUILD)/flash.elf $(BUILD)/flash0.bin: $(BUILD)/flash.elf
arm-none-eabi-objcopy -O binary -j .isr_vector -j .text -j .data $^ $@ 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) $(BUILD)/flash.elf: $(OBJ)
$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LD) $(LDFLAGS) -o $@ $(OBJ)

View File

@ -1,5 +1,7 @@
#include <stdio.h>
#include <stm32f4xx.h> #include <stm32f4xx.h>
#include <stm32f4xx_flash.h> #include <stm32f4xx_flash.h>
#include "flash.h"
/* Base address of the Flash sectors */ /* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ #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_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 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) { void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
// unlock // 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); 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 // 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. /* Error occurred while sector erase.
User can add here some code to deal with this error */ User can add here some code to deal with this error */
return; return;
@ -51,59 +119,3 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32)
// lock // lock
FLASH_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;
}

2
stm/flash.h Normal file
View File

@ -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);

47
stm/led.c Normal file
View File

@ -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;
}
}

9
stm/led.h Normal file
View File

@ -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);

View File

@ -2,6 +2,9 @@
#include <stm32f4xx_rcc.h> #include <stm32f4xx_rcc.h>
#include "std.h" #include "std.h"
#include "misc.h"
#include "led.h"
#include "storage.h"
#include "font_petme128_8x8.h" #include "font_petme128_8x8.h"
void delay_ms(int ms); 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; 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) { 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->MODER, 2 * pin, 3, moder);
set_bits(&gpio->OTYPER, pin, 1, otyper); set_bits(&gpio->OTYPER, pin, 1, otyper);
@ -163,37 +159,6 @@ static void mma_stop() {
I2C1->CR1 |= I2C_CR1_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 (GPIOA)
#define PYB_USRSW_PORT_NUM (13) #define PYB_USRSW_PORT_NUM (13)
@ -402,11 +367,11 @@ void __fatal_error(const char *msg) {
lcd_print_strn(msg, strlen(msg)); lcd_print_strn(msg, strlen(msg));
for (;;) { for (;;) {
led_state(PYB_LEDR1_PORT_NUM, 1); led_state(PYB_LED_R1, 1);
led_state(PYB_LEDR2_PORT_NUM, 0); led_state(PYB_LED_R2, 0);
delay_ms(150); delay_ms(150);
led_state(PYB_LEDR1_PORT_NUM, 0); led_state(PYB_LED_R1, 0);
led_state(PYB_LEDR2_PORT_NUM, 1); led_state(PYB_LED_R2, 1);
delay_ms(150); 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) { 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; return state;
} }
@ -471,12 +436,8 @@ void nlr_test() {
} }
*/ */
int dummy_bss;
int main() { int main() {
int dummy; // TODO disable JTAG
// should disable JTAG
qstr_init(); qstr_init();
rt_init(); rt_init();
@ -485,25 +446,26 @@ int main() {
led_init(); led_init();
sw_init(); sw_init();
lcd_init(); lcd_init();
storage_init();
// print a message // print a message
printf(" micro py board\n"); printf(" micro py board\n");
// flash to indicate we are alive! // flash to indicate we are alive!
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
led_state(PYB_LEDR1_PORT_NUM, 1); led_state(PYB_LED_R1, 1);
led_state(PYB_LEDR2_PORT_NUM, 0); led_state(PYB_LED_R2, 0);
delay_ms(100); delay_ms(100);
led_state(PYB_LEDR1_PORT_NUM, 0); led_state(PYB_LED_R1, 0);
led_state(PYB_LEDR2_PORT_NUM, 1); led_state(PYB_LED_R2, 1);
delay_ms(100); delay_ms(100);
} }
// turn LEDs off // turn LEDs off
led_state(PYB_LEDR1_PORT_NUM, 0); led_state(PYB_LED_R1, 0);
led_state(PYB_LEDR2_PORT_NUM, 0); led_state(PYB_LED_R2, 0);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
led_state(PYB_LEDG2_PORT_NUM, 0); led_state(PYB_LED_G2, 0);
// get and print clock speeds // get and print clock speeds
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
@ -522,10 +484,12 @@ int main() {
usb_init(); usb_init();
} }
/*
// to print info about memory
for (;;) { for (;;) {
led_state(PYB_LEDG1_PORT_NUM, 1); led_state(PYB_LED_G1, 1);
delay_ms(100); delay_ms(100);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
extern void *_sidata; extern void *_sidata;
extern void *_sdata; extern void *_sdata;
extern void *_edata; extern void *_edata;
@ -543,14 +507,11 @@ int main() {
printf("_estack=%p\n", &_estack); printf("_estack=%p\n", &_estack);
printf("_etext=%p\n", &_etext); printf("_etext=%p\n", &_etext);
printf("_heap_start=%p\n", &_heap_start); 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(1000);
} }
delay_ms(500); delay_ms(500);
} }
*/
//printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init
//delay_ms(1000); //delay_ms(1000);
@ -662,7 +623,7 @@ int main() {
printf("pars;al=%u\n", m_get_total_bytes_allocated()); printf("pars;al=%u\n", m_get_total_bytes_allocated());
delay_ms(1000); delay_ms(1000);
//parse_node_show(pn, 0); //parse_node_show(pn, 0);
py_compile(pn); py_compile(pn, false);
printf("comp;al=%u\n", m_get_total_bytes_allocated()); printf("comp;al=%u\n", m_get_total_bytes_allocated());
delay_ms(1000); delay_ms(1000);
@ -677,9 +638,9 @@ int main() {
py_obj_t module_fun = rt_make_function_from_id(1); py_obj_t module_fun = rt_make_function_from_id(1);
// flash once // flash once
led_state(PYB_LEDG1_PORT_NUM, 1); led_state(PYB_LED_G1, 1);
delay_ms(100); delay_ms(100);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
nlr_buf_t nlr; nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) { if (nlr_push(&nlr) == 0) {
@ -696,9 +657,9 @@ int main() {
} }
// flash once // flash once
led_state(PYB_LEDG1_PORT_NUM, 1); led_state(PYB_LED_G1, 1);
delay_ms(100); delay_ms(100);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
delay_ms(1000); delay_ms(1000);
printf("nalloc=%u\n", m_get_total_bytes_allocated()); printf("nalloc=%u\n", m_get_total_bytes_allocated());
@ -710,13 +671,13 @@ int main() {
// benchmark C version of impl02.py // benchmark C version of impl02.py
if (0) { if (0) {
led_state(PYB_LEDG1_PORT_NUM, 1); led_state(PYB_LED_G1, 1);
delay_ms(100); delay_ms(100);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
impl02_c_version(); impl02_c_version();
led_state(PYB_LEDG1_PORT_NUM, 1); led_state(PYB_LED_G1, 1);
delay_ms(100); delay_ms(100);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
} }
// MMA testing // MMA testing
@ -834,8 +795,8 @@ int main() {
for (;;) { for (;;) {
delay_ms(10); delay_ms(10);
if (sw_get()) { if (sw_get()) {
led_state(PYB_LEDR1_PORT_NUM, 1); led_state(PYB_LED_R1, 1);
led_state(PYB_LEDG1_PORT_NUM, 0); led_state(PYB_LED_G1, 0);
i = 1 - i; i = 1 - i;
if (i) { if (i) {
printf(" angel %05x.\n", n); printf(" angel %05x.\n", n);
@ -846,8 +807,8 @@ int main() {
} }
n += 1; n += 1;
} else { } else {
led_state(PYB_LEDR1_PORT_NUM, 0); led_state(PYB_LED_R1, 0);
led_state(PYB_LEDG1_PORT_NUM, 1); led_state(PYB_LED_G1, 1);
} }
} }

View File

@ -6,7 +6,7 @@ static uint32_t mem = 0;
void *malloc(size_t n) { void *malloc(size_t n) {
if (mem == 0) { if (mem == 0) {
extern uint32_t _heap_start; 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; void *ptr = (void*)mem;
mem = (mem + n + 3) & (~3); mem = (mem + n + 3) & (~3);

View File

@ -5,7 +5,9 @@
/* Specify the memory areas */ /* Specify the memory areas */
MEMORY 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 */ CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 0x010000 /* 64 KiB */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */
} }
@ -27,7 +29,7 @@ SECTIONS
KEEP(*(.isr_vector)) /* Startup code */ KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4); . = ALIGN(4);
} >FLASH } >FLASH_ISR
/* The program code and other data goes into FLASH */ /* The program code and other data goes into FLASH */
.text : .text :
@ -43,7 +45,7 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
_etext = .; /* define a global symbol at end of code */ _etext = .; /* define a global symbol at end of code */
_sidata = _etext; /* This is used by the startup in order to initialize the .data secion */ _sidata = _etext; /* This is used by the startup in order to initialize the .data secion */
} >FLASH } >FLASH_TEXT
/* /*
.ARM.extab : .ARM.extab :

142
stm/storage.c Normal file
View File

@ -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;
}
}

4
stm/storage.h Normal file
View File

@ -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);