cflash speedup

Using the "UNLOCK BYPASS" commands for the flash it takes half as many cycles to program each word

Also bump the task priority and enable compiler optimization
This commit is contained in:
Matt Harlum 2023-04-18 20:47:21 +00:00
parent b1fb7b8aaa
commit 618089c795
7 changed files with 82 additions and 33 deletions

View File

@ -1,6 +1,6 @@
PROJECT=cflash
CC=m68k-amigaos-gcc
CFLAGS=-lamiga -mcrt=nix13 -mcpu=68000 -Wall -Wno-pointer-sign -Os -fomit-frame-pointer
CFLAGS=-lamiga -mcrt=nix13 -mcpu=68000 -Wall -Wno-pointer-sign -O3 -fomit-frame-pointer
.PHONY: clean all
all: $(PROJECT)

View File

@ -26,6 +26,9 @@
ULONG ide_flashBase;
static inline void ide_flash_command(UBYTE);
static inline void ide_flash_poll(UWORD);
/** ide_flash_writeByte
*
* @brief Write a byte to the Flash
@ -37,7 +40,7 @@ void ide_flash_writeByte(UWORD address, UBYTE data) {
address <<= 1;
ide_flash_unlock_sdp();
ide_flash_command(CMD_BYTE_PROGRAM);
*(UBYTE *)(ide_flashBase + address) = data;
*(volatile UBYTE *)(ide_flashBase + address) = data;
ide_flash_poll(address);
return;
@ -48,8 +51,8 @@ void ide_flash_writeByte(UWORD address, UBYTE data) {
* @brief send a command to the Flash
* @param command
*/
void ide_flash_command(UBYTE command) {
*(UBYTE *)(ide_flashBase + ADDR_CMD_STEP_1) = command;
static inline void ide_flash_command(UBYTE command) {
*(volatile UBYTE *)(ide_flashBase + ADDR_CMD_STEP_1) = command;
return;
}
@ -59,8 +62,8 @@ void ide_flash_command(UBYTE command) {
* @brief Send the SDP command sequence
*/
void ide_flash_unlock_sdp() {
*(UBYTE *)(ide_flashBase + ADDR_CMD_STEP_1) = CMD_SDP_STEP_1;
*(UBYTE *)(ide_flashBase + ADDR_CMD_STEP_2) = CMD_SDP_STEP_2;
*(volatile UBYTE *)(ide_flashBase + ADDR_CMD_STEP_1) = CMD_SDP_STEP_1;
*(volatile UBYTE *)(ide_flashBase + ADDR_CMD_STEP_2) = CMD_SDP_STEP_2;
return;
}
@ -83,7 +86,7 @@ void ide_flash_erase_chip() {
* @brief Poll the status bits at address, until they indicate that the operation has completed.
* @param address Address to poll
*/
void ide_flash_poll(UWORD address) {
static inline void ide_flash_poll(UWORD address) {
address &= (FLASH_SIZE-1);
address <<= 1;
volatile UBYTE *read1 = ((void *)ide_flashBase + address);
@ -109,8 +112,8 @@ bool ide_flash_init(UBYTE *manuf, UBYTE *devid, ULONG *flashBase) {
ide_flash_unlock_sdp();
ide_flash_command(CMD_ID_ENTRY);
manufId = *(UBYTE *)ide_flashBase;
deviceId = *(UBYTE *)(ide_flashBase + 2);
manufId = *(volatile UBYTE *)ide_flashBase;
deviceId = *(volatile UBYTE *)(ide_flashBase + 2);
ide_flash_command(CMD_CFI_ID_EXIT);

View File

@ -24,10 +24,8 @@
void ide_flash_unlock_sdp();
void ide_flash_erase_chip();
void ide_flash_command(UBYTE);
void ide_flash_writeByte(UWORD, UBYTE);
bool ide_flash_init(UBYTE *, UBYTE *, ULONG *);
void ide_flash_poll(UWORD);
void ide_flash_erase_block(UWORD);
#endif

View File

@ -32,6 +32,10 @@ enum {
BOTTOM
} flash_bootbank;
static inline void kick_flash_poll(ULONG address);
static inline void kick_flash_command(UWORD command);
/** kick_flash_writeWord
*
* @brief Write a word to the Flash
@ -42,7 +46,7 @@ void kick_flash_writeWord(ULONG address, UWORD data) {
address &= (FLASH_SIZE-1);
kick_flash_unlock_sdp();
kick_flash_command(CMD_WORD_PROGRAM);
*(UWORD *)(flashbase + address) = data;
*(volatile UWORD *)(flashbase + address) = data;
kick_flash_poll(address);
return;
@ -53,8 +57,8 @@ void kick_flash_writeWord(ULONG address, UWORD data) {
* @brief send a command to the Flash
* @param command
*/
void kick_flash_command(UWORD command) {
*(UWORD *)(flashbase + ADDR_CMD_STEP_1) = command;
static inline void kick_flash_command(UWORD command) {
*(volatile UWORD *)(flashbase + ADDR_CMD_STEP_1) = command;
return;
}
@ -64,8 +68,8 @@ void kick_flash_command(UWORD command) {
* @brief Send the SDP command sequence
*/
void kick_flash_unlock_sdp() {
*(UWORD *)(flashbase + ADDR_CMD_STEP_1) = CMD_SDP_STEP_1;
*(UWORD *)(flashbase + ADDR_CMD_STEP_2) = CMD_SDP_STEP_2;
*(volatile UWORD *)(flashbase + ADDR_CMD_STEP_1) = CMD_SDP_STEP_1;
*(volatile UWORD *)(flashbase + ADDR_CMD_STEP_2) = CMD_SDP_STEP_2;
return;
}
@ -88,7 +92,7 @@ void kick_flash_erase_chip() {
* @brief Poll the status bits at address, until they indicate that the operation has completed.
* @param address Address to poll
*/
void kick_flash_poll(ULONG address) {
static inline void kick_flash_poll(ULONG address) {
address &= (FLASH_SIZE-1);
volatile UWORD *read1 = ((void *)flashbase + address);
volatile UWORD *read2 = ((void *)flashbase + address);
@ -110,8 +114,8 @@ bool kick_flash_init(UWORD *manuf, UWORD *devid) {
kick_flash_unlock_sdp();
kick_flash_command(CMD_ID_ENTRY);
manufId = *(UWORD *)flashbase;
deviceId = *(UWORD *)(flashbase + 2);
manufId = *(volatile UWORD *)flashbase;
deviceId = *(volatile UWORD *)(flashbase + 2);
kick_flash_command(CMD_CFI_ID_EXIT);
@ -149,7 +153,7 @@ void kick_flash_erase_block(ULONG address) {
kick_flash_unlock_sdp();
kick_flash_command(CMD_ERASE);
kick_flash_unlock_sdp();
*(UWORD *)(flashbase + address) = CMD_ERASE_BLOCK;
*(volatile UWORD *)(flashbase + address) = CMD_ERASE_BLOCK;
kick_flash_poll(address);
}
@ -198,4 +202,38 @@ void kick_flash_erase_bank(int bank) {
kick_flash_erase_block(block);
}
}
}
/** kick_flash_unlock_bypass
*
* @brief Sends UNLOCK BYPASS command to flash
*/
void kick_flash_unlock_bypass() {
kick_flash_unlock_sdp();
kick_flash_command(CMD_UNLOCK_BYPASS);
}
/** kick_flash_unlock_bypass_reset
*
* @brief Sends UNLOCK BYPASS RESET command to flash returning it to read mode
*/
void kick_flash_unlock_bypass_reset() {
kick_flash_unlock_sdp();
kick_flash_command(CMD_UNLOCK_BYPASS_RESET);
*(volatile UWORD *)(flashbase) = 0;
}
/** kick_flash_bypass_program
*
* @brief Write a word to the Flash when in bypass mode
* @param address Address to write to
* @param data The word to write
*/
void kick_flash_bypass_program(ULONG address, UWORD data) {
address &= (FLASH_SIZE-1);
kick_flash_command(CMD_UNLOCK_BYPASS_PROGRAM);
*(volatile UWORD *)(flashbase + address) = data;
kick_flash_poll(address);
return;
}

View File

@ -24,12 +24,13 @@
void kick_flash_unlock_sdp();
void kick_flash_erase_chip();
void kick_flash_command(UWORD);
void kick_flash_writeWord(ULONG, UWORD);
bool kick_flash_init(UWORD *, UWORD *);
void kick_flash_poll(ULONG);
void kick_flash_reset();
void kick_flash_erase_bank(int);
void kick_flash_erase_block(ULONG);
void kick_flash_unlock_bypass();
void kick_flash_unlock_bypass_reset();
void kick_flash_bypass_program(ULONG address, UWORD data);
#endif

View File

@ -34,15 +34,18 @@
#define ADDR_CMD_STEP_1 (0x555 << 1)
#define ADDR_CMD_STEP_2 (0x2AA << 1)
#define CMD_SDP_STEP_1 0xAA
#define CMD_SDP_STEP_2 0x55
#define CMD_WORD_PROGRAM 0xA0
#define CMD_ERASE 0x80
#define CMD_ERASE_BLOCK 0x30
#define CMD_ERASE_CHIP 0x10
#define CMD_ID_ENTRY 0x90
#define CMD_CFI_ENTRY 0x98
#define CMD_CFI_ID_EXIT 0xF0
#define CMD_READ_RESET 0xF0
#define CMD_SDP_STEP_1 0xAA
#define CMD_SDP_STEP_2 0x55
#define CMD_WORD_PROGRAM 0xA0
#define CMD_ERASE 0x80
#define CMD_ERASE_BLOCK 0x30
#define CMD_ERASE_CHIP 0x10
#define CMD_ID_ENTRY 0x90
#define CMD_CFI_ENTRY 0x98
#define CMD_CFI_ID_EXIT 0xF0
#define CMD_READ_RESET 0xF0
#define CMD_UNLOCK_BYPASS 0x20
#define CMD_UNLOCK_BYPASS_PROGRAM 0xA0
#define CMD_UNLOCK_BYPASS_RESET 0x90
#endif

View File

@ -63,6 +63,8 @@ int main(int argc, char *argv[])
printf("CIDER FlashROM tool\n");
struct Config *config;
struct Task *task = FindTask(0);
SetTaskPri(task,20);
if ((config = configure(argc,argv)) != NULL) {
if ((ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",0)) != NULL) {
@ -429,6 +431,8 @@ void copyBufToFlash(ULONG *source, ULONG destination, ULONG romSize, bool skipVe
fprintf(stdout,"Writing: ");
fflush(stdout);
kick_flash_unlock_bypass(); // Enter unlock bypass mode
for (ULONG i=0; i<byteCount; i+=2) {
sourcePtr = ((void *)source + (i % romSize)); // Loop the source address around when programming 256K
progress = i*100/(byteCount-2);
@ -439,9 +443,11 @@ void copyBufToFlash(ULONG *source, ULONG destination, ULONG romSize, bool skipVe
lastProgress = progress;
}
kick_flash_writeWord(destination+i,*sourcePtr);
kick_flash_bypass_program(destination+i,*sourcePtr);
}
kick_flash_unlock_bypass_reset(); // Return to read mode
printf("\n");
if (skipVerify == false) {
verifyBank(source,destination,romSize);