Partially implement proper flash storage.
This commit is contained in:
parent
5ac1b2efbd
commit
995b8aabb1
13
stm/Makefile
13
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)
|
||||
|
128
stm/flash.c
128
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;
|
||||
}
|
||||
|
2
stm/flash.h
Normal file
2
stm/flash.h
Normal 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
47
stm/led.c
Normal 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
9
stm/led.h
Normal 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);
|
111
stm/main.c
111
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 :
|
||||
|
142
stm/storage.c
Normal file
142
stm/storage.c
Normal 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
4
stm/storage.h
Normal 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);
|
Loading…
Reference in New Issue
Block a user