Preface
The following documentation refers to a setup with CrossCore Embedded Studio (CCES) version 3.0.2 and handles cases for both ADSP-SC83x/ADSP-2183x SHARC-FX cores and SC594 family devices with the ARM Cortex A5 core. All example reference code is in the attached zip file.
Import Algorithm Project
- Launch CCES and import the project with the correct device that the algorithm is being developed for. Please name target side algorithm project appropriately. A project can be created from scratch but it is highly recommended to import one of the projects provided and modify if necessary.
- After the project has been imported, a major component of the algorithm generation is making sure the final compiled application contains contiguous memory locations. In order to accomplish this, we need to verify the memory sections so that all valid areas in the application are within the same section. The screenshot below is an example for the SHARC-FX of placing all areas into the L2_ram section to maintain contiguous memory locations.
- If the application is not all in contiguous memory the following must take place:
- For SHARC-FX, select the system.svc file and navigate to the "Startup Code/LSP" tab and place any non default populated sections into L2 ram.
- For ARM projects, select the system.svc file and navigate to the "Heap and Stack" tab in order to customize the system heap to 16kB (suggested) to ensure the heap can fit into the algorithm project. Next, navigate to the "Linker Files" folder to change the target memory for code and data to L2. The L2 region has been the default for algorithm projects and matches up with the working area for all openOCD support. Lastly once the system.svc is saved the the linker scripts have been generated, find the "app.ld" file in the "system/linker" folder. Open in a text editor and similar to the SHARC-FX make sure that all non default populated sections into "MEM_L2_CACHED". The entries may need to be updated as well. Below is an example of a possible change...
/* Abort mode stack */ .stack_abort (NOLOAD) : { __stack_abort_end = . ; KEEP(*(.stack_abort)) __stack_abort_start = . ; } > MEM_L2_CACHED = 0
would be change to...
/* Abort mode stack */ .stack_abort : { __stack_abort_start = . ; KEEP(*(.stack_abort)) __stack_abort_end = . ; } > MEM_L2_CACHED
Lastly, navigate to the "app_heap_stack.c" file in the system/heap_stack folder and open in a text editor. To ensure that all information is stored in contiguous memory and the same program headers, the object entries under the definitions need to be updated accordingly...
/* The object used for the system heap. */ uint8_t __adi_heap_object[__ADI_SYSTEM_HEAP_SIZE * __ADI_SYSTEM_HEAP_SIZE_UNITS] __attribute__ ((aligned (__ADI_SYSTEM_HEAP_ALIGN))) __attribute__ ((section (".heap,\"aw\",%nobits //")));
would be change to...
/* The object used for the system heap. */ uint8_t __adi_heap_object[__ADI_SYSTEM_HEAP_SIZE * __ADI_SYSTEM_HEAP_SIZE_UNITS] __attribute__ ((aligned (__ADI_SYSTEM_HEAP_ALIGN))) __attribute__ ((section (".heap")));
This would be done for all corresponding entries in the "app_heap_stack.c" file.
To ensure the memory locations are all correct, generate and reference the *.map.xml to validate memory locations for all areas. Map files may not be generated by default. To enable map file generation go into the Project Properties → C/C++ Build → Settings and under
the Tool Settings tab select General under the CrossCore SHARC-FX C Linker (or linker specific to your project) section. Here there should be a checkbox to generate symbol map.
If any areas that may be accessed are not included in the memory organization, please add them to avoid any access violations.
- Within the system.svc, ensure that the SPI driver is included in the project generation. The "Pin Multiplexing" may differ depending on the SPI peripheral selection and setup. The Pin Multiplexing used for the standard 2183x_flash example is based on the ADSP-21835W-EV-SOM evaluation board. This board uses the SPI1 peripheral in single SPI mode using CLK, D2, D3, MISO, MOSI and SS selections. D2 and D3 might not be necessary in single SPI mode however. Based on the custom board configuration, this should be checked and updated accordingly. Below is a screenshot of the example Pin Multiplexing page within system.svc.
Update source files if necessary
Now that the project is generated and all areas of memory are set up, the algorithm development can be started. Update the main.c and main.h files with any additional information for the custom algorithm. The default main.c and main.h should work for standard ADI evaluation boards with their corresponding processors and external flash devices.
Essentials for the target side algorithm main.c
- The external flash device will differ depending on the user's setup. For example, the ADSP21835W-EV-SOM is connected via SPI to the IS25LP512M external flash device by default. This external flash contains a unique manufacturer and device id that are identified in main.c as shown below
/* Chip info (for IS25LP512M) */ #define MANUF_ID 0x9D #define DEVICE_ID 0x601A
- The IS25LP512M external flash also contains specific flash commands. The flash commands will depend on the external flash that is being used with the customer's setup and could vary. Below is the example code in main.c for the IS25LP512M flash commands. As the comment suggests, refer to the corresponding data sheet for the flash commands on a specific flash chip
IS25LP512M flash commands
/* Select SPI Flash Commands (from ISSI IS25LP512M, 512-MBit serial flash device data sheet) */
#define CMD_RESET_ENABLE 0x66u
#define CMD_RESET_DEVICE 0x99u
#define CMD_SR1_READ 0x05u
#define CMD_SR1_WRITE 0x01u
#define CMD_JEDEC_READ 0x9fu
#define CMD_SECTOR_ERASE 0x20u
#define CMD_BLOCK_ERASE 0xD8u
#define CMD_WRITE_ENABLE 0x06u
#define CMD_SINGLE_MODE_WRITE 0x02u
#define CMD_SINGLE_MODE_READ 0x03u
#define CMD_SINGLE_FAST_READ 0x13u
#define CMD_ENABLE_RESET 0x66u
#define CMD_RESET_DEVICE 0x99u
#define CMD_CHIP_ERASE 0xC7u
flash_commands_t
typedef enum {
CMD_NO_ACTION = 0,
CMD_READ = 1,
CMD_PROGRAM = 2,
CMD_LOCK = 3,
CMD_ERASE_ALL = 4,
CMD_ERASE_SECTOR = 5,
CMD_READID = 6,
} flash_commands_t;
- The flash_commands_t enum indicates the commands that will be available for execution. It is highly recommended not to change or add any commands as these directly relate to command numbers used in OpenOCD driver support.
flash_params
struct __attribute__((__packed__)) flash_params {
uint32_t offset; /* offset */
uint32_t len; /* Number of bytes */
uint32_t cmd; /* Command */
uint32_t status; /* Return status */
uint32_t ready; /* Handshake signal. Is buffer ready? */
uint32_t device_id; /* Device ID of flash */
uint32_t buf_addr; /* Address of data buffer. */
};
- The flash_params structure is where all of the input parameters from OpenOCD are saved. This should not have to be modified unless there are some additional parameters down the road might need to be included.
flashloader_init
void flashloader_init(struct flash_params *params, uint32_t *buf1) {
/* Initialize params buffers */
memset((void *)params, 0, 1 * sizeof(struct flash_params));
params[0].buf_addr = (uint32_t)buf1;
}
- The flashloader_init function sets up the parameter structure and buffer address in memory.
Memory attributes
/* Flashloader parameter structure. */
__attribute__ ((section(".buffer.g_cfg")))
volatile struct flash_params g_cfg[1];
/* Data buffer 1. */
__attribute__ ((section(".buffer.g_buf1")))
volatile uint8_t g_buf1[BUFFER_SIZE];
- This code portion is setting up the memory attributes for the flash parameters and data buffer. We are creating the
.buffer.g_cfg
and.buffer.g_buf1
sections that will need to be added to the memory map in the startup/LSP. There is room for double buffering down the road, we would just need to increase theflash_params
array and add.buffer.g_buf2
.
Algorithm Version
/* Set the algorithm version following yy/mm/dd format */
#pragma message("Warning: Ensure the algorithm version (algo_version) is updated if any changes are made to this file.")
uint32_t algo_version = 0x240815;
- The algorithm version is also an important aspect that should be included to be able to keep track and update any changes to the algorithm project in the future. Below is the code portion that should be included.
- The major portion of the flash algorithm template within
main.c
is the top level while loop containing theProcessCommand()
function. Here is where we wait for the flash command provided, along with all of the input parameters provided by the user when constructing their target-side flash algorithm driver in OpenOCD. In theProcessCommand()
function, add all of the flash command cases enabled inflash_commands_t
and their corresponding functions to execute the flash commands. Remember to save the result tostatus
attribute ofg_cfg
so that OpenOCD side can recognize success or failure.
Process Command Function
static ERROR_CODE ProcessCommand(void)
{
int result = 0;
uint32_t *pstatus;
uint8_t prog_buffer[g_cfg[0].len];
uint8_t read_buffer[g_cfg[0].len];
switch (g_cfg[0].cmd) {
case CMD_READ:
result = ReadData(g_cfg[0].offset, g_cfg[0].len, 1, (int *) read_buffer, 1);
if (result == NO_ERR)
memcpy((uint8_t *)g_cfg[0].buf_addr, read_buffer, g_cfg[0].len);
break;
case CMD_PROGRAM:
memcpy(prog_buffer, (uint8_t *)g_cfg[0].buf_addr, g_cfg[0].len);
result = WriteData(g_cfg[0].offset, g_cfg[0].len, 1, (int *)prog_buffer, 1);
break;
case CMD_LOCK:
/*
* Handle lock if applicable
* pstatus = &g_cfg[0].status;
*/
break;
case CMD_ERASE_ALL:
result = FlashChipErase();
break;
case CMD_ERASE_SECTOR:
result = FlashEraseSector(g_cfg[0].offset);
break;
case CMD_READID:
result = ReadDeviceID();
if (result == NO_ERR)
g_cfg[0].device_id = AFP_IdCode;
break;
default:
/* Command not listed */
result = UNKNOWN_COMMAND;
break;
}
return result;
}
- Please note, the usage of assembly breakpoints as shown below is essential during target-side algorithm development. This allows the OpenOCD target-side flash algorithm driver to recognize when the current flash command is done executing. The assembly syntax and command will vary depending architecture and instruction set that is used with the above example being for SHARC-FX.
Assembly Breakpoint Example
// Halt to read status and detect error during algorithm initialization asm("BREAK.N 0;")
- Once the development is complete for the target-side algorithm, build and retrieve the resultant binary file that should be located in the corresponding build configuration folder (typically "Debug" or "Release"). This binary file can be used directly with the -driver switch in cldp
Debug Use
- Like any other application, the algorithm project created can be debugged and stepped through to ensure that the custom algorithm project is behaving as intended. To do so, comment out the
#define ASM_HALT
in themain.h
file to make sure the assembly breakpoints are not hit. - From there, the user can start a normal debug session to run until main and proceed to the main while loop looking for
g_cfg[0].ready == BUFFER_EMPTY
. This is where the user can manipulate theg_cfg[0]
structure variable in a watch list to input any necessary parameters that would be tested. For example, modifying theg.ready
to 0xFFFFFFFF, theg.cmd
to 0x4 would allow the start of a mass erase command to execute. Stepping through or running to make sure that theg.status
attribute of the structure remains 0x0 for success. This process can be handled for any commands that wish to be tested with the addition of any necessary parameters - Please note that it is essential to uncomment
#define ASM_HALT
before rebuilding the algorithm binary. This is necessary for running the algorithm successfully outside of a debug environment.
Board and algorithm .cfg
file hierarchy
- The current process utilizes three files to accurately set up the flash banks for each memory supported; the board file, the specific memory file and the algo finder file.
Board File
- The top level of the hierarchy is the board file where generally any information regarding board setups are present. Please note that board files are separate from target files. Below is an updated snippet of
adsp21835w_ev_som.cfg.
The flash bank parameters for each memory region supported are filled in via the specific memory regions.cfg
file. Definitions for enabling different memory regions has been included, however, it is recommended not to disable memory regions for standard board files.
adsp21835w_ev_som.cfg snippet
if { $ENABLE_SPI_FLASH == 1 } { # Find and set up SPI flash algorithm parameters source [find board/flash_algorithms/issi25lp512m.cfg] set SPI_FLASH_ALGO_FILENAME 2183x_flash.inc set SPI_FLASH_PARAMETER_FILENAME 2183x_flash_params.inc set_algo_paths $SPI_FLASH_ALGO_FILENAME $SPI_FLASH_PARAMETER_FILENAME flash bank $_CHIPNAME.spi adsp2183x $_FLASH_BASE $_FLASH_SIZE 0 0 $_TARGETNAME_SFX $_FLASH_SECTOR_SIZE $ALGO_PATH $PARAMETER_PATH }
- The flash bank name ("$_CHIPNAME.spi" in this case) is extremely important especially when planning to use support with CCES. The names are what allow CCES to recognize how and what flash banks are available to compare to the xml for a specific processor selected.
- The location of all board files will reside in <CCES_PATH>\3.0.2\ARM\openocd\share\scripts\board
Specific Memory File
- The second level of the hierarchy is the specific memory file. This could include a different number of memory types such as SPI, xSPI hyperflash, xSPI NOR flash, etc. The main purpose of this file is to create the algorithm file and algorithm parameter file variables for flash bank usage. Below is an example of the
issi25lp512m.cfg
that supports SPI flash for the ADSP-SC83x SOM board. These files can be changed, updated, or created based on the specific.inc
algorithm and params file included.
ISSI25LP512M.cfg
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2024 Analog Devices, Inc.
# Set flash parameters
set _FLASH_BASE 0x0
set _FLASH_SIZE 0x4000000
set _FLASH_SECTOR_SIZE 0x10000
proc set_algo_paths { inc_file param_file } {
global ALGO_PATH PARAMETER_PATH
source [find board/flash_algorithms/algoFileFinder.cfg]
# Find and set the ALGO_PATH
set ALGO_PATH [findAndSetFile $scriptDirectory $inc_file]
if { [string length $ALGO_PATH] <= 0} {
set ALGO_PATH $inc_file
echo "Could not find $inc_file in [file dirname [info script]]"
}
# Find and set PARAMETER_PATH
set PARAMETER_PATH [findAndSetFile $scriptDirectory $param_file]
if { [string length $PARAMETER_PATH] <= 0} {
set PARAMETER_PATH $param_file
echo "Could not find $param_file in [file dirname [info script]]"
}
}
- The location of all specific memory files will reside in "<CCES_PATH>\3.0.2\ARM\openocd\share\openocd\board\flash_algorithms"
Algo Finder File
- This helper file is a simple routine to search for the specified files in order to successfully set up variables for the flash bank parameters. This file should not be modified and is simply a helper file for shared functionality used by specific memory files in the second layer.
algoFileFinder.cfg
# Copyright (c) 2024 Analog Devices, Inc. All Rights Reserved.
# This software is proprietary to Analog Devices, Inc. and its licensors.
# Define a procedure to find and set the file path
proc findAndSetFile {directory pattern} {
set files [glob -nocomplain -directory $directory $pattern]
if {[llength $files] > 0} {
return [lindex $files 0]
} else {
return ""
}
}
# Get the directory of the current script
set scriptDirectory [file dirname [info script]]
- Please note, this process slightly differs for ARM and other non SHARC-FX architectures, primarily with project generation and handling of the linker scripts with memory allocation. For any questions, please contact Analog Devices support team to provide additional information and references.
- The location of the algo finder file will reside in "<CCES_PATH>\3.0.2\ARM\openocd\share\openocd\board\flash_algorithms"
Cldp usage
- The included command line switches are also necessary when running cldp:
- -board customBoardFile.cfg
- -driver <PATH_TO_FLASH_DRIVER> (flash driver is what was created earlier in this document)
- More information on the above additional switches can be found in the CCES 3.0.2 Release Notes.
- Here are some command line examples for an ADSP-SC83x/ADSP-2183x SHARC-FX cores and SC594 ARM, respectively...
- cldp.exe -proc ADSP-21835 -emu 2000 -driver "<PATH_TO_FLASH_DRIVER>" -board customBoardFile.cfg -cmd prog -file "program.ldr"
- cldp.exe -proc ADSP-SC594 -emu 2000 -core 0 -driver "<PATH_TO_FLASH_DRIVER>" -board customBoardFile.cfg -cmd prog -file "program.ldr"