"Imprecise external abort" when performing ioread32 on AXI DMA - c

I am using the openwifi project and I am trying to extract data out of the FPGA (Zedboard) to the ZYNQ. Therefore, I added a AXI DMA in scatter gather mode to my block diagram with the following configuration:
The addresses are:
As far as I know, everything should be correctly configured and connected in Vivado. Because of the additional AXI DMA, I had to add it to the linux device tree:
dma#80420000 {
#dma-cells = <0x01>;
clock-names = "s_axi_lite_aclk\0m_axi_sg_aclk\0m_axi_mm2s_aclk\0m_axi_s2mm_aclk";
clocks = <0x02 0x11 0x02 0x11 0x02 0x11 0x02 0x11>;
compatible = "xlnx,axi-dma-1.00.a";
interrupt-names = "mm2s_introut\0s2mm_introut";
interrupt-parent = <0x01>;
interrupts = <0x00 0x27 0x04 0x00 0x28 0x04>;
reg = <0x80420000 0x10000>;
xlnx,addrwidth = <0x20>;
xlnx,include-sg ;
xlnx,sg-length-width = <0x0e>;
phandle = <0x0c>;
dma-channel#80420000 {
compatible = "xlnx,axi-dma-mm2s-channel";
dma-channels = <0x1>;
interrupts = <0x00 0x44 0x04>;
xlnx,datawidth = <0x40>;
xlnx,device-id = <0x2>;
};
dma-channel#80420030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <0x1>;
interrupts = <0x00 0x45 0x04>;
xlnx,datawidth = <0x40>;
xlnx,device-id = <0x2>;
};
};
2 AXI DMAs were already configured by openwifi (dma#80410000 & dma#80400000). The complete modified device-tree can be found here. The original tree by openwifi is here (Due to the length I can't post it on SO).
My problem is that when I am trying to load the xilinx_dma driver into linux, I get the following error:
Unhandled fault: imprecise external abort (0x406) at 0xb6f38000
pgd = df614000
[b6f38000] *pgd=1627f831, *pte=1ece359f, *ppte=1ece3e7e
Internal error: : 406 [#1] PREEMPT SMP ARM
Modules linked in: xilinx_dma(+) ad9361_drv mac80211 cfg80211 ipv6
CPU: 0 PID: 2093 Comm: insmod Not tainted 4.14.0-gb6e379910a11-dirty #2
Hardware name: Xilinx Zynq Platform
task: df7ff280 task.stack: d622c000
PC is at xilinx_dma_chan_reset+0x58/0x27c [xilinx_dma]
LR is at xilinx_dma_chan_reset+0x44/0x27c [xilinx_dma]
pc : [<bf17d600>] lr : [<bf17d5ec>] psr: 60060013
sp : d622dce0 ip : 00000000 fp : 00000001
r10: dfbb5094 r9 : 00000000 r8 : 00000000
r7 : 00000000 r6 : 00000000 r5 : 00000000 r4 : df493410
r3 : dec0de1c r2 : 00000000 r1 : dfb89374 r0 : 00000058
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
Control: 18c5387d Table: 1f61404a DAC: 00000051
Process insmod (pid: 2093, stack limit = 0xd622c210)
Stack: (0xd622dce0 to 0xd622e000)
dce0: df493410 d6023010 00000000 00000000 00000000 00000000 dfbb5094 bf17dff4
dd00: bf180dc0 df493410 bf180ca0 bf180cb4 014080c0 d6023018 d6023020 dfbb4d78
dd20: df572610 00000000 bf180c70 bf180c80 df576a50 cf73edc0 00000020 0000000e
dd40: 00000001 00000040 00000001 df572610 ffffffed bf182014 fffffdfb 00000000
dd60: 00000000 00000007 00000028 c03b2a20 df572610 c0c79fa8 c0c79fac bf182014
dd80: 00000000 c03b1240 df572610 bf182014 df572644 00000000 cf73d924 00000001
dda0: 00000000 c03b1394 00000000 bf182014 c03b12f0 c03af7a0 df491f58 df570ab4
ddc0: bf182014 d6ae7000 c0c1f458 c03b07a0 bf1810f8 00000000 bf185000 bf182014
dde0: 00000000 bf185000 d4b80600 c03b1c3c ffffe000 00000000 bf185000 c0101a20
de00: 00000000 00000000 c0c54234 c0c54220 c0994394 00000000 014000c0 e30a4000
de20: dfda5600 c0c54380 00000000 0000f730 c0c54380 c01af084 00000001 a0030013
de40: d4b80600 e3057000 bf1820c0 00000001 cf73d900 d4b80600 cf73d924 c018895c
de60: bf1820c0 cf73d924 00000001 d622df50 00000001 cf73d900 bf1820c0 c01875f0
de80: bf1820cc 00007fff bf1820c0 c0184b7c bf182108 00000000 bf1821c0 c0805304
dea0: bf1821f0 c0a0d880 bf18227c bf1821d4 c0998804 00000000 bf181104 bf000001
dec0: 0004bad4 00000000 d622df48 bf180024 00000001 00000000 00000000 00000000
dee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
df00: 00000000 00000000 7fffffff 00000000 00000003 0046e398 0000017b c0107b24
df20: d622c000 00000000 00000000 c0188008 7fffffff 00000000 00000003 00000000
df40: 00000000 e3057000 0004bad4 00000000 e305c1b7 e3057000 0004bad4 e30a223c
df60: e30a2020 e308d180 00008000 00008310 00000000 00000000 00000000 00002bb0
df80: 00000034 00000035 00000020 0000001b 00000018 00000000 be8646c4 be864844
dfa0: 45194a00 c0107960 be8646c4 be864844 00000003 0046e398 00000000 00000000
dfc0: be8646c4 be864844 45194a00 0000017b 0047adc8 00000000 0046ab60 00000000
dfe0: be864670 be864660 00465177 b6f312b2 80030030 00000003 00000000 00000000
[<bf17d600>] (xilinx_dma_chan_reset [xilinx_dma]) from [<bf17dff4>] (xilinx_dma_probe+0x424/0xb04 [xilinx_dma])
[<bf17dff4>] (xilinx_dma_probe [xilinx_dma]) from [<c03b2a20>] (platform_drv_probe+0x50/0xac)
[<c03b2a20>] (platform_drv_probe) from [<c03b1240>] (driver_probe_device+0x238/0x2e8)
[<c03b1240>] (driver_probe_device) from [<c03b1394>] (__driver_attach+0xa4/0xa8)
[<c03b1394>] (__driver_attach) from [<c03af7a0>] (bus_for_each_dev+0x4c/0x9c)
[<c03af7a0>] (bus_for_each_dev) from [<c03b07a0>] (bus_add_driver+0x188/0x20c)
[<c03b07a0>] (bus_add_driver) from [<c03b1c3c>] (driver_register+0x78/0xf4)
[<c03b1c3c>] (driver_register) from [<c0101a20>] (do_one_initcall+0x44/0x168)
[<c0101a20>] (do_one_initcall) from [<c018895c>] (do_init_module+0x60/0x1f0)
[<c018895c>] (do_init_module) from [<c01875f0>] (load_module+0x1b8c/0x23a0)
[<c01875f0>] (load_module) from [<c0188008>] (SyS_finit_module+0x9c/0xb4)
[<c0188008>] (SyS_finit_module) from [<c0107960>] (ret_fast_syscall+0x0/0x48)
Code: e5933000 e0833005 e5933000 f57ff04f (e5943000)
---[ end trace e3cdb0330d71dd39 ]---
I identified that the error occurs in this function inside xilinx_dma.c:
/* IO accessors */
static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
{
return ioread32(chan->xdev->regs + reg); // Here
}
So the ioread32 doesn't work. My question is: Why is this and what can I do about it?
If I remove the new AXI DMA from the device tree or change its compatible property to something random it works fine. So I suppose something has to be wrongly configured in the AXI DMA I added.

Related

Read binary file in C skip byte of 0

When i read a binary file the program skip the byte who are equal to 0.
There is my program in C :
int main(int argc, char const *argv[])
{
FILE * input_file = fopen("binary.bin", "rb");
uint32_t b = 0 ;
fread(&b, sizeof(uint32_t) , 1 , input_file);
printf("----- Here are the data stored in the file -----\n");
printf("First uint_32 : %d\n", b);
printf("------------------------------------------------\n");
return 0;
}
The output :
----- Here are the data stored in the file -----
First uint_32 : 16777216
------------------------------------------------
The binary file :
xxd -b binary.bin
00000000: 00000000 00000000 00000000 00000001 00000000 00000000 ......
00000006: 00000000 00110010 00000000 00000000 00000000 01100100 .2...d
0000000c: 00000000 00000000 00000000 00010100 00000000 00000000 ......
00000012: 00000000 00000000 00000000 00000000 01011001 00110000 ....Y0
Why the output is not 1 ?
You got 16777216 as an output.
Let's see its binary representation
00000001000000000000000000000000
That's due to how data is written in the memory depending on the architecture of the system.
That's endianness of the system. You should read about little-endian and big-endian

String literal not working if passed as argument

I'm trying to write a bootloader in c and I noticed that string literals only worked if I passed them as a char *.
If it Could help:
when I converted both versions to assembly I found one difference that was only in the working version which is
mov DWORD PTR -8[ebp], eax
push DWORD PTR -8[ebp]
just before calling puts
Here's my code :
asm("jmp main");
void putc(char c) {
asm volatile("mov %%al, %0" :: "a"(c));
asm volatile("mov %ah, 0x0e");
asm volatile("int 0x10");
}
void puts(const char *s) {
while(*s) putc(*s++);
}
void newl() {
char s[] = { 0x0D, 0x0A, 0 };
puts(s);
}
void clear() {
asm volatile("mov ah, 0");
asm volatile("mov al, 0x3");
asm volatile("int 0x10");
}
void __attribute__((optimize("-O0"))) main() {
clear();
char * a = "Hello World";
puts(a); // WORKS
puts("Hello World"); // DOESN'T WORK (DOES NOT WRITE ANYTHING)
newl();
}
LD.LD :
ENTRY(main)
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00)
{
*(.text);
}
.sig : AT(0x7C00 + 510)
{
SHORT(0xaa55);
}
/DISCARD/ : {
*(.comment)
*(.eh_frame)
}
}
How I compiled:
gcc -m16 -c -ffreestanding -fno-pie -fno-exceptions -masm=intel -s -Os -static -Wall -ffunction-sections -fdata-sections main.cpp -o main.o
ld -m elf_i386 -o main.elf -T ld.ld main.o
objcopy -O binary main.elf main.bin
and I ran it with : qemu-system-x86_64 -fda main.bin
with char * a = "Hello World"; puts(a); :
objdump -h:
Idx Name Size VMA LMA File off Algn
0 .text 00000003 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000037 2**0
ALLOC
3 .rodata 0000000c 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text.main 00000051 00000000 00000000 00000043 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
5 .text.putc 00000014 00000000 00000000 00000094 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
6 .text.puts 0000002f 00000000 00000000 000000a8 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
7 .text.newl 00000029 00000000 00000000 000000d7 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
8 .text.clear 00000008 00000000 00000000 00000100 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .comment 0000001f 00000000 00000000 00000108 2**0
CONTENTS, READONLY
10 .note.GNU-stack 00000000 00000000 00000000 00000127 2**0
CONTENTS, READONLY
11 .eh_frame 000000b8 00000000 00000000 00000128 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
with puts("Hello World");:
objdump -h:
Idx Name Size VMA LMA File off Algn
0 .text 00000003 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000037 2**0
ALLOC
3 .rodata 0000000c 00000000 00000000 00000037 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text.main 00000047 00000000 00000000 00000043 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
5 .text.putc 00000014 00000000 00000000 0000008a 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
6 .text.puts 0000002f 00000000 00000000 0000009e 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
7 .text.newl 00000029 00000000 00000000 000000cd 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
8 .text.clear 00000008 00000000 00000000 000000f6 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .comment 0000001f 00000000 00000000 000000fe 2**0
CONTENTS, READONLY
10 .note.GNU-stack 00000000 00000000 00000000 0000011d 2**0
CONTENTS, READONLY
11 .eh_frame 000000b8 00000000 00000000 00000120 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

