Skip to content

Instantly share code, notes, and snippets.

@f-steff
Last active May 7, 2024 13:01
Show Gist options
  • Save f-steff/386775b0afb778f4516e128fbc946940 to your computer and use it in GitHub Desktop.
Save f-steff/386775b0afb778f4516e128fbc946940 to your computer and use it in GitHub Desktop.
Renesas RX MCU code flash programming - the example Renesas didn't provide.

Test project to try the four known modes of Code Flash self Programming of the RX family.

This code is tested on the RX651 Test board, with the R5F565NEDDFP MCU,

Compiled using CC-RX v3.06.00, and utilizing r_bsp 7.42 and r_flash_rx v5.11

It is expected that this code can be used on at least other RX MCU's from Renesas.

Not all of the tested features are expected to work on all of the various RX MCU's.

The code is a heavily modified version of the flash_demo_rskrx65n example from Renesas.

Four scenarios to modify code flash are tested:

  • r_flash_rx functions executes in RAM - in blocking mode.

  • r_flash_rx functions executes in RAM - in background mode (callback when finishing).

  • r_flash_rx functions executes in ROM - in blocking mode.

  • r_flash_rx functions executes in ROM - in background mode (callback when finishing).

Choose the mode by making modifications to the r_flash_rx component configuration

Note

Debugging of the R_FLASH_Erase() and R_FLASH_Write() functions from r_flash_rx usually results in some sort of crash, as ROM (aka Flash) can not be read while the device is in P/E (Program/Erase) mode. Stepping over the functions will work.

