Write(Program command) in flash using only registers

Hi,

 I'm trying to use only registers to write to a certain address in the code part of the flash. I'm following the usage flow chart you can see in the image below but it's not working. In the code below to this post, the function I'm having problem is "flashBootloaderWrite". Thanks for letting me know if you guys have any idea what is the problem with my function.

/* Includes ------------------------------------------------------------------*/
#define _FLASH_BOOTLOADER_GLOBAL
#include "flashBootloader.h"
#undef _FLASH_BOOTLOADER_GLOBAL

#include "timerBootloader.h"

/* Local Defines -------------------------------------------------------------*/
#define inRange(value, low, high)	( ( (value) >= (low) ) && ( (value) <= (high) ) ? 1 : 0)
#define BLOCK_SIZE                        (128)
#define WAIT_FOR_LAST_OP                50000U
#define WAIT_FOR_RDY_AFTER_CMD                1000000U
#define FLASH_HP_FREQUENCY_IN_HZ                      (1000000U)

/* Local Typedefs ------------------------------------------------------------*/

/* Local Constants -----------------------------------------------------------*/

/* Local Variables -----------------------------------------------------------*/

/* Local Prototype Functions -------------------------------------------------*/
static bool flashUnlock(void);
static void flashLock(void);
static void flashOpen(void);
static void flashClose(void);
static bool waitForLastOperation(uint32_t timeout);
static void getSector(uint32_t address, uint32_t *sector);

