Difference between revisions of "SEGGER Flash Loader"

From SEGGER Wiki
Jump to: navigation, search
(Extending an Existing Device)
(Stack usage)
 
(206 intermediate revisions by 12 users not shown)
Line 1: Line 1:
=Open Flash Loader=
+
== SEGGER Flash Loader ==
  +
The SEGGER Flash Loader (SFL) is part of the [[J-Link_Device_Support_Kit | J-Link Device Support Kit (DSK)]] and allows users to add flash programming support for a new device on their own.
==Introduction==
 
As the number of devices being available is steadily growing and sometimes in an early stage of the MCU development only a few samples/boards are available that may not be provided to third parties (e.g. SEGGER) to add support for a new device. Also the existence of the device may have confidential status, so it might not be mentioned as being supported in public releases yet. Therefore it might be desirable to be able to add support for new devices on your own, without depending on SEGGER and a new release of the J-Link Software & Documentation package being available.
 
   
  +
=== Minimum supported J-Link software version ===
The J-Link DLL allows customers to add support for new devices on their own. It is also possible to edit / extend existing device support by for example adding new flash banks (e.g. to add support for internal EEPROM programming or SPIFI programming). This article explains how new devices can be added to the DLL and how existing ones can be edited / extended.
 
  +
If not stated otherwise for a specific function / feature / etc., the minimum supported J-Link software version is V7.80.
   
  +
== Supported CPU architectures ==
==General Procedure==
 
  +
The SEGGER Flash Loader (SFL) is available for the following architectures:
By default, the J-Link DLL comes with a build-in device database that defines which device names are known and therefore officially supported by the J-Link DLL and software that uses the J-Link DLL. This list can also be viewed on our website: https://www.segger.com/downloads/supported-devices.php
 
  +
* ARMv4/v5
  +
** ARM720T, ARM7TDMI, ARM7TDMI-S
  +
** ARM920T, ARM922T, ARM926EJ-S, ARM946E-S, ARM966E-S
  +
* ARMv6-M
  +
** Cortex-M0, Cortex-M0+, Cortex-M1
  +
* ARMv7-M
  +
** Cortex-M3, Cortex-M4, Cortex-M7
  +
* ARMv8-M
  +
** Cortex-M23, Cortex-M33, Cortex-M55, Cortex-M85
  +
* ARMv7-A
  +
** Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A12, Cortex-A15, Cortex-A17
  +
* ARMv7-R
  +
** Cortex-R4, Cortex-R5, Cortex-R7, Cortex-R8
  +
* ARMv8-R
  +
** Cortex-R52
  +
* RISC-V RV32
   
  +
{{Note|1=
Additionally, the build-in device database can be extended by specifying devices in an XML file, named JLinkDevices.xml. It is also possible to edit / extend an device from the built-in device database via this XML file. There are different places where the JLinkDevices.xml can be referenced from (see list below). In case of several JLinkDevices.xml files are used, supplement each other as in the order specified below:
 
  +
Architectures / cores not listed here must be assumed as being not supported.<br>
#In the same directory as the J-Link DLL (JLinkARM.dll)
 
  +
While they may work by chance, no support is provided for problems in regards to getting SEGGER Flash Loaders running on non-listed architectures.<br>
#In the same directory as the J-Link settings file. The location of the settings file depends on the IDE / software being used.
 
  +
In case of doubt, please feel free to contact SEGGER.
#In the directory specified using the J-Link Command String ''JLinkDevicsXMLPath = <Path>''
 
  +
}}
   
  +
== Supported flash types ==
=Extend / Add Device Support=
 
  +
Because a SEGGER Flash Loader programs the flash via the MCU it runs on, basically any flash (or other non-volatile memories) can be supported.<br>
==Extending an Existing Device==
 
  +
This applies to flash that is memory mapped accessible by the MCU (internal flash, external QSPI NOR flash, ...) as well as to non-memory mapped flashes (external I2C EEPROM, external NAND flash, ...)<br>
In order to edit/extend a device that is already in the built-in device database of the J-Link DLL, the following needs to be added to the JLinkDevices.xml:
 
<Database>
 
<Device>
 
<ChipInfo Vendor="..." Name="..." />
 
<FlashBankInfo Name="..." BaseAddr="..." MaxSize="..." Loader="..." LoaderType="..." AlwaysPresent="..." />
 
</Device>
 
</Database>
 
The attribute Name of the tag <ChipInfo> must specify exactly the same name as the device in the built-in device database specifies. In case the value of the attribute BaseAddr specifies an address of an existing flash bank for the existing device, in the built-in device database, the flash bank from the built-in database is replaced by the one from the XML file.
 
   
  +
For non-memory-mapped flashes, the following additional entry functions must be implemented in an SFL:
When adding new flash banks or if the device in the built-in database does not specify any flash banks so far, the same attribute requirements as for adding a new device, apply. For more information, please refer to Adding a new device.
 
  +
* SEGGER_FL_CheckBlank()
  +
* SEGGER_FL_Verify()
  +
* SEGGER_FL_Read()
  +
* SEGGER_FL_CalcCRC()
   
  +
== Entry functions overview ==
In order to add more than one flash bank, just repeat the <FlashBankInfo … />> tag structure from above, inside the same <Device> tag. For more information about the tags and their attributes, please refer to XML Tags and Attributes.
 
   
  +
The following table gives an overview about the mandatory and optional entry functions, of a SEGGER Flash Loader:
==Adding a New Device==
 
  +
{| class="seggertable"
=Create a Flash Loader=
 
This article describes how to create a flash loader using the template projects (Cortex-M and Cortex-A/R) for SEGGER Embedded Studio.
 
== Debug Configurations ==
 
The example project contains two debug configurations:
 
*Debug
 
*Release
 
=== Debug configuration ===
 
This configuration allows to debug the flash algorithm in Embedded Studio. The configuration includes a main.c containing the typical function call order, executed by the J-Link DLL during flash programming. The optimization level for this configuration is set to "none".
 
=== Release configuration ===
 
This configuration does not allow debugging but creates the output elf file which can be referenced from within the JLinkDevices.xml file as "''Loader''". The optimization level is set to 3 (highest).
 
== Included files ==
 
{| class="wikitable"
 
 
|-
 
|-
  +
! Entry function !! Type
! Filename !! Content
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Prepare | SEGGER_FL_Prepare()]] || Mandatory
| '''FlashDev.c''' || Flash device description for the ST STM32F205RC
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Restore | SEGGER_FL_Restore()]] || Mandatory
| '''FlashOS.h''' || Function prototypes, definitions and structures
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Program | SEGGER_FL_Program()]] || Mandatory
| '''FlashPrg.c''' || Flash algorithm itself (e.g. ProgramPage(), EraseSector()
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Erase | SEGGER_FL_Erase()]] || Mandatory
| '''main.c''' || Flash algorithm debug code (used by debug configuration, only)
 
 
|-
 
