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 Reply Children