/** Test project to try the four known modes of Code Flash self Programming of the RX family. **/
/** **/
/** This code is tested on the RX651 Test board, with the R5F565NEDDFP MCU. **/
/** Compiled using CC-RX v3.06.00, and using r_bsp 7.42 and r_flash_rx v5.11 **/
/** **/
/** It is expected that this code can be used on at least other RX MCU's from Renesas. **/
/** Not all of the tested features are expected to work on all of the various RX MCU's. **/
/** **/
/** The code is a heavily modified version of the flash_demo_rskrx65n example from Renesas. **/
/** **/
/** Four scenarios to modify code flash are tested: **/
/** * r_flash_rx functions executes in RAM - in blocking mode. **/
/** * r_flash_rx functions executes in RAM - in background mode (callback when finishing). **/
/** * r_flash_rx functions executes in ROM - in blocking mode. **/
/** * r_flash_rx functions executes in ROM - in background mode (callback when finishing). **/
/** Choose the mode by making modifications to the r_flash_rx component configuration **/
/** **/
/** NOTE: Debugging of the R_FLASH_Erase() and R_FLASH_Write() functions from r_flash_rx usually **/
/** results in some sort of crash. Stepping over the functions will work. **/
/** **/
/** 2024-05-07 Flemming Steffensen **/
#include "platform.h"
#include "r_flash_rx_if.h"
#include "r_flash_rx_config.h"
/** The warnings section below reveals how r_flash_rx component are configured in the smart configurator. **/
#if (FLASH_CFG_CODE_FLASH_ENABLE == 1)
#if (FLASH_CFG_CODE_FLASH_RUN_FROM_ROM == 0)
#if (FLASH_CFG_CODE_FLASH_BGO == 0)
#warning "r_flash_rx functions executes in RAM, and blocks while executing. (BLOCK)"
#else
#warning "r_flash_rx functions executes in RAM, and runs in the background - calling a callback when finishing. (BGO)"
#endif
#else
#if (FLASH_CFG_CODE_FLASH_BGO == 0)
#warning "r_flash_rx functions executes in ROM, and blocks while executing. (BLOCK)"
#else
#warning "r_flash_rx functions executes in ROM, and runs in the background - calling a callback when finishing. (BGO)"
#endif
#endif
#else
#warning "Upgrade of code flash is disabled."
#endif
/***********************************************************************************************************************
Private global variables and functions
***********************************************************************************************************************/
static uint32_t ram_vector_table[256]; // RAM space to hold the vector table
volatile uint8_t g_buf[FLASH_CF_MEDIUM_BLOCK_SIZE];
#if (FLASH_CFG_CODE_FLASH_BGO == 1)
// Only needed for background operation.
typedef enum {
IDLE,
RUNNING
} flashOperation_t;
// Declare the global variable
volatile flashOperation_t flashBackgroundOperationCompleteFlag = IDLE;
volatile flash_interrupt_event_t flash_interrupt_event;
// Callback function for flash background operation.
void cb_flashBackgroundOperationComplete(void *event) {
flashBackgroundOperationCompleteFlag = IDLE;
flash_interrupt_event = *((flash_interrupt_event_t*)event);
}
static flash_err_t setupFlashCallback(void){
static bool Initialized = false;
flash_err_t err;
if (Initialized){
return FLASH_SUCCESS;
}
flash_interrupt_config_t cb_func_info;
cb_func_info.pcallback = cb_flashBackgroundOperationComplete;
cb_func_info.int_priority = 15;
err = R_FLASH_Control(FLASH_CMD_SET_BGO_CALLBACK, (void *)&cb_func_info);
if(err != FLASH_SUCCESS)
{
return err;
}
Initialized = true;
return err;
}
// Only needed for background operation.
#endif
/***********************************************************************************************************************
* Function Name: flash_copy_vector_table
* Description : Moves the relocatable vector table to RAM. This is only needed if ROM operations are performed.
* ROM cannot be accessed during operations. The vector table is located in ROM and will be accessed
* if an interrupt occurs.
* Note : This is STRICTLY NEEDED for any ROM modification to function!!
***********************************************************************************************************************/
static void flash_copy_vector_table(void)
{
uint32_t * flash_vect;
uint32_t i;
/* Get address of variable vector table in ROM */
flash_vect = (uint32_t *)get_intb();
/* Copy over variable vector table to RAM */
for(i = 0; i < 256; i++ )
{
ram_vector_table[i] = *flash_vect; // Copy over entry
flash_vect += 1; // Move pointer
}
/* Set INTB to ram address */
#if __RENESAS_VERSION__ >= 0x01010000
set_intb((void *)&ram_vector_table[0] );
#else
set_intb( (uint32_t)&ram_vector_table[0] );
#endif
}
/** Wrap R_FLASH_Erase, so that the optional interrupt flag is updated correctly. **/
static flash_err_t R_FLASH_Erase_Operation(flash_block_address_t block_start_address, uint32_t num_blocks) {
#if (FLASH_CFG_CODE_FLASH_BGO == 0)
// Blocking mode
return R_FLASH_Erase(block_start_address, num_blocks);
#else
// Non blocking mode
flash_err_t err;
flashBackgroundOperationCompleteFlag = RUNNING;
err = R_FLASH_Erase(block_start_address, num_blocks);
if (err != FLASH_SUCCESS){
flashBackgroundOperationCompleteFlag = IDLE;
}
return err;
#endif
}
/** Wrap R_FLASH_Write, so that the optional interrupt flag is updated correctly. **/
static flash_err_t R_FLASH_Write_Operation(uint32_t src_address, uint32_t dest_address, uint32_t num_bytes) {
#if (FLASH_CFG_CODE_FLASH_BGO == 0)
// Blocking mode
return R_FLASH_Write(src_address, dest_address, num_bytes);
#else
// Non blocking mode
flash_err_t err;
flashBackgroundOperationCompleteFlag = RUNNING;
err = R_FLASH_Write(src_address, dest_address, num_bytes);
if (err != FLASH_SUCCESS){
flashBackgroundOperationCompleteFlag = IDLE;
}
return err;
#endif
}
/*******************************************************************************
* Outline : Test of Blocking or nonBlocking code flash operations: erase, write, and read data back.
* Description : Will run either in RAM or ROM, either blocking or nonBlocking, depending on FIT Component settings.
* Note : Debugger cannot inspect ROM contents when in ROM P/E mode (P/E == Program/Erase)
*******************************************************************************/
int main(void)
{
uint32_t i;
flash_err_t err;
volatile uint32_t addr;
flash_access_window_config_t accessInfo;
/* Initialize test data to write */
for (i = 0; i < sizeof(g_buf); i++)
{
g_buf[i] = (uint8_t)i;
}
/* Copy vector table to RAM if interrupts possible while erasing/writing ROM */
/* THIS IS CRUCIAL for ROM programming to function.*/
flash_copy_vector_table();
/* Open flash driver */
err = R_FLASH_Open();
if (err != FLASH_SUCCESS)
while(1); // ERROR
#if (FLASH_CFG_CODE_FLASH_BGO == 1)
/* When running in BGO mode, a callback must be configures.*/
/* This function must be called after the R_FLASH_Open() call. */
err = setupFlashCallback();
if (err != FLASH_SUCCESS)
{
while (1); // ERROR
}
#endif
/* Specifically mark code flash address range as ok to erase/write */
accessInfo.start_addr = (uint32_t)FLASH_CF_BLOCK_9; // Lowest address
accessInfo.end_addr = (uint32_t)FLASH_CF_BLOCK_8; // Highest address
err = R_FLASH_Control(FLASH_CMD_ACCESSWINDOW_SET, (void *)&accessInfo);
if (err != FLASH_SUCCESS)
{
while (1); // ERROR
}
/* Overwrite the first 5 bytes of data */
g_buf[0] = 'H';
g_buf[1] = 'e';
g_buf[2] = 'l';
g_buf[3] = 'l';
g_buf[4] = 'o';
/* Erase code flash block - again */
err = R_FLASH_Erase_Operation(FLASH_CF_BLOCK_9, 1);
if(err != FLASH_SUCCESS)
{
while(1); // ERROR
}
#if (FLASH_CFG_CODE_FLASH_BGO == 1)
while (RUNNING == flashBackgroundOperationCompleteFlag){};
if(flash_interrupt_event != FLASH_INT_EVENT_ERASE_COMPLETE)
{
while(1); // ERROR
}
#endif
/*
Note: The block size if defined in FLASH_CF_SMALL_BLOCK_SIZE and FLASH_CF_MEDIUM_BLOCK_SIZE.
The first 8 blocks are always small. For dual bank, the first 8 blocks in each bank is small.
Be aware that there's a minimum size to program at a time, defined in FLASH_CF_MIN_PGM_SIZE.
*/
addr = (uint32_t)FLASH_CF_BLOCK_9;
err = R_FLASH_Write_Operation((uint32_t)g_buf, addr, FLASH_CF_MIN_PGM_SIZE);
if(err != FLASH_SUCCESS)
{
while(1); // ERROR
}
#if (FLASH_CFG_CODE_FLASH_BGO == 1)
while (RUNNING == flashBackgroundOperationCompleteFlag){};
if(flash_interrupt_event != FLASH_INT_EVENT_WRITE_COMPLETE)
{
while(1); // ERROR
}
#endif
/* Verify code flash write */
for (i = 0; i < FLASH_CF_MIN_PGM_SIZE; i++) {
if (g_buf[i] != *((uint8_t *)(addr + i))) {
while(1); // Verify ERROR
}
}
/* Close flash driver */
err = R_FLASH_Close();
if (err != FLASH_SUCCESS)
while(1); // ERROR
while(1); // Everything worked!
return(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment