Difference between revisions of "SEGGER Flash Loader"

From SEGGER Wiki
Jump to: navigation, search
(General Procedure)
(FlashDevice struct)
(29 intermediate revisions by 4 users not shown)
Line 1: Line 1:
  +
== SEGGER Flash Loader ==
<div class="toclimit-3">
 
  +
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.
__TOC__
 
</div>
 
   
  +
=== 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 ==
=Open Flashloader=
 
  +
The SEGGER Flash Loader (SFL) is available for the following architectures:
==Introduction==
 
  +
* ARMv4/v5
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 and Documentation Pack]] being available.
 
  +
** 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
  +
* RISC-V RV32
   
  +
{{Note|1=
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.
 
  +
Architectures / cores not listed here must be assumed as being not supported.<br>
 
  +
While they may work by chance, no support is provided for problems in regards to getting open flash loaders running on non-listed architectures.<br>
==Supported CPU architectures==
 
The open flash loader is available for the following architectures:
 
* ARMv4 (ARM7)
 
* ARMv5 (ARM9)
 
* ARMv6-M (Cortex-M0, Cortex-M1, ...)
 
* ARMv7-M (Cortex-M3, Cortex-M4, ...)
 
* ARMv8-M (Cortex-M23, Cortex-M33, ...)
 
* ARMv7-A (Cortex-A8, Cortex-A9, ...)
 
* ARMv7-R (Cortex-R4, Cortex-R5, ...)
 
* RISC-V RV32
 
Architectures not listed here must be assumed as being not supported.<br>
 
While they may work by chance, no support is provided for problems in regards to getting open flash loaders running on non-listed architectures.
 
 
In case of doubt, please feel free to contact SEGGER.
 
In case of doubt, please feel free to contact SEGGER.
  +
}}
   
  +
== Supported flash types ==
==General Procedure==
 
  +
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>
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/supported-devices/jlink
 
  +
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>
   
  +
For non-memory-mapped flashes, the following additional entry functions must be implemented in an SFL:
Additionally, the build-in device database can be extended by specifying devices in a XML file. It is also possible to edit / extend an device from the built-in device database via this XML file. There is a standard [[#Location| location]] where the J-Link DLL will look for *.xml files.
 
  +
* SEGGER_FL_CheckBlank()
  +
* SEGGER_FL_Verify()
  +
* SEGGER_FL_Read()
  +
* SEGGER_FL_CalcCRC()
   
  +
== Entry functions overview ==
==Extending an Existing Device==
 
In order to edit/extend a device that is already in the built-in device database of the J-Link DLL, a *.xml with the following content has to be created or extended in the JLinkDevices folder:
 
<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.
 
   
  +
The following table gives an overview about the mandatory and optional entry functions, of a SEGGER Flash Loader:
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.
 
  +
{| class="seggertable"
 
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.
 
 
==Adding a New Device==
 
In order to add support for a new device to the J-Link DLL, the following needs to be added
 
to a *.xml file in the JLinkDevices folder:
 
<Database>
 
<Device>
 
<ChipInfo Vendor="..." Name="..." WorkRAMAddr="..." WorkRAMSize="..." Core="..." />
 
<FlashBankInfo Name="..." BaseAddr="..." MaxSize="..." Loader="..." LoaderType="..." AlwaysPresent="..." />
 
</Device>
 
</Database>
 
When adding a new device, the following attributes for the <ChipInfo> tag are mandatory:
 
*Vendor
 
*Name
 
*Core
 
In case a ''<FlashBankInfo>'' tag is also added, the following attributes in addition to the ones mentioned before, become mandatory:
 
'''ChipInfo-Tag'''
 
*WorkRAMAddr
 
*WorkRAMSize
 
*FlashBankInfo
 
'''FlashBankInfo-Tag'''
 
*Name
 
*BaseAddr
 
*MaxSize
 
*Loader
 
*LoaderType
 
*AlwaysPresent
 
For more information about the tags and their attributes, please refer to XML Tags and
 
Attributes .
 
In order to add more than one device to the device database, just repeat the <Device> …
 
</Device> tag structure from above for each device or create a separate *.xml file in the JLinkDevices folder.
 
 
==Adding a New Flash Bank==
 
In general, there are two possibilities to add a new flash bank for a new or existing device:
 
#Use a pre-compiled flash loader
 
#Compile / create the flash loader on your own
 
##Using Keil uVision (a license is required, no trial available; Supports Cortex-M, only)
 
##SEGGER Embedded Studio (can be evaluated without license; Supports Cortex-M, Cortex-A/R and RISC-V)<br>How to create a flash loader on your own using Embedded Studio is described below.
 
 
'''Note:''' The Open Flashloader concept replaces the previous RAMCode SDK.
 
 
== JLinkDevices folder ==
 
[[File: JLinkDevicesFolderExample.png | 400px | thumb | right | Example for JLinkDevices folder structure]]
 
 
[[File: OFL_Installer.png | 400px | thumb | right | The "Welcome" page of the Open Flashloader installer example]]
 
 
Customers and silicon vendors may add support for their own devices or extend support for already existing devices by passing a *.xml file to the J-Link DLL. Those *.xml files need to be located in the central SEGGER/JLinkDevices folder.
 
If the folder does not exist, it may be created.
 
The process of placing (i.e. copying) flash loader and XML files at the desired locations can be automated by using an installer as explained below.
 
 
=== Installer ===
 
 
For easier integration of Open Flashloader files, SEGGER provides a template for creating an installer which copies the flashloader and XML file(s) to their designated location.<br>
 
'''Windows installer template (NSIS based)''': [[Media: 220630_OpenFlashLoaderInstaller.zip | 220630_OpenFlashLoaderInstaller.zip]]
 
 
The template includes a pre-built example installer executable as well as sources for customizing and rebuilding the installer.<br>
 
The included README.txt goes into detail on how to customize and build the installer executable.
 
 
=== Location ===
 
* Windows: C:\Users\<USER>\AppData\Roaming\SEGGER\JLinkDevices
 
* Linux: $HOME/.config/SEGGER/JLinkDevices
 
* macOS: $HOME/Library/Application Support/SEGGER/JLinkDevices
 
 
<br clear="all">
 
 
=== Usage ===
 
The J-Link DLL will recursively look through the JLinkDevices folder for any *.xml files and evaluate them as JLinkDevices.xml files. Customers may freely structure the folder into subfolders with a maximum depth of four.
 
 
{{Note|This feature has been introduced with V7.62.}}
 
 
==JLinkDevices.xml Tags and Attributes==
 
 
 
XML Tags and Attributes
 
In the following, the valid XML tags and their possible attributes are explained.
 
General rules
 
• Attributes may only occur inside an opening tag
 
• Attribute values must be enclosed by quotation marks
 
Tag Description
 
 
{| class="wikitable"
 
!|Tag
 
!|Description
 
 
|-
 
|-
  +
! Entry function !! Type
|''<Database>''
 
|Opens the XML file top-level tag.
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Prepare | SEGGER_FL_Prepare()]] || Mandatory
|''<Device>''
 
|Opens the description for a new device.
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Restore | SEGGER_FL_Restore()]] || Mandatory
|''<ChipInfo>''
 