|-
  +
| [[#SEGGER_FL_EraseChip | SEGGER_FL_EraseChip()]] || Optional
| '''Cortex_M_Startup.s'''<br>'''ARM_Startup.s''' || Cortex-M startup code (used by debug configuration, only) <br> Cortex-A/R startup code (used by debug configuration, only)
 
 
|-
 
|-
  +
| [[#SEGGER_FL_CheckBlank | SEGGER_FL_CheckBlank()]] || Optional
| '''MemoryMap.xml''' || Memory map of the ST STM32F205RC
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Verify | SEGGER_FL_Verify()]] || Optional
| '''Placement_debug.xml''' || Debug configuration section placement file.
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Read | SEGGER_FL_Read()]] || Optional
| '''Placement_release.xml''' || Release configuration section placement file.
 
  +
|-
  +
| [[#SEGGER_FL_CalcCRC | SEGGER_FL_CalcCRC()]] || Optional
  +
|-
  +
| [[#SEGGER_FL_Start | SEGGER_FL_Start()]] || Optional
  +
|-
  +
| [[#SEGGER_FL_GetFlashInfo | SEGGER_FL_GetFlashInfo()]] || Optional
  +
|}
  +
  +
=== SEGGER_FL_Prepare ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_Prepare(U32 PreparePara0, U32 PreparePara1, U32 PreparePara2);</source>
  +
  +
'''Function description'''<br>
  +
Mandatory function. Must be present to make SFL detected as valid.<br>
  +
Prepares SFL for further usage. Very first function of SFL to be called.<br>
  +
Can rely on not being called multiple times in a row without a SEGGER_FL_Restore() in between.<br>
  +
This function may be used for example to initialize the PLL of the device before flash programming starts, to improve flash programming performance.<br>
  +
The following is a valid series of calls:
  +
<source>
  +
SEGGER_FL_Prepare()
  +
SEGGER_FL_Erase()
  +
SEGGER_FL_Program()
  +
SEGGER_FL_Restore()
  +
SEGGER_FL_Prepare()
  +
SEGGER_FL_Erase()
  +
SEGGER_FL_Restore()
  +
</source>
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| PreparePara0 || Reserved for future use. Always == 0 for now
  +
|-
  +
| PreparePara1 || Reserved for future use. Always == 0 for now
  +
|-
  +
| PreparePara2 || Reserved for future use. Always == 0 for now
 
|-
 
|-
| '''thumb_crt0.s'''<br>'''crt0.s''' || Initialization file for Cortex-M (used by debug configuration, only)<br>Initialization file for Cortex-A/R(used by debug configuration, only)
 
 
|}
 
|}
== Embedded Studio Template Projects ==
 
The template projects below have been tested with SEGGER Embedded Studio V3.10.
 
*[[File:OpenFlashLoader_CortexM_Template_EmbeddedStudio.zip]]
 
*[[File:OpenFlashLoader_CortexAR_Template_EmbeddedStudio.zip]]
 
   
  +
'''Return value'''<br>
== Step-By-Step Instruction ==
 
  +
{| class="seggertable"
This step-by-step instruction explains how to create your own flash loader using the template projects for Embedded Studio and how to use add a new flash bank for an existing or new device to the J-Link DLL, so that it can be used from within any application using the DLL.
 
  +
|-
#Adapt the template project
 
  +
! Value !! Meaning
##'''FlashDev.c''': Modify the FlashDevice structure according to your device
 
  +
|-
##'''FlashPrg.c''': Implement the flash routines Init(), UnInit(), EraseSector() and ProgramPage()
 
  +
| >= 0 || OK
##'''MemoryMap.xml''': Enter RAM base address and RAM size
 
  +
|-
##'''main.c''': Make sure that the define ''_FLASH_BASE_ADDR'' defines the correct flash base address
 
  +
| == 0 || OK, Clock speed of core not changed
#Test the debug configuration
 
  +
|-
##Connect the target to the J-Link and the J-Link to the PC
 
  +
| > 0 || New clock speed in [Hz](!) of core
##Switch to the '''Debug''' configuration in Embedded Studio ('''Build''' -> '''Set Active Build Configuration''' -> '''Debug''')
 
  +
|-
##Build the project by pressing '''F7'''
 
  +
| < 0 || Error
##Start the debug session by pressing '''F5'''
 
  +
|}
##PC should be halted at main. Now debug the flash algorithm and make sure that it behaves as expected.
 
#Build the flash loader using the release configuration
 
##Switch to the '''Release''' configuration in Embedded Studio ('''Build''' -> '''Set Active Build Configuration''' -> '''Release''')
 
##Build the project by pressing '''F7''' --> The flash loader file can be found here: $PROJ_DIR$\Output\Release\Exe\*.elf
 
#JLinkDevices.xml
 
##Create or adapt the '''JLinkDevices.xml''' (described in the J-Link User Manual (UM08001)).
 
##Place the '''JLinkDevices.xml''' file at the correct location (described in the J-Link User Manual (UM08001)).
 
Now you can select and use the created or adapted device which uses the new flash bank in any J-Link DLL based application (e.g. J-Link Commander / IDE / ...).
 
== Frequently Asked Questions ==
 
In which order does the J-Link DLL call the function during flash programming?
 
#Compare
 
##Init()
 
##Compare()<br>Memory is accessed so it has to be initialized during Init() so that it can be memory mapped accessed here. If it is not initialized correctly, the read access may results in confusing the MCU.
 
##UnInit()
 
# Erase
 
## Init()
 
## Erase()
 
## UnInit()
 
# Program
 
## Init()
 
## Program()
 
## UnInit()
 
== Troubleshoot ==
 
This section provides assistance in case of issues pops up when using custom added flash bank. The section assumes that the functionality has been verified using the debug configuration in Embedded Studio.
 
#Get the latest version of the template project
 
#Follow the Step-By-Step instructions expect of 2.1 FlashPrg.c --> Functions should not contain any code that accesses any SFRs
 
#Build the flash loader using the release configuration
 
#Perform a flash download using J-Link Commander. Flash download should report an error during verify
 
#Implement EraseSector() and retry the flash download test. J-Link Commander should still report verify failed but effected flash memory region should be empty. If not, check EraseSector().
 
#Implement ProgramPage() and retry the flash download test. Expected result: Test reports O.K. --> Programmed successfully. If not, check ProgramPage() code.
 
   
== Frequently Problems ==
+
=== SEGGER_FL_Restore ===
  +
'''Prototype'''<br>
=== PC has unexpected value after flash download ===
 
  +
<source lang="c">int SEGGER_FL_Restore(U32 RestorePara0, U32 RestorePara1, U32 RestorePara2);</source>
  +
  +
'''Function description'''<br>
  +
Mandatory function. Must be present to make SFL detected as valid.<br>
  +
Restores SFL after work is done. Very last function of SFL to be called.<br>
  +
This function may be used for example to restore the PLL settings of the device after flash programming is done.<br>
  +
This is for example needed when using the [https://www.segger.com/products/debug-probes/j-link/technology/flash-breakpoints/ unlimited number of breakpoints in flash] feature of J-Link.<br>
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| RestorePara0 || Reserved for future use. Always == 0 for now
  +
|-
  +
| RestorePara1 || Reserved for future use. Always == 0 for now
  +
|-
  +
| RestorePara2 || Reserved for future use. Always == 0 for now
  +
|-
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| >= 0 || OK
  +
|-
  +
| < 0 || Error
  +
|}
  +
  +
'''Notes'''<br>
  +
{{Note|1=
  +
Can rely on not being called multiple times in a row without a SEGGER_FL_Prepare() in between.<br>
  +
The following is a valid (but unlikely) series of calls:<br>
  +
* SEGGER_FL_Prepare()
  +
* SEGGER_FL_Erase()
  +
* SEGGER_FL_Program()
  +
* SEGGER_FL_Restore()
  +
* SEGGER_FL_Prepare()
  +
* SEGGER_FL_Erase()
  +
* SEGGER_FL_Restore()
  +
}}
  +
  +
=== SEGGER_FL_Program ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_Program(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff);</source>
  +
  +
'''Function description'''<br>
  +
Mandatory function. Must be present to make SFL detected as valid.<br>
  +
Programs flash. The block passed to this function is always a multiple of what is indicated as page size by FlashDevice.PageSize.<br>
  +
This function can rely on only being called with destination addresses and NumBytes that are aligned to FlashDevice.PageSize.
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| DestAddr || Destination address. Always aligned to FlashDevice.PageSize
  +
|-
  +
| NumBytes || Number of bytes to be programmed (always a multiple of FlashDevice.PageSize)
  +
|-
  +
| pSrcBuff || Pointer to the data to be programmed
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| == 0 || O.K.
  +
|-
  +
| == 1 || Error
  +
|-
  +
| == 2 || O.K., already performed implicit verify of block that was just programmed
  +
|}
  +
  +
=== SEGGER_FL_Erase ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_Erase(U32 SectorAddr, U32 SectorIndex, U32 NumSectors);</source>
  +
  +
'''Function description'''<br>
  +
Mandatory function. Must be present to make SFL detected as valid.<br>
  +
Erases flash. For one-time programmable memories (OTP), this function may check if the passed sector is still erased/not programmed and throw an error in case it already is programmed.
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| SectorAddr || Address of the first sector to be erased.
  +
|-
  +
| SectorIndex || Index of the start sector to be erased. Counting starts at 0 (first sector reported by FlashDevice.SectorInfo[0])
  +
|-
  +
| NumSectors || Number of sectors to be erased. It is the responsibility of this function to track the sector size in case a device provides multiple sector sizes.
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| == 0 || O.K.
  +
|-
  +
| == 1 || Error
  +
|}
  +
  +
=== SEGGER_FL_EraseChip ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_EraseChip(void);</source>
  +
  +
'''Function description'''<br>
  +
Optional function. May be present to speed up erase procedure under special circumstances
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| colspan="2" | None
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| == 0 || O.K.
  +
|-
  +
| == 1 || Error
  +
|}
  +
  +
