Monday, September 14, 2015

Flash Programming In System

After last night's discovery that I need to rethink how I program flash, the solution turned out to be pretty painless.

I modified the flash.c to handle the flash in system. Here is flash.c with a new function, activateFlash(uint8_t cmd, bool doCycle4_5):


#include <assert.h>
#include "common.h"
#include "flash.h"
#include "memBank.h"

// reads the flash and waits for the toggle bit to stop toggling.
// returns true if the read byte matched expected. Use 0xff when
// erasing
bool toggle(volatile uint8_t* vaddr, uint8_t expected)
{
    uint8_t b0 = *vaddr;
    uint8_t b1 = *vaddr;
    while (b0 != b1) {
        b0 = b1;
        b1 = *vaddr;
    }
    return b0 == expected;
}

// Flash activation from within the system requires the following:
// 1) program must be running from RAM
// 2) to activate the flash, specific bytes must be written to
//    2aaa and 5555 of the flash AFTER bank switching. This
//    means that banks 0 and 1 must be mapped into memory and
//    2aaa+offset and 5555+offset be programmed
// 3) the bank the user is interested in must be swapped in
//    before the action address is written.
void activateFlash(uint8_t cmd, bool doCycle4_5)
{
    volatile uint8_t* v2aaa = (uint8_t*)(0x2aaa + 0x4000);
    volatile uint8_t* v5555 = (uint8_t*)(0x5555 + 0x4000);
    uint8_t oldBanks[4];
    uint8_t banks[4];

    getBanks(banks);
    getBanks(oldBanks);
    banks[1] = 0;
    banks[2] = 1;
    setBanks(banks);
    switchBanks();

    *v5555 = (uint8_t)0xaa;
    *v2aaa = (uint8_t)0x55;
    *v5555 = cmd;

    if (doCycle4_5)
    {
        *v5555 = (uint8_t)0xaa;
        *v2aaa = (uint8_t)0x55;
    }

    setBanks(oldBanks);
    switchBanks();
}

// Programs a byte to flash. Returns true if the byte matches
// when toggling is finished
bool flashProgramByte(uint8_t b, uint8_t* addr)
{
    volatile uint8_t* vaddr = addr;
    activateFlash(0xa0, false);
    *vaddr = b;
    return toggle(vaddr, b);
}

// Programs a block to flash. Returns true if all the bytes match
// when toggling is finished.
bool flashProgramBlock(uint8_t* b, uint16_t count, uint8_t* addr)
{
    uint16_t i;
    bool ok = true;
    volatile uint8_t* vaddr = addr;
    for (i = 0; i < count; i++)
    {
        ok = ok && flashProgramByte(b[i], vaddr + i);
    }
    return ok;
}

// Erase a 4k sector. Sector must be 0-15
bool flashEraseSector(uint8_t sector)
{
    volatile uint8_t* vaddr = (uint8_t*)(sector<<12);
    assert(sector < 16);
    activateFlash(0x80, true);
    *vaddr = (uint8_t)0x30;
    return toggle(vaddr, 0xff);
}

// Returns true if all bytes in a sector are 0xff
bool flashVerifyErased(uint8_t sector)
{
    volatile uint8_t* vaddr = (uint8_t*)(sector << 12);
    uint16_t i;
    assert(sector < 16);
    for (i = 0; i < 0x1000; i++)
    {
        if (vaddr[i] != 0xff)
        {
            return false;
        }
    }
    return true;
}


I added a new function to activate the flash. It gets the current bank setup, swaps in banks 0 and 1 of flash, activates the flash, and restores the banks.

And here is my menu running:


Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 2
This will copy memory to RAM memory.
Source (hex)? 0
Dest (hex)? 8000
Length (hex)? 4000
Copied
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 8000
Length (hex)? 20
-8000: c3 69 00 ff ff ff ff ff  c3 a3 13 ff ff ff ff ff .i...... ........
-7ff0: c3 b4 13 ff ff ff ff ff  c3 c5 13 ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 6
This allows to switch all 4 banks
Only switch bank 0 when
Use hex where 0-f are flash and 10-17 are RAM
  bank #0 [now==00]? 10
  bank #1 [now==01]? 2
  bank #2 [now==10]? 2
  bank #3 [now==11]? 11
Switching...
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 3ff0
Length (hex)? 10
3ff0: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 5
This will write a byte.
Address (hex)? 3fff
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 3ff0
Length (hex)? 10
3ff0: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff 00 ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 4000
Length (hex)? 10
4000: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 4
This will program a byte.
Address (hex)? 4000
value (hex)? fe
Programmed

Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 4000
Length (hex)? 10
4000: fe ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 4
This will program a byte.
Address (hex)? 4001
value (hex)? fb
Programmed

Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 4000
Length (hex)? 10
4000: fe fb ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) dump copy blocktext
3) erase bank
4) program byte
5) write byte
6) bank switch
>

The next step was to see if I could erase it--but that took a couple of code changes first... But here is the result:

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) copy block
3) erase sector
4) program byte
5) write byte
6) bank switch
> 2
This will copy memory to RAM memory.
Source (hex)? 0
Dest (hex)? 8000
Length (hex)? 4000
Copied
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) copy block
3) erase sector
4) program byte
5) write byte
6) bank switch
> 6
This allows to switch all 4 banks
Only switch bank 0 when
Use hex where 0-f are flash and 10-17 are RAM
  bank #0 [now==00]? 10
  bank #1 [now==01]? 2
  bank #2 [now==10]? 2
  bank #3 [now==11]? 11
Switching...
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) copy block
3) erase sector
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 4000
Length (hex)? 10
4000: fe fb ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) copy block
3) erase sector
4) program byte
5) write byte
6) bank switch
> 3
This allows erase a sector. Ensure the sector is flash
sector (hex: 0-f)? 4
Erased and verified
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) copy block
3) erase sector
4) program byte
5) write byte
6) bank switch
> 1
Address (hex)? 4000
Length (hex)? 10
4000: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
Done!

Mark Hamann's Z80 Computer

Version: 0.1 beta
Menu

1) dump text
2) copy block
3) erase sector
4) program byte
5) write byte
6) bank switch
>


As you can see, the fe and fb that I programmed into bank 2 were erased. Yay!!!!

With this, I'm closer to having the ihx file uploading. I just need to do a visual inspection of my ihx upload code and then I'll be ready to load it into my menu. But first, I need a program block menu item that will copy a block into flash.

I also need to handle backspace better. It seems to work on the screen, but my hex conversion returns an error if I use the gets string where backspace happened. Also, the buffer limit for gets isn't working quite right.

No comments:

Post a Comment