|Specifies basic information about the device to be added, like the core it incorporates etc.
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Program | SEGGER_FL_Program()]] || Mandatory
|''<FlashBankInfo>''
 
|Specifies a flash bank for the device.
 
|}
 
 
====<Database>====
 
Opens the XML file top-level tag. Only present once per XML file.
 
'''Valid attributes'''
 
This tag has no attributes
 
'''Notes'''
 
*Must only occur once per XML file
 
*Must be closed via </Database>
 
====<Device>====
 
Opens the description for a new device.
 
'''Valid attributes'''
 
{| class="wikitable"
 
!|Parameter
 
!|Meaning
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Erase | SEGGER_FL_Erase()]] || Mandatory
|''InheritFrom''
 
|String that specifies the name of a parent device which the DLL already knows. The new child device will inherit all properties from the parent to use as a base. <br> If the child inherits from a parent that was defined through *.XML, the parent and child must be defined in the same *.XML file and the parent must be defined before the child.<br> Other configurations may lead to unspecified behavior.<br>This attribute is optional. E.g. InheritFrom=“STM32F767NI”.
 
|}
 
 
'''Notes'''
 
*Must be closed via </Device> .
 
*May occur multiple times in an XML file
 
====<ChipInfo>====
 
Specifies basic information about the device to be added, like the core it incorporates etc.
 
'''Valid attributes'''
 
 
 