bytes displayed differently when called differently

I'm using the below code for reading bits/bytes in a structure.
Each line is printed in two different methods when DEBUG is 1, else it uses only one method.
Code:
#include <stdio.h>
#define DEBUG 0
typedef struct n{
int a;
int b;
int (*add)(struct n*, int,int);
int (*sub)(struct n*, int,int);
} num;
int add (num *st, int a, int b){}
int sub(num *st, int a, int b){}
int main(){
num* var = calloc(1,sizeof(num));
var->add = add;
var->sub = sub;
var->a = 13;
var->b = 53;
long int *byte = (long int*)var;
int i;
int j;
for(i=0;i<6;i++){
# if DEBUG == 1
for(j=0;j<64;j++){
printf("%d",( *(byte+i) & (1UL<<(63-j)) )?1:0 );
putchar( ((j+1)%8 == 0)?' ':'\0' );
}
putchar('\n');
# endif
printf("0x%06x %06x\n",(*(byte+i) >> 32), *(byte+i));
}
printf("\n0x%x\n",var->add);
printf("0x%x\n",var->sub);
}
Output 1: (DEBUG==1)
00000000 00000000 00000000 00110101 00000000 00000000 00000000 00001101
0x000035 00000d
00000000 00000000 00000000 00000000 00000000 01000000 00000111 01110000
0x000000 400770
00000000 00000000 00000000 00000000 00000000 01000000 00000111 01100000
0x000000 400760
00000000 00000000 00000000 00000000 00000000 00000010 00001111 11100001
0x000000 020fe1
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0x000000 000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0x000000 000000
0x400770
0x400760
Output 2: (DEBUG==0)
0x000000 000000
0x000000 000000
0x000000 000000
0x000000 020fe1
0x000000 000000
0x000000 000000
0x400640
0x400630
As you can see, everything except one line is blank in Output 2.
I'm just curious to know why this is happening.
Also enlighten me, if there's a better way to print bits/bytes.
Nb: I'm using an online compiler(onlinegdb.com) for testing
What you are printing here is address of functions.
printf("\n0x%x\n",var->add);
printf("0x%x\n",var->sub);
When you enable DEBUG.
# if DEBUG == 1
for(j=0;j<64;j++){
printf("%d",( *(byte+i) & (1UL<<(63-j)) )?1:0 );
putchar( ((j+1)%8 == 0)?' ':'\0' );
}
putchar('\n');
# endif
You are adding above code to your code segment.
Hence addresses of function(add and sub) inside code segment may change.
Note:: You are not following strict aliasing rule here.
long int *byte = (long int*)var;
This appears to be an issue with the compiler you are using, I don't see any specific reason why your code would return 0's. When your code is compiled with GCC and run the results are as follows:
Debug = 1
00000000 00000000 00000000 00001101 00000000 00000000 00000000 00001101
0x00000d 00000d
00000000 00000000 00000000 00110101 00000000 00000000 00000000 00110101
0x000035 000035
00000000 01000000 00010101 01100000 00000000 01000000 00010101 01100000
0x401560 401560
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0x000000 000000
00000000 01000000 00010101 01110010 00000000 01000000 00010101 01110010
0x401572 401572
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0x000000 000000
0x401560
0x401572
And Debug = 0:
0x00000d 00000d
0x000035 000035
0x401560 401560
0x000000 000000
0x401572 401572
0x000000 000000
0x401560
0x401572
I'd recommend getting GCC on your machine and compiling your code with -Wall. There are a handful of things in this code that make it hard to understand and could make for unpredictable behavior that -Wall will warn you about.

Difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4) in linker script

Among other things I am trying to understand the difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4).
Assume we have next files (I have used linker script example from here as a basis):
main.c:
int main(void)
{
test_1();
test_2();
return 0;
}
main.lds:
OUTPUT_ARCH(arm)
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
test_1.c:
void test_1(void)
{
return;
}
test_2.c:
void test_2(void)
{
return;
}
If we compile it and dump its content we have next:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe test_1.c -c
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe test_2.c -c
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x test_1.o
test_1.o: file format elf32-littlearm
test_1.o
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 200: [APCS-32] [FPA float format] [software FP]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000014 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000048 2**0
CONTENTS, READONLY
4 .ARM.attributes 00000010 00000000 00000000 0000005a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 test_1.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text 00000014 test_1
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x main.elf
main.elf: file format elf32-littlearm
main.elf
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00010000
Program Header:
LOAD off 0x00008000 vaddr 0x00010000 paddr 0x00010000 align 2**15
filesz 0x00000028 memsz 0x00000028 flags r-x
private flags = 200: [APCS-32] [FPA float format] [software FP]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000028 00010000 00010000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 00000011 00000000 00000000 00008028 2**0
CONTENTS, READONLY
2 .ARM.attributes 00000010 00000000 00000000 00008039 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00010000 l d .text 00000000 .text
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test_1.c
00000000 l df *ABS* 00000000 test_2.c
00010014 g F .text 00000014 test_2
00010000 g F .text 00000014 test_1
But if I change OUTPUT_ARCH(arm) to OUTPUT_ARCH(armv4), I get an error from linker:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: error: test_1.o uses software FP, whereas main.elf uses hardware FP
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: failed to merge target specific data of file test_1.o
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: error: test_2.o uses software FP, whereas main.elf uses hardware FP
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: failed to merge target specific data of file test_2.o
collect2: ld returned 1 exit status
It can be fixed by specifying -mfloat-abi=hard option. In this case there is a difference in private flags comparing with previous output:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -mfloat-abi=hard test_1.c -c
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -mfloat-abi=hard test_2.c -c
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x test_1.o
test_1.o: file format elf32-littlearm
test_1.o
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 0: [APCS-32] [FPA float format]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000014 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000048 2**0
CONTENTS, READONLY
4 .ARM.attributes 00000010 00000000 00000000 0000005a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 test_1.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text 00000014 test_1
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x main.elf
main.elf: file format elf32-littlearm
main.elf
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00010000
Program Header:
LOAD off 0x00008000 vaddr 0x00010000 paddr 0x00010000 align 2**15
filesz 0x00000028 memsz 0x00000028 flags r-x
private flags = 0: [APCS-32] [FPA float format]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000028 00010000 00010000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 00000011 00000000 00000000 00008028 2**0
CONTENTS, READONLY
2 .ARM.attributes 00000010 00000000 00000000 00008039 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00010000 l d .text 00000000 .text
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test_1.c
00000000 l df *ABS* 00000000 test_2.c
00010014 g F .text 00000014 test_2
00010000 g F .text 00000014 test_1
Does it mean that OUTPUT_ARCH(armv4) causes linker to generate output solely for hard float?
In general, what is the difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4)?
According to ld manual OUTPUT_ARCH() specifies a particular output machine architecture.
The argument is one of the names used by the BFD library.
But I have found no clear information about BFD library except general information.
I use arm-elf toolchain from here (Binutils 2.22, GCC 4.6.3, Newlib 1.2.0, GDB 7.4).
Thank you in advance for help.
UPDATE 1:
This update is a reply for the comment below.
Compiler -v output from old toolchain we use now:
Using built-in specs.
Target: arm-elf
Configured with: ../gcc-4.4.1/configure --target=arm-elf --host=i686-pc-mingw32 --with-cpu=xscale --without-stabs -nfp --prefix=/c/cross-gcc/4.4.1 --disable-nls --disable-shared --disable-__cxa_atexit
--enable-threads --with-gnu-gcc --with-gnu-ld --with-gnu-as --with-dwarf2 --enable-languages=c,c++ --enable-interwork --disable-multilib --with-gmp=/c/cross-gcc/4.4.1 --with-mpfr=/c/cross-gcc/4.4.1 -
-with-newlib --with-headers=../../newlib-1.17.0/newlib-1.17.0/newlib/libc/include --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libgomp -v
Thread model: single
gcc version 4.4.1 (GCC)
Compiler -v output from newer toolchain I used in the examples (SysGCC arm-elf):
Using built-in specs.
COLLECT_GCC=arm-elf-gcc.exe
COLLECT_LTO_WRAPPER=c:/sysgcc/arm-elf/bin/../libexec/gcc/arm-elf/4.6.3/lto-wrapper.exe
Target: arm-elf
Configured with: ../gcc-4.6.3/configure --target arm-elf --enable-win32-registry=SysGCC-arm-elf-4.6.3 --prefix /c/gnu/auto/bu-2.22+gcc-4.6.3+gmp-4.2.4+mpfr-2.4.1+mpc-0.8+newlib-1.20.0-arm-elf/ --enabl
e-languages=c,c++ --disable-nls --with-newlib --with-headers=../newlib-1.20.0/newlib/libc/include --enable-interwork --enable-multilib --with-float=soft
Thread model: single
gcc version 4.6.3 (GCC)
There is no difference between linker output for OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4) for old compiler. I think I should have checked it before.
Seems that it is an answer to this question.
My goal is to use the combination -mfpu=vfpv3 -mfloat-abi=hard, but according to Debian documentation and GCC 4.4.7 manual this combination is not supported by GCC 4.4.
In fact if I try to compile with -mfpu=vfpv3 -mfloat-abi=hard by old compiler, it returns error:
sorry, unimplemented: -mfloat-abi=hard and VFP
Still and all it is possible to use -mfpu=vfpv3 -mfloat-abi=softfp with old compiler, but according to this comparison it gives big overhead for small routines.