=== SEGGER_FL_CheckBlank ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_CheckBlank(U32 Addr, U32 NumBytes, U8 BlankValue);</source>
  +
  +
'''Function description'''<br>
  +
Optional function. May not be present.<br>
  +
Checks if a memory region is blank / erased / unprogrammed.<br>
  +
Mainly used to speed up flash programming as it allows J-Link to skip calls to SEGGER_FL_Erase() before calling SEGGER_FL_Program(), in case a sector is already erased.
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| Addr || Address where checking for blank / erased data should start
  +
|-
  +
| NumBytes || Number of bytes to be checked
  +
|-
  +
| BlankValue || Blank (erased) value of flash (Most flashes have 0xFF, some have 0x00, some do not have a defined erased value)
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| >= 0 || OK
  +
|-
  +
| == 0 || OK, complete region is blank
  +
|-
  +
| == 1 || OK, not the complete region is blank
  +
|-
  +
| < 0 || Error
  +
|}
  +
  +
=== SEGGER_FL_Verify ===
  +
'''Prototype'''<br>
  +
<source lang="c">U32 SEGGER_FL_Verify(U32 Addr, U32 NumBytes, U8* pData);</source>
  +
  +
'''Function description'''<br>
  +
Optional function. May not be present. Not present for most memory-mapped accessible flash memories.<br>
  +
Verifies a given range by comparing the provided data versus the data in the flash.<br>
  +
Mainly used for non-memory mapped flashes in case flash is not simply read-accissble for the core at a certain address.
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| Addr || Address where verify should start
  +
|-
  +
| NumBytes || Number of bytes to verify
  +
|-
  +
| pBuff || Pointer to data to compare flash contents to
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| xxx || End address of verification.<br> ReturnVal == Addr+NumBytes indicates successful verification<br> ReturnVal != Addr+NumBytes indicates an error and gives the address where verification failed
  +
|}
  +
  +
=== SEGGER_FL_Read ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_Read(U32 Addr, U32 NumBytes, U8 *pDestBuff);</source>
  +
  +
'''Function description'''<br>
  +
Optional function. May not be present.<br>
  +
Not needed for memory-mapped flashes that can be just read by the MCU core as RAM or other memories. Mainly used for non-memory mapped flashes where a virtual addres has been assigned to make J-Link flash download work.<br>
  +
If this function is present, J-Link will call it to read flash memory instead of reading it directly via the core.
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| Addr || Address to start reading flash at
  +
|-
  +
| NumBytes || Number of bytes to read
  +
|-
  +
| pBuff || Pointer to buffer where to store read data to
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| >= 0 || OK, number of bytes read (usually == NumBytes)
  +
|-
  +
| < 0 || Error
  +
|}
  +
  +
=== SEGGER_FL_CalcCRC ===
  +
'''Prototype'''<br>
  +
<source lang="c">U32 SEGGER_FL_CalcCRC(U32 CRC, U32 Addr, U32 NumBytes, U32 Polynom);</source>
  +
  +
'''Function description'''<br>
  +
Optional function, may not be present.<br>
  +
If present, J-Link may call this function to speed up the verification because not all data must be read + transferred back to the host but instead only the CRC (calculated by the SFL) is transferred to the host.<br>
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| CRC || Start value of CRC
  +
|-
  +
| Addr || Address where calculation of CRC starts
  +
|-
  +
| NumBytes || Number of bytes to calculate CRC on
  +
|-
  +
| Polynom || Polynom to use for CRC calculation
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| xxx || Calculated CRC
  +
|}
  +
  +
