// tab space = 4
/*********************************************************************
* DISCLAIMER:                                                        *
* The software supplied by Renesas Technology America Inc. is        *
* intended and supplied for use on Renesas Technology products.      *
* This software is owned by Renesas Technology America, Inc. or      *
* Renesas Technology Corporation and is protected under applicable   *
* copyright laws. All rights are reserved.                           *
*                                                                    *
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, *
* IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO IMPLIED         *
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *
* APPLY TO THIS SOFTWARE. RENESAS TECHNOLOGY AMERICA, INC. AND       *
* AND RENESAS TECHNOLOGY CORPORATION RESERVE THE RIGHT, WITHOUT      *
* NOTICE, TO MAKE CHANGES TO THIS SOFTWARE. NEITHER RENESAS          *
* TECHNOLOGY AMERICA, INC. NOR RENESAS TECHNOLOGY CORPORATION SHALL, *
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR        *
* CONSEQUENTIAL DAMAGES FOR ANY REASON WHATSOEVER ARISING OUT OF THE *
* USE OR APPLICATION OF THIS SOFTWARE.                               *
*********************************************************************/

/*-----------------------------------------------------------------------------
  FILE NAME: Flash_API.c
-----------
DESCRIPTION: CPU Re-write functions for M16C and R8C and M32C.
-----------
    DETAILS:

------------------
 Revision History
------------------
   2.3 Sept 3, 2004
       Added support for M32C/83
   2.2 Aug 20, 2004
       Clear protect bits before R8C flash operations.
       R8C Data blocks A,B were in wrong order
   2.1 July 8, 2004
       Changed the way EW0 and EW1 Modes are defined.
       Got rid of all nested comments markers.
   2.0 May 21, 2004
       Initial Version
       Combined multiple different versions of this API for different
       MCUs into this one combined source.
       Added revision history and added tab setting at top of document
   1.0 [no date]
       Initial Version
       NOTE: Was originally multiple files like flash-62p-ew1, flash-62p-ew0,
             flash-26-ew0, flash-26-ew1, etc...

-----------------------------------------------------------------------------*/

#include "Flash_API.h"



/* This macro has been define in the h file and will create an array called block_addresses */
/* This array is made static in order for it to not show up in the debugger */
static DEFINE_ADDR_LOOKUP;

/* Variables only used by this file */
static _near unsigned int flags_reg;    /* For saving the Flags register (must be in near RAM) */
static unsigned char cm0_saved;         /* For saving the Clock Mode 0 register */
static unsigned char cm1_saved;         /* For saving the Clock Mode 1 register */
static unsigned char pm0_saved;         /* For saving the Processor Mode 0 register */
static unsigned char pm1_saved;         /* For saving the Processor Mode 1 register */
static unsigned char prcr_saved;        /*  Save Protection register */

#if (EW_MODE == 0)
#if (STATIC_RAM_CODE == 1)
/* Allocate RAM space statically to hold the CPU-Rewrite code. */
static _near unsigned char EW0_RAM_CODE[ RAM_CODE_SIZE ];
#endif /* (STATIC_RAM_CODE == 1) */
static long EW0_ARM_CODE_ptr;   /* This will server as a pointer to the code to use */
                                /* Note: 3 bytes needed for jmpi instruction */
#endif /* (EW_MODE == 0) */



/* Prototypes of functions and macros only used by this file */
static void SlowMCUClock(void);
static void RestoreMCUClock(void);

#define DISABLE_INTERRUPTS { _asm("STC FLG,_flags_reg"); _asm("FCLR I");}
#define RESTORE_INTERRUPTS { _asm("LDC _flags_reg,FLG"); }

