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):

  1 #include <assert.h>
  2 #include "common.h"
  3 #include "flash.h"
  4 #include "memBank.h"
  5 
  6 // reads the flash and waits for the toggle bit to stop toggling.
  7 // returns true if the read byte matched expected. Use 0xff when
  8 // erasing
  9 bool toggle(volatile uint8_t* vaddr, uint8_t expected)
 10 {
 11     uint8_t b0 = *vaddr;
 12     uint8_t b1 = *vaddr;
 13     while (b0 != b1) {
 14         b0 = b1;
 15         b1 = *vaddr;
 16     }
 17     return b0 == expected;
 18 }
 19 
 20 // Flash activation from within the system requires the following:
 21 // 1) program must be running from RAM
 22 // 2) to activate the flash, specific bytes must be written to
 23 //    2aaa and 5555 of the flash AFTER bank switching. This
 24 //    means that banks 0 and 1 must be mapped into memory and
 25 //    2aaa+offset and 5555+offset be programmed
 26 // 3) the bank the user is interested in must be swapped in
 27 //    before the action address is written.
 28 void activateFlash(uint8_t cmd, bool doCycle4_5)
 29 {
 30     volatile uint8_t* v2aaa = (uint8_t*)(0x2aaa + 0x4000);
 31     volatile uint8_t* v5555 = (uint8_t*)(0x5555 + 0x4000);
 32     uint8_t oldBanks[4];
 33     uint8_t banks[4];
 34 
 35     getBanks(banks);
 36     getBanks(oldBanks);
 37     banks[1] = 0;
 38     banks[2] = 1;
 39     setBanks(banks);
 40     switchBanks();
 41 
 42     *v5555 = (uint8_t)0xaa;
 43     *v2aaa = (uint8_t)0x55;
 44     *v5555 = cmd;
 45 
 46     if (doCycle4_5)
 47     {
 48         *v5555 = (uint8_t)0xaa;
 49         *v2aaa = (uint8_t)0x55;
 50     }
 51 
 52     setBanks(oldBanks);
 53     switchBanks();
 54 }
 55 
 56 // Programs a byte to flash. Returns true if the byte matches
 57 // when toggling is finished
 58 bool flashProgramByte(uint8_t b, uint8_t* addr)
 59 {
 60     volatile uint8_t* vaddr = addr;
 61     activateFlash(0xa0, false);
 62     *vaddr = b;
 63     return toggle(vaddr, b);
 64 }
 65 
 66 // Programs a block to flash. Returns true if all the bytes match
 67 // when toggling is finished.
 68 bool flashProgramBlock(uint8_t* b, uint16_t count, uint8_t* addr)
 69 {
 70     uint16_t i;
 71     bool ok = true;
 72     volatile uint8_t* vaddr = addr;
 73     for (i = 0; i < count; i++)
 74     {
 75         ok = ok && flashProgramByte(b[i], vaddr + i);
 76     }
 77     return ok;
 78 }
 79 
 80 // Erase a 4k sector. Sector must be 0-15
 81 bool flashEraseSector(uint8_t sector)
 82 {
 83     volatile uint8_t* vaddr = (uint8_t*)(sector<<12);
 84     assert(sector < 16);
 85     activateFlash(0x80, true);
 86     *vaddr = (uint8_t)0x30;
 87     return toggle(vaddr, 0xff);
 88 }
 89 
 90 // Returns true if all bytes in a sector are 0xff
 91 bool flashVerifyErased(uint8_t sector)
 92 {
 93     volatile uint8_t* vaddr = (uint8_t*)(sector << 12);
 94     uint16_t i;
 95     assert(sector < 16);
 96     for (i = 0; i < 0x1000; i++)
 97     {
 98         if (vaddr[i] != 0xff)
 99         {
100             return false;
101         }
102     }
103     return true;
104 }

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:

  1 Mark Hamann's Z80 Computer
  2 
  3 Version: 0.1 beta
  4 Menu
  5 
  6 1) dump text
  7 2) dump copy blocktext
  8 3) erase bank
  9 4) program byte
 10 5) write byte
 11 6) bank switch
 12 > 2
 13 This will copy memory to RAM memory.
 14 Source (hex)? 0
 15 Dest (hex)? 8000
 16 Length (hex)? 4000
 17 Copied
 18 Done!
 19 
 20 Mark Hamann's Z80 Computer
 21 
 22 Version: 0.1 beta
 23 Menu
 24 
 25 1) dump text
 26 2) dump copy blocktext
 27 3) erase bank
 28 4) program byte
 29 5) write byte
 30 6) bank switch
 31 > 1
 32 Address (hex)? 8000
 33 Length (hex)? 20
 34 -8000: c3 69 00 ff ff ff ff ff  c3 a3 13 ff ff ff ff ff .i...... ........
 35 -7ff0: c3 b4 13 ff ff ff ff ff  c3 c5 13 ff ff ff ff ff ........ ........
 36 Done!
 37 
 38 Mark Hamann's Z80 Computer
 39 
 40 Version: 0.1 beta
 41 Menu
 42 
 43 1) dump text
 44 2) dump copy blocktext
 45 3) erase bank
 46 4) program byte
 47 5) write byte
 48 6) bank switch
 49 > 6
 50 This allows to switch all 4 banks
 51 Only switch bank 0 when
 52 Use hex where 0-f are flash and 10-17 are RAM
 53   bank #0 [now==00]? 10
 54   bank #1 [now==01]? 2
 55   bank #2 [now==10]? 2
 56   bank #3 [now==11]? 11
 57 Switching...
 58 Done!
 59 
 60 Mark Hamann's Z80 Computer
 61 
 62 Version: 0.1 beta
 63 Menu
 64 
 65 1) dump text
 66 2) dump copy blocktext
 67 3) erase bank
 68 4) program byte
 69 5) write byte
 70 6) bank switch
 71 > 1
 72 Address (hex)? 3ff0
 73 Length (hex)? 10
 74 3ff0: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
 75 Done!
 76 
 77 Mark Hamann's Z80 Computer
 78 
 79 Version: 0.1 beta
 80 Menu
 81 
 82 1) dump text
 83 2) dump copy blocktext
 84 3) erase bank
 85 4) program byte
 86 5) write byte
 87 6) bank switch
 88 > 5
 89 This will write a byte.
 90 Address (hex)? 3fff
 91 Done!
 92 
 93 Mark Hamann's Z80 Computer
 94 
 95 Version: 0.1 beta
 96 Menu
 97 
 98 1) dump text
 99 2) dump copy blocktext
