Debugging in RAM, const strings in flash to save RAM is what i want…
i have remade James Lynch link script so all my (extensive!) const strings are linked to 0x100000. I can start the debugger in RAM but the program cannot find the strings, as i do not know how to load the part of the binary file containing the const strings into flash. I am using modified James Lynch all through, adapting his RAM linking version for debug. Can anybody give me a hint what to do, please?? Specifically how to load a PART of the binary file into flash! Debugging in RAM is very much an improvement compared to do it in flash. And thanks James Lynch for such a GOOD tutorial!
I haven’t tried this myself, but I think you can do something like that by specifying an extra section in your linker script, for example:
.strings 0x100000:
{
*(.rodata)
(.rodata)
}
Place the .strings section before the .text section. Pay careful attention to the map file to see how the addresses work out.
Then try to upload the resulting hexfile to flash using the Philips LPC2000 flash utility.
…my problem is how to load the part of the bin file (the part w address 0x100000) into flash, the rest into RAM! Then run in RAM w the strings in flash! Do you have any idéa how to do that?? Thank you for trying!
Nils
Hi Nils and thanks for your kind compliment about my tutorial.
I agree with Bertrik - link the rodata sections into Flash at 0x100000. You will also have to make sure that the makefile uses objcopy.exe to make a binary file.
Now you have two downloads to do. First, you have to program the Flash with the rodata sections using either OpenOCD or SAM-BA. Then you can run the debugger and let it download the rest of the application into RAM.
The idea, while technically feasible, seems to defeat the purpose of RAM debugging - rapidly compiling and downloading from within the debugger. You will have to exit the debugger at each re-build to Flash program using your idea. Considering the effort to set this up and then use it, it might be better to invest in a AT91 board with more RAM.
Cheers,
Jim Lynch
…but how do i flash with only part of the code, and to a particular address? Using Samba is a method i haven’t considered, thankyou for that idea! That might answer my question above.
My idea was based on the assumption that the const string parts were NOT going to be changed, at least very seldom. Do i need to reload into flash EVERY time if i do not change the const string code???
And thankyou for taking the time to answer, i suppose you are now working on the new release of your tutorial?
Might it not be an interest in beeing able to debug PART of the code in RAM, while the rest of the code are loaded and are executed in flash? Usually (at least myself) one is debugging one module at a time, only using part of the code at any one time. But to attempt to try writing a makefile enabeling this is way above my competence, unfortunately. (Debugging in RAM is SO much easier…)
James Lych tips to use Samba loading the strings works like a dream. Anyone interested in the makefile, linkfile etc for this??
# ***************************************************************
# * Makefile for Atmel AT91SAM7X256 - flash execution *
# * *
# * *
# * James P Lynch September 3, 2006 *
# sligthly changed by NSn 200700308 *
# ***************************************************************
NAME = TryOneMoreTime
# variables
##BINDIRS = E:/Program/yagarto/bin/
CC = arm-elf-gcc
LD = arm-elf-ld -v
AR = arm-elf-ar
AS = arm-elf-as
CP = arm-elf-objcopy
OD = arm-elf-objdump
#EXTRA_LIBDIRS = E:/Program/yagarto/arm-elf/lib/
EXTRA_LIBDIRS = E:/Program/yagarto/lib/gcc/arm-elf/4.1.1/
CFLAGS = -I./ -c -fno-common -O0 -g
AFLAGS = -ahls -mapcs-32 -o crt.o
LFLAGS = -Map main.map -Tlinkconfig_RAM.cmd
CPFLAGS = --output-target=binary
ODFLAGS = -x --syms
OBJECTS = crt.o main.o timerisr.o timersetup.o isrsupport.o lowlevelinit.o TWI_ctrl.o const_strings.o\
display.o menu.o buttons.o SPI_ctrl.o eepromhandler.o VoxControl.o ISD4002.o serialARM.o
# make target called by Eclipse (Project -> Clean ...)
clean:
-rm $(OBJECTS) crt.lst main.lst main.out main.bin main.hex main.map main.dmp
#make target called by Eclipse (Project -> Build Project)
#all: begin gccversion sizebefore build sizeafter finished end
all: main.out
@ echo "...copying"
$(CP) $(CPFLAGS) main.out main.bin
$(OD) $(ODFLAGS) main.out > main.dmp
$(CP) $(CPFLAGS) consts.out consts.bin
$(OD) $(ODFLAGS) consts.out > consts.dmp
main.out: $(OBJECTS) ./linkconfig_RAM.cmd
@ echo "..linking"
# $(LD) $(LFLAGS) -o main.out $(OBJECTS) -L%,$(EXTRA_LIBDIRS) -lgcc -lc
$(LD) $(LFLAGS) -o main.out $(OBJECTS) -L%,$(EXTRA_LIBDIRS)libgcc.a -lc
$(LD) -Map consts.map -Tlinkconfig_RAM.cmd -o consts.out const_strings.o -L%,$(EXTRA_LIBDIRS)libgcc.a -lc
crt.o: crt.s
@ echo ".assembling crt.s"
$(AS) $(AFLAGS) crt.s > crt.lst
main.o: main.c AT91SAM7X256.h board.h
@ echo ".compiling main.c"
$(CC) $(CFLAGS) main.c
timerisr.o: timerisr.c AT91SAM7X256.h board.h
@ echo ".compiling timerisr.c"
$(CC) $(CFLAGS) timerisr.c
const_strings.o: const_strings.c AT91SAM7X256.h board.h
@ echo ".compiling const_strings.c"
$(CC) $(CFLAGS) const_strings.c
lowlevelinit.o: lowlevelinit.c AT91SAM7X256.h board.h
@ echo ".compiling lowlevelinit.c"
$(CC) $(CFLAGS) lowlevelinit.c
timersetup.o: timersetup.c AT91SAM7X256.h board.h
@ echo ".compiling timersetup.c"
$(CC) $(CFLAGS) timersetup.c
isrsupport.o: isrsupport.c
@ echo ".compiling isrsupport.c"
$(CC) $(CFLAGS) isrsupport.c
display.o: display.c AT91SAM7X256.h board.h
@ echo ".compiling display.c"
$(CC) $(CFLAGS) display.c
menu.o: menu.c AT91SAM7X256.h board.h
@ echo ".compiling menu.c"
$(CC) $(CFLAGS) menu.c
buttons.o: buttons.c AT91SAM7X256.h board.h
@ echo ".compiling buttons.c"
$(CC) $(CFLAGS) buttons.c
eepromhandler.o: eepromhandler.c AT91SAM7X256.h board.h
@ echo ".compiling eepromhandler.c"
$(CC) $(CFLAGS) eepromhandler.c
VoxControl.o: VoxControl.c AT91SAM7X256.h board.h
@ echo ".compiling VoxControl.c"
$(CC) $(CFLAGS) VoxControl.c
ISD4002.o: ISD4002.c AT91SAM7X256.h board.h
@ echo ".compiling ISD4002.c"
$(CC) $(CFLAGS) ISD4002.c
SPI_ctrl.o: SPI_ctrl.c AT91SAM7X256.h board.h SPI_ctrl.h
@ echo ".compiling SPI_ctrl.c"
$(CC) $(CFLAGS) SPI_ctrl.c
TWI_ctrl.o: TWI_ctrl.c AT91SAM7X256.h board.h TWI_ctrl.h
@ echo ".compiling TWI_ctrl.c"
$(CC) $(CFLAGS) TWI_ctrl.c
serialARM.o: serialARM.c AT91SAM7X256.h board.h serialARM.h
@ echo ".compiling SPI_ctrl.c"
$(CC) $(CFLAGS) serialARM.c
# **********************************************************************************************
# FLASH PROGRAMMING (using OpenOCD and Amontec JTAGKey)
#
# Alternate make target for flash programming only
#
# You must create a special Eclipse make target (program) to run this part of the makefile
# (Project -> Create Make Target... then set the Target Name and Make Target to "program")
#
# OpenOCD is run in "batch" mode with a special configuration file and a script file containing
# the flash commands. When flash programming completes, OpenOCD terminates.
#
# Note that the make file below creates the script file of flash commands "on the fly"
#
# Programmers: Martin Thomas, Joseph M Dupre, James P Lynch
# **********************************************************************************************
# specify output filename here (must be *.bin file)
TARGET = consts.bin
# specify the directory where openocd executable resides (openocd-ftd2xx.exe or openocd-pp.exe)
OPENOCD_DIR = E:/Program/openocd-2007re128/bin/
# specify OpenOCD executable (pp is for the wiggler, ftd2xx is for the USB debugger)
#OPENOCD = $(OPENOCD_DIR)openocd-pp.exe
OPENOCD = $(OPENOCD_DIR)openocd-ftd2xx.exe
# specify OpenOCD configuration file (pick the one for your device)
#OPENOCD_CFG = $(OPENOCD_DIR)AT91SAM7X256-wiggler-flash-program.cfg
#OPENOCD_CFG = $(OPENOCD_DIR)AT91SAM7X256-jtagkey-flash-program.cfg
OPENOCD_CFG = $(OPENOCD_DIR)at91sam7X256-armusbocd-flash-program.cfg
# specify the name and folder of the flash programming script file
OPENOCD_SCRIPT = c:\TEMP\temp.ocd
# program the AT91SAM7X256 internal flash memory
program: consts.bin
-rm $(OPENOCD_SCRIPT)
@echo "Preparing OpenOCD script..."
@cmd /c 'echo wait_halt > $(OPENOCD_SCRIPT)'
@cmd /c 'echo armv4_5 core_state arm >> $(OPENOCD_SCRIPT)'
@cmd /c 'echo flash write 0 $(TARGET) 0x0 >> $(OPENOCD_SCRIPT)'
@cmd /c 'echo mww 0xfffffd08 0xa5000401 >> $(OPENOCD_SCRIPT)'
@cmd /c 'echo reset >> $(OPENOCD_SCRIPT)'
@cmd /c 'echo shutdown >> $(OPENOCD_SCRIPT)'
@echo "Flash Programming with OpenOCD..."
$(OPENOCD) -f $(OPENOCD_CFG)
@echo "Flash Programming Finished."
/* ******************************************************************************************************
demo_at91sam7_p64_blink_flash.cmd LINKER SCRIPT (for Olimex AT91SAM7-P64-A board)
The Linker Script defines how the code and data emitted by the GNU C compiler and assembler are
to be loaded into memory (code goes into FLASH, variables go into RAM).
Any symbols defined in the Linker Script are automatically global and available to the rest of the
program.
To force the linker to use this LINKER SCRIPT, just add the -T demo_at91sam7_p64_blink_flash.cmd
directive to the linker flags in the makefile. For example,
LFLAGS = -Map main.map -nostartfiles -T demo_at91sam7_p64_blink_flash.cmd
The order that the object files are listed in the makefile determines what .text section is
placed first.
For example: $(LD) $(LFLAGS) -o main.out crt.o main.o lowlevelinit.o
crt.o is first in the list of objects, so it will be placed at address 0x00000000
The top of the stack (_stack_end) is (last_byte_of_ram +1) - 4
Therefore: _stack_end = (0x00020FFFF + 1) - 4 = 0x000210000 - 4 = 0x0020FFFC
Note that this symbol (_stack_end) is automatically GLOBAL and will be used by the crt.s
startup assembler routine to specify all stacks for the various ARM modes
MEMORY MAP
| |
.-------->|---------------------------------|0x00204000
. | |0x0020FFFC <---------- _stack_end
. | UDF Stack 16 bytes |
. | |
. |---------------------------------|0x0020FFEC
. | |
. | ABT Stack 16 bytes |
. | |
. |---------------------------------|0x0020FFDC
. | |
. | |
. | FIQ Stack 128 bytes |
. | |
. | |
RAM |---------------------------------|0x0020FF5C
. | |
. | |
. | IRQ Stack 128 bytes |
. | |
. | |
. |---------------------------------|0x0020FEDC
. | |
. | SVC Stack 16 bytes |
. | |
. |---------------------------------|0x0020FECC
. | |
. | stack area for user program |
. | |
. | |
. | |
. | free ram |
. | |
. |.................................|0x00200054 <---------- _bss_end
. | |
. | .bss uninitialized variables |
. |.................................|0x0020003C <---------- _bss_start, _edata
. | |
. | .data initialized variables |
. | |
.-------->|_________________________________|0x00200000
.-------->|---------------------------------|0x00010000
. | |
. | |
. | free flash |
. | |
. | |
. |.................................|0x000008E4
. | |
. | .data initialized variables |
. | |
. |---------------------------------|0x000008A8 <----------- _etext
. | |
. | C code |
FLASH | |
. | |
. |---------------------------------|0x0000015C main()
. | |
. | Startup Code (crt.s) |
. | (assembler) |
. | |
. |---------------------------------|0x00000020
. | |
. | Interrupt Vector Table |
. | 32 bytes |
.-------->|---------------------------------|0x00000000 _vec_reset
Author: James P. Lynch
****************************************************************************************************** */
/*identify the Entry Point (_vec_reset is defined in file crt.s) */
ENTRY(_vec_reset)
/* specify the AT91SAM7S256X256 */
MEMORY
{
flash : ORIGIN = 0x100000, LENGTH = 256K /* FLASH EPROM */
ram : ORIGIN = 0, LENGTH = 64K /* static RAM area */
}
/* define a global symbol _stack_end (see analysis in annotation above) */
_stack_end = 0x00FFFC;
/* now define the output sections */
SECTIONS
{
. = 0; /* set location counter to address zero */
.text : /* collect all sections that should go into FLASH after startup */
{
*(.text) /* all .text sections (code) */
/* *(.rodata) all .rodata sections (constants, strings, etc.) */
/* *(.rodata*) all .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* all .glue_7 sections (no idea what these are) */
*(.glue_7t) /* all .glue_7t sections (no idea what these are) */
_etext = .; /* define a global symbol _etext just after the last code byte */
} >ram /* put all the above into RAM!!!!!!! */
.strings : /* collect all sections that should go into FLASH after startup */
{
*(.rodata) /* all .rodata sections (constants, strings, etc.) */
*(.rodata*) /* all .rodata* sections (constants, strings, etc.) */
_stext = .; /* define a global symbol _stext just after the last code byte */
} >flash /* put all the above into FLASH!!!!!!! */
.data : /* collect all initialized .data sections that go into RAM */
{
_data = .; /* create a global symbol marking the start of the .data section */
*(.data) /* all .data sections */
_edata = .; /* define a global symbol marking the end of the .data section */
} >ram /* put all the above into RAM (but load the LMA initializer copy into FLASH) */
.bss : /* collect all uninitialized .bss sections that go into RAM */
{
_bss_start = .; /* define a global symbol marking the start of the .bss section */
*(.bss) /* all .bss sections */
} >ram /* put all the above in RAM (it will be cleared in the startup code */
. = ALIGN(4); /* advance location counter to the next 32-bit boundary */
_bss_end = . ; /* define a global symbol marking the end of the .bss section */
}
_end = .; /* define a global symbol marking the end of application RAM */