/*****************************************************************************
Name:   FlashEraseEW0 (Should be called using the name FlashErase)
Parameters:
        block
            The block number to erase (BLOCK_0, BLOCK_1, etc...)
Returns:
        0 = Erase Successful
        1 = Erase error reported by flash control
Description:
        Erases an entire flash block.
******************************************************************************/
#if (EW_MODE == 0)
unsigned char FlashEraseEW0( unsigned char block )
{
    FLASH_PTR_TYPE flash_addr;

#if (STATIC_RAM_CODE == 0)
    /* Allocate RAM space to hold the CPU-Rewrite code on the stack. */
    unsigned char EW0_RAM_CODE[ RAM_CODE_SIZE ];
#endif

    // Get highest even block address
    flash_addr = (FLASH_PTR_TYPE) block_addresses[ block ];

    DISABLE_INTERRUPTS; // Turn off maskable interrupts

    /* Specify to the assemble code below the RAM code address */
    EW0_ARM_CODE_ptr = (long) EW0_RAM_CODE;

    /* Copy code to RAM using SMOVF instruction (faster than a loop in 'C') */
    /* Can use debugger to determine how big your RAM space needs to be */
#if (M16C_FLASH != 3)
    /* R8C and M16C */
#pragma ASM
    pushm   R1,R3,A0,A1
    mov.w   #((ERASE_CODE_END-ERASE_CODE_START+1) / 2 ),R3  ;// transfer count (number of words )
    mov.b   #((ERASE_CODE_START >> 16) & 0FFh),R1H  ;// source address
    mov.w   #(ERASE_CODE_START & 0FFFFh),A0         ;// source address
    mov.w   _EW0_ARM_CODE_ptr,A1                    ;// destination address (stored in EW0_ARM_CODE_ptr)
    smovf.w                                         ;// copy 16 bits at a time
    popm    R1,R3,A0,A1
#pragma ENDASM
#else
    /* M32C only */
#pragma ASM
    pushm   R3,A0,A1
    mov.w   #((ERASE_CODE_END-ERASE_CODE_START+1) / 2 ),R3  ;// transfer count (number of words )
    mov.l   #ERASE_CODE_START,A0                    ;// source address
    mov.l   _EW0_ARM_CODE_ptr,A1                    ;// destination address (stored in EW0_ARM_CODE_ptr)
    smovf.w                                         ;// copy 16 bits at a time
    popm    R3,A0,A1
#pragma ENDASM
#endif

    /* Must change main clock speed to meet flash requirements */
    SlowMCUClock();

    fmr01 = 0;
    fmr01 = 1;          // Set EW0 select bit

    /* !! DISABLE ALL FLASH MEMORY LOCK AND PROTECT FUNCTIONALITY !!
     * NOTE: In order to use lock/protect bit functionality, please refer to
     * the Flash Memory section in the data sheet for your specific device.
     * Also note the that following bits clear back to 0 every time you enter
     * CPU Rewrite Mode.
     * Note that for some MCUs, if the lock bit is disabled, the error bits
     * do not function.
    */
#if (PROTECT_BITS)
    fmr02 = 0;
    fmr02 = 1;          // Must write a 0 then a 1 in succession to SET
    /* Some devices have an extra bit to unprotect all blocks */
    fmr16 = 0;
    fmr16 = 1;          // Must write a 0 then a 1 in succession to SET
#endif /* (PROTECT_BITS) */

    _asm("jmpi.a _EW0_ARM_CODE_ptr");   // Jump into RAM routine spcified by EW0_ARM_CODE_ptr
    _asm("ERASE_CODE_START:");      // Create an address label so we know where copy code from

    *flash_addr = 0x50;     // Clear status register
    *flash_addr = 0x20;     // Send erase command
    *flash_addr = 0xD0;     // Send erase confirm command

    /* Note: In EW0 Mode, we need to poll the Ready/Busy bit until the operation completed */

    while(!fmr00)
    wdtr    = 0;            // wait for ready bit if executing in RAM for EW0 mode
    *flash_addr = 0xFF;     // Send Read Array command in order to tell flash controller
                            // to go back into Flash Read mode (as opposed to Read Status mode)

    /* Disable CPU rewriting commands by clearing EW entry bit */
    fmr0 = 0x20;
    _asm("nop");
    _asm("jmp.a ERASE_CODE_END");   // If in RAM, this will jump you back to flash memory
    _asm("ERASE_CODE_END:");

    RestoreMCUClock();      // Restore clock back to original speed

    if( fmr07 )             // Erasing error?
    {
        RESTORE_INTERRUPTS;
        return 1;           // Erase Fail
    }

    RESTORE_INTERRUPTS; // Restore I flag to previsous setting
    return 0;               // Erase Pass

}
#endif /* EW_MODE == 0*/