{| class="wikitable"
 
!|Parameter
 
!|Meaning
 
 
|-
 
|-
  +
| [[#SEGGER_FL_EraseChip | SEGGER_FL_EraseChip()]] || Optional
|''Vendor''
 
|String that specifies the name of the vendor of the device. This attribute is mandatory. E.g. Vendor=“ST”.
 
 
|-
 
|-
  +
| [[#SEGGER_FL_CheckBlank | SEGGER_FL_CheckBlank()]] || Optional
|''Name''
 
|Name of the device. This attribute is mandatory. E.g. Name=“STM32F407IE”
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Verify | SEGGER_FL_Verify()]] || Optional
|''WorkRAMAddr''
 
|Hexadecimal value that specifies the address of a RAM area that can be used by J-Link during flash programming etc. Should not be used by any DMAs on the device. Cannot exist without also specifying WorkRAMSize. If no flash banks are added for the new device, this attribute is optional. E.g. WorkRAMAddr=“ 0x20000000 ”
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Read | SEGGER_FL_Read()]] || Optional
|''WorkRAMSize''
 
|Hexadecimal value that specifies the size of the RAM area that can be used by J-Link during flash programming etc. Cannot exist without also specifying WorkRAMAddr. If no flash banks are added for the new device, this attribute is optional. E.g. WorkRAMSize=“ 0x10000 ”
 
 
|-
 
|-
  +
| [[#SEGGER_FL_CalcCRC | SEGGER_FL_CalcCRC()]] || Optional
|''Core''
 
|Specifies the core that the device incorporates. If a new device added, this attribute is mandatory. E.g. Core=“ JLINK_CORE_CORTEX_M0 ”For a list of valid attribute values, please refer to Attribute values - Core.
 
 
|-
 
|-
  +
| [[#SEGGER_FL_Start | SEGGER_FL_Start()]] || Optional
|''JLinkScriptFile''
 
  +
|-
|String that specifies the path to a J-Link script file if required for the device. Path can be relative or absolute. If path is
 
  +
| [[#SEGGER_FL_GetFlashInfo | SEGGER_FL_GetFlashInfo()]] || Optional
relative, it is relative to the location of the JLinkDevices.xml file. This attribute is optional. E.g. JLinkScriptFile=“ST/Example.jlinkscript”
 
|}
+
|}
  +
'''Notes'''
 
  +
=== SEGGER_FL_Prepare ===
*No separate closing tag.
 
  +
'''Prototype'''<br>
Directly closed after attributes have been specified: ''<ChipInfo … />''
 
  +
<source lang="c">int SEGGER_FL_Prepare(U32 PreparePara0, U32 PreparePara1, U32 PreparePara2);</source>
*Must not occur outside a ''<Device>'' tag.
 
   
  +
'''Function description'''<br>
====Attribute values - Core====
 
  +
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>
For a list of all available values for the ''Core'' attribute, please expand the following list:
 
  +
{| class="seggertable"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
 
|
 
 
|-
 
|-
  +
! Parameter !! Description
 
|-
 
|-
  +
| PreparePara0 || Reserved for future use. Always == 0 for now
|JLINK_CORE_CORTEX_M1
 
 
|-
 
|-
  +
| PreparePara1 || Reserved for future use. Always == 0 for now
|JLINK_CORE_CORTEX_M3
 
 
|-
 
|-
  +
| PreparePara2 || Reserved for future use. Always == 0 for now
|JLINK_CORE_CORTEX_M3_R1P0
 
 
|-
 
|-
  +
|}
|JLINK_CORE_CORTEX_M3_R1P1
 
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_CORTEX_M3_R2P0
 
 
|-
 
|-
  +
| >= 0 || OK
|JLINK_CORE_CORTEX_M3_R2P1
 
 
|-
 
|-
  +
| == 0 || OK, Clock speed of core not changed
|JLINK_CORE_CORTEX_M0
 
 
|-
 
|-
  +
| > 0 || New clock speed in [Hz](!) of core
|JLINK_CORE_CORTEX_M_V8BASEL
 
 
|-
 
|-
  +
| < 0 || Error
|JLINK_CORE_ARM7
 
  +
|}
  +
  +
=== SEGGER_FL_Restore ===
  +
'''Prototype'''<br>
  +
<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
|JLINK_CORE_ARM7TDMI
 
 
|-
 
|-
  +
| RestorePara0 || Reserved for future use. Always == 0 for now
|JLINK_CORE_ARM7TDMI_R3
 
 
|-
 
|-
  +
| RestorePara1 || Reserved for future use. Always == 0 for now
|JLINK_CORE_ARM7TDMI_R4
 
 
|-
 
|-
  +
| RestorePara2 || Reserved for future use. Always == 0 for now
|JLINK_CORE_ARM7TDMI_S
 
 
|-
 
|-
  +
|}
|JLINK_CORE_ARM7TDMI_S_R3
 
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_ARM7TDMI_S_R4
 
 
|-
 
|-
  +
| >= 0 || OK
|JLINK_CORE_CORTEX_A8
 
 
|-
 
|-
  +
| < 0 || Error
|JLINK_CORE_CORTEX_A7
 
  +
|}
  +
  +
'''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
|JLINK_CORE_CORTEX_A9
 
 
|-
 
|-
  +
| DestAddr || Destination address. Always aligned to FlashDevice.PageSize
|JLINK_CORE_CORTEX_A12
 
 
|-
 
|-
  +
| NumBytes || Number of bytes to be programmed (always a multiple of FlashDevice.PageSize)
|JLINK_CORE_CORTEX_A15
 
 
|-
 
|-
  +
| pSrcBuff || Pointer to the data to be programmed
|JLINK_CORE_CORTEX_A17
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_ARM9
 
 
|-
 
|-
  +
| == 0 || O.K.
|JLINK_CORE_ARM9TDMI_S
 
 
|-
 
|-
  +
| == 1 || Error
|JLINK_CORE_ARM920T
 
 
|-
 
|-
  +
| == 2 || O.K., already performed implicit verify of block that was just programmed
|JLINK_CORE_ARM922T
 
  +
|}
  +
  +
=== 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
|JLINK_CORE_ARM926EJ_S
 
 
|-
 
|-
  +
| SectorAddr || Address of the first sector to be erased.
|JLINK_CORE_ARM946E_S
 
 
|-
 
|-
  +
| SectorIndex || Index of the start sector to be erased. Counting starts at 0 (first sector reported by FlashDevice.SectorInfo[0])
|JLINK_CORE_ARM966E_S
 
 
|-
 
|-
  +
| 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.
|JLINK_CORE_ARM968E_S
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_ARM11
 
 
|-
 
|-
  +
| == 0 || O.K.
|JLINK_CORE_ARM1136
 
 
|-
 
|-
  +
| == 1 || Error
|JLINK_CORE_ARM1136J
 
  +
|}
  +
  +
=== 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
|JLINK_CORE_ARM1136J_S
 
 
|-
 
|-
  +
| colspan="2" | None
|JLINK_CORE_ARM1136JF
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_ARM1136JF_S
 
 
|-
 
|-
  +
| == 0 || O.K.
|JLINK_CORE_ARM1156
 
 
|-
 
|-
  +
| == 1 || Error
|JLINK_CORE_ARM1176
 
  +
|}
  +
  +
=== 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
|JLINK_CORE_ARM1176J
 
 
|-
 
|-
  +
| Addr || Address where checking for blank / erased data should start
|JLINK_CORE_ARM1176J_S
 
 
|-
 
|-
  +
| NumBytes || Number of bytes to be checked
|JLINK_CORE_ARM1176JF
 
 
|-
 
|-
  +
| BlankValue || Blank (erased) value of flash (Most flashes have 0xFF, some have 0x00, some do not have a defined erased value)
|JLINK_CORE_ARM1176JF_S
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_CORTEX_R4
 
 
|-
 
|-
  +
| >= 0 || OK
|JLINK_CORE_CORTEX_R5
 
 
|-
 
|-
  +
| == 0 || OK, complete region is blank
|JLINK_CORE_RX
 
 
|-
 
|-
  +
| == 1 || OK, not the complete region is blank
|JLINK_CORE_RX62N
 
 
|-
 
|-
  +
| < 0 || Error
|JLINK_CORE_RX62T
 
  +
|}
  +
  +
=== 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
|JLINK_CORE_RX63N
 
 
|-
 
|-
  +
| Addr || Address where verify should start
|JLINK_CORE_RX630
 
 
|-
 
|-
  +
| NumBytes || Number of bytes to verify
|JLINK_CORE_RX63T
 
 
|-
 
|-
  +
| pBuff || Pointer to data to compare flash contents to
|JLINK_CORE_RX621
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_RX62G
 
 
|-
 
|-
  +
| 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
|JLINK_CORE_RX631
 
  +
|}
  +
  +
=== 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
|JLINK_CORE_RX65N
 
 
|-
 
|-
  +
| Addr || Address to start reading flash at
|JLINK_CORE_RX21A
 
 
|-
 
|-
  +
| NumBytes || Number of bytes to read
|JLINK_CORE_RX220
 
 
|-
 
|-
  +
| pBuff || Pointer to buffer where to store read data to
|JLINK_CORE_RX230
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_RX231
 
 
|-
 
|-
  +
| >= 0 || OK, number of bytes read (usually == NumBytes)
|JLINK_CORE_RX23T
 
 
|-
 
|-
  +
| < 0 || Error
|JLINK_CORE_RX24T
 
  +
|}
  +
  +
=== 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
|JLINK_CORE_RX110
 
 
|-
 
|-
  +
| CRC || Start value of CRC
|JLINK_CORE_RX113
 
 
|-
 
|-
  +
| Addr || Address where calculation of CRC starts
|JLINK_CORE_RX130
 
 
|-
 
|-
  +
| NumBytes || Number of bytes to calculate CRC on
|JLINK_CORE_RX71M
 
 
|-
 
|-
  +
| Polynom || Polynom to use for CRC calculation
|JLINK_CORE_CORTEX_M4
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_CORTEX_M7
 
 
|-
 
|-
  +
| xxx || Calculated CRC
|JLINK_CORE_CORTEX_M_V8MAINL
 
  +
|}
  +
  +
'''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
|JLINK_CORE_CORTEX_A5
 
 
|-
 
|-
  +
| pInfo || Pointer to command info for SEGGER_OFL_Lib_StartTurbo()
|JLINK_CORE_POWER_PC
 
  +
|}
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|JLINK_CORE_POWER_PC_N1
 
 
|-
 
|-
  +
| colspan="2" | None
|JLINK_CORE_POWER_PC_N2
 
|-
 
|JLINK_CORE_MIPS
 
|-
 
|JLINK_CORE_MIPS_M4K
 
|-
 
|JLINK_CORE_MIPS_MICROAPTIV
 
|-
 
|JLINK_CORE_EFM8_UNSPEC
 
|-
 
|JLINK_CORE_CIP51
 
 
|}
 
