Files
2025-11-08 13:26:19 +08:00

1016 lines
34 KiB
C

/***********************************************************************
* SEGGER Microcontroller GmbH *
* The Embedded Experts *
************************************************************************
* *
* (c) SEGGER Microcontroller GmbH *
* All rights reserved *
* www.segger.com *
* *
************************************************************************
* *
************************************************************************
* *
* *
* Licensing terms *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* *
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY *
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE *
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, *
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY *
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH. *
* DAMAGE. *
* *
************************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : FlashPrg.c
Purpose : Implementation of RAMCode template
*/
#include <debug.h>
#include <flash_wrapper.h>
#include <flashloader_fuse_bin.h>
#include <param.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sd_boot_img/sd_boot_img.h>
#include <bpt_v2.h>
#include "FlashOS.h"
#include "flashloader.h"
/*********************************************************************
*
* Defines (configurable)
*
**********************************************************************
*/
//
// Only compile in functions that make sense to keep RAMCode as small as
// possible
//
#define SUPPORT_NATIVE_VERIFY \
(0) // Non-memory mapped flashes only. Flash cannot be read memory-mapped
#define SUPPORT_NATIVE_READ_FUNCTION \
(1) // Non-memory mapped flashes only. Flash cannot be read memory-mapped
#define SUPPORT_ERASE_CHIP \
(1) // To potentially speed up production programming: Erases whole flash
// bank / chip with special command
#define SUPPORT_TURBO_MODE (0) // Currently available for Cortex-M only
#define SUPPORT_SEGGER_OPEN_ERASE \
(1) // Flashes with uniform sectors only. Speed up erase because 1 OFL call
// may erase multiple sectors
/*********************************************************************
*
* Defines (fixed)
*
**********************************************************************
*/
#if CONFIG_HYPERBUS_MODE
#define SECTOR_SIZE_SHIFT \
(18) // Flashes with uniform sectors only. <SectorSize> = 2 ^ Shift. Shift =
// 12 => <SectorSize> = 2 ^ 12 = 4096 bytes
#define PAGE_SIZE_SHIFT \
(14) // Smallest amount of data that can be programmed. <PageSize> = 2 ^
// Shift. Shift = 3 => <PageSize> = 2^3 = 8 bytes
#else
#define SECTOR_SIZE_SHIFT \
(12) // Flashes with uniform sectors only. <SectorSize> = 2 ^ Shift. Shift =
// 12 => <SectorSize> = 2 ^ 12 = 4096 bytes
#define PAGE_SIZE_SHIFT \
(12) // Smallest amount of data that can be programmed. <PageSize> = 2 ^
// Shift. Shift = 3 => <PageSize> = 2^3 = 8 bytes
#endif
extern void device_init(void);
flash_wrapper_t *jflash_wrapper;
static struct spi_nor *jflash_loader;
char flash_buf[1uL << PAGE_SIZE_SHIFT];
char msg_buf[100];
static uint32_t msfs_crc = 0;
static uint32_t matched_sfs_crc = 0;
static const char *err_info[] = {
[ERR_UNKNOWN] = "unkown error",
[ERR_FUSE_READ_FAIL] = "Read fuse fail",
[ERR_FUSE_WRITE_CMD_VERIFY_FAIL] = "Write fuse cmd crc verify fail",
[ERR_FUSE_WRITE_FAIL] = "Write fuse fail",
[ERR_FUSE_READBACK_VERIFY_FAIL] = "Write fuse readback verify fail",
[ERR_INIT_FAIL] = "Init fail",
[ERR_BLANKCHECK_FAIL] = "Blankcheck fail",
[ERR_ERASE_ADDRESS_UNALIGNED] = "Erase address unaligned",
[ERR_ERASE_FAIL] = "Erase fail",
[ERR_ERASECHIP_FAIL] = "EraseChip fail",
[ERR_PROGRAM_ADDRESS_UNALIGNED] = "Program length unaligned",
[ERR_PROGRAM_FAIL] = "Program fail",
[ERR_PROGRAM_HYPERFLASH_FUSE_FAIL] = "Program hyperflash fuse fail",
[ERR_READ_LENGTH_UNALIGNED] = "Read address unaligned",
[ERR_READ_FAIL] = "Read fail",
[ERR_VERIFY_FAIL] = "Verify fail",
[ERR_FL_FUSE_SIZE_CHECK_FAIL] = "fuse bin size check fail",
[ERR_FL_FUSE_LENGTH_CHECK_FAIL] = "fuse item length check fail",
[ERR_FL_FUSE_ACTION_TYPE_NOT_FIND] = "fuse action type not find",
[ERR_FL_FUSE_CRC_CHECK_FAIL] = "fuse crc check fail",
[ERR_FL_FUSE_ENC_INIT_FAIL] = "fuse encrypto init fail",
[ERR_FL_FUSE_ENC_FAIL] = "fuse encrypto fail",
[ERR_FL_FUSE_MALLOC_FAIL] = "fuse malloc fail",
[ERR_FL_FUSE_GEN_DATA_FAIL] = "fuse gen data fail",
[ERR_FL_FLASH_MSFS_FAIL] = "flash msfs error",
[ERR_FL_MSFS_VERIFY_FAIL] = "MSFS Verify fail",
};
void report_error(enum fl_err_code err)
{
if (err < ERR_UNKNOWN || err >= ERR_MAX) {
snprintf(msg_buf, sizeof(msg_buf), "%s", err_info[ERR_UNKNOWN]);
} else {
snprintf(msg_buf, sizeof(msg_buf), "%s", err_info[err]);
}
ssdk_printf(SSDK_ERR, "%s\r\n", msg_buf);
}
#define JFLASHLOADER_DEBUG_LEVEL SSDK_DEBUG
__SECTION(".data") static volatile int board_init_flag = 0;
void clean_bss(void)
{
#if __ICCARM__
extern void __iar_data_init3(void);
__iar_data_init3();
#else
extern volatile uint32_t __bss_start;
extern volatile uint32_t __bss_end;
volatile unsigned int *start = (volatile unsigned int *)&__bss_start;
volatile unsigned int *end = (volatile unsigned int *)&__bss_end;
while (start <= end) {
*start++ = 0;
}
#endif
}
#if __SES_ARM
static void ses_heap_init(void)
{
__ASM volatile("ldr R0, = _heap_start \n"
"ldr R1, = _heap_end \n"
"subs R1, R1, R0 \n"
"bl __SEGGER_RTL_init_heap \n");
}
#endif
void jflash_board_init_once(void)
{
if (board_init_flag == 0) {
clean_bss();
#if __SES_ARM
/* initializes heap for SES library */
ses_heap_init();
#endif
device_init();
board_init();
board_init_flag = 1;
}
}
__USED static int32_t jflash_fuse_read(uint32_t index, uint32_t *value)
{
jflash_board_init_once();
int32_t ret = 0;
ssdk_printf(SSDK_NOTICE, "Read fuse index %d\r\n", index);
ret = fuse_read(index, value);
if (ret != 0) {
report_error(ERR_FUSE_READ_FAIL);
return ret;
}
ssdk_printf(SSDK_NOTICE, "Read fuse success, value 0x%08x\r\n", *value);
return 0;
}
__USED int32_t jflash_fuse_write(uint32_t index, uint32_t value, uint32_t crc)
{
jflash_board_init_once();
// crc verify
uint32_t crc_ret = 0;
int32_t ret = 0;
ssdk_printf(SSDK_NOTICE, "Write fuse index:%d, value:%08x, crc:0x%x\r\n",
index, value, crc);
crc_ret = flashloader_crc32((uint8_t *)&index, 4, 0x0);
crc_ret = flashloader_crc32((uint8_t *)&value, 4, crc_ret);
if (crc != crc_ret) {
report_error(ERR_FUSE_WRITE_CMD_VERIFY_FAIL);
return -1;
}
ret = fuse_write(index, value);
if (ret != 0) {
if (ret == FL_FUSE_READ_ERROR)
report_error(ERR_FUSE_READ_FAIL);
else if (ret == FL_FUSE_WRITE_ERROR)
report_error(ERR_FUSE_WRITE_FAIL);
else if (ret == FL_FUSE_READBACK_VERIFY_ERROR)
report_error(ERR_FUSE_READBACK_VERIFY_FAIL);
return ret;
}
ssdk_printf(SSDK_NOTICE, "Write fuse success\r\n");
return 0;
}
typedef struct {
int32_t (*pfFuseSense)(uint32_t index, uint32_t *data);
int32_t (*pfFuseProg)(uint32_t index, uint32_t value, uint32_t crc);
int32_t (*jflash_program_fuse_bin)(uint32_t nNumBytes,
const uint8_t *pSrcBuff);
} SEMIDRIVE_FUSE_API;
__USED __SECTION(".FUSECODE") const SEMIDRIVE_FUSE_API SEMIDRIVE_FUSE_Api = {
jflash_fuse_read, jflash_fuse_write, jflash_program_fuse_bin};
//
// Default definitions for optional functions if not compiled in
// Makes Api table code further down less ugly
//
#if (SUPPORT_ERASE_CHIP == 0)
#define EraseChip NULL
#endif
#if (SUPPORT_NATIVE_VERIFY == 0)
#define Verify NULL
#endif
#if (SUPPORT_NATIVE_READ_FUNCTION == 0)
#define SEGGER_OPEN_Read NULL
#endif
#if (SUPPORT_SEGGER_OPEN_ERASE == 0)
#define SEGGER_OPEN_Erase NULL
#endif
#if (SUPPORT_TURBO_MODE == 0)
#define SEGGER_OPEN_Start NULL
#endif
/*********************************************************************
*
* Types
*
**********************************************************************
*/
typedef struct {
U32 AddVariablesHere;
} RESTORE_INFO;
static void _FeedWatchdog(void);
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
// static RESTORE_INFO _RestoreInfo;
/*********************************************************************
*
* Public data
*
**********************************************************************
*/
__USED __SECTION(
".PRGDATA") volatile int PRGDATA_StartMarker; // Mark start of <PrgData>
// segment. Non-static to make
// sure linker can keep this
// symbol. Dummy needed to
// make sure that <PrgData>
// section in resulting ELF
// file is present. Needed by
// open flash loader logic on
// PC side
__USED __SECTION(".PRGCODE") const SEGGER_OFL_API
SEGGER_OFL_Api = { // Mark start of <PrgCode> segment. Non-static to
// make sure linker can keep this symbol.
_FeedWatchdog,
Init,
UnInit,
EraseSector,
ProgramPage,
BlankCheck,
EraseChip,
Verify,
SEGGER_OPEN_CalcCRC,
SEGGER_OPEN_Read,
SEGGER_OPEN_Program,
SEGGER_OPEN_Erase,
SEGGER_OPEN_Start};
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
/*********************************************************************
*
* _FeedWatchdog
*
* Function description
* Feeds the watchdog. Needs to be called during RAMCode execution in case of
* an watchdog is active. In case no handling is necessary, it could perform a
* dummy access, to make sure that this function is linked in
*/
static void _FeedWatchdog(void)
{
*((volatile int *)&PRGDATA_StartMarker); // Dummy operation
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* Init
*
* Function description
* Handles the initialization of the flash module.
* It is called once per flash programming step (Erase, Program, Verify)
*
* Parameters
* Addr: Flash base address
* Freq: Clock frequency in Hz
* Func: Specifies the action followed by Init() (e.g.: 1 - Erase, 2 -
* Program, 3 - Verify / Read)
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is mandatory.
* (2) Use "noinline" attribute to make sure that function is never inlined
* and label not accidentally removed by linker from ELF file.
*/
__SECTION(".data") static volatile int flashloader_init_flag = 0;
int Init(U32 Addr, U32 Freq, U32 Func)
{
(void)Addr;
(void)Freq;
(void)Func;
// Do not print here, otherwise an error occurs, UART has not been
// initialized
jflash_board_init_once();
if (flashloader_init_flag == 0) {
board_norflash_init();
flashloader_init(&jflash_loader);
read_back_buffer_flag = 0;
jflash_wrapper = flash_wrapper_init(jflash_loader);
if (jflash_wrapper == NULL) {
report_error(ERR_INIT_FAIL);
return 1;
}
flashloader_init_flag = 1;
}
ssdk_printf(SSDK_NOTICE, "Init Addr:0x%x, Func:0x%x\r\n", Addr, Func);
return 0;
}
/*********************************************************************
*
* UnInit
*
* Function description
* Handles the de-initialization of the flash module.
* It is called once per flash programming step (Erase, Program, Verify)
*
* Parameters
* Func Caller type (e.g.: 1 - Erase, 2 - Program, 3 - Verify)
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is mandatory.
* (2) Use "noinline" attribute to make sure that function is never inlined
* and label not accidentally removed by linker from ELF file.
*/
int UnInit(U32 Func)
{
(void)Func;
//
// Uninit code
//
ssdk_printf(SSDK_NOTICE, "UnInit Func:0x%x\r\n", Func);
return 0;
}
/*********************************************************************
*
* EraseSector
*
* Function description
* Erases one flash sector.
*
* Parameters
* SectorAddr Absolute address of the sector to be erased
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is mandatory.
* (2) Use "noinline" attribute to make sure that function is never inlined
* and label not accidentally removed by linker from ELF file.
*/
int EraseSector(U32 SectorAddr)
{
ssdk_printf(JFLASHLOADER_DEBUG_LEVEL, "EraseSector SectorAddr:0x%x\r\n",
(uint32_t)SectorAddr);
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(SectorAddr);
ret = flash_wrapper_erase(jflash_wrapper, addr,
(flash_size_t)jflash_wrapper->sector_size);
if (ret < 0) {
if (ret == FL_DL_ERASE_ADDRESS_UNALIGNED_ERROR)
report_error(ERR_ERASE_ADDRESS_UNALIGNED);
else
report_error(ERR_ERASE_FAIL);
return 1;
}
return 0;
}
/*********************************************************************
*
* ProgramPage
*
* Function description
* Programs one flash page.
*
* Parameters
* DestAddr Address to start programming on
* NumBytes Number of bytes to program. Guaranteed to be ==
* <FlashDevice.PageSize> pSrcBuff Pointer to data to be programmed
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is mandatory.
* (2) Use "noinline" attribute to make sure that function is never inlined
* and label not accidentally removed by linker from ELF file.
*/
__SECTION(".data") static volatile int program_hyperflash_fuse_flag = 0;
int ProgramPage(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff)
{
ssdk_printf(JFLASHLOADER_DEBUG_LEVEL,
"ProgramPage DestAddr:0x%x, "
"NumBytes:0x%x, pSrcBuff:0x%x\r\n",
(uint32_t)DestAddr, NumBytes, pSrcBuff);
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(DestAddr);
if((0 == addr) && is_msfs_data(pSrcBuff)) {
msfs_crc = flashloader_crc32((uint8_t *)pSrcBuff, NumBytes, 0);
if(0 != get_matched_sfs(&(jflash_loader->info.flash_id[0]), (void **)&pSrcBuff, (uint32_t *)&NumBytes)) {
report_error(ERR_FL_FLASH_MSFS_FAIL);
return 1;
}
matched_sfs_crc = flashloader_crc32((uint8_t *)pSrcBuff, NumBytes, 0);
}
ret = flash_wrapper_write(jflash_wrapper, addr, (const uint8_t *)pSrcBuff,
(flash_size_t)NumBytes);
if (ret < 0) {
if (ret == FL_DL_PROGRAM_ADDRESS_UNALIGNED_ERROR)
report_error(ERR_PROGRAM_ADDRESS_UNALIGNED);
else
report_error(ERR_PROGRAM_FAIL);
return 1;
}
#if (CONFIG_HYPERBUS_MODE == 1) && (CONFIG_SDFACTORYTOOL_HYPERFLASH_FUSE == 1)
if (program_hyperflash_fuse_flag == 0) {
ret = program_hyperflash_fuse();
if (ret != 0) {
report_error(ERR_PROGRAM_HYPERFLASH_FUSE_FAIL);
return 1;
}
ssdk_printf(JFLASHLOADER_DEBUG_LEVEL,
"program hyperflash fuse done\r\n");
program_hyperflash_fuse_flag = 1;
}
#endif
return 0;
}
/*********************************************************************
*
* BlankCheck
*
* Function description
* Checks if a memory region is blank
*
* Parameters
* Addr Address to start checking
* NumBytes Number of bytes to be checked
* BlankData Blank (erased) value of flash (Most flashes have 0xFF, some
* have 0x00, some do not have a defined erased value)
*
* Return value
* == 0 O.K., blank
* == 1 O.K., *not* blank
* < 0 Error
*
* Notes
* (1) This function is optional. If not present, the J-Link software will
* assume that erased state of a sector can be determined via normal
* memory-mapped readback of sector. (2) Use "noinline" attribute to make sure
* that function is never inlined and label not accidentally removed by linker
* from ELF file.
*/
int BlankCheck(U32 Addr, U32 NumBytes, U8 BlankData)
{
U32 ByteNumOfPage, NumCheck, NumCheck_tmp;
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(Addr);
ssdk_printf(SSDK_NOTICE,
"BlankCheck Addr:0x%x, "
"NumBytes:0x%x, BlankData:0x%x\r\n",
(uint32_t)Addr, NumBytes, BlankData);
if (!IS_ALIGNED(addr, 4)) {
ssdk_printf(SSDK_NOTICE, "BlankCheck Addr unaligned:0x%x\r\n",
(uint32_t)Addr);
return -1;
}
ByteNumOfPage = (1uL << PAGE_SIZE_SHIFT);
do {
NumCheck = (NumBytes >= ByteNumOfPage) ? ByteNumOfPage : NumBytes;
NumCheck_tmp = NumCheck;
volatile U8 *pDestBuff = (U8 *)flash_buf;
ret = flash_wrapper_read(jflash_wrapper, addr, (uint8_t *)pDestBuff,
(flash_size_t)NumCheck_tmp);
if (ret < 0) {
report_error(ERR_BLANKCHECK_FAIL);
return -1;
}
do {
if (*pDestBuff++ != BlankData) {
return 1;
}
} while (--NumCheck_tmp);
addr += NumCheck;
NumBytes -= NumCheck;
} while (NumBytes);
return 0;
}
/*********************************************************************
*
* SEGGER_OPEN_CalcCRC
*
* Function description
* Calculates the CRC over a specified number of bytes
* Even more optimized version of Verify() as this avoids downloading the
* compare data into the RAMCode for comparison. Heavily reduces traffic between
* J-Link software and target and therefore speeds up verification process
* significantly.
*
* Parameters
* CRC CRC start value
* Addr Address where to start calculating CRC from
* NumBytes Number of bytes to calculate CRC on
* Polynom Polynom to be used for CRC calculation
*
* Return value
* CRC
*
* Notes
* (1) This function is optional
* (2) Use "noinline" attribute to make sure that function is never inlined
* and label not accidentally removed by linker from ELF file.
*/
U32 SEGGER_OPEN_CalcCRC(U32 CRC, U32 Addr, U32 NumBytes, U32 Polynom)
{
ssdk_printf(SSDK_NOTICE,
"CalcCRC CRC:0x%x, "
"Addr:0x%x, NumBytes:0x%x, Polynom:0x%x\r\n",
CRC, (uint32_t)Addr, NumBytes, Polynom);
U32 ByteNumOfPage, NumCalcCRC;
uint32_t crc_ret = CRC;
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(Addr);
ByteNumOfPage = (1uL << PAGE_SIZE_SHIFT);
/* msfs mode */
if((0 == addr) && (msfs_crc != 0) && (NumBytes < ByteNumOfPage)) {
/* sfs internal crc check */
if(0 != read_sfs(jflash_wrapper)) {
ssdk_printf(SSDK_ALERT, "sfs internal crc check error\r\n");
report_error(ERR_FL_MSFS_VERIFY_FAIL);
return -1;
}
/* check sfs is from msfs data */
ret = flash_wrapper_read(jflash_wrapper, FL_SFS_BASE, (uint8_t *)flash_buf,
(flash_size_t)FL_SFS_SIZE);
if (ret < 0) {
ssdk_printf(SSDK_ALERT, "read back sfs error\r\n");
report_error(ERR_FL_MSFS_VERIFY_FAIL);
return -1;
}
if(matched_sfs_crc != flashloader_crc32((uint8_t *)flash_buf, FL_SFS_SIZE, 0)) {
ssdk_printf(SSDK_ALERT, "check sfs is from msfs data error\r\n");
report_error(ERR_FL_MSFS_VERIFY_FAIL);
return -1;
}
ssdk_printf(SSDK_ALERT, "msfs check ok\r\n");
crc_ret = msfs_crc;
msfs_crc = 0;
return crc_ret;
}
/* normal mode */
do {
NumCalcCRC = (NumBytes >= ByteNumOfPage) ? ByteNumOfPage : NumBytes;
volatile U8 *pDestBuff = (U8 *)flash_buf;
ret = flash_wrapper_read(jflash_wrapper, addr, (uint8_t *)pDestBuff,
(flash_size_t)NumCalcCRC);
if (ret < 0) {
report_error(ERR_VERIFY_FAIL);
return -1;
}
crc_ret = flashloader_crc32((uint8_t *)pDestBuff, NumCalcCRC, crc_ret);
addr += NumCalcCRC;
NumBytes -= NumCalcCRC;
} while (NumBytes);
return crc_ret;
}
/*********************************************************************
*
* SEGGER_OPEN_Program
*
* Function description
* Optimized variant of ProgramPage() which allows multiple pages to be
* programmed in 1 RAMCode call.
*
* Parameters
* DestAddr Address to start flash programming at.
* NumBytes Number of bytes to be program. Guaranteed to be multiple of
* <FlashDevice.PageSize> pSrcBuff Pointer to data to be programmed
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is optional. If not present, the J-Link software will
* use ProgramPage() (2) Use "noinline" attribute to make sure that function is
* never inlined and label not accidentally removed by linker from ELF file.
*/
int SEGGER_OPEN_Program(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff)
{
U32 ByteNumOfSector, NumProgram;
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(DestAddr);
ssdk_printf(SSDK_NOTICE,
"Program DestAddr:0x%x, "
"NumBytes:0x%x, pSrcBuff:0x%x\r\n",
(uint32_t)DestAddr, NumBytes, pSrcBuff);
ByteNumOfSector = jflash_wrapper->sector_size;
if((0 == addr) && is_msfs_data(pSrcBuff)) {
msfs_crc = flashloader_crc32((uint8_t *)pSrcBuff, NumBytes, 0);
if(0 != get_matched_sfs(&(jflash_loader->info.flash_id[0]), (void **)&pSrcBuff, (uint32_t *)&NumBytes)) {
report_error(ERR_FL_FLASH_MSFS_FAIL);
return 1;
}
matched_sfs_crc = flashloader_crc32((uint8_t *)pSrcBuff, NumBytes, 0);
}
do {
NumProgram = (NumBytes >= ByteNumOfSector) ? ByteNumOfSector : NumBytes;
ret =
flash_wrapper_write(jflash_wrapper, addr, (const uint8_t *)pSrcBuff,
(flash_size_t)NumProgram);
if (ret < 0) {
if (ret == FL_DL_PROGRAM_ADDRESS_UNALIGNED_ERROR)
report_error(ERR_PROGRAM_ADDRESS_UNALIGNED);
else
report_error(ERR_PROGRAM_FAIL);
return 1;
}
pSrcBuff += NumProgram;
addr += NumProgram;
NumBytes -= NumProgram;
} while (NumBytes);
#if (CONFIG_HYPERBUS_MODE == 1) && (CONFIG_SDFACTORYTOOL_HYPERFLASH_FUSE == 1)
if (program_hyperflash_fuse_flag == 0) {
ret = program_hyperflash_fuse();
if (ret != 0) {
report_error(ERR_PROGRAM_HYPERFLASH_FUSE_FAIL);
return 1;
}
ssdk_printf(JFLASHLOADER_DEBUG_LEVEL,
"program hyperflash fuse done\r\n");
program_hyperflash_fuse_flag = 1;
}
#endif
return 0;
}
/*********************************************************************
*
* Verify
*
* Function description
* Verifies flash contents.
* Usually not compiled in. Only needed for non-memory mapped flashes.
*
* Parameters
* Addr Address to start verify on
* NumBytes Number of bytes to verify
* pBuff Pointer data to compare flash contents to
*
* Return value
* == (Addr + NumBytes): O.K.
* != (Addr + NumBytes): *not* O.K. (ideally the fail address is returned)
*
* Notes
* (1) This function is optional. If not present, the J-Link software will
* assume that flash memory can be verified via memory-mapped readback of flash
* contents. (2) Use "noinline" attribute to make sure that function is never
* inlined and label not accidentally removed by linker from ELF file.
*/
#if SUPPORT_NATIVE_VERIFY
U32 Verify(U32 Addr, U32 NumBytes, U8 *pBuff)
{
unsigned char *pFlash;
unsigned long r;
U32 ByteNumOfPage, NumVerify, NumVerify_tmp;
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(Addr);
ssdk_printf(JFLASHLOADER_DEBUG_LEVEL,
"Verify Addr:0x%x, "
"NumBytes:0x%x, pBuff:0x%x\r\n",
(uint32_t)Addr, NumBytes, pBuff);
ByteNumOfPage = (1uL << PAGE_SIZE_SHIFT);
r = Addr;
do {
NumVerify = (NumBytes >= ByteNumOfPage) ? ByteNumOfPage : NumBytes;
NumVerify_tmp = NumVerify;
pFlash = (U8 *)flash_buf;
ret = flash_wrapper_read(jflash_wrapper, addr, (uint8_t *)pFlash,
(flash_size_t)NumVerify_tmp);
if (ret < 0) {
if (ret == FL_DL_READ_LENGTH_UNALIGNED_ERROR)
report_error(ERR_READ_LENGTH_UNALIGNED);
else
report_error(ERR_READ_FAIL);
return -1;
}
do {
if (*pFlash != *pBuff) {
r = (unsigned long)pFlash;
return r;
}
pFlash++;
pBuff++;
} while (--NumVerify_tmp);
r += NumVerify;
addr += NumVerify;
NumBytes -= NumVerify;
} while (NumBytes);
return r;
}
#endif
/*********************************************************************
*
* EraseChip
*
* Function description
* Erases the entire flash.
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is optional. If not present, J-Link will always use
* EraseSector() for erasing. (2) Use "noinline" attribute to make sure that
* function is never inlined and label not accidentally removed by linker from
* ELF file.
*/
#if SUPPORT_ERASE_CHIP
int EraseChip(void)
{
ssdk_printf(SSDK_NOTICE, "EraseChip\r\n");
int ret;
ret = flash_wrapper_erase(jflash_wrapper, 0,
(flash_size_t)jflash_wrapper->flash_size);
if (ret < 0) {
report_error(ERR_ERASECHIP_FAIL);
return 1;
}
return 0;
}
#endif
/*********************************************************************
*
* SEGGER_OPEN_Read
*
* Function description
* Reads a specified number of bytes from flash into the provided buffer.
* Usually not compiled in. Only needed for non-memory mapped flashes.
*
* Parameters
* Addr Address to start reading from
* NumBytes Number of bytes to read
* pDestBuff Pointer to buffer to store read data
*
* Return value
* >= 0: O.K., NumBytes read
* < 0: Error
*
* Notes
* (1) This function is optional. If not present, the J-Link software will
* assume that a normal memory-mapped read can be performed to read from flash.
* (2) Use "noinline" attribute to make sure that function is never inlined
* and label not accidentally removed by linker from ELF file.
*/
#if SUPPORT_NATIVE_READ_FUNCTION
int SEGGER_OPEN_Read(U32 Addr, U32 NumBytes, U8 *pDestBuff)
{
int ret;
flash_addr_t addr = FLASH_ADDR_MASK(Addr);
ssdk_printf(SSDK_NOTICE,
"Read Addr:0x%x, "
"NumBytes:0x%x, pDestBuff:0x%x\r\n",
(uint32_t)Addr, NumBytes, pDestBuff);
ret = flash_wrapper_read(jflash_wrapper, addr, (uint8_t *)pDestBuff,
(flash_size_t)NumBytes);
if (ret < 0) {
if (ret == FL_DL_READ_LENGTH_UNALIGNED_ERROR)
report_error(ERR_READ_LENGTH_UNALIGNED);
else
report_error(ERR_READ_FAIL);
return -1;
}
_FeedWatchdog();
return NumBytes;
}
#endif
/*********************************************************************
*
* SEGGER_OPEN_Erase
*
* Function description
* Erases one or more flash sectors.
* The implementation from this template only works on flashes that have
* uniform sectors.
*
* Notes
* (1) This function can rely on that at least one sector will be passed
* (2) This function must be able to handle multiple sectors at once
* (3) This function can rely on that only multiple sectors of the same
* sector size will be passed. (e.g. if the device has two sectors with
* different sizes, the DLL will call this function two times with NumSectors =
* 1)
*
* Parameters
* SectorAddr: Address of the start sector to be erased
* SectorIndex: Index of the start sector to be erased (1st sector handled by
* this flash bank: SectorIndex == 0) NumSectors: Number of sectors to be
* erased. Min. 1
*
* Return value
* == 0 O.K.
* == 1 Error
*
* Notes
* (1) This function is optional. If not present, the J-Link software will
* use EraseSector() (2) Use "noinline" attribute to make sure that function is
* never inlined and label not accidentally removed by linker from ELF file.
*/
#if SUPPORT_SEGGER_OPEN_ERASE
int SEGGER_OPEN_Erase(U32 SectorAddr, U32 SectorIndex, U32 NumSectors)
{
int r;
ssdk_printf(SSDK_NOTICE,
"Erase SectorAddr:0x%x, "
"SectorIndex:0x%x, NumSectors:0x%x\r\n",
(uint32_t)SectorAddr, SectorIndex, NumSectors);
(void)SectorIndex;
_FeedWatchdog();
r = 0;
do {
r = EraseSector(SectorAddr);
if (r) {
break;
}
SectorAddr += (1 << SECTOR_SIZE_SHIFT);
} while (--NumSectors);
return r;
}
#endif
/*********************************************************************
*
* SEGGER_OPEN_Start
*
* Function description
* Starts the turbo mode of flash algo.
* Currently only available for Cortex-M based targets.
*/
#if SUPPORT_TURBO_MODE
void SEGGER_OPEN_Start(volatile struct SEGGER_OPEN_CMD_INFO *pInfo)
{
SEGGER_OFL_Lib_StartTurbo(&SEGGER_OFL_Api, pInfo);
}
#endif
/**************************** End of file ***************************/