From f5718fb448558281d20b98d9d8547bdf14b4556b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 20 Apr 2018 16:11:10 +0200 Subject: [PATCH] chg: wiping / reading / writing flashmem --- armsrc/appmain.c | 35 +++++++++++++- armsrc/flashmem.c | 113 +++++++++++++++++++++++++++------------------- armsrc/flashmem.h | 14 ++++-- 3 files changed, 109 insertions(+), 53 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 86291e841..f055e57f0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1121,7 +1121,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; } } - // Trigger a finish downloading signal with an ACK frame cmd_send(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; @@ -1137,8 +1136,40 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; } case CMD_UPLOAD_FLASH_MEM: - case CMD_DOWNLOAND_FLASH_MEM: + LED_B_ON(); + + cmd_send(CMD_ACK, isok, 0, 0, 0, 0); + LED_B_OFF(); break; + case CMD_DOWNLOAND_FLASH_MEM: { + + LED_B_ON(); + uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); + bool isok = false; + size_t len = 0; + uint32_t startidx = c->arg[0]; + uint32_t numofbytes = c->arg[1]; + // arg0 = startindex + // arg1 = length bytes to transfer + // arg2 = RFU + //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); + + for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { + len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + + isok = Flash_ReadData(startidx + i, mem, len); + if (!isok ) + Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); + + isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len); + if (!isok) + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + } + + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); + LED_B_OFF(); + break; + } #endif case CMD_SET_LF_DIVISOR: FpgaDownloadAndGo(FPGA_BITSTREAM_LF); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index c03eb91a3..0e44e02e5 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -146,7 +146,7 @@ uint8_t Flash_ReadStat2(void) { } // determine whether FLASHMEM is busy -bool Flash_CheckBusy(uint16_t times){ +bool Flash_CheckBusy(uint16_t times) { bool ret = (Flash_ReadStat1() & BUSY); if (!ret || !times || !(times--)) @@ -166,7 +166,7 @@ bool Flash_CheckBusy(uint16_t times){ // read ID out uint8_t Flash_ReadID(void) { - if (Flash_CheckBusy(1000)) return 0; + if (Flash_CheckBusy(100)) return 0; // Manufacture ID / device ID FlashSendByte(ID); @@ -188,7 +188,7 @@ uint8_t Flash_ReadID(void) { // read unique id for chip. void Flash_UniqueID(uint8_t *uid) { - if (Flash_CheckBusy(1000)) return; + if (Flash_CheckBusy(100)) return; // reading unique serial number FlashSendByte(UNIQUE_ID); @@ -214,7 +214,7 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { Flash_ReadStat1(); // length should never be zero - if (!len || Flash_CheckBusy(1000)) return 0; + if (!len || Flash_CheckBusy(100)) return 0; FlashSendByte(READDATA); FlashSendByte((address >> 16) & 0xFF); @@ -231,42 +231,36 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { return len; } -// Write data +// Write data can only program one page. A page has 256 bytes. +// if len > 256, it might wrap around and overwrite pos 0. uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { // length should never be zero - if (!len) { - Dbprintf("Flash_WriteData len is zero error"); + if (!len) + return 0; + + // Max 256 bytes write + if (((address & 255) + len) > 256) { + Dbprintf("Flash_WriteData 256 fail"); return 0; } + // out-of-range + if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { + Dbprintf("Flash_WriteData, block out-of-range"); + return 0; + } + + // if 256b, empty out lower index. + if (len == 256) + address &= 0xFFFF00; + if (!FlashInit()) { Dbprintf("Flash_WriteData init fail"); return 0; } Flash_ReadStat1(); - - Flash_WriteEnable(); - - if ( len < 0x1000 ) - Flash_Erase4k(0x00); - else if ( len >= 0x1000 && len < 0x7FFF ) - Flash_Erase32k(0x00); - else - Flash_Erase64k(0x00); - - // busy after erasing - if (Flash_CheckBusy(1000)) { - Dbprintf("Flash_WriteData check busy"); - return 0; - } - - // 不能跨越 256 字节边界 - if (((address & 255) + len) > 256) { - Dbprintf("Flash_WriteData 256 fail"); - return 0; - } Flash_WriteEnable(); @@ -285,6 +279,25 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return len; } +// Wipes flash memory completely, fills with 0xFF +bool Flash_WipeMemory() { + if (!FlashInit()) { + Dbprintf("Flash_WriteData init fail"); + return false; + } + Flash_ReadStat1(); + + // Each block is 64Kb. Four blocks + // one block erase takes 1s ( 1000ms ) + Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(1000); + + FlashStop(); + return true; +} + // enable the flash write void Flash_WriteEnable() { FlashSendLastByte(WRITEENABLE); @@ -292,20 +305,21 @@ void Flash_WriteEnable() { } // erase 4K at one time -bool Flash_Erase4k(uint32_t address) { - if (address & (4096 - 1)) { - if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase4k : Address is not align at 4096"); - return false; - } +// execution time: 0.8ms / 800us +bool Flash_Erase4k(uint8_t block, uint8_t sector) { + + if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false; FlashSendByte(SECTORERASE); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendLastByte((address >> 0) & 0xFF); + FlashSendByte(block); + FlashSendByte(sector << 4); + FlashSendLastByte(00); return true; } +/* // erase 32K at one time +// execution time: 0,3s / 300ms bool Flash_Erase32k(uint32_t address) { if (address & (32*1024 - 1)) { if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096"); @@ -317,17 +331,24 @@ bool Flash_Erase32k(uint32_t address) { FlashSendLastByte((address >> 0) & 0xFF); return true; } +*/ -// erase 64k at one time -bool Flash_Erase64k(uint32_t address) { - if (address & (64*1024 - 1)) { - if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase64k : Address is not align at 4096"); - return false; - } +// erase 64k at one time +// since a block is 64kb, and there is four blocks. +// we only need block number, as MSB +// execution time: 1s / 1000ms +// 0x00 00 00 -- 0x 00 FF FF == block 0 +// 0x01 00 00 -- 0x 01 FF FF == block 1 +// 0x02 00 00 -- 0x 02 FF FF == block 2 +// 0x03 00 00 -- 0x 03 FF FF == block 3 +bool Flash_Erase64k(uint8_t block) { + + if (block > MAX_BLOCKS) return false; + FlashSendByte(BLOCK64ERASE); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendLastByte((address >> 0) & 0xFF); + FlashSendByte(block); + FlashSendByte(0x00); + FlashSendLastByte(0x00); return true; } @@ -342,7 +363,7 @@ bool FlashInit(void) { StartTicks(); - if (Flash_CheckBusy(1000)) { + if (Flash_CheckBusy(100)) { StopTicks(); return false; } diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 7122aea42..a8fd4e627 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -89,8 +89,6 @@ #define NO_CONTINUE 0x00 #define PASS 0x01 #define FAIL 0x00 -#define arrayLen(x) (sizeof(x) / sizeof(*x)) -#define lengthOf(x) (sizeof(x))/sizeof(byte) #define maxAddress capacity //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// @@ -108,6 +106,11 @@ #define NOSUSPEND 0x09 #define UNKNOWNERROR 0xFF +// List of blocks +#define MAX_BLOCKS 4 +#define MAX_SECTORS 16 + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// extern void Dbprintf(const char *fmt, ...); @@ -119,9 +122,10 @@ uint8_t Flash_ReadStat2(void); uint16_t FlashSendByte(uint32_t data); void Flash_WriteEnable(); -bool Flash_Erase4k(uint32_t address); -bool Flash_Erase32k(uint32_t address); -bool Flash_Erase64k(uint32_t address); +bool Flash_WipeMemory(); +bool Flash_Erase4k(uint8_t block, uint8_t sector); +//bool Flash_Erase32k(uint32_t address); +bool Flash_Erase64k(uint8_t block); bool FlashInit();