moved pkernel in a own directory
[pyfrprog.git] / pkernel / flash.c
diff --git a/pkernel/flash.c b/pkernel/flash.c
new file mode 100644 (file)
index 0000000..c72b463
--- /dev/null
@@ -0,0 +1,328 @@
+/*****************************************************************************/
+/* THIS SAMPLE CODE IS PROVIDED AS IS AND IS SUBJECT TO ALTERATIONS. FUJITSU */
+/* MICROELECTRONICS ACCEPTS NO RESPONSIBILITY OR LIABILITY FOR ANY ERRORS OR */
+/* ELIGIBILITY FOR ANY PURPOSES.                                             */
+/*                 (C) Fujitsu Microelectronics Europe GmbH                  */
+/*****************************************************************************/
+
+#include "flash.h"
+#include "mb91465k.h"
+
+static unsigned int IFlag;
+
+#pragma section CODE=IRAM,attr=CODE
+       
+
+void FLASH_PrepareWriteHalfWordMode()
+{
+       /*      Set FLASH Access Mode via BootROM Routine       */
+       /*      For details refer to the Hardware Manual or Data Sheet */
+#pragma asm
+       ST              RP,@-R15
+       STM0    (R4,R5)
+       STM1    (R12)
+       LDI             #0x01,R4        ; Set FLASH to 16Bit read/write Mode
+       LDI             #0x04,R5        ; Go 4 times through delay loop (64MHz CLKB)
+       LDI             #0xBF60,R12
+       CALL    @R12
+       LDM1    (R12)
+       LDM0    (R4,R5)
+       LD              @R15+,RP
+#pragma endasm
+       
+       /*      Set the FLASH Interface to Write Timing */
+       /*      For details refer to the Hardware Manual or Data Sheet */
+       /*      Setting shown here is for CLKB = 64MHz  */
+       FMWT_ATD = 1;
+       FMWT_WEXH = 0;
+       FMWT_WTC = 8;
+}
+
+void FLASH_PrepareReadMode()
+{
+       /*      Set FLASH Access Mode via BootROM Routine       */
+       /*      For details refer to the Hardware Manual or Data Sheet */
+#pragma asm
+       ST              RP,@-R15
+       STM0    (R4,R5)
+       STM1    (R12)
+       LDI             #0x00,R4        ; Set FLASH to 32Bit read/write Mode
+       LDI             #0x04,R5        ; Go 4 times through delay loop (64MHz CLKB)
+       LDI             #0xBF60,R12
+       CALL    @R12
+       LDM1    (R12)
+       LDM0    (R4,R5)
+       LD              @R15+,RP
+#pragma endasm
+       
+       /*      Set the FLASH Interface to Read Timing  */
+       /*      For details refer to the Hardware Manual or Data Sheet */
+       /*      Setting shown here is for CLKB = 64MHz  */
+       FMWT_ATD = 1;
+       FMWT_EQ = 3;
+       FMWT_WTC = 4;
+}              
+               
+       
+unsigned char FLASH_SectorErase(unsigned int secadr)
+{
+       unsigned char flag = 0;
+       volatile unsigned int value = 0;
+       
+       /*      Disable Interrupts if necessary */
+       IFlag = FLASH_SaveDisableInterruptFlag();
+
+       /*      Set FLASH access mode to 16Bit Write Mode       */
+       FLASH_PrepareWriteHalfWordMode();
+                                       
+       secadr |= 0x0003;
+       
+       /*      Start FLASH Sector Erase Sequence       */
+       *hseq_1 = 0x00AA;
+       *hseq_2 = 0x0055;
+       *hseq_1 = 0x0080;
+       *hseq_1 = 0x00AA;
+       *hseq_2 = 0x0055;
+       *(unsigned  short int *)secadr = 0x0030;
+
+       /*      Wait for the Auto Algorithm to start    */
+       while( !( *(unsigned  short int *)secadr & SETIMR ) )
+       {
+               /*      Feed the Hardware Watchdog      */
+               HWWD_CL = 0;
+               
+               /*      Check for Pending Interrupts    */
+               if( FLASH_CheckPendingInterrupt() )
+               {               
+                       /*      Wait for Sector Erase Suspend   */
+                       FLASH_SuspendSectorErase(secadr);
+                       
+               /*      Set FLASH access mode to 32Bit Read Mode        */
+               FLASH_PrepareReadMode();
+                       
+                       /*      Restore the original Interrupt Flag     */
+                       FLASH_RestoreInterruptFlag(IFlag);
+                                               
+                       /*      Keep on checking for pending Interrupts */
+                       while( FLASH_CheckPendingInterrupt() ) HWWD_CL = 0;
+                       
+                       /*      Disable Interrupts if necessary */
+                       IFlag = FLASH_SaveDisableInterruptFlag();
+                       
+                       /*      Set FLASH access mode to 16Bit Write Mode       */
+               FLASH_PrepareWriteHalfWordMode();
+                                               
+                       /*      Sector Erase Resume     */
+                       FLASH_ResumeSectorErase(secadr);
+               }               
+       }
+
+       /*      Wait for the Auto Algorithm to finish   */
+       while( flag == 0 )
+       {
+               /* Feed Hardware Watchdog */
+               HWWD_CL = 0;
+
+               /*      Check for Pending Interrupts    */
+               if( FLASH_CheckPendingInterrupt() )
+               {               
+                       /*      Sector Erase Suspend    */
+                       FLASH_SuspendSectorErase(secadr);
+                       
+               /*      Set FLASH access mode to 32Bit Read Mode        */
+               FLASH_PrepareReadMode();
+                                       
+                       /*      Restore the original Interrupt Flag     */
+                       FLASH_RestoreInterruptFlag(IFlag);
+                                                                       
+                       /*      Keep on checking for pending Interrupts */
+                       while( FLASH_CheckPendingInterrupt() ) HWWD_CL = 0;
+
+                       /*      Disable Interrupts if necessary */
+                       IFlag = FLASH_SaveDisableInterruptFlag();
+                       
+                       /*      Set FLASH access mode to 16Bit Write Mode       */
+               FLASH_PrepareWriteHalfWordMode();
+                                               
+                       /*      Sector Erase Resume     */
+                       FLASH_ResumeSectorErase(secadr);
+               }               
+               
+                       
+               /*      Check the Hardware Sequence Flags       */                              
+               if( ( *(unsigned short int *)secadr /* value */ & DPOLL ) )
+               {
+                       flag = 1;
+               }
+               if( ( *(unsigned short int *)secadr /* value */ & TLOVER ) )
+               {
+                       if( ( *(unsigned short int *)secadr /* value */ & DPOLL ) )
+                       {
+                               flag = 1;
+                       }
+                       else
+                       {
+                               /*      Reset FLASH     */
+                               FLASH_ReadReset();
+                               
+                               flag = 2;
+                       }
+               }
+       }
+       
+
+       /*      Restore the original Interrupt Flag     */
+       FLASH_RestoreInterruptFlag(IFlag);
+       
+       /*      Set FLASH access mode to 32Bit Read Mode        */
+       FLASH_PrepareReadMode();
+               
+       return flag;
+}
+
+unsigned char FLASH_SectorBlankCheck(unsigned int secaddr, unsigned int size)
+{
+       unsigned int count;
+       unsigned char empty_flag = 0;
+       unsigned int addr = secaddr;
+               
+       /*      Clear FIXE bit to see FLASH memory content instead of fixed reset vector        */
+       FMCS_FIXE = 0;
+       
+       for(count = 0; count < size; count ++)
+       {
+               /*      Clear Hardware Watchdog */
+               HWWD_CL = 0;
+               if( *(unsigned int *)addr != 0xFFFFFFFF ) empty_flag = 1;
+               addr += 4;
+       }
+       
+       /*      Set FIXE bit to see fixed reset vector  */
+       FMCS_FIXE = 1;
+
+       if( empty_flag != 0 )
+       {
+               return 2;
+       }
+       
+       return 1;
+}
+
+unsigned char FLASH_WriteHalfWord(unsigned int adr, unsigned short int data)
+{
+       unsigned char flag = 0;
+
+       /*      Disable Interrupts if necessary */
+       IFlag = FLASH_SaveDisableInterruptFlag();
+                       
+       /*      Set FLASH access mode to 16Bit Write Mode       */
+       FLASH_PrepareWriteHalfWordMode();
+       
+       /*      Start Write FLASH Sequence      */
+       *hseq_1 = 0x00AA;
+       *hseq_2 = 0x0055;
+       *hseq_1 = 0x00A0;
+       *((volatile unsigned short int *)adr) = data;
+       
+       /*      Wait for the Auto Algorithm to finish   */
+       while( flag == 0 )
+       {
+               /* Feed Hardware Watchdog */
+               HWWD_CL = 0;
+               
+               if( ( *(volatile unsigned short int *)adr & DPOLL ) == (data & DPOLL) )
+               {
+                       flag = 1;
+               }
+               if( ( *(volatile unsigned short int *)adr & TLOVER ) == TLOVER )
+               {
+                       if( ( *(volatile unsigned short int *)adr & DPOLL ) == (data & DPOLL) )
+                       {
+                               flag = 1;
+                       }
+                       else
+                       {
+                               /*      Reset FLASH (keep in mind 16Bit access to FLASH)        */
+                               *hseq_1 = 0x00F0;       // Keep in Mind (16Bit access)
+                               
+                               flag = 2;
+                       }
+               }
+       }
+
+       /*      Set FLASH access mode to 32Bit Read Mode        */
+       FLASH_PrepareReadMode();
+       
+       /*      Restore the original Interrupt Flag     */
+       FLASH_RestoreInterruptFlag(IFlag);
+       
+       return flag;
+}
+
+
+unsigned char FLASH_ReadReset()
+{
+       *hseq_1 = 0x00F0;
+       
+       return 1;
+}
+
+#pragma asm
+_FLASH_SaveDisableInterruptFlag:
+       STM0 (R0)
+       MOV PS,R4
+       LDI     #0x00000010,R0  
+       AND R0,R4                       ; Store Original Flag
+       ANDCCR #0xFFFFFFEF      ; Clear Interrupt Flag
+       LDM0 (R0)       
+       RET
+#pragma endasm
+
+
+#pragma asm
+_FLASH_RestoreInterruptFlag:
+       STM0 (R0)
+       MOV PS,R0                       ; Get current PS
+       OR R4,R0                        ; Set Flag as saved
+       MOV R0,PS                       ; Write back PS
+       LDM0 (R0)
+       RET
+#pragma endasm
+
+
+unsigned char FLASH_SuspendSectorErase(unsigned int secaddr)
+{              
+       /* Write Sector Erase Suspend Command   */
+       *(volatile unsigned short int *)secaddr = 0x00B0;
+
+       /*      Wait for the FLASH macro to suspend sector erase        */              
+       while(!(*(unsigned short int *)secaddr /* value */ & DPOLL) && (*(unsigned short int *)secaddr /* value */ & SETIMR))
+       {
+               HWWD_CL=0;
+       }
+       
+       return 1;
+}
+
+unsigned char FLASH_ResumeSectorErase(unsigned int secaddr)
+{
+       /*      Write the Sector Erase Resume Command   */
+       *(volatile unsigned short int *)secaddr = 0x0030;
+       
+       /*      Wait for the FLASH Macro to resume sector erase */              
+       while((*(unsigned short int *)secaddr /*value */ & DPOLL) && !(*(unsigned short int *)secaddr /*value */ & SETIMR))
+       {
+               HWWD_CL=0;
+       }
+       
+       return 1;               
+}
+
+unsigned char FLASH_CheckPendingInterrupt()
+{
+       /*      Poll for Pending Interrupts which are needed here       */
+       if(TMCSR0_UF) return 1; /* in this sample the only interrupt source supervised is Reload Timer 0        */
+       
+       /*      and return 1 when an Interrupt is pending       */
+       return 0;
+}