/*****************************************************************************
Name:   FlashWriteEW0 (Should be called using the name FlashWrite)
Parameters:
        flash_addr
            Flash address location to write to. For M16C & M32C devices, this MUST
            be an EVEN address. For R8C, odd address is OK.
        buffer_addr
            Address location of data buffer to write to flash
        bytes
            The number of bytes to write. For M16C devices, this MUST be an EVEN number
            because the M16C does word writes only. For R8C devices, an odd number is OK.
            For the M32C/83 only, the number MUST be a multiple of 256 bytes.
Returns:
        0 = Operation Successful
        1 = Write Error reported by flash control register
        2 = Invalid parameter passed
Description:
        Writes bytes into flash. The value of BUF_PTR_TYPE can be made a
        "far" pointer for M16C devices if you wish to pass a buffer address
        that is greater than 0xFFFF. This is set in the header file.
*****************************************************************************/
#if (EW_MODE == 0)
unsigned char FlashWriteEW0(FLASH_PTR_TYPE flash_addr,
                            BUF_PTR_TYPE buffer_addr,
                            unsigned int bytes)
{
    unsigned char ret_value = 0;

#if (STATIC_RAM_CODE == 0)
    /* Allocate RAM space to hold the CPU-Rewrite code on the stack. */
    unsigned char EW0_RAM_CODE[ RAM_CODE_SIZE ];
#endif

#if (M16C_FLASH)
    /* Check for odd number of bytes */
    if( bytes & 1)
        return 2;   // ERROR!! You must always pass an even number of bytes.

    /* Check for odd address */
    if( (int)flash_addr & 1)
        return 2;   // ERROR!! You must always pass an even flash address
#endif /* M16C_FLASH */

    DISABLE_INTERRUPTS; // Turn off maskable interrupts

    /* Specify to the assemble code below the RAM code address */
    EW0_ARM_CODE_ptr = (long) EW0_RAM_CODE;

    /* Copy code to RAM using SMOVF instruction (faster than a loop in 'C') */
    /* Can use debugger to determine how big your RAM space needs to be */
#if (M16C_FLASH != 3)
    /* R8C and M16C */
#pragma ASM
    pushm   R1,R3,A0,A1
    mov.w   #((WRITE_CODE_END-WRITE_CODE_START+1) / 2 ),R3  ;// transfer count (number of words )
    mov.b   #((WRITE_CODE_START >> 16) & 0FFh),R1H  ;// source address
    mov.w   #(WRITE_CODE_START & 0FFFFh),A0         ;// source address
    mov.w   _EW0_ARM_CODE_ptr,A1                    ;// destination address (stored in EW0_ARM_CODE_ptr)
    smovf.w                                         ;// copy 16 bits at a time
    popm    R1,R3,A0,A1
#pragma ENDASM
#else
    /* M32C only */
#pragma ASM
    pushm   R3,A0,A1
    mov.w   #((WRITE_CODE_END-WRITE_CODE_START+1) / 2 ),R3  ;// transfer count (number of words )
    mov.l   #WRITE_CODE_START,A0                    ;// source address
    mov.l   _EW0_ARM_CODE_ptr,A1                    ;// destination address (stored in EW0_ARM_CODE_ptr)
    smovf.w                                         ;// copy 16 bits at a time
    popm    R3,A0,A1
#pragma ENDASM
#endif

    /* Must change main clock speed to meet flash requirements */
    SlowMCUClock();

    fmr01 = 0;
    fmr01 = 1;              // Set EW0 select bit

    /* !! DISABLE ALL FLASH MEMORY LOCK AND PROTECT FUNCTIONALITY !!
     * NOTE: In order to use lock/protect bit functionality, please refer to
     * the Flash Memory section in the data sheet for your specific device.
     * Also note the that following bits clear back to 0 every time you enter
     * CPU Rewrite Mode.
     * Note that for some MCUs, if the lock bit is disabled, the error bits
     * do not function.
     */
#if (PROTECT_BITS)
    fmr02 = 0;
    fmr02 = 1;          // Must write a 0 then a 1 in succession to SET
    /* Some devices have an extra bit to unprotect all blocks */
    fmr16 = 0;
    fmr16 = 1;          // Must write a 0 then a 1 in succession to SET
#endif /* (PROTECT_BITS) */

    _asm("jmpi.a _EW0_ARM_CODE_ptr");   // Jump into RAM routine spcified by EW0_ARM_CODE_ptr
    _asm("WRITE_CODE_START:");          // Create an address label so we know where copy code from

    *flash_addr = 0x50;     // Clear status register
    while(bytes)
    {
        wdtr    = 0;
#if (M32C_83 != 1)
        /* All MCUs except M32C/83 */
        /* Write to the flash sequencer by writting to that area of flash memory */
        *flash_addr = 0x40;             // Send write command
        *flash_addr = *buffer_addr;     // Write next word of data
#else
        /* M32C/83 ONLY */
        /* Write to the flash sequencer by writting to that area of flash memory */
        *flash_addr = 0x41;             // Send page write command
        do
        {
            *flash_addr++ = *buffer_addr++;     // Write next word of data. We have to
            bytes -= 2;                         // write 128 words (256 bytes) at a time.
        }
        while( bytes % 256);            // do untill amount left is devisable by 256
        // account for loop decrement below
        flash_addr--;
        buffer_addr--;
        bytes += 2;
#endif  /* (M32C_83 != 1) */

        /* Note: In EW0 Mode, we need to poll the Ready/Busy bit until the operation completed */
        while(!fmr00)
        wdtr    = 0;            // wait for ready bit if executing in RAM for EW0 mode

        /* Read flash program status flag */
        if( fmr06 )     // Write error?
        {
            ret_value = 1;      // Signal that we had got an error
            break;              // Break out of while loop
        }

        flash_addr++;           // Advance to next flash write address
        buffer_addr++;          // Advance to next data buffer address

        /* NOTE: The R8C writes to flash a 8 bits at a time where as the M16C
         * writes to flash 16 bits at a time. */
#if (M16C_FLASH)
        bytes -= 2;             // Subract 2 from byte counter
#elif (R8C_FLASH)
        bytes--;                // Subract 1 from byte counter
#endif

    }

    *flash_addr = 0xFF;     // Send Read Array command in order to tell flash controller
                            // to go back into Flash Read mode (as opposed to Read Status mode)
    fmr0 = 0x20;            // disable EW mode by clearing EW entry bit
    _asm("nop");

    _asm("jmp.a WRITE_CODE_END");   // If in RAM, this will jump you back to flash memory
    _asm("WRITE_CODE_END:");

    RestoreMCUClock();      // Restore clock back to original speed
    RESTORE_INTERRUPTS; // Restore I flag to previous setting

    return ret_value;       // Return Pass/Fail
}
#endif /* EW_MODE == 0*/