|}
   
  +
=== SEGGER_FL_GetFlashInfo ===
====<FlashBankInfo>====
 
  +
'''Prototype'''<br>
Specifies a flash bank for the device. This allows to use the J-Link flash download functionality with IDEs, debuggers and other software that uses the J-Link DLL (e.g. J-Link Commander) for this device. The flash bank can then be programmed via the normal flash download functionality of the J-Link DLL. For more information about flash download, please refer to Flash download . For possible limitations etc. regarding newly added flash banks, please refer to Add. Info / Considerations / Limitations .
 
  +
<source lang="c">int SEGGER_FL_GetFlashInfo(SEGGER_FL_FLASH_INFO* pInfo, U32 InfoAreaSize);</source>
'''Valid attributes'''
 
   
  +
'''Function description'''<br>
{| class="wikitable"
 
  +
Optional function. May not be present.<br>
!|Parameter
 
  +
Only needed for flash loaders where the exact sectorization is determined at runtime.<br>
!|Meaning
 
  +
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
|''Name''
 
|String that specifies the name of the flash bank. Only used for visualization. Can be freely chosen. This attribute is mandatory. E.g. Name=“SPIFI flash”
 
 
|-
 
|-
  +
| pInfo || Points to info area which is used to store the flash info.
|''BaseAddr''
 
|Hexadecimal value that specifies the start address of the flash bank. The J-Link DLL uses this attribute together with MaxSize to determine which memory write accesses performed by the debugger, shall be redirected to the flash loader instead of being written directly to the target as normal memory access. This attribute is mandatory. E.g. BaseAddr=“ 0x08000000 ”
 
 
|-
 
|-
  +
| 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.
|''MaxSize''
 
  +
|}
|Hexadecimal value that specifies the max. size of the flash bank in bytes. For many flash loader types the real bank size may depend on the actual flash being connected (e.g. SPIFI flash where the loader can handle different SPIFI flashes so size may differ from hardware to hardware). Also, for some flash loaders the sectorization is extracted from the flash loader at runtime. The real size of the flash bank may be smaller than MaxSize but must never be bigger. The J-Link DLL uses this attribute together with BaseAddr to determine which memory write accesses performed by the debugger, shall be redirected to the flash loader instead of being written directly to the target as normal memory access. This attribute is mandatory. E.g. MaxSize=“ 0x80000 ”
 
  +
  +
'''Return value'''<br>
  +
{| class="seggertable"
 
|-
 
|-
  +
! Value !! Meaning
|''Loader''
 
|String that specifies path to the ELF file that holds the flash loader. Path can be relative or absolute. If path is relative, it
 
is relative to the location of the JLinkDevices.xml file. This attribute is mandatory. E.g. Loader=“ST/MyFlashLoader.elf” For CMSIS flash loaders the file extension is usually FLM, however any extension is accepted by the J-Link DLL.
 
 
|-
 
|-
  +
| >= 0 || OK, number of bytes read (usually == NumBytes)
|''LoaderType''
 
|Specifies the type of the loader specified by Loader. This attribute is mandatory. E.g. LoaderType=“ FLASH_ALGO_TYPE_OPEN ” For a list of valid attribute values, please refer to Attribute values LoaderType.
 
 
|-
 
|-
  +
| < 0 || Error
|''AlwaysPresent''
 
|Specifies if a flash bank is always present (e.g. internal flash). If this element is set to one, this flash bank will be affected by the “erase” command. This attribute is optional. E.g. AlwaysPresent=“1”.
 
 
|}
 
|}
   
'''Notes'''
+
'''Notes'''<br>
  +
{{Note|1=
*No separate closing tag. Directly closed after attributes have been specified:
 
  +
# If present, this function is called before any erase, program, verify operation but after Preare().<br>
<FlashBankInfo … />
 
  +
# If present, this function overrides the information provided by FlashDevice.TotalSize and FlashDevice.SectorInfo[]
*Must not occur outside a <Device> tag
 
  +
}}
====Attribute values - LoaderType====
 
The following values are valid for the LoaderType attribute:
 
*FLASH_ALGO_TYPE_OPEN
 
Describes that the used algorithm is an Open Flashloader algorithm. CMSIS based
 
algorithms are also supported via the Open Flashloader concept. For additional
 
information, see Add. Info / Considerations / Limitations .
 
   
  +
== FlashDevice struct ==
==Example JLinkDevices.xml file==
 
  +
The FlashDevice structure variable contains all the static information about the flash algorithm like sectorization of the flash, programming chunk size, ...<br>
==Add. Information / Considerations / Limitations ==
 
  +
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">
=Create a Flash Loader=
 
  +
struct FlashDevice {
This article describes how to add support for new devices / flash banks to the J-Link DLL so that they can be used with any J-Link DLL based application like for example J-Flash, J-Link Commander, IDEs, etc...The description is based on the template projects (Cortex-M, Cortex-A/R, ARM7/9 and RISC-V) for SEGGER Embedded Studio. This article assumes that there is already a basic understanding of the method of adding new devices using the Open Flashloader concept. If this is not the case, we recommend to read the article above. In general, there are two possibilities to add support for a new device:
 
