Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12603 Discussions

Nios Debugger does not load all memory sections

Altera_Forum
Honored Contributor II
1,429 Views

I have three onchip memories in my design. They occupy separate non-contiguous address space. I use the __attribute__ tag to place variables or functions into the other sections. The problem is the Nios debugger will only load code and data into the first memory section. It never loads the other two memory sections. 

 

I have tried placing my main() function in the latter memories, and the debugger won't load it. I have tried setting up the syslib so that the .text or .rwdata memory is set to use the later sections and the debugger won't load them. I have verified this by using the elf objdump tool to make sure the linker was linking these sections into the elf file and that it was creating a proper program header. I also look at the debugger load window, which shows only the first memory address space ever getting loaded. 

 

I have tried looking through the help and reading a few app notes like the Tightly Coupled Memory Tutorial that I thought would give me a clue on the matter, but no luck. 

 

Thanks for any information, 

-todd-
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
473 Views

So your code can't run correctly?

0 Kudos
Altera_Forum
Honored Contributor II
473 Views

today, 

 

the function attributes must be used in the prototype only, not in the function declaration itself: 

<div class='quotetop'>QUOTE </div> 

--- Quote Start ---  

extern void foobar (void) __attribute__ ((section ("bar")));[/b] 

--- Quote End ---  

 

Did you consider this? 

Mike
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

 

--- Quote Start ---  

originally posted by mir@Sep 10 2006, 02:19 AM 

today, 

 

the function attributes must be used in the prototype only, not in the function declaration itself: 

extern void foobar (void) __attribute__ ((section ("bar"))); 

did you consider this? 

mike 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=18187)</div> 

--- Quote End ---  

 

 

Yes, that is how I set it up. The compile will fail otherwise. Here&#39;s what my map looks like 

 

onchip_memory_main @ 0x10000 onchip_memory_int_code_s2 @ 0x20000 onchip_memory_int_data_s2 @ 0x40000 

 

There is an appendage of "_s2" because these blocks are shared with another processor and therefore use the second port of a dual-port RAM. And here&#39;s how I defined my variables and functions. 

 

volatile int value_in __attribute__ ((section(".onchip_memory_int_data_s2"))); void test() __attribute__ ((section(".onchip_memory_int_code_s2"))); void test() {     puts("got here...\n\n"); }; 

 

If I check the hex files for that memory, the last two are full of zeros as well. 

 

The assembly code is correctly assembled. When I try to execute the test function, it just lands in a patch of zeros @ 20000. My code in main() is correctly manipulating variables declared @ 40000. 

 

What is mind-boggling to me is that the ELF file looks completely legit. Here&#39;s a dump. 

 

Program Header:    LOAD off    0x000000b4 vaddr 0x00010000 paddr 0x00010000 align 2**0         filesz 0x00001980 memsz 0x00001980 flags r-x    LOAD off    0x00001a34 vaddr 0x00011980 paddr 0x00011980 align 2**0         filesz 0x0000055c memsz 0x00000670 flags rw-    LOAD off    0x00001f90 vaddr 0x00020000 paddr 0x00011ff0 align 2**0         filesz 0x00000048 memsz 0x00000048 flags r-x    LOAD off    0x00001fd8 vaddr 0x00040000 paddr 0x00012038 align 2**0         filesz 0x00000008 memsz 0x00000008 flags rw- Sections: Idx Name          Size      VMA       LMA       File off  Algn  6 .onchip_memory_main 00000000  00011ff0  00011ff0  00001fe0  2**0                  CONTENTS  7 .onchip_memory_int_code_s1 00000000  00020000  00020000  00001fe0  2**0                  CONTENTS  8 .onchip_memory_int_code_s2 00000048  00020000  00011ff0  00001f90  2**2                  CONTENTS, ALLOC, LOAD, READONLY, CODE  9 .onchip_memory_int_data_s1 00000000  00040000  00040000  00001fe0  2**0                  CONTENTS 10 .onchip_memory_int_data_s2 00000008  00040000  00012038  00001fd8  2**2                  CONTENTS, ALLOC, LOAD, DATA 

 

As far as I can tell, those load commands at the beginning are legit, and for some reason, they are completely ignored by the debugger. The debugger map looks fine as well. The only possible clue is that the "_s1" section is showing up here. s1 is connected to the other processor, so I don&#39;t know why that is showing. 

 

Here&#39;s what the debugger is actually doing - only loading the first RAM device. 

 

Using cable "USB-Blaster ", device 1, instance 0x01 Processor is already paused Reading System ID at address 0x00002280: verified Initializing CPU cache (if present) OK Downloading 00010000 ( 0%) Downloading 00011FF0 (98%) Downloaded 8KB in 0.1s         Verifying 00010000 ( 0%) Verifying 00011FF0 (98%) Verified OK                         Leaving target processor paused 

 

I think the next thing I might try is to delete the second processor and remove the dual-ports from the RAM and see if that clears things up. I don&#39;t know where to go from there since I think I really need to use the dual-port for my dual-proc design for the best performance.
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

Okay, I just went and deleted the second processor, and removed all the dual-port stuff from my RAM blocks. I left the two extra RAM blocks at the same non-contiguous addresses mentioned above. I get the exact same behavior as above http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/mad.gif - the extra blocks are never populated by the debugger even though these blocks show up in all of the generated.* script files, and are clearly properly embedded in the ELF objects. 

 

generated.x: 

   /* Define symbols for each memory base-address */ __alt_mem_onchip_memory_main = 0x00010000; __alt_mem_onchip_memory_int_code = 0x00020000; __alt_mem_onchip_memory_int_data = 0x00040000; 

 