'''Notes'''<br>
  +
{{Note|1=
  +
# If an SFL implements this function, it is recommended to simply call SEGGER_OFL_Lib_CalcCRC() from the SEGGER_SFL_Lib.a library and pass its return value to the caller.
  +
}}
  +
  +
=== SEGGER_FL_Start ===
  +
'''Prototype'''<br>
  +
<source lang="c">void SEGGER_FL_Start(volatile struct SEGGER_FL_CMD_INFO* pInfo);</source>
  +
  +
'''Function description'''<br>
  +
Optional function, may not be present.<br>
  +
If present and target architecture supports turbo mode, J-Link will use this entry function to start turbo mode which will lead to a big performance gain in flash programming.<br>
  +
If an SFL implements this function, it should simply call SEGGER_OFL_Lib_StartTurbo() from the SEGGER_SFL_Lib.a library. The exact operation of SEGGER_OFL_Lib_StartTurbo() is not disclosed.
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| pInfo || Pointer to command info for SEGGER_OFL_Lib_StartTurbo()
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| colspan="2" | None
  +
|}
  +
  +
=== SEGGER_FL_GetFlashInfo ===
  +
'''Prototype'''<br>
  +
<source lang="c">int SEGGER_FL_GetFlashInfo(SEGGER_FL_FLASH_INFO* pInfo, U32 InfoAreaSize);</source>
  +
  +
'''Function description'''<br>
  +
Optional function. May not be present.<br>
  +
Only needed for flash loaders where the exact sectorization is determined at runtime.<br>
  +
This is for example the case for some loaders for external QSPI NOR flash, where different users may have different QSPI flashes connected to their hardware.<br>
  +
This allows to have only 1 loader to serve many different setups.<br>
  +
  +