  +
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"
#Use a pre-compiled flash loader
 
#Compile / create the flash loader on your own
 
##Using Keil uVision (a license is required, no trial available; Supports Cortex-M, only)
 
##SEGGER Embedded Studio (Supports Cortex-M, Cortex-A/R and RISC-V)<br>Basically, any usage of ES in a commercial scope requires a valid license.<br>However, the Open Flashloader is an exception. The evaluation license can be used to debug & create a flashloader; a valid license is not required.<br>How to create a flash loader on your own using Embedded Studio is described below.<br>
 
 
 
 
'''Supported cores:'''
 
*Cortex-M
 
*Cortex-A/R
 
*ARM7/9
 
*RISC-V
 
 
'''Note:''' The Open Flashloader concept replaces the previous RAMCode SDK.
 
 
== Build Configurations ==
 
The example project contains two build configurations:
 
* Debug: 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.
 
* Release: Creates elf file which can be referenced from within the JLinkDevices.xml file as "''Loader''".
 
 
== Included files ==
 
{| class="wikitable"
 
 
|-
 
|-
! Filename !! Content
+
! Member !! Explanation
 
|-
 
|-
  +
| AlgoVer || Set to 0x0101. Do not set to anything else!
| '''FlashDev.c''' || Flash device description for the ST STM32F205RC
 
 
|-
 
|-
  +
| 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!
| '''FlashOS.h''' || Function prototypes, definitions and structures
 
 
|-
 
|-
  +
| Type || Flash device type. Currently ignored. Set to 1 to get max. compatibility.
| '''FlashPrg.c''' || Flash algorithm itself (e.g. ProgramPage(), EraseSector()
 
 
|-
 
|-
  +
| 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.
| '''main.c''' || Flash algorithm debug code (used by debug configuration, only)
 
 
|-
 
|-
  +
| 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)
| '''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)
 
 
|-
 
|-
  +
| 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.
| '''MemoryMap.xml''' || Memory map of the ST STM32F205RC
 
 
|-
 
|-
  +
| Reserved || Set this element to 0
| '''Placement_debug.xml''' || Debug configuration section placement file.
 
 
|-
 
|-
  +
| 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)
| '''Placement_release.xml''' || Release configuration section placement file.
 
 
|-
 
|-
  +
| TimeoutProg || Timeout in milliseconds (ms) to program one chunk of <PageSize>
| '''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)
 
|}
 
 
== ARM Cortex-A and Cortex-R template projects ==
 