generated.gdb: 

# onchip_memory_main mem 0x00010000 0x00010000+20480 cache # onchip_memory_int_code mem 0x00020000 0x00020000+4096 cache # onchip_memory_int_data mem 0x00040000 0x00040000+1024 cache 

 

Even the .hex files for these last two sections are empty, which means that elf2hex is busted as well since I can tell from the elfobj dump that the data should be there 

$(QUARTUS_PROJECT_DIR)/onchip_memory_main.hex: $(ELF)     @echo Post-processing to create $(notdir $@)     elf2hex $(ELF) 0x00010000 0x14FFF --width=32 $(QUARTUS_PROJECT_DIR)/onchip_memory_main.hex --create-lanes=0 $(QUARTUS_PROJECT_DIR)/onchip_memory_int_code.hex: $(ELF)     @echo Post-processing to create $(notdir $@)     elf2hex $(ELF) 0x00020000 0x20FFF --width=32 $(QUARTUS_PROJECT_DIR)/onchip_memory_int_code.hex --create-lanes=0 $(QUARTUS_PROJECT_DIR)/onchip_memory_int_data.hex: $(ELF)     @echo Post-processing to create $(notdir $@)     elf2hex $(ELF) 0x00040000 0x403FF --width=32 $(QUARTUS_PROJECT_DIR)/onchip_memory_int_data.hex --create-lanes=0
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

Ugh, I think I just figured it out. Looking over my replies above, I noticed something really strange about the elfobj dump. Note that for the first couple of sections in the program load header, the thing called vaddr matches the thing called paddr. However, the last two sections don&#39;t match. Below again are the relevant sections, clipped this time. 

 

   LOAD off    0x000000b4 vaddr 0x00010000 paddr 0x00010000    LOAD off    0x00001a34 vaddr 0x00011980 paddr 0x00011980    LOAD off    0x00001f84 vaddr 0x00020000 paddr 0x00011fe4    LOAD off    0x00001fcc vaddr 0x00040000 paddr 0x0001202c 

 

What&#39;s happening here is that the linker is merely jamming all the code together into the first block, even the stuff that belongs in the second and third blocks. What causes this to happen? Look at this bs from "generated.x" (you might have to maximize your browser to make sense of it) 

 

   .onchip_memory_int_code : AT (LOADADDR (.onchip_memory_main) + SIZEOF (.onchip_memory_main))    {        PROVIDE (_alt_partition_onchip_memory_int_code_start = ABSOLUTE(.));        *(.onchip_memory_int_code .onchip_memory_int_code.*)        . = ALIGN(32 / 8);        PROVIDE (_alt_partition_onchip_memory_int_code_end = ABSOLUTE(.));    } > onchip_memory_int_code    PROVIDE (_alt_partition_onchip_memory_int_code_load_addr = LOADADDR(.onchip_memory_int_code));    .onchip_memory_int_data : AT (LOADADDR (.onchip_memory_int_code) + SIZEOF (.onchip_memory_int_code))    {        PROVIDE (_alt_partition_onchip_memory_int_data_start = ABSOLUTE(.));        *(.onchip_memory_int_data .onchip_memory_int_data.*)        . = ALIGN(32 / 8);        PROVIDE (_alt_partition_onchip_memory_int_data_end = ABSOLUTE(.));    } > onchip_memory_int_data    PROVIDE (_alt_partition_onchip_memory_int_data_load_addr = LOADADDR(.onchip_memory_int_data)); 

 

You can see from the first line of each of these sections that the linker is merely tacking the code intended for these next two RAM blocks onto the main RAM block. My suspicion here is that it is set up for storage into a Flash EPROM. 

 

So short of writing my own make file, where is the magic switch that tells the system builder and compiler not to cram all my stuff together? 

 

Bonus question - why does the debugger not notice the vaddr stuff and load my code into RAM properly for debugging?
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

Well, I&#39;m getting in the habbit of answering my own questions. At least some of them. I happened to stumble across the HAL API function named alt_load_section(). This is the function you are supposed to use if you are booting your project from some sort of ROM. You see, many of the sections you place using the system libary setup panel are automagically set up by the runtime library boot function. But if you specify special sections using the __attribute__ descriptor, you will have to go fetch and place those yourself. Lucky for us, they provide a nifty macro. So all I had to do was add the following lines to the top of my main() function. 

 

    ALT_LOAD_SECTION_BY_NAME(onchip_memory_int_code);     ALT_LOAD_SECTION_BY_NAME(onchip_memory_int_data); 

 

Now all my sections are loaded properly and it all works as it is supposed to. http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/cool.gif Unfortunately for my case, due to the way I will be downloading dyamic code to the Nios, I won&#39;t be able to convince the IDE to stop jamming all my sections together into one memory block, short of writing my own makefile. That is, unless one of you guys knows the magic. http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/tongue.gif
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

Hi, 

 

I have read all the posts, and I thinks it&#39;s a great experience in NiosII and worth of learning. 

It will be very appreciable if you sum it up in a more readable way. 

 

Thanks in advance, 

David
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

 

--- Quote Start ---  

originally posted by david_cai@Sep 10 2006, 06:18 PM 

it will be very appreciable if you sum it up in a more readable way. 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=18199) 

--- quote end ---  

 

--- Quote End ---  

 

 

see here (http://forum.niosforum.com/forum/index.php?showtopic=4757)
0 Kudos
Altera_Forum
Honored Contributor II
473 Views

Hi, 

 

Could you tell me which version of IDE are you using? 

 

I have tested your code in NiosII IDE6.0 and everything is OK. 

 

FYI. 

David
0 Kudos
Reply