'''Parameters'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Parameter !! Description
  +
|-
  +
| pInfo || Points to info area which is used to store the flash info.
  +
|-
  +
| InfoAreaSize || Indicates how big the area pointed to by SEGGER_FL_FLASH_INFO really is.<br>May be used to extend pInfo->aRangeInfo[] in case more elements are needed for the detected flash memory.
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
  +
|-
  +
! Value !! Meaning
  +
|-
  +
| >= 0 || OK, number of bytes read (usually == NumBytes)
  +
|-
  +
| < 0 || Error
  +
|}
  +
  +
'''Notes'''<br>
  +
{{Note|1=
  +
# If present, this function is called before any erase, program, verify operation but after Preare().<br>
  +
# If present, this function overrides the information provided by FlashDevice.TotalSize and FlashDevice.SectorInfo[]
  +
}}
  +
  +
== FlashDevice struct ==
  +
The FlashDevice structure variable contains all the static information about the flash algorithm like sectorization of the flash, programming chunk size, ...<br>
  +
In the following, the structure elements are explained in detail to give a good idea about what needs to be filled in for a new flash loader.
  +
  +
<source lang="c">
  +
struct FlashDevice {
  +
U16 AlgoVer;
  +
U8 Name[128];
  +
U16 Type;
  +
U32 BaseAddr;
  +
U32 TotalSize;
  +
U32 PageSize;
  +
U32 Reserved;
  +
U8 ErasedVal;
  +
U32 TimeoutProg;
  +
U32 TimeoutErase;
  +
struct SECTOR_INFO SectorInfo[MAX_NUM_SECTORS];
  +
};
  +
</source>
  +
  +
{| class="seggertable"
  +
|-
  +
! Member !! Explanation
  +
|-
  +
| AlgoVer || Set to 0x0101. Do not set to anything else!
  +
|-
  +
| Name || Name of the flash bank this flash loader handles. (E.g. "internal flash", "QSPI", ...). Must not exceed 127 characters (last character reserved for string termination). NEVER change the size of this array!
  +
|-
  +
| Type || Flash device type. Currently ignored. Set to 1 to get max. compatibility.
  +
|-
  +
| BaseAddr || Flash base address. It is recommended to always use the real address of the flash here, even if the flash is also available at other addresses (via an alias / remap), depending on the current settings of the device.
  +
|-
  +
| TotalSize || Total flash device size in bytes. This describes the total size of the flash that is achieved when summing up all sector info from <SectorInfo>. If the flash is 512 KB in size, <TotalSize> must be 0x80000 (524,288 => 512 KB)
  +
|-
  +
| PageSize || This field describes in what chunks J-Link feeds the flash loader. The SEGGER_FL_Program() function will be called with a data chunk of multiple of <PageSize> bytes. For example if the flash requires to be programmed in multiple of 128 bytes, <PageSize> should be set to 128. If the flash can be programmed 4 byte wise, <PageSize> should be set to 4.
  +
|-
  +
| Reserved || Set this element to 0
  +
|-
  +
| ErasedVal || Most flashes have an erased value of 0xFF (set this element to 0xFF in such cases). However, some flashes have different erased value like for example 0x00 (set element to 0x00 for such cases)
  +
|-
  +
| TimeoutProg || Timeout in milliseconds (ms) to program one chunk of <PageSize>. <br> Since SEGGER_FL_Program can handle multiple pages at once, the J-Link software calculates how many pages should be programmed and accordingly calculates the total timeout for one call of SEGGER_FL_Program. Therefore the total programming timeout for one call of SEGGER_FL_Program is NumPagesAtOnce * TimeoutProg.
  +
|-
  +
| TimeoutErase || Timeout in milliseconds (ms) to erase one sector. <br> Since SEGGER_FL_Erase can handle multiple sectors at once, the J-Link software calculates how many sectors should be erased and accordingly calculates the total timeout for one call of SEGGER_FL_Erase. Therefore the total erase timeout for one call of SEGGER_FL_Erase is NumSectorsAtOnce * TimeoutErase.
  +
|-
  +
| SectorInfo ||
  +
This element is actually a list of '''different sector sizes''' present on target flash.<br>
  +
Having a flash with uniform sectors will result in only SectorInfo[0] being used for sectorization information.<br>
  +
In case the initial number of [4] regions is not sufficient, the array may be expanded up to [8] by the user when writing the flash algorithm.<br>
  +
For more information, see the example below.
  +
|}
  +
  +
'''Example for SectorInfo[] member'''<br>
  +
<source lang="c">
  +
// Example device with 256 KB divided into:
  +
// 4 * 16 KB sectors
  +
// 1 * 64 KB sectors
  +
// 1 * 128 KB sectors
  +
//
  +
// FlashDevice.TotalSize:
  +
// 0x40000
  +
//
  +
// FlashDevice.SectorInfo[]:
  +
// {
  +
// SectSize StartAddr
  +
// { 0x00004000, 0x00000000 }, // 4 * 16 KB = 64 KB
  +
// { 0x00010000, 0x00010000 }, // 1 * 64 KB = 64 KB
  +
// { 0x00020000, 0x00020000 }, // 1 * 128 KB = 128 KB
  +
// { 0xFFFFFFFF, 0xFFFFFFFF } // Indicates the end of the flash sector layout. Must be present.
  +
// }
  +
//
  +
//
  +
// Example device with 256 KB divided into:
  +
// 256 * 1 KB sectors
  +
//
  +
// FlashDevice.TotalSize:
  +
// 0x40000
  +
//
  +
// FlashDevice.SectorInfo[]:
  +
// {
  +
// SectSize StartAddr
  +
// { 0x00000400, 0x00000000 }, // 256 * 1 KB = 256 KB
  +
// { 0xFFFFFFFF, 0xFFFFFFFF } // Indicates the end of the flash sector layout. Must be present.
  +
// }
  +
//
  +
</source>
  +
  +
== Integrate SFL in J-Link software ==
  +
For more information about how to actually integrate the resulting SFL binary into the J-Link software and connect it with support for your new device, please refer to the [[J-Link_Device_Support_Kit | J-Link DSK wiki article]]
  +
  +
== Stack usage ==
  +
J-Link reserves 512 bytes stack for the SEGGER Flash Loader. This value is fixed and cannot be changed. If 512 bytes cannot be allocated (e.g. for devices with small RAM areas), 256 bytes are used as fallback.
  +
  +
== Section layout ==
  +
The J-Link software expects a special layout when it comes to RO code, RO data, RW data placement in the SFL binary.<br>
  +
The reference algorithms and templates provided with the J-Link DSK already take care of that layout, so there is nothing special to be considered by the user.
  +
  +
The section layout is as expected:
  +
<source lang="c">
  +
section PrgCode // Marks the start of the SFL. Must be the very first section
  +
sections .text, .rodata, ... // In any order
  +
section PrgData // Marks the end of the code + rodata region (functions, const data, ...) and the start of the data region (static + global variables)
  +
sections .textrw, .data, .fast, ... // In any order
  +
section DevDscr // Marks the location of the <FlashDevice> structure variable and also the end of the loader. Must(!!!) be the very last section
  +
</source>
  +
  +
== Templates ==
  +
There are templates as well as functioning reference loaders available in source. These are part of the [[J-Link_Device_Support_Kit| J-Link Device Support Kit (DSK)]].
  +
  +
== Troubleshooting ==
  +
'''General considerations'''<br>
  +
# Get the latest version of the template project
  +
# Follow the Step-By-Step instructions except of 1.2 FlashPrg.c --> Functions should not contain any code that accesses any SFRs
  +
# Build the flash loader using the release configuration
  +
# Perform a flash download using J-Link Commander. Flash download should report an error during verify
  +
# Implement SEGGER_FL_Erase() and retry the flash download test. J-Link Commander should still report verify failed but effected flash memory region should be empty. If not, check SEGGER_FL_Erase().
  +
# Implement SEGGER_FL_Program() and retry the flash download test. Expected result: Test reports O.K. --> Programmed successfully. If not, check SEGGER_FL_Program() code.
  +
  +
'''PC has unexpected value after flash download'''<br>
 
This error may have different root causes:
 
This error may have different root causes:
*Watchdog is enabled but not fed in the flash loader functions. This may result in a watchdog timeout pops up during RAMCode execution. The behavior is different but usually a reset will be triggered.
+
* Watchdog is enabled but not fed in the flash loader functions. This may result in a watchdog timeout pops up during RAMCode execution. The behavior is different but usually a reset will be triggered.
*Accessing not enabled / clocked special function registers / peripherals
+
* Accessing not enabled / clocked special function registers / peripherals
*Accessing invalid memory regions (reserved)
+
* Accessing invalid memory regions (reserved)
  +
===(Q)SPI flashes===
 
  +
'''External flash pin init'''<br>
*The Init() code has to make sure that the (Q)SPI pins as well as the (Q)SPI controller are configured so that the flash can be memory mapped (read) accessed. This is necessary as the J-Link DLL reads the data before programming to check if flash content does already match. This can be validated by setting the compare method in J-Link Commander to "skip" (exec SetCompareMode 0). Now start flash download. J-Link Commander should report a verify error but the flash should be memmory mapped accessible from now. If not, check the Init() code.
 
  +
The SEGGER_FL_Prepare() code has to make sure that the (QSPI) pins as well as the (QSPI) controller are configured so that the flash is memory-mapped read-accessible.<br>
  +
This is necessary as the J-Link software by default compares flash contents before starting the flash programming, to save time in case large portions of the flash are already identical to the programming data.<br>
  +
This can be validated by setting the compare method in J-Link Commander to "skip" (exec SetCompareMode 0). Now start flash download.<br>
  +
J-Link Commander should report a verify error but the flash should be memmory mapped accessible from now. If not, check the Init() code.<br>
  +
  +
'''I get build errors in release build config'''<br>
  +
If you get build errors when switching from "Debug" to "Release" build in the template project the main cause is that third party libraries are used.<br>
  +
The SEGGER Flash Loader interface expects all program parts to be linked to sections PrgCode and PrgData.<br>
  +
Third party libraries often use statically linked program parts which will not be put in the aforementioned sections which will cause a build or linker error.<br>
  +
Generally we recommend not using any third party libraries when creating Flash loaders as they will increase the Flash loader size drastically while usually slowing down the maximum possible Flash loader speed.<br>
  +
If you happen to have to use an external library in your project it is user responsibility to make sure this external library is linked to the aforementioned sections for all application parts.
  +
  +
== SFL FAQ ==
  +
'''Q:''' Do I need a valid Embedded Studio license when using the SEGGER Flash Loader in a commercial scope?<br>
  +
'''A:''' Basically, any usage of ES in a commercial scope requires a valid license. However, the SEGGER Flash Loader is an exception. The evaluation license suffice; a valid license is not required.<br><br>
  +
'''Q:''' How is the *.elf file that is the result from building the SLF executed?<br>
  +
'''A:''' The *.elf file is loaded into the RAM of the target device and executed on its processor.<br><br>
  +
'''Q:''' How are the functions like "SEGGER_FL_Program()" called and executed on the target?<br>
  +
'''A:''' The J-Link DLL analyzes the ELF file to determine the function entry points and then calls those functions.<br><br>
  +
'''Q:''' What does the "SEGGER_FL_Lib_<CORE>_LE.a" file contain and how are they used by SEGGER flash loader?<br>
  +
'''A:''' The file contains generic (not device specific) logic which interacts with the custom Flashloader functions SEGGER_FL_*. It needs to be included in any build.<br><br>
  +
'''Q:''' There are two files "SEGGER_FL_Lib_<CORE>_'''LE'''.a" and "SEGGER_FL_Lib_<CORE>_'''BE'''.a". Which one do I have to use?<br>
  +
'''A:''' "SEGGER_FL_Lib_<CORE>_'''LE'''.a" is used for '''L'''ittle '''E'''ndian targets while "SEGGER_FL_Lib_<CORE>_'''BE'''.a" is used for '''B'''ig '''E'''ndian targets.<br><br>
  +
'''Q:''' My flash loader uses interrupts. It works when debugging, but does not work when inegrated with J-Link software. How can this be solved?<br>
  +
'''A:''' Before calling the flash loader functions, J-Link will disable interrupts on the device. If you require interrupts, you will need to reenable those e.g. in SEGGER_FL_Prepare().

Latest revision as of 14:59, 20 November 2023

SEGGER Flash Loader

The SEGGER Flash Loader (SFL) is part of the J-Link Device Support Kit (DSK) and allows users to add flash programming support for a new device on their own.

Minimum supported J-Link software version

If not stated otherwise for a specific function / feature / etc., the minimum supported J-Link software version is V7.80.

Supported CPU architectures

The SEGGER Flash Loader (SFL) is available for the following architectures:

  • ARMv4/v5
    • ARM720T, ARM7TDMI, ARM7TDMI-S
    • ARM920T, ARM922T, ARM926EJ-S, ARM946E-S, ARM966E-S
  • ARMv6-M
    • Cortex-M0, Cortex-M0+, Cortex-M1
  • ARMv7-M
    • Cortex-M3, Cortex-M4, Cortex-M7
  • ARMv8-M
    • Cortex-M23, Cortex-M33, Cortex-M55, Cortex-M85
  • ARMv7-A
    • Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A12, Cortex-A15, Cortex-A17
  • ARMv7-R
    • Cortex-R4, Cortex-R5, Cortex-R7, Cortex-R8
  • ARMv8-R
    • Cortex-R52
  • RISC-V RV32
Note:

Architectures / cores not listed here must be assumed as being not supported.
While they may work by chance, no support is provided for problems in regards to getting SEGGER Flash Loaders running on non-listed architectures.

In case of doubt, please feel free to contact SEGGER.

Supported flash types

Because a SEGGER Flash Loader programs the flash via the MCU it runs on, basically any flash (or other non-volatile memories) can be supported.
This applies to flash that is memory mapped accessible by the MCU (internal flash, external QSPI NOR flash, ...) as well as to non-memory mapped flashes (external I2C EEPROM, external NAND flash, ...)

For non-memory-mapped flashes, the following additional entry functions must be implemented in an SFL:

  • SEGGER_FL_CheckBlank()
  • SEGGER_FL_Verify()
  • SEGGER_FL_Read()
  • SEGGER_FL_CalcCRC()

Entry functions overview

The following table gives an overview about the mandatory and optional entry functions, of a SEGGER Flash Loader:

Entry function Type
SEGGER_FL_Prepare() Mandatory
SEGGER_FL_Restore() Mandatory
SEGGER_FL_Program() Mandatory
SEGGER_FL_Erase() Mandatory
SEGGER_FL_EraseChip() Optional
SEGGER_FL_CheckBlank() Optional
SEGGER_FL_Verify() Optional
SEGGER_FL_Read() Optional
SEGGER_FL_CalcCRC() Optional
SEGGER_FL_Start() Optional
SEGGER_FL_GetFlashInfo() Optional

SEGGER_FL_Prepare

Prototype

int SEGGER_FL_Prepare(U32 PreparePara0, U32 PreparePara1, U32 PreparePara2);

Function description
Mandatory function. Must be present to make SFL detected as valid.
Prepares SFL for further usage. Very first function of SFL to be called.
Can rely on not being called multiple times in a row without a SEGGER_FL_Restore() in between.
This function may be used for example to initialize the PLL of the device before flash programming starts, to improve flash programming performance.
The following is a valid series of calls:

SEGGER_FL_Prepare()
SEGGER_FL_Erase()
SEGGER_FL_Program()
SEGGER_FL_Restore()
SEGGER_FL_Prepare()
SEGGER_FL_Erase()
SEGGER_FL_Restore()

Parameters

Parameter Description
PreparePara0 Reserved for future use. Always == 0 for now
PreparePara1 Reserved for future use. Always == 0 for now
PreparePara2 Reserved for future use. Always == 0 for now

Return value

Value Meaning
>= 0 OK
== 0 OK, Clock speed of core not changed
> 0 New clock speed in [Hz](!) of core
< 0 Error

SEGGER_FL_Restore

Prototype

int SEGGER_FL_Restore(U32 RestorePara0, U32 RestorePara1, U32 RestorePara2);

Function description
Mandatory function. Must be present to make SFL detected as valid.
Restores SFL after work is done. Very last function of SFL to be called.
This function may be used for example to restore the PLL settings of the device after flash programming is done.
This is for example needed when using the unlimited number of breakpoints in flash feature of J-Link.

Parameters

Parameter Description
RestorePara0 Reserved for future use. Always == 0 for now
RestorePara1 Reserved for future use. Always == 0 for now
RestorePara2 Reserved for future use. Always == 0 for now

Return value

Value Meaning
>= 0 OK
< 0 Error

Notes

Note:

Can rely on not being called multiple times in a row without a SEGGER_FL_Prepare() in between.
The following is a valid (but unlikely) series of calls:

  • SEGGER_FL_Prepare()
  • SEGGER_FL_Erase()
  • SEGGER_FL_Program()
  • SEGGER_FL_Restore()
  • SEGGER_FL_Prepare()
  • SEGGER_FL_Erase()
  • SEGGER_FL_Restore()

SEGGER_FL_Program

Prototype

int SEGGER_FL_Program(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff);

Function description
Mandatory function. Must be present to make SFL detected as valid.
Programs flash. The block passed to this function is always a multiple of what is indicated as page size by FlashDevice.PageSize.
This function can rely on only being called with destination addresses and NumBytes that are aligned to FlashDevice.PageSize.

Parameters

Parameter Description
DestAddr Destination address. Always aligned to FlashDevice.PageSize
NumBytes Number of bytes to be programmed (always a multiple of FlashDevice.PageSize)
pSrcBuff Pointer to the data to be programmed

Return value

Value Meaning
== 0 O.K.
== 1 Error
== 2 O.K., already performed implicit verify of block that was just programmed

SEGGER_FL_Erase

Prototype

int SEGGER_FL_Erase(U32 SectorAddr, U32 SectorIndex, U32 NumSectors);

Function description
Mandatory function. Must be present to make SFL detected as valid.
Erases flash. For one-time programmable memories (OTP), this function may check if the passed sector is still erased/not programmed and throw an error in case it already is programmed.

Parameters

Parameter Description
SectorAddr Address of the first sector to be erased.
SectorIndex Index of the start sector to be erased. Counting starts at 0 (first sector reported by FlashDevice.SectorInfo[0])
NumSectors Number of sectors to be erased. It is the responsibility of this function to track the sector size in case a device provides multiple sector sizes.

Return value

Value Meaning
== 0 O.K.
== 1 Error

SEGGER_FL_EraseChip

Prototype

int SEGGER_FL_EraseChip(void);

Function description
Optional function. May be present to speed up erase procedure under special circumstances

Parameters

Parameter Description
None

Return value

Value Meaning
== 0 O.K.
== 1 Error

SEGGER_FL_CheckBlank

Prototype

int SEGGER_FL_CheckBlank(U32 Addr, U32 NumBytes, U8 BlankValue);

Function description
Optional function. May not be present.
Checks if a memory region is blank / erased / unprogrammed.
Mainly used to speed up flash programming as it allows J-Link to skip calls to SEGGER_FL_Erase() before calling SEGGER_FL_Program(), in case a sector is already erased.

Parameters

Parameter Description
Addr Address where checking for blank / erased data should start
NumBytes Number of bytes to be checked
BlankValue Blank (erased) value of flash (Most flashes have 0xFF, some have 0x00, some do not have a defined erased value)

Return value

Value Meaning
>= 0 OK
== 0 OK, complete region is blank
== 1 OK, not the complete region is blank
< 0 Error

SEGGER_FL_Verify

Prototype

U32 SEGGER_FL_Verify(U32 Addr, U32 NumBytes, U8* pData);

Function description
Optional function. May not be present. Not present for most memory-mapped accessible flash memories.
Verifies a given range by comparing the provided data versus the data in the flash.
Mainly used for non-memory mapped flashes in case flash is not simply read-accissble for the core at a certain address.

Parameters

Parameter Description
Addr Address where verify should start
NumBytes Number of bytes to verify
pBuff Pointer to data to compare flash contents to

Return value

Value Meaning
xxx End address of verification.
ReturnVal == Addr+NumBytes indicates successful verification
ReturnVal != Addr+NumBytes indicates an error and gives the address where verification failed

SEGGER_FL_Read

Prototype

int SEGGER_FL_Read(U32 Addr, U32 NumBytes, U8 *pDestBuff);

Function description
Optional function. May not be present.
Not needed for memory-mapped flashes that can be just read by the MCU core as RAM or other memories. Mainly used for non-memory mapped flashes where a virtual addres has been assigned to make J-Link flash download work.
If this function is present, J-Link will call it to read flash memory instead of reading it directly via the core.

Parameters

Parameter Description
Addr Address to start reading flash at
NumBytes Number of bytes to read
pBuff Pointer to buffer where to store read data to

Return value

Value Meaning
>= 0 OK, number of bytes read (usually == NumBytes)
< 0 Error

SEGGER_FL_CalcCRC

Prototype

U32 SEGGER_FL_CalcCRC(U32 CRC, U32 Addr, U32 NumBytes, U32 Polynom);

Function description
Optional function, may not be present.
If present, J-Link may call this function to speed up the verification because not all data must be read + transferred back to the host but instead only the CRC (calculated by the SFL) is transferred to the host.

Parameters

Parameter Description
CRC Start value of CRC
Addr Address where calculation of CRC starts
NumBytes Number of bytes to calculate CRC on
Polynom Polynom to use for CRC calculation

Return value

Value Meaning
xxx Calculated CRC

Notes

Note:
  1. If an SFL implements this function, it is recommended to simply call SEGGER_OFL_Lib_CalcCRC() from the SEGGER_SFL_Lib.a library and pass its return value to the caller.

SEGGER_FL_Start

Prototype

void SEGGER_FL_Start(volatile struct SEGGER_FL_CMD_INFO* pInfo);

Function description
Optional function, may not be present.
If present and target architecture supports turbo mode, J-Link will use this entry function to start turbo mode which will lead to a big performance gain in flash programming.
If an SFL implements this function, it should simply call SEGGER_OFL_Lib_StartTurbo() from the SEGGER_SFL_Lib.a library. The exact operation of SEGGER_OFL_Lib_StartTurbo() is not disclosed.

Parameters

Parameter Description
pInfo Pointer to command info for SEGGER_OFL_Lib_StartTurbo()

Return value

Value Meaning
None

SEGGER_FL_GetFlashInfo

Prototype

int SEGGER_FL_GetFlashInfo(SEGGER_FL_FLASH_INFO* pInfo, U32 InfoAreaSize);

Function description
Optional function. May not be present.
Only needed for flash loaders where the exact sectorization is determined at runtime.
This is for example the case for some loaders for external QSPI NOR flash, where different users may have different QSPI flashes connected to their hardware.
This allows to have only 1 loader to serve many different setups.

Parameters

Parameter Description
pInfo Points to info area which is used to store the flash info.
InfoAreaSize Indicates how big the area pointed to by SEGGER_FL_FLASH_INFO really is.
May be used to extend pInfo->aRangeInfo[] in case more elements are needed for the detected flash memory.

Return value

Value Meaning
>= 0 OK, number of bytes read (usually == NumBytes)
< 0 Error

Notes

Note:
  1. If present, this function is called before any erase, program, verify operation but after Preare().
  2. If present, this function overrides the information provided by FlashDevice.TotalSize and FlashDevice.SectorInfo[]

FlashDevice struct

The FlashDevice structure variable contains all the static information about the flash algorithm like sectorization of the flash, programming chunk size, ...
In the following, the structure elements are explained in detail to give a good idea about what needs to be filled in for a new flash loader.

struct FlashDevice  {
  U16 AlgoVer;
  U8  Name[128];
  U16 Type;
  U32 BaseAddr;
  U32 TotalSize;
  U32 PageSize;
  U32 Reserved;
  U8  ErasedVal;
  U32 TimeoutProg;
  U32 TimeoutErase;
  struct SECTOR_INFO SectorInfo[MAX_NUM_SECTORS];
};
Member Explanation
AlgoVer Set to 0x0101. Do not set to anything else!
Name Name of the flash bank this flash loader handles. (E.g. "internal flash", "QSPI", ...). Must not exceed 127 characters (last character reserved for string termination). NEVER change the size of this array!
Type Flash device type. Currently ignored. Set to 1 to get max. compatibility.
BaseAddr Flash base address. It is recommended to always use the real address of the flash here, even if the flash is also available at other addresses (via an alias / remap), depending on the current settings of the device.
TotalSize Total flash device size in bytes. This describes the total size of the flash that is achieved when summing up all sector info from <SectorInfo>. If the flash is 512 KB in size, <TotalSize> must be 0x80000 (524,288 => 512 KB)
PageSize This field describes in what chunks J-Link feeds the flash loader. The SEGGER_FL_Program() function will be called with a data chunk of multiple of <PageSize> bytes. For example if the flash requires to be programmed in multiple of 128 bytes, <PageSize> should be set to 128. If the flash can be programmed 4 byte wise, <PageSize> should be set to 4.
Reserved Set this element to 0
ErasedVal Most flashes have an erased value of 0xFF (set this element to 0xFF in such cases). However, some flashes have different erased value like for example 0x00 (set element to 0x00 for such cases)
TimeoutProg Timeout in milliseconds (ms) to program one chunk of <PageSize>.
Since SEGGER_FL_Program can handle multiple pages at once, the J-Link software calculates how many pages should be programmed and accordingly calculates the total timeout for one call of SEGGER_FL_Program. Therefore the total programming timeout for one call of SEGGER_FL_Program is NumPagesAtOnce * TimeoutProg.
TimeoutErase Timeout in milliseconds (ms) to erase one sector.
Since SEGGER_FL_Erase can handle multiple sectors at once, the J-Link software calculates how many sectors should be erased and accordingly calculates the total timeout for one call of SEGGER_FL_Erase. Therefore the total erase timeout for one call of SEGGER_FL_Erase is NumSectorsAtOnce * TimeoutErase.
SectorInfo

This element is actually a list of different sector sizes present on target flash.
Having a flash with uniform sectors will result in only SectorInfo[0] being used for sectorization information.
In case the initial number of [4] regions is not sufficient, the array may be expanded up to [8] by the user when writing the flash algorithm.
For more information, see the example below.

Example for SectorInfo[] member

// Example device with 256 KB divided into:
//   4 *  16 KB sectors
//   1 *  64 KB sectors
//   1 * 128 KB sectors
//
// FlashDevice.TotalSize:
//   0x40000
//
// FlashDevice.SectorInfo[]:
//   {
//       SectSize    StartAddr
//     { 0x00004000, 0x00000000 },   // 4 *  16 KB =  64 KB
//     { 0x00010000, 0x00010000 },   // 1 *  64 KB =  64 KB
//     { 0x00020000, 0x00020000 },   // 1 * 128 KB = 128 KB
//     { 0xFFFFFFFF, 0xFFFFFFFF }    // Indicates the end of the flash sector layout. Must be present.
//   }
//
//
// Example device with 256 KB divided into:
// 256 *   1 KB sectors
//
// FlashDevice.TotalSize:
//   0x40000
//
// FlashDevice.SectorInfo[]:
//   {
//       SectSize    StartAddr
//     { 0x00000400, 0x00000000 },   // 256 *  1 KB =  256 KB
//     { 0xFFFFFFFF, 0xFFFFFFFF }    // Indicates the end of the flash sector layout. Must be present.
//   }
//

Integrate SFL in J-Link software

For more information about how to actually integrate the resulting SFL binary into the J-Link software and connect it with support for your new device, please refer to the J-Link DSK wiki article

Stack usage

J-Link reserves 512 bytes stack for the SEGGER Flash Loader. This value is fixed and cannot be changed. If 512 bytes cannot be allocated (e.g. for devices with small RAM areas), 256 bytes are used as fallback.

Section layout

The J-Link software expects a special layout when it comes to RO code, RO data, RW data placement in the SFL binary.
The reference algorithms and templates provided with the J-Link DSK already take care of that layout, so there is nothing special to be considered by the user.

The section layout is as expected:

section PrgCode                     // Marks the start of the SFL. Must be the very first section
sections .text, .rodata, ...        // In any order
section PrgData                     // Marks the end of the code + rodata region (functions, const data, ...) and the start of the data region (static + global variables)
sections .textrw, .data, .fast, ... // In any order
section DevDscr                     // Marks the location of the <FlashDevice> structure variable and also the end of the loader. Must(!!!) be the very last section

Templates

There are templates as well as functioning reference loaders available in source. These are part of the J-Link Device Support Kit (DSK).

Troubleshooting

General considerations

  1. Get the latest version of the template project
  2. Follow the Step-By-Step instructions except of 1.2 FlashPrg.c --> Functions should not contain any code that accesses any SFRs
  3. Build the flash loader using the release configuration
  4. Perform a flash download using J-Link Commander. Flash download should report an error during verify
  5. Implement SEGGER_FL_Erase() and retry the flash download test. J-Link Commander should still report verify failed but effected flash memory region should be empty. If not, check SEGGER_FL_Erase().
  6. Implement SEGGER_FL_Program() and retry the flash download test. Expected result: Test reports O.K. --> Programmed successfully. If not, check SEGGER_FL_Program() code.

PC has unexpected value after flash download
This error may have different root causes:

  • Watchdog is enabled but not fed in the flash loader functions. This may result in a watchdog timeout pops up during RAMCode execution. The behavior is different but usually a reset will be triggered.
  • Accessing not enabled / clocked special function registers / peripherals
  • Accessing invalid memory regions (reserved)

External flash pin init
The SEGGER_FL_Prepare() code has to make sure that the (QSPI) pins as well as the (QSPI) controller are configured so that the flash is memory-mapped read-accessible.
This is necessary as the J-Link software by default compares flash contents before starting the flash programming, to save time in case large portions of the flash are already identical to the programming data.
This can be validated by setting the compare method in J-Link Commander to "skip" (exec SetCompareMode 0). Now start flash download.
J-Link Commander should report a verify error but the flash should be memmory mapped accessible from now. If not, check the Init() code.

I get build errors in release build config
If you get build errors when switching from "Debug" to "Release" build in the template project the main cause is that third party libraries are used.
The SEGGER Flash Loader interface expects all program parts to be linked to sections PrgCode and PrgData.
Third party libraries often use statically linked program parts which will not be put in the aforementioned sections which will cause a build or linker error.
Generally we recommend not using any third party libraries when creating Flash loaders as they will increase the Flash loader size drastically while usually slowing down the maximum possible Flash loader speed.
If you happen to have to use an external library in your project it is user responsibility to make sure this external library is linked to the aforementioned sections for all application parts.

SFL FAQ

Q: Do I need a valid Embedded Studio license when using the SEGGER Flash Loader in a commercial scope?
A: Basically, any usage of ES in a commercial scope requires a valid license. However, the SEGGER Flash Loader is an exception. The evaluation license suffice; a valid license is not required.

Q: How is the *.elf file that is the result from building the SLF executed?
A: The *.elf file is loaded into the RAM of the target device and executed on its processor.

Q: How are the functions like "SEGGER_FL_Program()" called and executed on the target?
A: The J-Link DLL analyzes the ELF file to determine the function entry points and then calls those functions.

Q: What does the "SEGGER_FL_Lib_<CORE>_LE.a" file contain and how are they used by SEGGER flash loader?
A: The file contains generic (not device specific) logic which interacts with the custom Flashloader functions SEGGER_FL_*. It needs to be included in any build.

Q: There are two files "SEGGER_FL_Lib_<CORE>_LE.a" and "SEGGER_FL_Lib_<CORE>_BE.a". Which one do I have to use?
A: "SEGGER_FL_Lib_<CORE>_LE.a" is used for Little Endian targets while "SEGGER_FL_Lib_<CORE>_BE.a" is used for Big Endian targets.

Q: My flash loader uses interrupts. It works when debugging, but does not work when inegrated with J-Link software. How can this be solved?
A: Before calling the flash loader functions, J-Link will disable interrupts on the device. If you require interrupts, you will need to reenable those e.g. in SEGGER_FL_Prepare().