Mercurial > ~darius > hgwebdir.cgi > stm32temp
changeset 27:5c9d2e3d6591
Add flashread/writeblock commands which read/write a block of data to
flash with a CRC.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Tue, 20 Nov 2012 21:54:06 +1030 |
parents | 74efdb21ae5d |
children | 7f8e5780024b |
files | BSDmakefile flash.c flash.h hw.c |
diffstat | 4 files changed, 191 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/BSDmakefile Sat Nov 17 18:03:48 2012 +1030 +++ b/BSDmakefile Tue Nov 20 21:54:06 2012 +1030 @@ -15,7 +15,7 @@ system_stm32f10x.c \ touch.c -STM32LIBS= usart gpio rcc rtc pwr bkp fsmc spi tim i2c +STM32LIBS= usart gpio rcc rtc pwr bkp fsmc spi tim i2c crc .for f in ${STM32LIBS} SRCS+= stm32f10x_${f}.c
--- a/flash.c Sat Nov 17 18:03:48 2012 +1030 +++ b/flash.c Tue Nov 20 21:54:06 2012 +1030 @@ -24,14 +24,80 @@ #define RW_IDLE 0 #define RW_RUNNING 1 -#define RW_IDLE 0 + +/* Holds all the settings needed */ +typedef struct { + uint8_t fermenter_ROM[8]; + uint8_t fridge_ROM[8]; + uint8_t ambient_ROM[8]; + int16_t target_temp; + uint16_t hysteresis; + /* How much to under/overshoot on heating/cooling */ + int16_t minheatovershoot; + int16_t mincoolovershoot; + + /* Minimum time the cooler can be on/off */ + int16_t mincoolontime; + int16_t mincoolofftime; + + /* Minimum time the heater can be on/off */ + int16_t minheatontime; + int16_t minheatofftime; + +#define TC_MODE_AUTO 'a' /* Automatic control */ +#define TC_MODE_HEAT 'h' /* Force heating */ +#define TC_MODE_COOL 'c' /* Force cooling */ +#define TC_MODE_IDLE 'i' /* Force idle */ +#define TC_MODE_NOTHING 'n' /* Do nothing (like idle but log nothing) */ + char mode; + /* Bit patterns for various modes */ + uint8_t coolbits; + uint8_t heatbits; + uint8_t idlebits; + + /* Check/stale times */ + int16_t check_interval; + int16_t stale_factor; + + /* Beep if stale */ + int8_t dobeep; + + /* Pad to 4 bytes */ + uint8_t pad[1]; + +} __attribute__((packed, aligned(4))) settings_t; + +const settings_t default_settings = { + .fermenter_ROM = { 0x10, 0x4c, 0x7d, 0x53, 0x01, 0x08, 0x00, 0xff }, + .fridge_ROM = { 0x10, 0x6f, 0x40, 0x53, 0x01, 0x08, 0x00, 0x16 }, + .ambient_ROM = { 0x10, 0x76, 0x05, 0x53, 0x01, 0x08, 0x00, 0x8c }, + .target_temp = 1000, + .hysteresis = 100, + .minheatovershoot = 50, + .mincoolovershoot = -50, + .mincoolontime = 300, + .mincoolofftime = 600, + .minheatontime = 60, + .minheatofftime = 60, + .mode = TC_MODE_AUTO, + .coolbits = 1 << 6, + .heatbits = 1<< 7, + .idlebits = 0x00, + .check_interval = 10, + .stale_factor = 3, + .dobeep = 0 +}; + +/* RAM copy of setting */ +static settings_t ram_settings; + static int writestate = RW_IDLE; static int readstate = RW_IDLE; void flashcmd(char **argv, int argc) { - uint8_t status, tmp; + uint8_t status, tmp, len; uint32_t addr; if (argc == 0) { @@ -66,27 +132,37 @@ flash4kerase(addr); printf("Erased 0x%x\r\n", (unsigned int)addr); } else if (!strcmp(argv[0], "rd")) { - if (argc != 2) { + if (argc < 2) { + fputs("Incorrect number of arguments\r\n", stdout); + return; + } + + addr = atoi(argv[1]); + + if (argc > 2) + len = atoi(argv[2]); + else + len = 16; + + flashstartread(addr); + + for (uint32_t i = 0; i < len; i++) + printf("Read 0x%02x from 0x%06x\r\n", flashreadbyte(), (unsigned int)(addr + i)); + flashstopread(); + + fputs("\r\n", stdout); + } else if (!strcmp(argv[0], "wr")) { + if (argc < 2) { fputs("Incorrect number of arguments\r\n", stdout); return; } addr = atoi(argv[1]); - flashstartread(addr); - - for (int i = 0; i < 16; i++) - printf("Read 0x%02x from 0x%06x\r\n", flashreadbyte(), (unsigned int)(addr + i)); - flashstopread(); - - fputs("\r\n", stdout); - } else if (!strcmp(argv[0], "wr")) { - if (argc != 2) { - fputs("Incorrect number of arguments\r\n", stdout); - return; - } - - addr = atoi(argv[1]); + if (argc > 2) + len = atoi(argv[2]); + else + len = 16; for (int i = 0; i < 16; i += 2) { uint16_t data; @@ -99,6 +175,19 @@ flashwriteword(data); } flashstopwrite(); + } else if (!strcmp(argv[0], "tw")) { + /* Copy default to RAM */ + bcopy(&default_settings, &ram_settings, sizeof(default_settings)); + + /* Write RAM copy into flash */ + flashwriteblock(0, sizeof(ram_settings), &ram_settings); + } else if (!strcmp(argv[0], "tr")) { + int crcok; + + /* Read flash copy to RAM */ + crcok = flashreadblock(0, sizeof(ram_settings), &ram_settings); + + printf("CRC is %s\r\n", crcok ? "OK" : "bad"); } else if (!strcmp(argv[0], "id")) { printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid()); } else { @@ -120,6 +209,7 @@ FL_DESELECT(); + //fputs("4k erase ", stdout); flashwait(); } @@ -210,6 +300,7 @@ void flashwrite(uint32_t addr, uint8_t data) { + flashwait(); flashenablewrite(); /* Enable writes */ FL_SELECT(); /* Select device */ @@ -295,6 +386,7 @@ flashwriteword(uint16_t data) { assert(writestate == RW_RUNNING); + //fputs("write word ", stdout); flashwait(); /* Wait until not busy */ FL_SELECT(); /* Select device */ @@ -310,6 +402,7 @@ flashstopwrite(void) { assert(writestate == RW_RUNNING); + //fputs("flash stop write start ", stdout); flashwait(); /* Wait until not busy */ FL_SELECT(); /* Select device */ @@ -318,8 +411,85 @@ FL_DESELECT(); /* Deselect device */ + //fputs("flash stop write end ", stdout); flashwait(); /* Wait until not busy */ writestate = RW_IDLE; } +int +flashreadblock(uint32_t addr, uint32_t len, void *_data) { + uint8_t *data = _data; + uint32_t flashcrc, ramcrc; + + /* Must be a multiple of 4 due to CRC check */ + assert(len % 4 == 0); + + flashstartread(addr); + for (int i = len; i > 0; i--) { + *data = flashreadbyte(); + data++; + } + + flashcrc = flashreadbyte(); + flashcrc |= flashreadbyte() << 8; + flashcrc |= flashreadbyte() << 16; + flashcrc |= flashreadbyte() << 24; + + flashstopread(); + + /* Calculate CRC */ + CRC_ResetDR(); + ramcrc = CRC_CalcBlockCRC((uint32_t *)_data, len / 4); + + printf("RAM CRC 0x%08x Flash CRC 0x%08x\r\n", (uint)ramcrc, (uint)flashcrc); + + if (ramcrc == flashcrc) + return 1; + else + return 0; +} + +void +flashwriteblock(uint32_t addr, uint32_t len, void *_data) { + uint16_t *data = _data; + uint32_t crc; + + printf("Writing %u bytes to 0x%06x\r\n", (uint)len, (uint)addr); + + /* Ensure data is + * - 16 bit aligned + * - a multiple of 32 bits in length (for CRCs, the flash only need 16 bits) + * - not longer than a sector + */ + assert(addr % 2 == 0); + assert(len % 4 == 0); + assert(len <= 4096); + + /* Disable write protect */ + flashwritestatus(0x00); + + /* Erase sector */ + flash4kerase(addr); + + /* Write data */ + for (uint i = 0; i < len / 2; i++) { + if (i == 0) + flashstartwrite(addr, *data); + else + flashwriteword(*data); + data++; + } + + /* Calculate CRC */ + CRC_ResetDR(); + crc = CRC_CalcBlockCRC((uint32_t *)_data, len / 4); + + printf("CRC is 0x%08x\r\n", (uint)crc); + + /* Write CRC */ + flashwriteword(crc); + flashwriteword(crc >> 16); + + flashstopwrite(); +}
--- a/flash.h Sat Nov 17 18:03:48 2012 +1030 +++ b/flash.h Tue Nov 20 21:54:06 2012 +1030 @@ -8,6 +8,8 @@ void flashenablewrite(void); void flashwrite(uint32_t addr, uint8_t data); void flashwait(void); +int flashreadblock(uint32_t addr, uint32_t len, void *_data); +void flashwriteblock(uint32_t addr, uint32_t len, void *_data); /* Streaming read/write */ void flashstartread(uint32_t addr);
--- a/hw.c Sat Nov 17 18:03:48 2012 +1030 +++ b/hw.c Tue Nov 20 21:54:06 2012 +1030 @@ -43,7 +43,7 @@ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE | RCC_APB2Periph_SPI1, ENABLE); - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC | RCC_AHBPeriph_CRC, ENABLE); /* Allow access to BKP Domain */ PWR_BackupAccessCmd(ENABLE);