/*****************************************************************************
Name:   FlashEraseEW1 (Should be called using the name FlashErase)
Parameters:
        block
            The block number to erase (BLOCK_0, BLOCK_1, etc...)
Returns:
        0 = Erase Successful
        1 = Erase error reported by flash control
Description:
        Erases an entire flash block.
******************************************************************************/
#if ( EW_MODE == 1)
unsigned char FlashEraseEW1( unsigned char block )
{
    FLASH_PTR_TYPE flash_addr;

    // Get highest even block address
    flash_addr = (FLASH_PTR_TYPE) block_addresses[ block ];

    DISABLE_INTERRUPTS; // Turn off maskable interrupts

    /* Must change main clock speed to meet flash requirements */
    SlowMCUClock();

    fmr01 = 0;
    fmr01 = 1;              // Set EW0 select bit
    fmr11 = 0;
    fmr11 = 1;              // Set to EW1 mode

    /* !! DISABLE ALL FLASH MEMORY LOCK AND PROTECT FUNCTIONALITY !!
     * NOTE: In order to use lock/protect bit functionality, please refer to
     * the Flash Memory section in the data sheet for your specific device.
     * Also note the that following bits clear back to 0 every time you enter
     * CPU Rewrite Mode.
     * Note that for some MCUs, if the lock bit is disabled, the error bits
     * do not function.
     */
#if (PROTECT_BITS)
    fmr02 = 0;
    fmr02 = 1;          // Must write a 0 then a 1 in succession to SET
    /* Some devices have an extra bit to unprotect all blocks */
    fmr16 = 0;
    fmr16 = 1;          // Must write a 0 then a 1 in succession to SET
#endif /* (PROTECT_BITS) */

    *flash_addr = 0x50;     // Clear status register
    *flash_addr = 0x20;     // Send erase command
    *flash_addr = 0xD0;     // Send erase confirm command

    /* Note: In EW1 Mode, the MCU is suspended until the operation is completed */

    /* Disable CPU rewriting commands by clearing EW entry bit */
    fmr0 = 0x20;            // (must be 16-bit write for M32C while in EW1 Mode)

    RestoreMCUClock();      // Restore clock back to original speed

    if( fmr07 )             // Erasing error?
    {
        RESTORE_INTERRUPTS;
        return 1;           // Erase Fail
    }

    RESTORE_INTERRUPTS; // Restore I flag to previsous setting
    return 0;               // Erase Pass

}
#endif /* EW_MODE == 1*/

