f20807395d8e30108bc202c3cf4875f6ee138e60
[pyfrprog.git] / Flash.c
1 /*****************************************************************************/
2 /* THIS SAMPLE CODE IS PROVIDED AS IS AND IS SUBJECT TO ALTERATIONS. FUJITSU */
3 /* MICROELECTRONICS ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR */
4 /* ELIGIBILITY FOR ANY PURPOSES.                                             */
5 /*                 (C) Fujitsu Microelectronics Europe GmbH                  */
6 /*****************************************************************************/
7
8 #include "Flash.h"
9 #include "mb91465k.h"
10
11 static unsigned int IFlag;
12
13 #pragma section CODE=IRAM,attr=CODE
14         
15
16 void FLASH_PrepareWriteHalfWordMode()
17 {
18         /*      Set FLASH Access Mode via BootROM Routine       */
19         /*      For details refer to the Hardware Manual or Data Sheet */
20 #pragma asm
21         ST              RP,@-R15
22         STM0    (R4,R5)
23         STM1    (R12)
24         LDI             #0x01,R4        ; Set FLASH to 16Bit read/write Mode
25         LDI             #0x04,R5        ; Go 4 times through delay loop (64MHz CLKB)
26         LDI             #0xBF60,R12
27         CALL    @R12
28         LDM1    (R12)
29         LDM0    (R4,R5)
30         LD              @R15+,RP
31 #pragma endasm
32         
33         /*      Set the FLASH Interface to Write Timing */
34         /*      For details refer to the Hardware Manual or Data Sheet */
35         /*      Setting shown here is for CLKB = 64MHz  */
36         FMWT_ATD = 1;
37         FMWT_WEXH = 0;
38         FMWT_WTC = 8;
39 }
40
41 void FLASH_PrepareReadMode()
42 {
43         /*      Set FLASH Access Mode via BootROM Routine       */
44         /*      For details refer to the Hardware Manual or Data Sheet */
45 #pragma asm
46         ST              RP,@-R15
47         STM0    (R4,R5)
48         STM1    (R12)
49         LDI             #0x00,R4        ; Set FLASH to 32Bit read/write Mode
50         LDI             #0x04,R5        ; Go 4 times through delay loop (64MHz CLKB)
51         LDI             #0xBF60,R12
52         CALL    @R12
53         LDM1    (R12)
54         LDM0    (R4,R5)
55         LD              @R15+,RP
56 #pragma endasm
57         
58         /*      Set the FLASH Interface to Read Timing  */
59         /*      For details refer to the Hardware Manual or Data Sheet */
60         /*      Setting shown here is for CLKB = 64MHz  */
61         FMWT_ATD = 1;
62         FMWT_EQ = 3;
63         FMWT_WTC = 4;
64 }               
65                 
66         
67 unsigned char FLASH_SectorErase(unsigned int secadr)
68 {
69         unsigned char flag = 0;
70         volatile unsigned int value = 0;
71         
72         /*      Disable Interrupts if necessary */
73         IFlag = FLASH_SaveDisableInterruptFlag();
74
75         /*      Set FLASH access mode to 16Bit Write Mode       */
76         FLASH_PrepareWriteHalfWordMode();
77                                         
78         secadr |= 0x0003;
79         
80         /*      Start FLASH Sector Erase Sequence       */
81         *hseq_1 = 0x00AA;
82         *hseq_2 = 0x0055;
83         *hseq_1 = 0x0080;
84         *hseq_1 = 0x00AA;
85         *hseq_2 = 0x0055;
86         *(unsigned  short int *)secadr = 0x0030;
87
88         /*      Wait for the Auto Algorithm to start    */
89         while( !( *(unsigned  short int *)secadr & SETIMR ) )
90         {
91                 /*      Feed the Hardware Watchdog      */
92                 HWWD_CL = 0;
93                 
94                 /*      Check for Pending Interrupts    */
95                 if( FLASH_CheckPendingInterrupt() )
96                 {               
97                         /*      Wait for Sector Erase Suspend   */
98                         FLASH_SuspendSectorErase(secadr);
99                         
100                 /*      Set FLASH access mode to 32Bit Read Mode        */
101                 FLASH_PrepareReadMode();
102                         
103                         /*      Restore the original Interrupt Flag     */
104                         FLASH_RestoreInterruptFlag(IFlag);
105                                                 
106                         /*      Keep on checking for pending Interrupts */
107                         while( FLASH_CheckPendingInterrupt() ) HWWD_CL = 0;
108                         
109                         /*      Disable Interrupts if necessary */
110                         IFlag = FLASH_SaveDisableInterruptFlag();
111                         
112                         /*      Set FLASH access mode to 16Bit Write Mode       */
113                 FLASH_PrepareWriteHalfWordMode();
114                                                 
115                         /*      Sector Erase Resume     */
116                         FLASH_ResumeSectorErase(secadr);
117                 }               
118         }
119
120         /*      Wait for the Auto Algorithm to finish   */
121         while( flag == 0 )
122         {
123                 /* Feed Hardware Watchdog */
124                 HWWD_CL = 0;
125
126                 /*      Check for Pending Interrupts    */
127                 if( FLASH_CheckPendingInterrupt() )
128                 {               
129                         /*      Sector Erase Suspend    */
130                         FLASH_SuspendSectorErase(secadr);
131                         
132                 /*      Set FLASH access mode to 32Bit Read Mode        */
133                 FLASH_PrepareReadMode();
134                                         
135                         /*      Restore the original Interrupt Flag     */
136                         FLASH_RestoreInterruptFlag(IFlag);
137                                                                         
138                         /*      Keep on checking for pending Interrupts */
139                         while( FLASH_CheckPendingInterrupt() ) HWWD_CL = 0;
140
141                         /*      Disable Interrupts if necessary */
142                         IFlag = FLASH_SaveDisableInterruptFlag();
143                         
144                         /*      Set FLASH access mode to 16Bit Write Mode       */
145                 FLASH_PrepareWriteHalfWordMode();
146                                                 
147                         /*      Sector Erase Resume     */
148                         FLASH_ResumeSectorErase(secadr);
149                 }               
150                 
151                         
152                 /*      Check the Hardware Sequence Flags       */                              
153                 if( ( *(unsigned short int *)secadr /* value */ & DPOLL ) )
154                 {
155                         flag = 1;
156                 }
157                 if( ( *(unsigned short int *)secadr /* value */ & TLOVER ) )
158                 {
159                         if( ( *(unsigned short int *)secadr /* value */ & DPOLL ) )
160                         {
161                                 flag = 1;
162                         }
163                         else
164                         {
165                                 /*      Reset FLASH     */
166                                 FLASH_ReadReset();
167                                 
168                                 flag = 2;
169                         }
170                 }
171         }
172         
173
174         /*      Restore the original Interrupt Flag     */
175         FLASH_RestoreInterruptFlag(IFlag);
176         
177         /*      Set FLASH access mode to 32Bit Read Mode        */
178         FLASH_PrepareReadMode();
179                 
180         return flag;
181 }
182
183 unsigned char FLASH_SectorBlankCheck(unsigned int secaddr, unsigned int size)
184 {
185         unsigned int count;
186         unsigned char empty_flag = 0;
187         unsigned int addr = secaddr;
188                 
189         /*      Clear FIXE bit to see FLASH memory content instead of fixed reset vector        */
190         FMCS_FIXE = 0;
191         
192         for(count = 0; count < size; count ++)
193         {
194                 /*      Clear Hardware Watchdog */
195                 HWWD_CL = 0;
196                 if( *(unsigned int *)addr != 0xFFFFFFFF ) empty_flag = 1;
197                 addr += 4;
198         }
199         
200         /*      Set FIXE bit to see fixed reset vector  */
201         FMCS_FIXE = 1;
202
203         if( empty_flag != 0 )
204         {
205                 return 2;
206         }
207         
208         return 1;
209 }
210
211 unsigned char FLASH_WriteHalfWord(unsigned int adr, unsigned short int data)
212 {
213         unsigned char flag = 0;
214
215         /*      Disable Interrupts if necessary */
216         IFlag = FLASH_SaveDisableInterruptFlag();
217                         
218         /*      Set FLASH access mode to 16Bit Write Mode       */
219         FLASH_PrepareWriteHalfWordMode();
220         
221         /*      Start Write FLASH Sequence      */
222         *hseq_1 = 0x00AA;
223         *hseq_2 = 0x0055;
224         *hseq_1 = 0x00A0;
225         *((volatile unsigned short int *)adr) = data;
226         
227         /*      Wait for the Auto Algorithm to finish   */
228         while( flag == 0 )
229         {
230                 /* Feed Hardware Watchdog */
231                 HWWD_CL = 0;
232                 
233                 if( ( *(volatile unsigned short int *)adr & DPOLL ) == (data & DPOLL) )
234                 {
235                         flag = 1;
236                 }
237                 if( ( *(volatile unsigned short int *)adr & TLOVER ) == TLOVER )
238                 {
239                         if( ( *(volatile unsigned short int *)adr & DPOLL ) == (data & DPOLL) )
240                         {
241                                 flag = 1;
242                         }
243                         else
244                         {
245                                 /*      Reset FLASH (keep in mind 16Bit access to FLASH)        */
246                                 *hseq_1 = 0x00F0;       // Keep in Mind (16Bit access)
247                                 
248                                 flag = 2;
249                         }
250                 }
251         }
252
253         /*      Set FLASH access mode to 32Bit Read Mode        */
254         FLASH_PrepareReadMode();
255         
256         /*      Restore the original Interrupt Flag     */
257         FLASH_RestoreInterruptFlag(IFlag);
258         
259         return flag;
260 }
261
262
263 unsigned char FLASH_ReadReset()
264 {
265         *hseq_1 = 0x00F0;
266         
267         return 1;
268 }
269
270 #pragma asm
271 _FLASH_SaveDisableInterruptFlag:
272         STM0 (R0)
273         MOV PS,R4
274         LDI     #0x00000010,R0  
275         AND R0,R4                       ; Store Original Flag
276         ANDCCR #0xFFFFFFEF      ; Clear Interrupt Flag
277         LDM0 (R0)       
278         RET
279 #pragma endasm
280
281
282 #pragma asm
283 _FLASH_RestoreInterruptFlag:
284         STM0 (R0)
285         MOV PS,R0                       ; Get current PS
286         OR R4,R0                        ; Set Flag as saved
287         MOV R0,PS                       ; Write back PS
288         LDM0 (R0)
289         RET
290 #pragma endasm
291
292
293 unsigned char FLASH_SuspendSectorErase(unsigned int secaddr)
294 {               
295         /* Write Sector Erase Suspend Command   */
296         *(volatile unsigned short int *)secaddr = 0x00B0;
297
298         /*      Wait for the FLASH macro to suspend sector erase        */              
299         while(!(*(unsigned short int *)secaddr /* value */ & DPOLL) && (*(unsigned short int *)secaddr /* value */ & SETIMR))
300         {
301                 HWWD_CL=0;
302         }
303         
304         return 1;
305 }
306
307 unsigned char FLASH_ResumeSectorErase(unsigned int secaddr)
308 {
309         /*      Write the Sector Erase Resume Command   */
310         *(volatile unsigned short int *)secaddr = 0x0030;
311         
312         /*      Wait for the FLASH Macro to resume sector erase */              
313         while((*(unsigned short int *)secaddr /*value */ & DPOLL) && !(*(unsigned short int *)secaddr /*value */ & SETIMR))
314         {
315                 HWWD_CL=0;
316         }
317         
318         return 1;               
319 }
320
321 unsigned char FLASH_CheckPendingInterrupt()
322 {
323         /*      Poll for Pending Interrupts which are needed here       */
324         if(TMCSR0_UF) return 1; /* in this sample the only interrupt source supervised is Reload Timer 0        */
325         
326         /*      and return 1 when an Interrupt is pending       */
327         return 0;
328 }