0f57ccf7f2
Signed-off-by: Takeo Takahashi <takeo.takahashi.xv@renesas.com>
299 lines
9.1 KiB
C
299 lines
9.1 KiB
C
/*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2021 Renesas Electronics Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include "hal_data.h"
|
|
#include "ra_config.h"
|
|
#include "ra_utils.h"
|
|
#include "ra_flash.h"
|
|
|
|
#if !defined(USE_FSP_FLASH)
|
|
#define USE_FSP_FLASH
|
|
#endif
|
|
|
|
#if defined(USE_FSP_FLASH)
|
|
|
|
#if defined(__GNUC__)
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
#pragma GCC diagnostic ignored "-Wmissing-declarations"
|
|
#endif
|
|
|
|
/* Flags, set from Callback function */
|
|
static volatile _Bool g_b_flash_event_not_blank = false;
|
|
static volatile _Bool g_b_flash_event_blank = false;
|
|
static volatile _Bool g_b_flash_event_erase_complete = false;
|
|
static volatile _Bool g_b_flash_event_write_complete = false;
|
|
|
|
static uint8_t flash_buf[FLASH_BUF_SIZE] __attribute__((aligned(2)));
|
|
|
|
void *FLASH_SECTION lmemset(void *dst, int c, size_t len) {
|
|
char *p;
|
|
for (p = (char *)dst; len > 0; len--) {
|
|
*(p++) = (char)c;
|
|
}
|
|
return (void *)dst;
|
|
}
|
|
|
|
void *FLASH_SECTION lmemcpy(void *dst, const void *src, size_t len) {
|
|
char *d = (char *)dst;
|
|
const char *s = (const char *)src;
|
|
for (; len > 0; len--) {
|
|
*(d++) = *(s++);
|
|
}
|
|
return (void *)dst;
|
|
}
|
|
|
|
int FLASH_SECTION lmemcmp(const void *p1, const void *p2, size_t len) {
|
|
unsigned char *a, *b;
|
|
size_t i;
|
|
|
|
a = (unsigned char *)p1;
|
|
b = (unsigned char *)p2;
|
|
for (i = 0; i < len; i++) {
|
|
if (*a != *b) {
|
|
return (*a < *b) ? -1 : 1;
|
|
}
|
|
a++;
|
|
b++;
|
|
}
|
|
return (int)0;
|
|
}
|
|
|
|
#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1)
|
|
|
|
uint32_t FLASH_SECTION sector_size(uint32_t addr) {
|
|
return FLASH_SECTOR_SIZE;
|
|
}
|
|
|
|
uint32_t FLASH_SECTION sector_start(uint32_t addr) {
|
|
return addr & ~(FLASH_SECTOR_SIZE - 1);
|
|
}
|
|
|
|
uint32_t FLASH_SECTION sector_index(uint32_t addr) {
|
|
return (addr - 0x00000000) / FLASH_SECTOR_SIZE;
|
|
}
|
|
|
|
#elif defined(RA6M1) | defined(RA6M2)
|
|
|
|
#define REGION1_SECTOR_SIZE 0x8000 // 32K
|
|
#define REGION1_SECTOR_MAX 14
|
|
#define REGION0_SECTOR_SIZE 0x2000 // 8K
|
|
#define REGION0_SECTOR_MAX 8
|
|
|
|
uint32_t FLASH_SECTION sector_size(uint32_t addr) {
|
|
if (addr <= 0x00010000) {
|
|
return REGION0_SECTOR_SIZE;
|
|
} else {
|
|
return REGION1_SECTOR_SIZE;
|
|
}
|
|
}
|
|
|
|
uint32_t FLASH_SECTION sector_start(uint32_t addr) {
|
|
if (addr <= 0x00010000) {
|
|
return addr & ~(REGION0_SECTOR_SIZE - 1);
|
|
} else {
|
|
return addr & ~(REGION1_SECTOR_SIZE - 1);
|
|
}
|
|
}
|
|
|
|
uint32_t FLASH_SECTION sector_index(uint32_t addr) {
|
|
if (addr <= 0x00010000) {
|
|
return (addr - 0x00010000) / REGION0_SECTOR_SIZE;
|
|
} else {
|
|
return (addr - 0x000100000) / REGION1_SECTOR_SIZE;
|
|
}
|
|
}
|
|
|
|
#else
|
|
#error "CMSIS MCU Series is not specified."
|
|
#endif
|
|
|
|
bool internal_flash_read(uint8_t *addr, uint32_t NumBytes, uint8_t *pSectorBuff) {
|
|
CHIP_WORD *startaddr = (CHIP_WORD *)addr;
|
|
CHIP_WORD *endaddr = (CHIP_WORD *)(addr + NumBytes);
|
|
while (startaddr < endaddr) {
|
|
*pSectorBuff++ = *startaddr++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool internal_flash_write(uint8_t *addr, uint32_t NumBytes, uint8_t *pSectorBuff, bool ReadModifyWrite) {
|
|
return internal_flash_writex(addr, NumBytes, pSectorBuff, ReadModifyWrite, true);
|
|
}
|
|
|
|
bool internal_flash_writex(uint8_t *addr, uint32_t NumBytes, uint8_t *pSectorBuff, bool ReadModifyWrite, bool fIncrementDataPtr) {
|
|
fsp_err_t err = FSP_SUCCESS;
|
|
bool flag;
|
|
uint32_t count;
|
|
uint8_t *buf_addr = (uint8_t *)&flash_buf[0];
|
|
uint32_t startaddr = (uint32_t)addr & FLASH_BUF_ADDR_MASK;
|
|
uint32_t offset = (uint32_t)addr & FLASH_BUF_OFF_MASK;
|
|
uint32_t endaddr = (uint32_t)addr + NumBytes;
|
|
uint32_t error_code = 0;
|
|
while (startaddr < endaddr) {
|
|
// copy from dst rom addr to flash buffer to keep current data
|
|
lmemcpy(flash_buf, (void *)startaddr, FLASH_BUF_SIZE);
|
|
// memset(flash_buf, 0xff, FLASH_BUF_SIZE);
|
|
if (NumBytes + offset > FLASH_BUF_SIZE) {
|
|
count = FLASH_BUF_SIZE - offset;
|
|
NumBytes -= count;
|
|
} else {
|
|
count = NumBytes;
|
|
}
|
|
// overwrite data from src addr to flash buffer
|
|
if (fIncrementDataPtr) {
|
|
lmemcpy(flash_buf + offset, pSectorBuff, count);
|
|
} else {
|
|
lmemset(flash_buf + offset, (int)*pSectorBuff, count);
|
|
}
|
|
g_b_flash_event_write_complete = false;
|
|
uint8_t *flash_addr = (uint8_t *)((uint32_t)startaddr & FLASH_BUF_ADDR_MASK);
|
|
uint32_t state = ra_disable_irq();
|
|
#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1)
|
|
err = R_FLASH_LP_Write(&g_flash0_ctrl, (uint32_t const)buf_addr, (uint32_t)flash_addr, FLASH_SECTOR_SIZE);
|
|
#elif defined(RA6M1) | defined(RA6M2)
|
|
err = R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t const)buf_addr, (uint32_t)flash_addr, FLASH_SECTOR_SIZE);
|
|
#else
|
|
#error "CMSIS MCU Series is not specified."
|
|
#endif
|
|
ra_enable_irq(state);
|
|
if (FSP_SUCCESS != err) {
|
|
error_code = 1;
|
|
goto WriteX_exit;
|
|
}
|
|
if (fIncrementDataPtr) {
|
|
flag = (lmemcmp((void *)(startaddr + offset), flash_buf + offset, count) == 0);
|
|
if (!flag) {
|
|
error_code = 2;
|
|
break;
|
|
}
|
|
}
|
|
offset = 0;
|
|
startaddr += FLASH_BUF_SIZE;
|
|
pSectorBuff += count;
|
|
}
|
|
WriteX_exit:
|
|
if (error_code == 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool internal_flash_memset(uint8_t *addr, uint8_t Data, uint32_t NumBytes) {
|
|
return true;
|
|
}
|
|
|
|
bool internal_flash_isblockerased(uint8_t *addr, uint32_t BlockLength) {
|
|
fsp_err_t err = FSP_SUCCESS;
|
|
flash_result_t blankCheck = FLASH_RESULT_BLANK;
|
|
g_b_flash_event_not_blank = false;
|
|
g_b_flash_event_blank = false;
|
|
uint32_t state = ra_disable_irq();
|
|
#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1)
|
|
err = R_FLASH_LP_BlankCheck(&g_flash0_ctrl, (uint32_t const)((uint32_t)addr & FLASH_BUF_ADDR_MASK), FLASH_SECTOR_SIZE, &blankCheck);
|
|
#elif defined(RA6M1) | defined(RA6M2)
|
|
err = R_FLASH_HP_BlankCheck(&g_flash0_ctrl, (uint32_t const)((uint32_t)addr & FLASH_BUF_ADDR_MASK), FLASH_SECTOR_SIZE, &blankCheck);
|
|
#else
|
|
#error "CMSIS MCU Series is not specified."
|
|
#endif
|
|
ra_enable_irq(state);
|
|
if (err == FSP_SUCCESS) {
|
|
if (FLASH_RESULT_BLANK == blankCheck) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool internal_flash_eraseblock(uint8_t *addr) {
|
|
uint32_t error_code = 0;
|
|
fsp_err_t err = FSP_SUCCESS;
|
|
g_b_flash_event_erase_complete = false;
|
|
uint32_t state = ra_disable_irq();
|
|
#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1)
|
|
err = R_FLASH_LP_Erase(&g_flash0_ctrl, (uint32_t const)addr, 1);
|
|
#elif defined(RA6M1) | defined(RA6M2)
|
|
err = R_FLASH_HP_Erase(&g_flash0_ctrl, (uint32_t const)addr, 1);
|
|
#else
|
|
#error "CMSIS MCU Series is not specified."
|
|
#endif
|
|
ra_enable_irq(state);
|
|
if (err == FSP_SUCCESS) {
|
|
error_code = 0;
|
|
} else {
|
|
error_code = 1;
|
|
}
|
|
if (error_code == 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* Callback function */
|
|
void callback_flash(flash_callback_args_t *p_args) {
|
|
/* TODO: add your own code here */
|
|
switch (p_args->event) {
|
|
case FLASH_EVENT_NOT_BLANK:
|
|
g_b_flash_event_not_blank = true;
|
|
break;
|
|
case FLASH_EVENT_BLANK:
|
|
g_b_flash_event_blank = true;
|
|
break;
|
|
case FLASH_EVENT_ERASE_COMPLETE:
|
|
g_b_flash_event_erase_complete = true;
|
|
break;
|
|
case FLASH_EVENT_WRITE_COMPLETE:
|
|
g_b_flash_event_write_complete = true;
|
|
break;
|
|
default:
|
|
/* Do nothing */
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool internal_flash_init(void) {
|
|
fsp_err_t err = FSP_SUCCESS;
|
|
#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1)
|
|
err = R_FLASH_LP_Open(&g_flash0_ctrl, &g_flash0_cfg);
|
|
#elif defined(RA6M1) | defined(RA6M2)
|
|
err = R_FLASH_HP_Open(&g_flash0_ctrl, &g_flash0_cfg);
|
|
#else
|
|
#error "CMSIS MCU Series is not specified."
|
|
#endif
|
|
if (err == FSP_SUCCESS) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
// ToDo: implementation
|
|
|
|
#endif
|