/*****************************************************************************
Name:   FlashWriteEW1 (Should be called using the name FlashWrite)
Parameters:
        flash_addr
            Flash address location to write to. For M16C devices, this MUST be an EVEN
            address. For R8C, odd address is OK.
        buffer_addr
            Address location of data buffer to write to flash
        bytes
            The number of bytes to write. For M16C devices, this MUST be an EVEN number
            because the M16C does word writes only. For R8C devices, an odd number is OK.
Returns:
        0 = Operation Successful
        1 = Write Error reported by flash control register
        2 = Invalid parameter passed
Description:
        Writes bytes into flash. The value of BUF_PTR_TYPE can be made a
        "far" pointer for M16C devices if you wish to pass a buffer address
        that is greater than 0xFFFF. This is set in the header file.
*****************************************************************************/
#if ( EW_MODE == 1)
unsigned char FlashWriteEW1(    FLASH_PTR_TYPE flash_addr,
                            BUF_PTR_TYPE buffer_addr,
                            unsigned int bytes)
{
    unsigned char ret_value = 0;

#if (M16C_FLASH)
    /* Check for odd number of bytes */
    if( bytes & 1)
        return 2;   // ERROR!! You must always pass an even number of bytes.

    /* Check for odd address */
    if( (int)flash_addr & 1)
        return 2;   // ERROR!! You must always pass an even flash address
#endif /* M16C_FLASH */

    DISABLE_INTERRUPTS; // Turn off maskable interrupts

    /* Must change main clock speed to meet flash requirements */
    SlowMCUClock();

    fmr01 = 0;
    fmr01 = 1;              // Set EW0 select bit
    fmr11 = 0;
    fmr11 = 1;              // Set to EW1 mode

    /* !! DISABLE ALL FLASH MEMORY LOCK AND PROTECT FUNCTIONALITY !!
     * NOTE: In order to use lock/protect bit functionality, please refer to
     * the Flash Memory section in the data sheet for your specific device.
     * Also note the that following bits clear back to 0 every time you enter
     * CPU Rewrite Mode.
     * Note that for some MCUs, if the lock bit is disabled, the error bits
     * do not function.
     */
#if (PROTECT_BITS)
    fmr02 = 0;
    fmr02 = 1;          // Must write a 0 then a 1 in succession to SET
    /* Some devices have an extra bit to unprotect all blocks */
    fmr16 = 0;
    fmr16 = 1;          // Must write a 0 then a 1 in succession to SET
#endif /* (PROTECT_BITS) */

    *flash_addr = 0x50;     // Clear status register
    while(bytes)
    {
        /* Write to the flash sequencer by writting to that area of flash memory */
        *flash_addr = 0x40;         // Send write command
        *flash_addr = *buffer_addr;     // Write next word of data

        /* Note: In EW1 Mode, the MCU is suspended until the operation completed */

        /* Read flash program status flag */
        if( fmr06 )     // Write error?
        {
            ret_value = 1;      // Signal that we had got an error
            break;              // Break out of while loop
        }

        flash_addr++;           // Advance to next flash write address
        buffer_addr++;          // Advance to next data buffer address

        /* NOTE: The R8C writes to flash a 8 bits at a time where as the M16C
         * writes to flash 16 bits at a time. */
#if (M16C_FLASH)
        bytes -= 2;             // Subract 2 from byte counter
#elif (R8C_FLASH)
        bytes--;                // Subract 1 from byte counter
#endif

    }

    /* Disable CPU rewriting commands by clearing EW entry bit */
    fmr0 = 0x20;                // (must be 16-bit write for M32C while in EW1 Mode)

    RestoreMCUClock();      // Restore clock back to original speed
    RESTORE_INTERRUPTS; // Restore I flag to previous setting

    return ret_value;       // Return Pass/Fail
}
#endif /* EW_MODE == 1*/


