1 /*********************************************************************
  2     FileName:           Flash.c
  3     Dependencies:       See #includes
  4     Processor:          PIC32MZ
  5     Hardware:           MainBrain MZ
  6     Complier:           XC32 4.40
  7     Author:             Larry Knight 2023
  8 /*********************************************************************
  9  
 10     Software License Agreement:
 11  
 12     Licensed under the Apache License, Version 2.0 (the "License");
 13     you may not use this file except in compliance with the License.
 14     You may obtain a copy of the License at
 15 
 16     http://www.apache.org/licenses/LICENSE-2.0
 17 
 18     Unless required by applicable law or agreed to in writing, software
 19     distributed under the License is distributed on an "AS IS" BASIS,
 20     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 21     See the License for the specific language governing permissions and
 22     limitations under the License.
 23  
 24     Description:
 25         System Clock = 200 - 250 MHz
 26 
 27     File Description:
 28 
 29     Change History:
 30  
 31 /***********************************************************************/
 32 
 33 #include <xc.h>
 34 #include <stdbool.h>
 35 #include "MainBrain.h"
 36 
 37 //Flash Sector Size
 38 const uint16_t SECTOR_SIZE = 4095;
 39 
 40 uint8_t data_flash;
 41 unsigned long address_flash;
 42 uint8_t Flash_MID;
 43 uint8_t Flash_DID;
 44 int flash_size;
 45 unsigned long Bytes_used;
 46 uint32_t dly = 10000;
 47 
 48 void Flash_Init(void)
 49 {
 50     //RB2 = A16
 51     TRISBbits.TRISB2 = 0;
 52     PORTBbits.RB2 = 0;
 53     
 54     //RB4 = A17
 55     TRISBbits.TRISB4 = 0;
 56     PORTBbits.RB4 = 0;
 57     
 58     //RB3 = A18
 59     TRISBbits.TRISB3 = 0;
 60     PORTBbits.RB3 = 0;
 61         
 62     //RA10 = /CS2
 63     TRISAbits.TRISA10 = 0;
 64     PORTAbits.RA10 = 1;
 65     
 66 //******************************************************    
 67 //          Get Manufacturer ID
 68 //******************************************************    
 69     //CS2
 70     PORTAbits.RA10 = 0;
 71     
 72     //Enter sequence
 73     PMWADDR = 0x5555;
 74     PMDOUT = 0xaa;
 75     while(PMMODEbits.BUSY == 1);  
 76 
 77     PMWADDR = 0x2aaa;
 78     PMDOUT = 0x55;
 79     while(PMMODEbits.BUSY == 1);  
 80     Delay32(0, dly);
 81     PMWADDR = 0x5555;
 82     PMDOUT = 0x90;
 83     while(PMMODEbits.BUSY == 1);  
 84                 
 85     //read device ID
 86     PMRADDR = 0x0;
 87     //dummy read for PMP
 88     Flash_MID = PMRDIN;
 89     while(PMMODEbits.BUSY == 1); 
 90     
 91     Flash_MID = PMRDIN;
 92     while(PMMODEbits.BUSY == 1);  
 93     
 94     //Exit sequence
 95     PMWADDR = 0;
 96     PMDOUT = 0xf0;
 97     while(PMMODEbits.BUSY == 1);  
 98             
 99 
100     PORTAbits.RA10 = 1;
101     
102     //If the manufacturer ID is not 0xC2 then set error bit 0
103     if(Flash_MID != 0xc2)
104     {
105         lastError = lastError | 1;
106     }
107     
108 //******************************************************    
109 //          Get Device ID
110 //******************************************************    
111     //CS2
112     PORTAbits.RA10 = 0;
113         
114     //Get Chip ID
115     //Enter sequence
116     PMWADDR = 0x5555;
117     PMDOUT = 0xaa;
118     while(PMMODEbits.BUSY == 1);  
119    
120     PMWADDR = 0x2aaa;
121     PMDOUT = 0x55;
122     while(PMMODEbits.BUSY == 1);  
123     
124     PMWADDR = 0x5555;
125     PMDOUT = 0x90;
126     while(PMMODEbits.BUSY == 1);  
127             
128     Delay32(0, dly);
129     
130     //read device ID
131     PMRADDR = 0x1;
132     
133     //dummy read for PMP
134     Flash_DID = PMRDIN;
135     while(PMMODEbits.BUSY == 1); 
136     
137     Flash_DID = PMRDIN;
138     while(PMMODEbits.BUSY == 1);  
139     
140     //Exit sequence
141     PMWADDR = 1;
142     PMDOUT = 0xf0;
143     while(PMMODEbits.BUSY == 1);  
144             
145     Delay32(0, dly);
146     
147     //CS2
148     PORTAbits.RA10 = 1;    
149     
150     //If device code is not 0x4F the set error bit 1
151     if(Flash_DID != 0x4f)
152     {
153         lastError = lastError | 2;
154     }
155 
156 }
157 
158 void Flash_High_Address(unsigned address_flash)
159 {
160     //Handle the upper address pins (A16-18)
161     //0000-ffff
162     if(address_flash > 0xffff)
163     {
164         //RB2 = A16
165         PORTBbits.RB2 = 1;
166 
167         //RB4 = A17
168         PORTBbits.RB4 = 0;
169 
170         //RB3 = A18
171         PORTBbits.RB3 = 0;
172     }
173     
174     //10000-1ffff
175     if(address_flash > 0x1ffff)
176     {
177         //RB2 = A16
178         PORTBbits.RB2 = 0;
179 
180         //RB4 = A17
181         PORTBbits.RB4 = 1;
182 
183         //RB3 = A18
184         PORTBbits.RB3 = 0;
185     }
186     
187     //20000-2ffff
188     if(address_flash > 0x2ffff)
189     {
190         //RB2 = A16
191         PORTBbits.RB2 = 1;
192 
193         //RB4 = A17
194         PORTBbits.RB4 = 1;
195 
196         //RB3 = A18
197         PORTBbits.RB3 = 0;
198     }
199     
200     //30000-3ffff
201     if(address_flash > 0x3ffff)
202     {
203         //RB2 = A16
204         PORTBbits.RB2 = 0;
205 
206         //RB4 = A17
207         PORTBbits.RB4 = 0;
208 
209         //RB3 = A18
210         PORTBbits.RB3 = 1;
211     }
212     
213      //40000-4ffff
214     if(address_flash > 0x4ffff)
215     {
216         //RB2 = A16
217         PORTBbits.RB2 = 1;
218 
219         //RB4 = A17
220         PORTBbits.RB4 = 0;
221 
222         //RB3 = A18
223         PORTBbits.RB3 = 1;
224     }
225     
226     //50000-5ffff
227     if(address_flash > 0x5ffff)
228     {
229         //RB2 = A16
230         PORTBbits.RB2 = 0;
231 
232         //RB4 = A17
233         PORTBbits.RB4 = 1;
234 
235         //RB3 = A18
236         PORTBbits.RB3 = 1;
237     }
238     
239     //60000-6ffff
240     if(address_flash > 0x6ffff)
241     {
242         //RB2 = A16
243         PORTBbits.RB2 = 1;
244 
245         //RB4 = A17
246         PORTBbits.RB4 = 1;
247 
248         //RB3 = A18
249         PORTBbits.RB3 = 1;
250     }    
251 }
252 
253 void Flash_RD(unsigned address_flash)
254 {  
255     //Handle the upper address pins (A16-18)
256     Flash_High_Address(address_flash);
257 
258     //Clear off upper bits and load in to PMP
259     PMRADDR = address_flash & 0x0ffff;
260     
261     ///CS2
262     PORTAbits.RA10 = 0;
263         
264     //dummy read
265     data_flash = PMRDIN;
266     while(PMMODEbits.BUSY == 1);
267    
268     data_flash = PMRDIN;
269     while(PMMODEbits.BUSY == 1);
270 
271     ///CS2
272     PORTAbits.RA10 = 1;
273     
274     //RB2 = A16
275     PORTBbits.RB2 = 0;
276 
277     //RB4 = A17
278     PORTBbits.RB4 = 0;
279 
280     //RB3 = A18
281     PORTBbits.RB3 = 0;
282 }
283 
284 void Flash_WR(unsigned address_flash, uint8_t data_flash)
285 {        
286     LED_Port(2);
287     //Handle the upper address pins (A16-18)
288     Flash_High_Address(address_flash);
289     
290     ///CS2
291     PORTAbits.RA10 = 0;
292     
293     //Enter sequence
294     PMWADDR = 0x5555;
295     PMDOUT = 0xaa;
296     while(PMMODEbits.BUSY == 1);  
297    
298     PMWADDR = 0x2aaa;
299     PMDOUT = 0x55;
300     while(PMMODEbits.BUSY == 1);  
301     
302     PMWADDR = 0x5555;
303     PMDOUT = 0xa0;
304     while(PMMODEbits.BUSY == 1);  
305             
306     //write data
307     //Clear off upper bits and load in to PMP
308     PMWADDR = address_flash & 0x0ffff;
309     PMRADDR = PMWADDR;
310     
311     PMDOUT = data_flash;
312     while(PMMODEbits.BUSY == 1); 
313     
314     uint8_t j = 0;
315     uint8_t i = PMRDIN;
316     //Wait for end of program
317     //using D7 - Data# polling
318     
319     while(data_flash != i)
320     {
321         i = PMRDIN;
322         while(PMMODEbits.BUSY == 1);
323         j++;
324         LED_Port(j);
325     }
326     
327     j = 0;
328     
329     //now we must verify at least 2 times
330     //to prevent false rejection
331     
332     
333     while(i != data_flash)
334     {
335         i = PMRDIN;
336         while(PMMODEbits.BUSY == 1);
337         j++;
338         LED_Port(j);
339 
340     }
341     LED_Port(0);
342     ///CS2
343     PORTAbits.RA10 = 1;
344     
345     //RB2 = A16
346     PORTBbits.RB2 = 0;
347 
348     //RB4 = A17
349     PORTBbits.RB4 = 0;
350 
351     //RB3 = A18
352     PORTBbits.RB3 = 0; 
353 }
354 
355 void Flash_Sector_Erase(int erase_sector)
356 {  
357     data_flash = 0;
358     
359     erase_sector = erase_sector << 12;
360     ///CS2
361     PORTAbits.RA10 = 0;
362     
363     //Enter sequence
364     PMWADDR = 0x5555;
365     PMDOUT = 0xaa;
366     while(PMMODEbits.BUSY == 1);  
367    
368     PMWADDR = 0x2aaa;
369     PMDOUT = 0x55;
370     while(PMMODEbits.BUSY == 1);  
371     
372     PMWADDR = 0x5555;
373     PMDOUT = 0x80;
374     while(PMMODEbits.BUSY == 1);  
375             
376     PMWADDR = 0x5555;
377     PMDOUT = 0xaa;
378     while(PMMODEbits.BUSY == 1);  
379    
380     PMWADDR = 0x2aaa;
381     PMDOUT = 0x55;
382     while(PMMODEbits.BUSY == 1);  
383     
384     //Sector address
385     PMWADDR = erase_sector;
386     PMDOUT = 0x30;
387     while(PMMODEbits.BUSY == 1);  
388     int j = 0;
389     while(data_flash != 0xff)
390     {
391         data_flash = PMRDIN;
392         while(PMMODEbits.BUSY == 1);
393         
394         j++;
395         LED_Port(j);
396     }
397     //CS2
398     PORTAbits.RA10 = 1;
399 }
400 
401 void Flash_Chip_Erase(void)
402 {  
403     int i;
404     data_flash = 0;
405     
406     //CS2
407     PORTAbits.RA10 = 0;
408    
409     //Enter sequence
410     PMWADDR = 0x5555;
411     PMDOUT = 0xaa;
412     while(PMMODEbits.BUSY == 1);  
413    
414     PMWADDR = 0x2aaa;
415     PMDOUT = 0x55;
416     while(PMMODEbits.BUSY == 1);  
417     
418     PMWADDR = 0x5555;
419     PMDOUT = 0x80;
420     while(PMMODEbits.BUSY == 1);  
421             
422     PMWADDR = 0x5555;
423     PMDOUT = 0xaa;
424     while(PMMODEbits.BUSY == 1);  
425    
426     PMWADDR = 0x2aaa;
427     PMDOUT = 0x55;
428     while(PMMODEbits.BUSY == 1);  
429     
430     PMWADDR = 0x5555;
431     PMDOUT = 0x10;
432     while(PMMODEbits.BUSY == 1);  
433     
434     while(data_flash != 0xff)
435     {
436         data_flash = PMRDIN;
437         while(PMMODEbits.BUSY == 1);
438     }
439 
440     //CS2
441     PORTAbits.RA10 = 1;
442 }
443 
444 void Flash_Get_Bytes_Used(void)
445 {  
446     unsigned long i;
447     Bytes_used = 0;
448     
449     if(Flash_DID == 0xd5)
450     {
451         for(i=0; i <= 0x1ffff; i++)
452         {
453             Flash_RD(i);
454             if(data_flash != 0xff)
455             {
456                 Bytes_used++;
457             }
458         }
459     }
460     if(Flash_DID == 0xd6)
461     {
462         for(i=0; i <= 0x2ffff; i++)
463         {
464             Flash_RD(i);
465             if(data_flash != 0xff)
466             {
467                 Bytes_used++;
468             }
469         }
470     }
471     
472     if(Flash_DID == 0xd7)
473     {
474         for(i=0; i <= 0x7ffff; i++)
475         {
476             Flash_RD(i);
477             if(data_flash != 0xff)
478             {
479                 Bytes_used++;
480             }
481         }
482     }
483     
484     PORTBbits.RB8 = 0;
485     PORTAbits.RA5 = 0;
486     PORTAbits.RA3 = 0;        
487 
488     return;
489 }
490 
491 
492