Memory not allocating (Embedded uC MSP430)

I'm using an MSP430G2553 microcontroller (500 bytes of SRAM and 16kB of flash). I have 4 ring buffers allocating memory at the initialization of my code (using malloc)
typedef struct
{
unsigned char Head;
unsigned char Tail;
unsigned char Size;
unsigned char *Buffer;
} RingBuffer;
void RB_Init(RingBuffer *RB)
{
RB->Size = 32;
RB->Tail = 0;
RB->Head = 0;
RB->Buffer = (unsigned char*) malloc(RB->Size);
}
Basically I'm calling RB_Init four times to create those ring buffers. When the size (capacity of the ring buffer) is 16 everything is fine and I check all four and they each have a memory address. When I change the size to 32 only 2 get memory addresses, the last two aren't getting memory allocated.
Based on the memory map I get from code composer studio (shown below) it looks like I still have a lot of space (under RAM and FLASH). Why aren't the last two buffer arrays getting addresses when I have the sizes at 32 bytes (Why does it seem I hit my limit at 64 bytes?)
******************************************************************************
MSP430 Linker PC v4.1.5
******************************************************************************
>> Linked Fri Dec 27 22:53:28 2013
OUTPUT FILE NAME: <xxx.out>
ENTRY POINT SYMBOL: "_c_int00" address: 0000c672
MEMORY CONFIGURATION
name origin length used unused attr fill
---------------------- -------- --------- -------- -------- ---- --------
SFR 00000000 00000010 00000000 00000010 RWIX
PERIPHERALS_8BIT 00000010 000000f0 00000000 000000f0 RWIX
PERIPHERALS_16BIT 00000100 00000100 00000000 00000100 RWIX
RAM 00000200 00000200 000000cf 00000131 RWIX
INFOD 00001000 00000040 00000000 00000040 RWIX
INFOC 00001040 00000040 00000000 00000040 RWIX
INFOB 00001080 00000040 00000000 00000040 RWIX
INFOA 000010c0 00000040 00000000 00000040 RWIX
FLASH 0000c000 00003fe0 00000802 000037de RWIX
INT00 0000ffe0 00000002 00000000 00000002 RWIX
INT01 0000ffe2 00000002 00000000 00000002 RWIX
INT02 0000ffe4 00000002 00000002 00000000 RWIX
INT03 0000ffe6 00000002 00000002 00000000 RWIX
INT04 0000ffe8 00000002 00000000 00000002 RWIX
INT05 0000ffea 00000002 00000000 00000002 RWIX
INT06 0000ffec 00000002 00000002 00000000 RWIX
INT07 0000ffee 00000002 00000002 00000000 RWIX
INT08 0000fff0 00000002 00000000 00000002 RWIX
INT09 0000fff2 00000002 00000002 00000000 RWIX
INT10 0000fff4 00000002 00000000 00000002 RWIX
INT11 0000fff6 00000002 00000000 00000002 RWIX
INT12 0000fff8 00000002 00000000 00000002 RWIX
INT13 0000fffa 00000002 00000000 00000002 RWIX
INT14 0000fffc 00000002 00000000 00000002 RWIX
RESET 0000fffe 00000002 00000002 00000000 RWIX
It's unimportant how much RAM your system has, in your case the configured heap size is too small.
But if you always need 4 ringbuffers with a fixed size, it makes no sense to allocate them via malloc.
You could better define static variables, so you will know at link time if your RAM is enough.
#define RING_BUF_SIZE 32
typedef struct
{
unsigned char Head;
unsigned char Tail;
unsigned char buffer[RING_BUF_SIZE];
} RingBuffer;
static RingBuffer myRingbuffer[4];
void RB_Init(RingBuffer *RB)
{
memset(RB, 0, sizeof(RingBuffer) );
}
It's important to initialize them, as the code composer is not ANSI-C compliant here and the startup code will not zero all variables at startup.

Resources