/*****************************************************************************
Name:       SlowMCUClock
Parameters: none
Returns:  nothing
Description: Sets the processor mode for programming flash and saves current
             settings to restore later. You cannot run the processor faster
             than 10.0 MHz (with wait state) or 6.25MHz (without wait state)
             when sending commanads to the flash controller.
*****************************************************************************/
static void SlowMCUClock(void)
{
    /* Unprotect registers CM0 and CM1 and PM0 registers by writting to protection register */
    prcr_saved = *((char *)0xA);    // Save Protection register
    *((char *)0xA) = 3;             // Allow writting to protected system registers

#if ( (EW_MODE == 1) && ((M16C_FLASH == 1) || (M16C_FLASH == 3)) )
    /* Force to Single chip mode for processors that have memory expansion mode */
    pm0_saved = *((char *)0x4);             // Save pm0 register
    *((char *)0x4) = pm0_saved & 0xFC;      // bit 0 and 1 to zero
#endif



#if (M16C_FLASH != 3 )
    /***********************************/
    /* Clock settings for R8C and M16C */
    /***********************************/
    cm0_saved = *((char *)0x6);     // Save cm0 register
    cm1_saved = *((char *)0x7);     // Save cm1 register
    pm1_saved = *((char *)0x5);     // Save pm1 register

    /* Insert Wait state for all bus access (needed for talking to the */
    /* internal flash controller) */
    _asm("BSET  7,05h");        /* Set bit PM17 */

    /* Now slow the clock down to at least 10MHz */
#if (BCLK_FREQUENCY <= 10000000)
    /* NO NEED TO SLOW DOWN CLOCK */
#elif (BCLK_FREQUENCY <= 20000000 )
/* Set main clock divide by 2 */
    _asm("BSET  6,07h");        /* Set bit CM16 */
    _asm("BCLR  7,07h");        /* Clear bit CM17 */
    _asm("BCLR  6,06h");        /* Clear bit CM06 */
#elif (BCLK_FREQUENCY <= 40000000)
    /* Set main clock divide by 4 */
    _asm("BCLR  6,07h");        /* Clear bit CM16 */
    _asm("BSET  7,07h");        /* Set bit CM17   */
    _asm("BCLR  6,06h");        /* Clear bit CM06 */
#else /* BCLK_FREQUENCY > 40000000 */
    /* Set main clock divide by 8 */
    _asm("BSET  6,06h");        /* Set bit CM06 */
#endif /* BCLK_FREQUENCY */


#else /* (M16C_FLASH == 3 ) */
    /***************************/
    /* Clock settings for M32C */
    /***************************/
    cm0_saved = *((char *)0xC);     // Save MCD regsiter to "cm0_saved"
    pm1_saved = *((char *)0x5);     // Save pm1 regsiter

    /* Insert Wait state for all bus access (needed for talking to the */
    /* internal flash controller) */
    _asm("BSET  2,05h");        /* Set bit PM12 */

#if (BCLK_FREQUENCY <= 10000000)
    /* NO NEED TO SLOW DOWN CLOCK */
#elif (BCLK_FREQUENCY <= 20000000)
    /* Set main clock divide by 2 */
    *((char *)0xC) = 2;
#elif (BCLK_FREQUENCY <= 30000000)
    /* Set main clock divide by 3 */
    *((char *)0xC) = 3;
#elif (BCLK_FREQUENCY <= 40000000)
    /* Set main clock divide by 4 */
    *((char *)0xC) = 4;
#endif /* BCLK_FREQUENCY */


#endif /* (M16C_FLASH != 3 ) */

}

/*****************************************************************************
Name:       RestoreMCUClock
Parameters: none
Returns:    nothing
Description: Restores the processor mode back to original settings.
*****************************************************************************/
static void RestoreMCUClock(void)
{
#if ( (EW_MODE == 1) && ((M16C_FLASH == 1) || (M16C_FLASH == 3)) )
    *((char *)0x4) = pm0_saved;     // Restore pm0 register
#endif

#if (M16C_FLASH != 3 )
    /* Clock settings for R8C and M16C */
    *((char *)0x7) = cm1_saved;     // Restore cm1 register
    *((char *)0x6) = cm0_saved;     // Restore cm0 register
    *((char *)0x5) = pm1_saved;     // Restore pm1 register
#else
    /* Clock settings for M32C */
    *((char *)0xC) = cm0_saved;     // MCD regsiter was saved to "cm0_saved"
    *((char *)0x5) = pm1_saved;     // Restore pm1 register
#endif

    *((char *)0xA) = prcr_saved;    // Protection back on
}