100 3) erase bank
101 4) program byte
102 5) write byte
103 6) bank switch
104 > 1
105 Address (hex)? 3ff0
106 Length (hex)? 10
107 3ff0: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff 00 ........ ........
108 Done!
109 
110 Mark Hamann's Z80 Computer
111 
112 Version: 0.1 beta
113 Menu
114 
115 1) dump text
116 2) dump copy blocktext
117 3) erase bank
118 4) program byte
119 5) write byte
120 6) bank switch
121 > 1
122 Address (hex)? 4000
123 Length (hex)? 10
124 4000: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
125 Done!
126 
127 Mark Hamann's Z80 Computer
128 
129 Version: 0.1 beta
130 Menu
131 
132 1) dump text
133 2) dump copy blocktext
134 3) erase bank
135 4) program byte
136 5) write byte
137 6) bank switch
138 > 4
139 This will program a byte.
140 Address (hex)? 4000
141 value (hex)? fe
142 Programmed
143 
144 Done!
145 
146 Mark Hamann's Z80 Computer
147 
148 Version: 0.1 beta
149 Menu
150 
151 1) dump text
152 2) dump copy blocktext
153 3) erase bank
154 4) program byte
155 5) write byte
156 6) bank switch
157 > 1
158 Address (hex)? 4000
159 Length (hex)? 10
160 4000: fe ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
161 Done!
162 
163 Mark Hamann's Z80 Computer
164 
165 Version: 0.1 beta
166 Menu
167 
168 1) dump text
169 2) dump copy blocktext
170 3) erase bank
171 4) program byte
172 5) write byte
173 6) bank switch
174 > 4
175 This will program a byte.
176 Address (hex)? 4001
177 value (hex)? fb
178 Programmed
179 
180 Done!
181 
182 Mark Hamann's Z80 Computer
183 
184 Version: 0.1 beta
185 Menu
186 
187 1) dump text
188 2) dump copy blocktext
189 3) erase bank
190 4) program byte
191 5) write byte
192 6) bank switch
193 > 1
194 Address (hex)? 4000
195 Length (hex)? 10
196 4000: fe fb ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
197 Done!
198 
199 Mark Hamann's Z80 Computer
200 
201 Version: 0.1 beta
202 Menu
203 
204 1) dump text
205 2) dump copy blocktext
206 3) erase bank
207 4) program byte
208 5) write byte
209 6) bank switch
210 >

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:

  1 Mark Hamann's Z80 Computer
  2 
  3 Version: 0.1 beta
  4 Menu
  5 
  6 1) dump text
  7 2) copy block
  8 3) erase sector
  9 4) program byte
 10 5) write byte
 11 6) bank switch
 12 > 2
 13 This will copy memory to RAM memory.
 14 Source (hex)? 0
 15 Dest (hex)? 8000
 16 Length (hex)? 4000
 17 Copied
 18 Done!
 19 
 20 Mark Hamann's Z80 Computer
 21 
 22 Version: 0.1 beta
 23 Menu
 24 
 25 1) dump text
 26 2) copy block
 27 3) erase sector
 28 4) program byte
 29 5) write byte
 30 6) bank switch
 31 > 6
 32 This allows to switch all 4 banks
 33 Only switch bank 0 when
 34 Use hex where 0-f are flash and 10-17 are RAM
 35   bank #0 [now==00]? 10
 36   bank #1 [now==01]? 2
 37   bank #2 [now==10]? 2
 38   bank #3 [now==11]? 11
 39 Switching...
 40 Done!
 41 
 42 Mark Hamann's Z80 Computer
 43 
 44 Version: 0.1 beta
 45 Menu
 46 
 47 1) dump text
 48 2) copy block
 49 3) erase sector
 50 4) program byte
 51 5) write byte
 52 6) bank switch
 53 > 1
 54 Address (hex)? 4000
 55 Length (hex)? 10
 56 4000: fe fb ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
 57 Done!
 58 
 59 Mark Hamann's Z80 Computer
 60 
 61 Version: 0.1 beta
 62 Menu
 63 
 64 1) dump text
 65 2) copy block
 66 3) erase sector
 67 4) program byte
 68 5) write byte
 69 6) bank switch
 70 > 3
 71 This allows erase a sector. Ensure the sector is flash
 72 sector (hex: 0-f)? 4
 73 Erased and verified
 74 Done!
 75 
 76 Mark Hamann's Z80 Computer
 77 
 78 Version: 0.1 beta
 79 Menu
 80 
 81 1) dump text
 82 2) copy block
 83 3) erase sector
 84 4) program byte
 85 5) write byte
 86 6) bank switch
 87 > 1
 88 Address (hex)? 4000
 89 Length (hex)? 10
 90 4000: ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff ........ ........
 91 Done!
 92 
 93 Mark Hamann's Z80 Computer
 94 
 95 Version: 0.1 beta
 96 Menu
 97 
 98 1) dump text
 99 2) copy block
100 3) erase sector
101 4) program byte
102 5) write byte
103 6) bank switch
104 >

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.