The template projects below have been tested with [https://www.segger.com/downloads/embedded-studio/#ESforARM SEGGER Embedded Studio for ARM V5.34].
 
*[[Media:OFL_Template_CortexA.zip | OFL_Template_CortexA.zip]]
 
*[[Media:OFL_Template_CortexR.zip | OFL_Template_CortexR.zip]]
 
 
== ARM Cortex-M template projects ==
 
The template projects below have been tested with [https://www.segger.com/downloads/embedded-studio/#ESforARM SEGGER Embedded Studio for ARM V5.34].
 
*[[Media:OFL_Template_CortexM.zip | OFL_Template_CortexM.zip]]
 
 
== ARM7/9 template projects ==
 
The template projects below have been tested with [https://www.segger.com/downloads/embedded-studio/#ESforARM SEGGER Embedded Studio for ARM V5.34].
 
*[[Media:OFL_Template_ARM7.zip | OFL_Template_ARM7.zip]]
 
 
== RISC-V template projects ==
 
The template projects below have been tested with [https://www.segger.com/downloads/embedded-studio/#ESforRISCV SEGGER Embedded Studio for RISC-V V5.34].
 
*[[Media:OFL_Template_RV32.zip | OFL_Template_RV32.zip]]
 
'''Note:''' The template project is configured for "Enable Linker Relaxation = no". Linker relaxation is not supported for open flash loaders.
 
 
== Reference algorithms ==
 
* [[Media:OFL_RefAlgo_Gigadevice_GD32VF103.zip | Gigadevice GD32VF103(internal flash, RV32)]]
 
* [[Media:OFL_RefAlgo_ST_STM32F407VE.zip | ST STM32F407VE (internal flash, Cortex-M4)]]
 
 
== Step-By-Step Instruction ==
 
This step-by-step instruction explains how to create your own flash loader using the template projects for Embedded Studio.
 
#Adapt the template project
 
##'''FlashDev.c''': Modify the FlashDevice structure according to your device
 
##'''FlashPrg.c''': Implement the flash routines Init(), UnInit(), EraseSector() and ProgramPage()
 
##'''MemoryMap.xml''': Enter RAM base address and RAM size
 
##'''Placement_debug.xml''': Enter RAM address in the program section element.
 
##'''main.c''': Make sure that the define ''_FLASH_BASE_ADDR'' defines the correct flash base address
 
#Test the debug configuration
 
##Connect the target to the J-Link and the J-Link to the PC
 
##Switch to the '''Debug''' configuration in Embedded Studio ('''Build''' -> '''Set Active Build Configuration''' -> '''Debug''')
 
##Build the project by pressing '''F7'''
 
##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| 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 / ...).
 
 
== FAQ ==
 
#'''Q:''' Do I need a valid Embedded Studio license when using the Open Flashloader in a commercial scope?<br>'''A:''' Basically, any usage of ES in a commercial scope requires a valid license. However, the Open Flashloader is an exception. The evaluation license suffice; a valid license is not required.
 
 
TBD
 
<!--
 
// EL xxx look here
 
'''Question #1:''' 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()
 
 
'''How much stack is reserved by the J-Link software for the RAMCode?'''
 
 
256 bytes are reserved for the stack. The stack size is fixed and cannot be configured.
 
 
'''Question #3:'''
 
-->
 
 
== 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 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 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 ==
 
=== 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)
 
===(Q)SPI flashes===
 
*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.
 
===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 Open Flashloader 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.
 
== Example projects ==
 
The projects below are based on the template projects (see links above). They can be used as reference when creating your own flashloader using the Open Flashloader.
 
*[[File:Microchip_AT91SAM7S64_ES.zip]]
 
*[[File:ST_STM32F205RC_ES_V310a.zip]]
 
 
= Algorithm Functions =
 
The following tables provide an overview of all available functions. The tables are split into mandatory and optional functions.
 
 
Following functions are mandatory.
 
'''Note: '''The functions EraseSector and ProgramPage have been extended by new functions optimized for speed. Either of these func
 
{| class="wikitable"
 
!|Function Name
 
!|Description
 
 
|-
 
|-
  +
| TimeoutErase || Timeout in milliseconds (ms) to erase one sector
|[[Open_Flashloader#Init | Init]]
 
|Handles the initialization of the flash module.
 
 
|-
 
|-
  +
| SectorInfo ||
|[[Open_Flashloader#UnInit | UnInit]]
 
  +
This element is actually a list of '''different sector sizes''' present on target flash.<br>
|Handles the de-initialization of the flash module.
 
  +
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>
|[[Open_Flashloader#SEGGER_OPEN_Erase | SEGGER_OPEN_Erase]]<br>
 
  +
For more information, see the example below.
|Erases one or more flash sector(s). Alternatively, the deprecated function [[Open_Flashloader#EraseSector | EraseSector]] can be used which does support single sector erase, only.
 
|-
 
|[[Open_Flashloader#SEGGER_OPEN_Program | SEGGER_OPEN_Program]]
 
|Programs one or multiple flash page(s). Alternatively, the deprecated function [[Open_Flashloader#ProgramPage | ProgramPage]] can be used which does support single page program, only.<br>We highly recommend to use the SEGGER_OPEN_Program() because a much higher throughput can be achieved compared to the legacy one.
 
 
|}
 
|}
'''Note: '''In order to stay backward compatible, the DLL accepts both program / erase functions. In this case, the SEGGER_OPEN_XXX variant will be used.
 
In general, users have to make sure that at least one program / erase function is implemented in the flashloader.
 
   
  +
'''Example for SectorInfo[] member'''<br>
Following functions are optional:
 
  +
<source lang="c">
{| class="wikitable"
 
  +
// Example device with 256 KB divided into:
!|Function Name
 
  +
// 4 * 16 KB sectors
!|Description
 
  +
// 1 * 64 KB sectors
|-
 
  +
// 1 * 128 KB sectors
|[[Open_Flashloader#BlankCheck | BlankCheck]]
 
  +
//
|Checks if a memory region is blank
 
  +
// FlashDevice.TotalSize:
|-
 
  +
// 0x40000
|[[Open_Flashloader#EraseChip| EraseChip]]
 
  +
//
|Erases the entire chip (flash bank)
 
  +
// FlashDevice.SectorInfo[]:
|-
 
  +
// {
|[[Open_Flashloader#Verify| Verify]]
 
  +
// SectSize StartAddr
|Compares a specified number of bytes of a provided data buffer with the content of the device
 
  +
// { 0x00004000, 0x00000000 }, // 4 * 16 KB = 64 KB
|-
 
  +
// { 0x00010000, 0x00010000 }, // 1 * 64 KB = 64 KB
|[[Open_Flashloader#SEGGER_OPEN_Read | SEGGER_OPEN_Read]]
 
  +
// { 0x00020000, 0x00020000 }, // 1 * 128 KB = 128 KB
|Reads the target memory (e.g. can be used to read data from non-memory mapped flashes)
 
  +
// { 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 ==
==Flash Erase Procedure==
 
  +
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]]
This procedure is executed to erase the flash before programming it.
 
   
  +
== Stack usage ==
[[File:Flash_Erase_Procedure.svg| 700px]]
 
  +
J-Link reserves 256 bytes stack for the SEGGER Flash Loader. This value is fixed and cannot be changed.
   
  +
== Section layout ==
==Flash Program Procedure==
 
  +
The J-Link software expects a special layout when it comes to RO code, RO data, RW data placement in the SFL binary.<br>
This procedure is executed to program the flash. The DLL makes sure that the effected sectors are erased.
 
  +
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:
[[File:Flash_Program_Procedure.svg | 700px]]
 
  +
<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>
   
==Flash Verify Procedure==
+
== 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)]].
This procedure verifies that the programmed data have been programmed successfully.
 
   
  +
== Troubleshooting ==
TBD
 
  +
'''General considerations'''<br>
==Flash Read Procedure==
 
  +
# Get the latest version of the template project
This procedure reads back the flash content. Please note that this sequence is executed in case of SEGGER_OPEN_Read() has been implemented. If this function is not available, the read back is done using memory mapped read accesses to the specified address.
 
  +
# 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>
TBD
 
  +
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.
=Function Overview=
 
  +
* Accessing not enabled / clocked special function registers / peripherals
 
  +
* Accessing invalid memory regions (reserved)
==Init==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int Init(U32 Addr, U32 Freq, U32 Func);
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Handles the initialization of the flash module. This function will be called prior any flash action (read, program, erase, etc...).
 
 
'''Parameters'''
 
*Addr: Specifies the base address of the flash.
 
*Freq: Specifies the CPU clock frequency.
 
*Func: Specifies the action followed by Init() (e.g.: 1 - Erase, 2 - Program, 3 - Verify / Read)
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int Init(U32 Addr, U32 Freq, U32 Func) {
 
(void)Addr;
 
(void)Freq;
 
(void)Func;
 
//
 
// Init code
 
//
 
FLASH->ACR = 7; // Disable all caches and set wait-states to 7
 
do {
 
v = FLASH->ACR;
 
if ((v & 0x00001F07) == 7) { // Wait until write has completely succeeded
 
break;
 
}
 
} while (1);
 
FLASH->ACR = (1 << 11) | (1 << 12) | 7; // Reset data and instruction cache
 
FLASH->ACR = 7; // Invalidate reset of data and instruction cache
 
return 0;
 
}
 
</syntaxhighlight>
 
 
==UnInit==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int UnInit(U32 Func);
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Handles the de-initialization of the flash module.
 
 
'''Parameters'''
 
*Func: Specifies the previous flash action before the call of UniInit() (e.g.: 1 - Erase, 2 - Program, 3 - Verify / Read)
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int UnInit(U32 Func) {
 
(void)Func;
 
//
 
// Uninit code
 
//
 
return 0;
 
}
 
</syntaxhighlight>
 
 
==SEGGER_OPEN_Erase==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int SEGGER_OPEN_Erase(U32 SectorAddr, U32 SectorIndex, U32 NumSectors)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Erases one or more flash sector(s).
 
 
'''Parameters'''
 
*SectorAddr: Address of the start sector to be erased
 
*SectorIndex: Index of the start sector to be erased
 
*NumSectors: Number of sectors to be erased
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int SEGGER_OPEN_Erase(U32 SectorAddr, U32 SectorIndex, U32 NumSectors) {
 
do {
 
//
 
// Erase sector code
 
//
 
_FeedWatchdog();
 
SectorAddr += SECTOR_SIZE;
 
SectorIndex++;
 
} while (--NumSectors);
 
return 0;
 
}
 
</syntaxhighlight>
 
 
==EraseSector==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int EraseSector(U32 SectorAddr)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Erases one flash sector.
 
 
'''Parameters'''
 
*Addr: Address of the sector to be erased
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int EraseSector(U32 SectorAddr) {
 
//
 
// Erase sector code
 
//
 
_FeedWatchdog();
 
return 0;
 
}
 
</syntaxhighlight>
 
 
==SEGGER_OPEN_Program==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int SEGGER_OPEN_Program(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Programs one or more flash pages.
 
 
'''Parameters'''
 
*DestAddr: Destination address
 
*NumBytes: Number of bytes to be programmed (always a multiple of program page size, defined in FlashDev.c)
 
*pSrcBuff: Point to the source buffer
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int SEGGER_OPEN_Program(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff) {
 
volatile U8 * pSrc;
 
volatile U8 * pDest;
 
U8 AccessWidth;
 
U32 Status;
 
U32 NumPages;
 
U32 NumBytesAtOnce;
 
int r;
 
 
r = -1;
 
pSrc = (volatile U8*)pSrcBuff;
 
pDest = (volatile U8*)DestAddr;
 
//
 
// RAMCode is able to program multiple pages
 
//
 
NumPages = NumBytes >> PAGE_SIZE_SHIFT;
 
//
 
// Program page-wise
 
//
 
if (NumPages) {
 
r = 0;
 
do {
 
NumBytesAtOnce = (1 << PAGE_SIZE_SHIFT);
 
_FeedWatchdog();
 
//
 
// Program one page
 
//
 
do {
 
//
 
// Program page code
 
//
 
*pDest++ = *pSrc++;
 
} while(--NumBytesAtOnce);
 
} while (--NumPages);
 
}
 
return r;
 
}
 
</syntaxhighlight>
 
 
==ProgramPage==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int ProgramPage(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Programs one flash page.
 
 
'''Parameters'''
 
*DestAddr: Destination address
 
*NumBytes: Number of bytes to be programmed (Program page size, defined in FlashDev.c; The J-Link DLL is not allowed to pass multiple pages at once. We recommend to use SEGGER_OPEN_Program() instead.)
 
*pSrcBuff: Point to the source buffer
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int ProgramPage(U32 DestAddr, U32 NumBytes, U8 *pSrcBuff) {
 
volatile U8 * pSrc;
 
volatile U8 * pDest;
 
U8 AccessWidth;
 
U32 Status;
 
U32 NumBytesAtOnce;
 
int r;
 
 
r = -1;
 
pSrc = (volatile U8*)pSrcBuff;
 
pDest = (volatile U8*)DestAddr;
 
//
 
// Program page-wise
 
//
 
r = 0;
 
do {
 
NumBytesAtOnce = (1 << PAGE_SIZE_SHIFT);
 
_FeedWatchdog();
 
//
 
// Program one page
 
//
 
do {
 
//
 
// Program page code
 
//
 
*pDest++ = *pSrc++;
 
} while(--NumBytesAtOnce);
 
} while (--NumPages);
 
return r;
 
}
 
</syntaxhighlight>
 
 
==BlankCheck==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int BlankCheck(U32 Addr, U32 NumBytes, U8 BlankData)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Checks if a memory region is blank
 
 
'''Parameters'''
 
*Addr: Blank check start address
 
*NumBytes: Number of bytes to be checked
 
*BlankData: Pointer to the destination data
 
 
'''Return values'''
 
*0: O.K., blank
 
*1: O.K., *not* blank
 
*< 0: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int BlankCheck(U32 Addr, U32 NumBytes, U8 BlankData) {
 
U8* pData;
 
 
pData = (U8 *)Addr;
 
do {
 
if (*pData++ != BlankData) {
 
return 1;
 
}
 
} while (--NumBytes);
 
return 0;
 
}
 
</syntaxhighlight>
 
 
==EraseChip==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int EraseChip(void)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Erases the entire flash
 
 
'''Return values'''
 
*0: O.K.
 
*1: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int EraseChip(void) {
 
//
 
// Erase chip code
 
//
 
*(volatile U32*)(0x000000) = SectorAddr; // Dummy code, needs to be replaced with erase chip code
 
_FeedWatchdog();
 
return 0;
 
}
 
</syntaxhighlight>
 
 
==Verify==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>U32 Verify(U32 Addr, U32 NumBytes, U8 *pBuff)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Compares a specified number of bytes of a provided data buffer with the content of the device
 
 
'''Parameters'''
 
*Addr: Start address in memory which should be compared
 
*NumBytes: Number of bytes to be compared
 
*pBuff: Pointer to the data to be compared
 
 
'''Return values'''
 
*== (Addr + NumBytes): O.K.
 
*!= (Addr + NumBytes): *not* O.K. (ideally the fail address is returned)
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
U32 Verify(U32 Addr, U32 NumBytes, U8 *pBuff) {
 
unsigned char *pFlash;
 
unsigned long r;
 
 
pFlash = (unsigned char *)Addr;
 
r = Addr + NumBytes;
 
do {
 
if (*pFlash != *pBuff) {
 
r = (unsigned long)pFlash;
 
break;
 
}
 
pFlash++;
 
pBuff++;
 
} while (--NumBytes);
 
return r;
 
}
 
</syntaxhighlight>
 
 
==SEGGER_OPEN_Read==
 
'''Prototype'''
 
<syntaxhighlight lang="c" line='line'>
 
int SEGGER_OPEN_Read(U32 Addr, U32 NumBytes, U8 *pDestBuff)
 
</syntaxhighlight>
 
 
'''Function description'''
 
 
Reads a specified number of bytes into the provided buffer
 
 
'''Parameters'''
 
*Addr: Start read address
 
*NumBytes: Number of bytes to be read
 
*pBuff: Pointer to the destination data
 
 
'''Return values'''
 
*>= 0: O.K., NumBytes read
 
*< 0: Error
 
 
'''Code Example'''
 
 
<syntaxhighlight lang="c" line='line'>
 
int SEGGER_OPEN_Read(U32 Addr, U32 NumBytes, U8 *pDestBuff) {
 
//
 
// Read function
 
// Add your code here...
 
//
 
return NumBytes;
 
}
 
</syntaxhighlight>
 
 
= 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];
 
};
 
 
==== AlgoVer ====
 
Set to <ALGO_VERSION>. 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)
 
 
==== Type ====
 
Currently ignored. Set to <ONCHIP> to get max. compatibility.
 
 
==== BaseAddr ====
 
This element describes the base address of the flash. It is recommended to always use the real address of the flash here, even if the flash is also available at other addresses, depending on the current settings of the device.
 
 
==== TotalSize ====
 
This describes the total size of the flash that is achieved when summing up all sector info from <SectorInfo>. If the flash is 512 KiB in size, <TotalSize> must be 0x80000 (524,288 => 512 KiB)
 
 
==== PageSize ====
 
This field describes in what chunks J-Link feeds the flash loader. The SEGGER_OPEN_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 miliseconds (ms) to program one chunk of <PageSize>
 
 
==== TimeoutErase ====
 
Timeout in miliseconds (ms) to erase one sector
 
==== SectorInfo ====
 
This element is actually a list of different sector sizes present on target flash. The define MAX_NUM_SECTORS '''does not''' describe the max. number of sectors the algorithm can handle, it describes how many blocks of sectors of different sizes can be handled. The MAX_NUM_SECTORS define '''must not''' be changed! This spec. comes from the original Keil MDK-ARM flash loaders the Open Flashloader is compatible to and is not really well explained.
 
 
'''Example'''
 
 
The algorithm handles a flash with the following sectorization:
 
256 KiB divided into:
 
4 * 16 KiB
 
1 * 64 KiB
 
1 * 128 KiB
 
 
<SectorInfo>:
 
// SectSize StartAddr of block (absolute)
 
0x00004000, 0x00000000, // 4 * 16 KiB = 64 KiB
 
0x00010000, 0x00010000, // 1 * 64 KiB = 64 KiB
 
0x00020000, 0x00020000, // 1 * 128 KiB = 128 KiB
 
0xFFFFFFFF, 0xFFFFFFFF // Indicates the end of the flash sector layout. Must be present.
 
 
256 KiB divided into:
 
256 * 1 KiB
 
 
<SectorInfo>:
 
// SectSize StartAddr of block (absolute)
 
0x00000800, 0x00000000, // 256 * 1 KiB = 256 KiB
 
0xFFFFFFFF, 0xFFFFFFFF // Indicates the end of the flash sector layout. Must be present.
 
 
256 KiB divided into:
 
4 * 64 KiB
 
 
<SectorInfo>:
 
// SectSize StartAddr of block (absolute)
 
0x00010000, 0x00000000, // 4 * 64 KiB = 256 KiB
 
0xFFFFFFFF, 0xFFFFFFFF // Indicates the end of the flash sector layout. Must be present.
 
 
Example for STM32F401VC (256 KiB internal flash):
 
   
  +
'''External flash pin init'''<br>
struct FlashDevice const FlashDevice __attribute__ ((section ("DevDscr"))) = {
 
  +
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>
ALGO_VERSION, // Algo version
 
  +
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>
"Template internal flash", // Flash device name
 
  +
This can be validated by setting the compare method in J-Link Commander to "skip" (exec SetCompareMode 0). Now start flash download.<br>
ONCHIP, // Flash device type
 
  +
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>
0x00000000, // Flash base address
 
0x00040000, // Total flash device size in Bytes (256 KiB)
 
128, // Page Size (Flash needs to be programmed 128 byte aligned, in 128 byte chunks)
 
0, // Reserved, should be 0
 
0xFF, // Flash erased value
 
100, // Program page timeout in ms
 
6000, // Erase sector timeout in ms
 
//
 
// Flash sector layout definition
 
//
 
0x00004000, 0x00000000, // 4 * 16 KiB = 64 KiB
 
0x00010000, 0x00010000, // 1 * 64 KiB = 64 KiB
 
0x00020000, 0x00020000, // 1 * 128 KiB = 128 KiB
 
0xFFFFFFFF, 0xFFFFFFFF // Indicates the end of the flash sector layout. Must be present.
 
};
 
   
  +
'''I get build errors in release build config'''<br>
= Using a Precompiled Flashloader =
 
  +
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>
<ul>
 
  +
The Open Flashloader interface expects all program parts to be linked to sections PrgCode and PrgData.<br>
<ol>
 
  +
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>
<li>Make sure that J-Link software V6.16f or later is installed:<br>https://www.segger.com/downloads/jlink/</li>
 
  +
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>
<li>Browse to the [[#Location| location]] of the JLinkDevices folder. If it does not exist, create it.
 
  +
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.
<li>Create a new *.xml file in a text editor and add the device entry.<br>Example:</li>
 
<Database>
 
<Device>
 
&lt;!-- This entry will overwrite the existing device entry in the J-Link software, so that a custom flash algorithm is used for the internal flash -->
 
<ChipInfo Vendor="ST" Name="STM32F767ZI" Core="JLINK_CORE_CORTEX_M7" />
 
<FlashBankInfo Name="Internal flash" BaseAddr="0x08000000" MaxSize="0x00200000 " Loader="ST_STM32F7xxxx_2MB_DualBank.elf" LoaderType="FLASH_ALGO_TYPE_OPEN" />
 
</Device>
 
</Database>
 
<li>Copy the flashloader file, referenced in the JLinkDevices.xml entry, into the same directory where also the JLinkDevices.xml is located (in this example ST_STM32F7xxxx_2MB_DualBank.elf).</li>
 
<li>Start JFlash.exe (or any other application which supports J-Link) and select the device</li>
 
</ol>
 
</ul>
 
   
  +
== SFL FAQ ==
<!-- = Information for Silicon Vendors =
 
  +
'''Q:''' Do I need a valid Embedded Studio license when using the Open Flashloader in a commercial scope?<br>
SEGGER offers the opportunity to hand in custom created flash algorithms which will then be included in the official J-Link Software and Documentation Package hence distributed to any J-Link customer who is using the latest software package.
 
  +
'''A:''' Basically, any usage of ES in a commercial scope requires a valid license. However, the Open Flashloader is an exception. The evaluation license suffice; a valid license is not required.<br><br>
The following files and hardware need to be provided to SEGGER:
 
  +
'''Q:''' How is the *.elf file that is the result from building the SLF executed?<br>
*All required source files + the project which can be used to rebuild the algorithm of the flashloader
 
  +
'''A:''' The *.elf file is loaded into the RAM of the target device and executed on its processor.<br><br>
*JLinkDevices.xml - including the device entry / entries
 
  +
'''Q:''' How are the functions like "SEGGER_FL_Program()" called and executed on the target?<br>
*Flash loader file - referenced in the JLinkDevices.xml (which is based on the provided source files)
 
  +
'''A:''' The J-Link DLL analyzes the ELF file to determine the function entry points and then calls those functions.<br><br>
*Two hardware samples which can be used to verify the functionality of the compiled flashloader
 
  +
'''Q:''' What does the "SEGGER_FL_Lib_<CORE>_LE.a" file contain and how are they used by SEGGER flash loader?<br>
*Readme.txt which may includes additional information or at least a contact e-mail address which can be used by customers in case support is needed.
 
  +
'''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>
This applies to all new flashloaders which should be shipped with the J-Link package.
 
  +
'''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>
If a silicon vendor cannot meet the requirements, the alternative option is to deliver the flashloader to the customers manually.
 
  +
'''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.
-->
 

Revision as of 12:25, 20 April 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
  • 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 open 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>
TimeoutErase Timeout in milliseconds (ms) to erase one sector
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 256 bytes stack for the SEGGER Flash Loader. This value is fixed and cannot be changed.

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 Open Flashloader 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 Open Flashloader in a commercial scope?
A: Basically, any usage of ES in a commercial scope requires a valid license. However, the Open Flashloader 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.