source: ISPProgrammer/ISPprog/SerialFlash.pas

Last change on this file was 363, checked in by chronos, 13 years ago
  • Added: Package ISPProgrammer for in-system programming of various chips. Supports Dallas ISP protocol, Presto, Rabbit RFU and some others Atmel devices.
File size: 5.9 KB
Line 
1unit SerialFlash;
2
3{$MODE Delphi}
4
5interface
6
7const
8 // Error codes
9 ERROR_STOP = -1;
10 ERROR_TIMEOUT = -2;
11 ERROR_PROGRAM = -3;
12
13procedure SerialflashUnprotectAll;
14function SerialflashErase:integer;
15procedure SerialflashReadFlashPage(adres:integer; dane:pointer);
16function SerialflashWriteFlashPage(adres:integer; dane:pointer):integer;
17procedure SerialflashReadSign(s:pointer);
18
19implementation
20
21uses Delays, Globals, // MainWnd
22 PinsIO, Processors, SPI;
23
24const
25 // Status Register bit masks
26 STATUS_SPRL = $80; // Sector Protection Registers Locked
27 STATUS_RES = $40;
28 STATUS_EPE = $20; // Erase/Program Error
29 STATUS_WPP = $10; // Write Protect (/WP) Pin Status
30 STATUS_SWP = $0C; // Software Protection Status
31 STATUS_WEL = $02; // Write Enable Latch Status
32 STATUS_BUSY = $01; // Ready/Busy Status
33
34 // Commands
35 AT25_CMD_READ_ARRAY_FAST = $0B;
36 AT25_CMD_READ_ARRAY_SLOW = $03;
37 AT25_CMD_CHIP_ERASE = $60;
38 AT25_CMD_64KB_BLOCK_ERASE = $D8;
39 AT25_CMD_PAGE_PROGRAM = $02;
40 AT25_CMD_WRITE_ENABLE = $06;
41 AT25_CMD_WRITE_DISABLE = $04;
42 AT25_CMD_READ_STATUS = $05;
43 AT25_CMD_WRITE_STATUS = $01;
44 AT25_CMD_READ_DEVICE_ID = $15;
45
46 AT25F_CMD_CHIP_ERASE = $62;
47
48function SerialflashReadStatus:byte;
49begin
50 ChipselectOn;
51 WriteByte(AT25_CMD_READ_STATUS);
52 Result:=ReadByte;
53 ChipselectOff;
54end;
55
56procedure SerialflashReadDeviceID(var b1,b2:byte);
57begin
58 ChipselectOn;
59 WriteByte(AT25_CMD_READ_DEVICE_ID);
60 b1:=ReadByte;
61 b2:=ReadByte;
62 ChipselectOff;
63end;
64
65procedure SerialflashWriteEnable;
66begin
67 ChipselectOn;
68 WriteByte(AT25_CMD_WRITE_ENABLE);
69 ChipselectOff;
70end;
71
72procedure SerialflashWriteDisable;
73begin
74 ChipselectOn;
75 WriteByte(AT25_CMD_WRITE_DISABLE);
76 ChipselectOff;
77end;
78
79procedure SerialflashUnprotectAll;
80var
81 i:integer;
82begin
83 // repeat twice (first clear SPRL, next do Global Unprotect)
84 for i:=0 to 1 do
85 begin
86 // Write Enable
87 SerialflashWriteEnable;
88 // Write Status Register
89 ChipselectOn;
90 WriteByte(AT25_CMD_WRITE_STATUS);
91 WriteByte($00); // SPRL=0, Global Unprotect
92 ChipselectOff;
93 WaitMS(100); // tSR (Status Register Write Cycle Time)
94 end;
95end;
96
97function SerialflashWaitForReady(timeout:integer):integer;
98var
99 t1:Int64;
100 status:byte;
101begin
102 Result:=ERROR_TIMEOUT;
103 t1:=0;
104 Tic(t1);
105 repeat
106 if devicenr < 1 then
107 begin
108 Result:=ERROR_STOP;
109 Exit;
110 end;
111 if TocMS(t1) > timeout then
112 Exit;
113 status:=SerialflashReadStatus;
114 until (status and STATUS_BUSY) = 0;
115 if (status and STATUS_EPE) <> 0 then
116 begin
117 Result:=ERROR_PROGRAM;
118 Exit;
119 end;
120 Result:=0;
121end;
122
123function SerialflashErase:integer;
124var
125 blocks, i, adres:integer;
126 data:array[0..3] of byte;
127begin
128 if devicenr < 1 then
129 begin
130 Result:=ERROR_STOP;
131 Exit;
132 end;
133 blocks:=Signatures[devicenr].fsize div 65536;
134 adres:=0;
135 Result:=0;
136 // Global Unprotect
137 SerialflashUnprotectAll;
138 if blocks >= 16 then
139 begin
140 for i:=0 to blocks - 1 do
141 begin
142 if devicenr < 1 then
143 begin
144 Result:=ERROR_STOP;
145 Exit;
146 end;
147 // Write Enable
148 SerialflashWriteEnable;
149 // 64KB Block Erase
150 ChipselectOn;
151 data[0] := AT25_CMD_64KB_BLOCK_ERASE;
152 data[1] := (adres shr 16) and $FF;
153 data[2] := (adres shr 8) and $FF;
154 data[3] := adres and $FF;
155 WriteBytes(@data, 4);
156 Sync;
157 ChipselectOff;
158 // wait for ready
159 WaitMS(100);
160 Result := SerialflashWaitForReady((Signatures[devicenr].prog_time + blocks - 1) div blocks);
161 if Result <> 0 then
162 Exit;
163 Inc(adres, 65536);
164 //MainWindow.Progress (adres, Signatures[devicenr].fsize);
165 end;
166 end
167 else
168 begin
169 // Write Enable
170 SerialflashWriteEnable;
171 // Chip Erase
172 ChipselectOn;
173 if Pos('AT25F', Signatures[devicenr].name) = 1 then
174 WriteByte(AT25F_CMD_CHIP_ERASE)
175 else
176 WriteByte(AT25_CMD_CHIP_ERASE);
177 ChipselectOff;
178 // wait for ready
179 WaitMS(100);
180 Result := SerialflashWaitForReady(Signatures[devicenr].prog_time);
181 end;
182end;
183
184procedure SerialflashReadFlashPage(adres:integer; dane:pointer);
185var
186 data:array[0..4] of byte;
187begin
188 if devicenr < 1 then
189 Exit;
190 ChipselectOn;
191 data[0] := AT25_CMD_READ_ARRAY_SLOW; //AT25_CMD_READ_ARRAY_FAST;
192 data[1] := (adres shr 16) and $FF;
193 data[2] := (adres shr 8) and $FF;
194 data[3] := adres and $FF;
195 //data[4] := $00; // Dummy byte needed for AT25_CMD_READ_ARRAY_FAST
196 WriteBytes(@data, 4 {5});
197 ReadBytes(dane, Signatures[devicenr].fpagesize);
198 ChipselectOff;
199end;
200
201function SerialflashWriteFlashPage(adres:integer; dane:pointer):integer;
202var
203 data:array[0..3] of byte;
204 len, pagelen:integer;
205 b:^byte;
206begin
207 b := dane;
208 len := Signatures[devicenr].fpagesize;
209 pagelen := 1 shl Signatures[devicenr].fpage;
210 repeat
211 if devicenr < 1 then
212 begin
213 Result:=ERROR_STOP;
214 Exit;
215 end;
216 // Write Enable
217 SerialflashWriteEnable;
218 // Page Program
219 ChipselectOn;
220 data[0] := AT25_CMD_PAGE_PROGRAM;
221 data[1] := (adres shr 16) and $FF;
222 data[2] := (adres shr 8) and $FF;
223 data[3] := adres and $FF;
224 WriteBytes(@data, 4);
225 WriteBytes(b, pagelen);
226 Sync;
227 ChipselectOff;
228 // wait for ready
229 Result := SerialflashWaitForReady(60000); // 60ms max
230 if Result <> 0 then
231 Exit;
232 Inc(adres, pagelen);
233 Inc(b, pagelen);
234 Dec(len, pagelen);
235 until len = 0;
236end;
237
238procedure SerialflashReadSign(s:pointer);
239var
240 ptr:^byte;
241const
242 b1:byte = 0;
243 b2:byte = 0;
244begin
245 SerialflashReadDeviceID(b1, b2);
246 ptr:=s;
247 if b1 = $1f then
248 ptr^:=$25 // constant for AT25F memories
249 else
250 ptr^:=$ff; // $FF and no Manufacturer/Device ID
251 Inc(ptr);
252 ptr^:=b1;
253 Inc(ptr);
254 ptr^:=b2;
255end;
256
257end.
Note: See TracBrowser for help on using the repository browser.