/* Local Functions -----------------------------------------------------------*/
/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
static void getSector(uint32_t address, uint32_t *sector)
{
    static const uint32_t sector_start_addresses[] = {
        FLASH_BL_SECTOR_0_START_ADDRESS, FLASH_BL_SECTOR_1_START_ADDRESS, FLASH_BL_SECTOR_2_START_ADDRESS, FLASH_BL_SECTOR_3_START_ADDRESS,
        FLASH_BL_SECTOR_4_START_ADDRESS, FLASH_BL_SECTOR_5_START_ADDRESS, FLASH_BL_SECTOR_6_START_ADDRESS, FLASH_BL_SECTOR_7_START_ADDRESS,
        FLASH_BL_SECTOR_8_START_ADDRESS, FLASH_BL_SECTOR_9_START_ADDRESS, FLASH_BL_SECTOR_10_START_ADDRESS, FLASH_BL_SECTOR_11_START_ADDRESS,
        FLASH_BL_SECTOR_12_START_ADDRESS, FLASH_BL_SECTOR_13_START_ADDRESS, FLASH_BL_SECTOR_14_START_ADDRESS, FLASH_BL_SECTOR_15_START_ADDRESS,
        FLASH_BL_SECTOR_16_START_ADDRESS, FLASH_BL_SECTOR_17_START_ADDRESS, FLASH_BL_SECTOR_18_START_ADDRESS, FLASH_BL_SECTOR_19_START_ADDRESS,
        FLASH_BL_SECTOR_20_START_ADDRESS, FLASH_BL_SECTOR_21_START_ADDRESS, FLASH_BL_SECTOR_22_START_ADDRESS, FLASH_BL_SECTOR_23_START_ADDRESS,
        FLASH_BL_SECTOR_24_START_ADDRESS, FLASH_BL_SECTOR_25_START_ADDRESS, FLASH_BL_SECTOR_26_START_ADDRESS, FLASH_BL_SECTOR_27_START_ADDRESS,
        FLASH_BL_SECTOR_28_START_ADDRESS, FLASH_BL_SECTOR_29_START_ADDRESS, FLASH_BL_SECTOR_30_START_ADDRESS, FLASH_BL_SECTOR_31_START_ADDRESS,
        FLASH_BL_SECTOR_32_START_ADDRESS, FLASH_BL_SECTOR_33_START_ADDRESS, FLASH_BL_SECTOR_34_START_ADDRESS, FLASH_BL_SECTOR_35_START_ADDRESS,
        FLASH_BL_SECTOR_36_START_ADDRESS, FLASH_BL_SECTOR_37_START_ADDRESS, FLASH_BL_SECTOR_38_START_ADDRESS
    };

    static const uint32_t sector_end_addresses[] = {
        FLASH_BL_SECTOR_0_END_ADDRESS, FLASH_BL_SECTOR_1_END_ADDRESS, FLASH_BL_SECTOR_2_END_ADDRESS, FLASH_BL_SECTOR_3_END_ADDRESS,
        FLASH_BL_SECTOR_4_END_ADDRESS, FLASH_BL_SECTOR_5_END_ADDRESS, FLASH_BL_SECTOR_6_END_ADDRESS, FLASH_BL_SECTOR_7_END_ADDRESS,
        FLASH_BL_SECTOR_8_END_ADDRESS, FLASH_BL_SECTOR_9_END_ADDRESS, FLASH_BL_SECTOR_10_END_ADDRESS, FLASH_BL_SECTOR_11_END_ADDRESS,
        FLASH_BL_SECTOR_12_END_ADDRESS, FLASH_BL_SECTOR_13_END_ADDRESS, FLASH_BL_SECTOR_14_END_ADDRESS, FLASH_BL_SECTOR_15_END_ADDRESS,
        FLASH_BL_SECTOR_16_END_ADDRESS, FLASH_BL_SECTOR_17_END_ADDRESS, FLASH_BL_SECTOR_18_END_ADDRESS, FLASH_BL_SECTOR_19_END_ADDRESS,
        FLASH_BL_SECTOR_20_END_ADDRESS, FLASH_BL_SECTOR_21_END_ADDRESS, FLASH_BL_SECTOR_22_END_ADDRESS, FLASH_BL_SECTOR_23_END_ADDRESS,
        FLASH_BL_SECTOR_24_END_ADDRESS, FLASH_BL_SECTOR_25_END_ADDRESS, FLASH_BL_SECTOR_26_END_ADDRESS, FLASH_BL_SECTOR_27_END_ADDRESS,
        FLASH_BL_SECTOR_28_END_ADDRESS, FLASH_BL_SECTOR_29_END_ADDRESS, FLASH_BL_SECTOR_30_END_ADDRESS, FLASH_BL_SECTOR_31_END_ADDRESS,
        FLASH_BL_SECTOR_32_END_ADDRESS, FLASH_BL_SECTOR_33_END_ADDRESS, FLASH_BL_SECTOR_34_END_ADDRESS, FLASH_BL_SECTOR_35_END_ADDRESS,
        FLASH_BL_SECTOR_36_END_ADDRESS, FLASH_BL_SECTOR_37_END_ADDRESS, FLASH_BL_SECTOR_38_END_ADDRESS
    };

    size_t num_sectors = sizeof(sector_start_addresses) / sizeof(sector_start_addresses[0]);

    for (size_t i = 0; i < num_sectors; i++)
    {
        if (inRange(address, sector_start_addresses[i], sector_end_addresses[i]))
        {
            *sector = sector_start_addresses[i];
            return;
        }
    }
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
static bool flashUnlock(void)
{
        /* Disable the C-Cache. */
        R_CACHE->CCACTL = 0U;
        
        R_FACI_HP->FMEPROT = 0xD900;
        
        /* Enter Data Flash PE mode. */
        R_FACI_HP->FENTRYR = 0xAA01;

        /* Read FENTRYR until it has been set to 0x0001 indicating that we have successfully entered P/E mode.*/
	uint32_t timeoutTimer = timerBootloaderCreate(10000);
        while(0x0001 != R_FACI_HP->FENTRYR)
        {
          /* Wait until FENTRYR is 0x0001UL unless timeout occurs. */          
          if(timerBootloaderIsExpired(timeoutTimer))
          {
            /* if FENTRYR is not set after max timeout*/
            return false;
          }

        }
	return true;
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
static void flashLock(void)
{
        uint32_t  pe_mode  = R_FACI_HP->FENTRYR;
        
        /* Transition to Read mode */
        R_FACI_HP->FENTRYR = 0xAA00;

        /* Read FENTRYR until it has been set to 0 indicating that we have successfully entered P/E mode.*/
	uint32_t timeoutTimer = timerBootloaderCreate(10000);
        while(0 != R_FACI_HP->FENTRYR)
        {
          /* Wait until FENTRYR is 0x0000UL unless timeout occurs. */

            if(timerBootloaderIsExpired(timeoutTimer))
            {
              /* if FENTRYR is not set after max timeout*/
              uint8_t error = 1;
            }
        }
        if(pe_mode == 0x0001U)
        {
            R_FACI_HP->FMEPROT = 0xD901;
            
            /* Invalidate the flash cache and wait until it is invalidated. (See section 55.3.2.2 "Operation" of the Flash Cache
             * in the RA6M3 manual R01UH0878EJ0100). */
            R_FCACHE->FCACHEIV = 1U;
            while (R_FCACHE->FCACHEIV != 0U) { /* Wait. */}

            /* Enable flash cache. */
            R_FCACHE->FCACHEE = 1U;

            /* Configure the C-Cache line size. */
            R_CACHE->CCALCF = 1U;

            /* Enable the C-Cache. */
            R_CACHE->CCACTL = 1U;
        }
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
static void flashOpen(void)
{
        /* Disable Flash Rdy interrupt in the FLASH peripheral. */
        R_FACI_HP->FRDYIE = 0U;

        /* Disable Flash Error interrupt in the FLASH peripheral */
        R_FACI_HP->FAEINT = 0U;
        
        
        /* Allow Access to the Flash registers*/
        R_SYSTEM->FWEPROR = 0x01U;

        uint32_t flash_clock_freq_hz  = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_FCLK);
        uint32_t system_clock_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_ICLK);

        /* Round up the frequency to a whole number */
        uint32_t flash_clock_freq_mhz = (flash_clock_freq_hz + (FLASH_HP_FREQUENCY_IN_HZ - 1)) /
                                        FLASH_HP_FREQUENCY_IN_HZ;

        /* Set the Clock */
        R_FACI_HP->FPCKAR = (uint16_t) (0x1E00U + flash_clock_freq_mhz);
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
static void flashClose(void)
{

        /* Disable Flash Rdy interrupt in the FLASH peripheral */
        R_FACI_HP->FRDYIE = 0x00U;

        /* Disable Flash Error interrupt in the FLASH peripheral */
        R_FACI_HP->FAEINT = 0x00U;
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
static bool waitForLastOperation(uint32_t timeout)
{
        volatile uint32_t wait_count = timeout;

        while (1U != R_FACI_HP->FSTATR_b.FRDY)
        {
          /* Wait until FRDY is 1 unless timeout occurs. */
          if (wait_count == 0U)
          {
              /* if FENTRYR is not set after max timeout*/
              return false;
          }
          wait_count--;
        }

	return true;
}
/* Global Functions ----------------------------------------------------------*/
/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
void flashBootloaderRead(uint32_t address, uint32_t *data, byteOrWord_te type)
{
	if(type == FLASH_BOOTLOADER_BYTE)
	{
		*data = ((*(uint32_t*)address) & 0xFF000000) >> 24;
	}
	else if(type == FLASH_BOOTLOADER_WORD)
	{
		*data = (*(uint32_t*)address);
	}
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
bool flashBootloaderErase(uint32_t addressInSector)
{
	uint32_t sector = 0;
        
        flashOpen();
	if(flashUnlock() == true)
	{
                __disable_irq();
		if(waitForLastOperation(WAIT_FOR_LAST_OP))
		{
                        getSector(addressInSector, &sector);
                        
                        /* Set Erasure Priority Mode*/
                        R_FACI_HP->FCPSR = 1U;

//                        R_FLASH_HP_Erase(&g_flash0_ctrl, sector, 1);
                        /* Set block start address*/
                        R_FACI_HP->FSADDR = sector;
                        /* Issue two part Block Erase commands */
                        R_FACI_HP_CMD->FACI_CMD8 = 0x20;
                        R_FACI_HP_CMD->FACI_CMD8 = 0xD0;
			if(waitForLastOperation(WAIT_FOR_RDY_AFTER_CMD))
			{
			}
			else
			{
                                flashLock();
                                __enable_irq();
                                flashClose();
				return false;
			}
		}
		else
		{
                        flashLock();
                        __enable_irq();
                        flashClose();
			return false;
		}

		flashLock();
                __enable_irq();
	}
	else
	{
		flashLock();
                __enable_irq();
                flashClose();
		return false;
	}

        flashClose();
	return true;
}

/**
  *-----------------------------------------------------------------------------
  *
  * @brief  None
  *
  * @param  None
  *
  * @note
  *
  * @retval None
  *
  *-----------------------------------------------------------------------------
  */
bool flashBootloaderWrite(uint32_t address, uint32_t *data, uint8_t len, byteOrWord_te type)
{
    uint8_t write_buffer[BLOCK_SIZE];
    uint32_t sector = 0;
    static unsigned int i_test = 0;
    static uint32_t wait_count = WAIT_FOR_RDY_AFTER_CMD;
    getSector(address, &sector);

    // Clear the buffer with zeroes.
    memset(write_buffer, 0, BLOCK_SIZE);     

    // Modify the buffer with new data, ensure aligned copy
    memcpy(&write_buffer[address - sector], (uint8_t*)data, len*4); //4 because there's 4 byte into a uint32_t

    uint8_t* write_ptr = write_buffer;  // Create a pointer to walk through the buffer

    flashOpen();
    if (flashUnlock() == true)
    {
        __disable_irq();
        if(waitForLastOperation(WAIT_FOR_LAST_OP))
        {
            /* Set block start address */
            R_FACI_HP->FSADDR = sector;

            /* Issue two-part Write commands */
            R_FACI_HP_CMD->FACI_CMD8 = 0xE8;
//            if(R_FACI_HP->FASTAT_b.CMDLK && R_FACI_HP->FSTATR_b.ILGLERR)
//            {
//              R_FACI_HP_CMD->FACI_CMD8 = 0x50;
//              
//              R_FACI_HP_CMD->FACI_CMD8 = 0xE8;
//              R_FACI_HP_CMD->FACI_CMD8 = (uint8_t) 0x40; // 64 words, 128 bytes
//            }
//            else
            R_FACI_HP_CMD->FACI_CMD8 = 0x40; // 64 words, 128 bytes

            /* Write one line. If timeout, stop the flash and return error. */
            for (; i_test < (64); i_test++)
            {
                /* Copy data from source address to destination area */
                R_FACI_HP_CMD->FACI_CMD16 = *(uint16_t *)write_ptr;

                /* Wait until DBFULL is 0 unless timeout occurs */
                while (R_FACI_HP->FSTATR_b.DBFULL == 1U)
                {
                    if(wait_count == 0)
                    {
                        /* If DBFULL is not set to 0, return timeout */
                        uint16_t test = R_FACI_HP_CMD->FACI_CMD16;
                        flashLock();
                        __enable_irq();
                        flashClose();
                        return false;
                    }
                    wait_count--;
                }

                /* Increment the write pointer */
                write_ptr += 2U;  // Now this pointer is incremented, not the array
                sector += 2U;
            }

            /* Issue write end command */
            R_FACI_HP_CMD->FACI_CMD8 = 0xD0;
            if(waitForLastOperation(WAIT_FOR_RDY_AFTER_CMD))
            {
            }
            else
            {
                    flashLock();
                    __enable_irq();
                    flashClose();
                    return false;
            }
        }
        else
        {
                flashLock();
                __enable_irq();
                flashClose();
                return false;
        }
        flashLock();
        __enable_irq();
    }
    else
    {
        flashLock();
        __enable_irq();
        flashClose();
        return false;
    }

    flashClose();
    return true;
}



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

Parents
  • Hi Manchanck,

    Thank you for your patience. We've created a sample code for your application that performs erase and write operations to the code flash. You can refer to it to help improve your implementation. its the working and tested code without stack.

    #define DATA_WRITE_SIZE (4)
    #define FLASH_START_ADD 0x08000000U  // Flash memory address
    uint32_t *read_value = (uint32_t *)FLASH_START_ADD; // Assuming the read address
    #define FLASH_HP_MINIMUM_SUPPORTED_FCLK 4000000U  // Adjust this based on your specific requirement
    #define FLASH_HP_FREQUENCY_IN_HZ        1000000U  // 1 MHz for rounding up
    #define R_FLASH_HP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP 1U  // Adjust based on hardware
    #define FLASH_HP_FPCKAR_KEY 0x1A
    #define FLASH_HP_MAX_WRITE_CF_US                      (15800)
    #define FLASH_HP_FSTATR_PRGERR                        (1U << 12U)
    #define FLASH_HP_MAX_WRITE_DF_US                      (3800)
    #define FLASH_HP_MAX_DBFULL_US                        (2)
    #define FLASH_HP_MAX_BLANK_CHECK_US                   (84)
    #define FLASH_HP_MAX_WRITE_CONFIG_US                  (307000)
    #define FLASH_HP_MAX_ERASE_DF_BLOCK_US                (18000)
    #define FLASH_HP_MAX_ERASE_CF_LARGE_BLOCK_US          (1040000)
    #define FLASH_HP_MAX_ERASE_CF_SMALL_BLOCK_US          (260000)
    #define FLASH_HP_FRDY_CMD_TIMEOUT                     (19200)
    #define FLASH_HP_FENTRYR_TRANSITION_TO_DF_PE          (0xAA80U)
    #define FLASH_HP_FENTRYR_DF_PE_MODE                   (0x0080U)
    #define FLASH_HP_FACI_CMD_BLOCK_ERASE                 (0x20U)
    #define FLASH_HP_FENTRYR_READ_MODE                    (0xAA00U)
    #define FLASH_HP_FACI_CMD_BLANK_CHECK                 (0x71U)
    #define FLASH_HP_FACI_CMD_PROGRAM                     (0xE8U)
    #define FLASH_HP_FSTATR_ERSERR                        (1U << 13U)
    #define FLASH_HP_FACI_CMD_FINAL                       (0xD0U)
    #define FLASH_HP_FENTRYR_CF_PE_MODE                   (0x0001U)
    /* Minimum FCLK for Flash Operations in Hz */
    #define FLASH_HP_MINIMUM_SUPPORTED_FCLK_FREQ          (4000000U)
    #define FLASH_HP_FMEPROT_LOCK                         (0xD901)
     uint32_t timeout_erase_df_block;
     uint32_t timeout_dbfull ;
     uint32_t timeout_write_df;
     uint32_t timeout_write_cf;
     uint32_t timeout_blank_check;
     uint32_t timeout_write_config;
     uint32_t timeout_erase_cf_large_block;
     uint32_t timeout_erase_cf_small_block;
    
     // Define essential structures and types
     typedef struct
     {
         void (*p_callback)(void *p_args); // Simplified callback type
     } flash_cfg_t;
    
     typedef struct
     {
         const flash_cfg_t *p_cfg;
         uint32_t source_start_address;
         uint32_t dest_end_address;
         uint32_t operations_remaining;
     } flash_hp_instance_ctrl_t;
    
     // Global flash control
     flash_hp_instance_ctrl_t g_flash0_ctrl = {0};
    
     // Simplified flash initialization
     static fsp_err_t flash_init()
     {
         R_FACI_HP->FRDYIE = 0U;  // Disable Flash Rdy interrupt
         R_FACI_HP->FAEINT = 0U;  // Disable Flash Error interrupt
         R_SYSTEM->FWEPROR = 0x01U; // Allow Access to the Flash registers
         R_FACI_HP->FPCKAR = (uint16_t)(FLASH_HP_FPCKAR_KEY + 4); // Set Clock (Assuming FCLK is 4MHz)
    
         return FSP_SUCCESS;
     }
    
     // Function to enter P/E mode for Data Flash
     static fsp_err_t flash_enter_pe_df_mode(flash_hp_instance_ctrl_t *const p_ctrl)
     {
         R_FACI_HP->FENTRYR = 0xAA80U; // Enter Data Flash P/E mode
         uint32_t wait_count = FLASH_HP_FRDY_CMD_TIMEOUT;
    
         while (R_FACI_HP->FENTRYR != 0x0080U && wait_count--) // Wait until P/E mode is entered
         {
             if (wait_count == 0U)
             {
                 return FSP_ERR_PE_FAILURE;
             }
         }
    
         return FSP_SUCCESS;
     }
    
     // Function to exit P/E mode
     static fsp_err_t flash_pe_mode_exit(void)
     {
         R_FACI_HP->FENTRYR = 0xAA00U; // Enter Read mode
         uint32_t wait_count = FLASH_HP_FRDY_CMD_TIMEOUT;
    
         while (R_FACI_HP->FENTRYR != 0x0000U && wait_count--) // Wait until Read mode is entered
         {
             if (wait_count == 0U)
             {
                 return FSP_ERR_PE_FAILURE;
             }
         }
    
         return FSP_SUCCESS;
     }
    
     // Erase block function
     static fsp_err_t flash_erase_block(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t block_size)
     {
         R_FACI_HP->FSADDR = p_ctrl->source_start_address; // Set block start address
         R_FACI_HP_CMD->FACI_CMD8 = 0x20; // Issue Block Erase command
         R_FACI_HP_CMD->FACI_CMD8 = FLASH_HP_FACI_CMD_FINAL; // Issue Final command
    
         while (R_FACI_HP->FSTATR_b.FRDY != 1U) // Wait until the operation is complete
         {
         }
    
         return FSP_SUCCESS;
     }
    
     // Flash erase API
     fsp_err_t R_FLASH_Erase(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t const address, uint32_t const num_blocks)
     {
         p_ctrl->source_start_address = address;
         p_ctrl->operations_remaining = num_blocks;
    
         // Enter PE mode for erasing
         fsp_err_t err = flash_enter_pe_df_mode(p_ctrl);
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         // Perform erase
         err = flash_erase_block(p_ctrl, 64); // Assuming 64-byte block size
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         return flash_pe_mode_exit(); // Exit PE mode
     }
    
     // Flash write data function
     static fsp_err_t flash_write_data(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t write_size)
     {
         R_FACI_HP->FSADDR = p_ctrl->dest_end_address; // Set destination address
         R_FACI_HP_CMD->FACI_CMD8 = FLASH_HP_FACI_CMD_PROGRAM; // Issue Program command
         R_FACI_HP_CMD->FACI_CMD8 = (uint8_t)(write_size / 2U); // Set size
    
         for (uint32_t i = 0; i < (write_size / 2U); i++)
         {
             R_FACI_HP_CMD->FACI_CMD16 = *(uint16_t *)p_ctrl->source_start_address; // Write data
             p_ctrl->source_start_address += 2U;
             p_ctrl->dest_end_address += 2U;
             p_ctrl->operations_remaining--;
    
             while (R_FACI_HP->FSTATR_b.DBFULL == 1U) // Wait until DBFULL is 0
             {
             }
         }
    
         R_FACI_HP_CMD->FACI_CMD8 = FLASH_HP_FACI_CMD_FINAL; // Issue Final command
    
         while (R_FACI_HP->FSTATR_b.FRDY != 1U) // Wait until flash is ready
         {
         }
    
         return FSP_SUCCESS;
     }
    
     // Flash write API
     fsp_err_t R_FLASH_Write(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t const src_address, uint32_t flash_address, uint32_t const num_bytes)
     {
         p_ctrl->source_start_address = src_address;
         p_ctrl->dest_end_address = flash_address;
         p_ctrl->operations_remaining = (num_bytes) >> 1; // Since two bytes will be written at a time
    
         fsp_err_t err = flash_enter_pe_df_mode(p_ctrl);
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         err = flash_write_data(p_ctrl, num_bytes);
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         return flash_pe_mode_exit(); // Exit PE mode
     }
    
     // Main function
     void hal_entry(void)
     {
         flash_init(); // Initialize flash
    
         char g_src[DATA_WRITE_SIZE] = "tata";
         uint32_t src_address = (uint32_t)g_src;
         uint32_t flash_address = FLASH_START_ADD;
    
         // Erase the flash memory
         fsp_err_t err_erase = R_FLASH_Erase(&g_flash0_ctrl, flash_address, DATA_WRITE_SIZE);
         if (err_erase != FSP_SUCCESS)
         {
             while (1); // Handle erase error
         }
    
         // Write data to the flash memory
         R_FLASH_Write(&g_flash0_ctrl, src_address, flash_address, DATA_WRITE_SIZE);
    
         while (1) // Infinite loop for debugging
    
         {
    
                 if (*read_value == *(uint32_t *)g_src)
                 {
                     // Success, value written correctly
                     while (1)
                     {
                         R_IOPORT_PinWrite(&g_ioport_ctrl, LED2, BSP_IO_LEVEL_HIGH);
                         R_BSP_SoftwareDelay(40, BSP_DELAY_UNITS_MILLISECONDS);
                         R_IOPORT_PinWrite(&g_ioport_ctrl, LED2, BSP_IO_LEVEL_LOW);
                         R_BSP_SoftwareDelay(40, BSP_DELAY_UNITS_MILLISECONDS);
                     }
         }
         }
    

    Regards,

    GN_Renesas

Reply
  • Hi Manchanck,

    Thank you for your patience. We've created a sample code for your application that performs erase and write operations to the code flash. You can refer to it to help improve your implementation. its the working and tested code without stack.

    #define DATA_WRITE_SIZE (4)
    #define FLASH_START_ADD 0x08000000U  // Flash memory address
    uint32_t *read_value = (uint32_t *)FLASH_START_ADD; // Assuming the read address
    #define FLASH_HP_MINIMUM_SUPPORTED_FCLK 4000000U  // Adjust this based on your specific requirement
    #define FLASH_HP_FREQUENCY_IN_HZ        1000000U  // 1 MHz for rounding up
    #define R_FLASH_HP_CYCLES_MINIMUM_PER_TIMEOUT_LOOP 1U  // Adjust based on hardware
    #define FLASH_HP_FPCKAR_KEY 0x1A
    #define FLASH_HP_MAX_WRITE_CF_US                      (15800)
    #define FLASH_HP_FSTATR_PRGERR                        (1U << 12U)
    #define FLASH_HP_MAX_WRITE_DF_US                      (3800)
    #define FLASH_HP_MAX_DBFULL_US                        (2)
    #define FLASH_HP_MAX_BLANK_CHECK_US                   (84)
    #define FLASH_HP_MAX_WRITE_CONFIG_US                  (307000)
    #define FLASH_HP_MAX_ERASE_DF_BLOCK_US                (18000)
    #define FLASH_HP_MAX_ERASE_CF_LARGE_BLOCK_US          (1040000)
    #define FLASH_HP_MAX_ERASE_CF_SMALL_BLOCK_US          (260000)
    #define FLASH_HP_FRDY_CMD_TIMEOUT                     (19200)
    #define FLASH_HP_FENTRYR_TRANSITION_TO_DF_PE          (0xAA80U)
    #define FLASH_HP_FENTRYR_DF_PE_MODE                   (0x0080U)
    #define FLASH_HP_FACI_CMD_BLOCK_ERASE                 (0x20U)
    #define FLASH_HP_FENTRYR_READ_MODE                    (0xAA00U)
    #define FLASH_HP_FACI_CMD_BLANK_CHECK                 (0x71U)
    #define FLASH_HP_FACI_CMD_PROGRAM                     (0xE8U)
    #define FLASH_HP_FSTATR_ERSERR                        (1U << 13U)
    #define FLASH_HP_FACI_CMD_FINAL                       (0xD0U)
    #define FLASH_HP_FENTRYR_CF_PE_MODE                   (0x0001U)
    /* Minimum FCLK for Flash Operations in Hz */
    #define FLASH_HP_MINIMUM_SUPPORTED_FCLK_FREQ          (4000000U)
    #define FLASH_HP_FMEPROT_LOCK                         (0xD901)
     uint32_t timeout_erase_df_block;
     uint32_t timeout_dbfull ;
     uint32_t timeout_write_df;
     uint32_t timeout_write_cf;
     uint32_t timeout_blank_check;
     uint32_t timeout_write_config;
     uint32_t timeout_erase_cf_large_block;
     uint32_t timeout_erase_cf_small_block;
    
     // Define essential structures and types
     typedef struct
     {
         void (*p_callback)(void *p_args); // Simplified callback type
     } flash_cfg_t;
    
     typedef struct
     {
         const flash_cfg_t *p_cfg;
         uint32_t source_start_address;
         uint32_t dest_end_address;
         uint32_t operations_remaining;
     } flash_hp_instance_ctrl_t;
    
     // Global flash control
     flash_hp_instance_ctrl_t g_flash0_ctrl = {0};
    
     // Simplified flash initialization
     static fsp_err_t flash_init()
     {
         R_FACI_HP->FRDYIE = 0U;  // Disable Flash Rdy interrupt
         R_FACI_HP->FAEINT = 0U;  // Disable Flash Error interrupt
         R_SYSTEM->FWEPROR = 0x01U; // Allow Access to the Flash registers
         R_FACI_HP->FPCKAR = (uint16_t)(FLASH_HP_FPCKAR_KEY + 4); // Set Clock (Assuming FCLK is 4MHz)
    
         return FSP_SUCCESS;
     }
    
     // Function to enter P/E mode for Data Flash
     static fsp_err_t flash_enter_pe_df_mode(flash_hp_instance_ctrl_t *const p_ctrl)
     {
         R_FACI_HP->FENTRYR = 0xAA80U; // Enter Data Flash P/E mode
         uint32_t wait_count = FLASH_HP_FRDY_CMD_TIMEOUT;
    
         while (R_FACI_HP->FENTRYR != 0x0080U && wait_count--) // Wait until P/E mode is entered
         {
             if (wait_count == 0U)
             {
                 return FSP_ERR_PE_FAILURE;
             }
         }
    
         return FSP_SUCCESS;
     }
    
     // Function to exit P/E mode
     static fsp_err_t flash_pe_mode_exit(void)
     {
         R_FACI_HP->FENTRYR = 0xAA00U; // Enter Read mode
         uint32_t wait_count = FLASH_HP_FRDY_CMD_TIMEOUT;
    
         while (R_FACI_HP->FENTRYR != 0x0000U && wait_count--) // Wait until Read mode is entered
         {
             if (wait_count == 0U)
             {
                 return FSP_ERR_PE_FAILURE;
             }
         }
    
         return FSP_SUCCESS;
     }
    
     // Erase block function
     static fsp_err_t flash_erase_block(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t block_size)
     {
         R_FACI_HP->FSADDR = p_ctrl->source_start_address; // Set block start address
         R_FACI_HP_CMD->FACI_CMD8 = 0x20; // Issue Block Erase command
         R_FACI_HP_CMD->FACI_CMD8 = FLASH_HP_FACI_CMD_FINAL; // Issue Final command
    
         while (R_FACI_HP->FSTATR_b.FRDY != 1U) // Wait until the operation is complete
         {
         }
    
         return FSP_SUCCESS;
     }
    
     // Flash erase API
     fsp_err_t R_FLASH_Erase(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t const address, uint32_t const num_blocks)
     {
         p_ctrl->source_start_address = address;
         p_ctrl->operations_remaining = num_blocks;
    
         // Enter PE mode for erasing
         fsp_err_t err = flash_enter_pe_df_mode(p_ctrl);
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         // Perform erase
         err = flash_erase_block(p_ctrl, 64); // Assuming 64-byte block size
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         return flash_pe_mode_exit(); // Exit PE mode
     }
    
     // Flash write data function
     static fsp_err_t flash_write_data(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t write_size)
     {
         R_FACI_HP->FSADDR = p_ctrl->dest_end_address; // Set destination address
         R_FACI_HP_CMD->FACI_CMD8 = FLASH_HP_FACI_CMD_PROGRAM; // Issue Program command
         R_FACI_HP_CMD->FACI_CMD8 = (uint8_t)(write_size / 2U); // Set size
    
         for (uint32_t i = 0; i < (write_size / 2U); i++)
         {
             R_FACI_HP_CMD->FACI_CMD16 = *(uint16_t *)p_ctrl->source_start_address; // Write data
             p_ctrl->source_start_address += 2U;
             p_ctrl->dest_end_address += 2U;
             p_ctrl->operations_remaining--;
    
             while (R_FACI_HP->FSTATR_b.DBFULL == 1U) // Wait until DBFULL is 0
             {
             }
         }
    
         R_FACI_HP_CMD->FACI_CMD8 = FLASH_HP_FACI_CMD_FINAL; // Issue Final command
    
         while (R_FACI_HP->FSTATR_b.FRDY != 1U) // Wait until flash is ready
         {
         }
    
         return FSP_SUCCESS;
     }
    
     // Flash write API
     fsp_err_t R_FLASH_Write(flash_hp_instance_ctrl_t *const p_ctrl, uint32_t const src_address, uint32_t flash_address, uint32_t const num_bytes)
     {
         p_ctrl->source_start_address = src_address;
         p_ctrl->dest_end_address = flash_address;
         p_ctrl->operations_remaining = (num_bytes) >> 1; // Since two bytes will be written at a time
    
         fsp_err_t err = flash_enter_pe_df_mode(p_ctrl);
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         err = flash_write_data(p_ctrl, num_bytes);
         if (err != FSP_SUCCESS)
         {
             return err;
         }
    
         return flash_pe_mode_exit(); // Exit PE mode
     }
    
     // Main function
     void hal_entry(void)
     {
         flash_init(); // Initialize flash
    
         char g_src[DATA_WRITE_SIZE] = "tata";
         uint32_t src_address = (uint32_t)g_src;
         uint32_t flash_address = FLASH_START_ADD;
    
         // Erase the flash memory
         fsp_err_t err_erase = R_FLASH_Erase(&g_flash0_ctrl, flash_address, DATA_WRITE_SIZE);
         if (err_erase != FSP_SUCCESS)
         {
             while (1); // Handle erase error
         }
    
         // Write data to the flash memory
         R_FLASH_Write(&g_flash0_ctrl, src_address, flash_address, DATA_WRITE_SIZE);
    
         while (1) // Infinite loop for debugging
    
         {
    
                 if (*read_value == *(uint32_t *)g_src)
                 {
                     // Success, value written correctly
                     while (1)
                     {
                         R_IOPORT_PinWrite(&g_ioport_ctrl, LED2, BSP_IO_LEVEL_HIGH);
                         R_BSP_SoftwareDelay(40, BSP_DELAY_UNITS_MILLISECONDS);
                         R_IOPORT_PinWrite(&g_ioport_ctrl, LED2, BSP_IO_LEVEL_LOW);
                         R_BSP_SoftwareDelay(40, BSP_DELAY_UNITS_MILLISECONDS);
                     }
         }
         }
    

    Regards,

    GN_Renesas

Children