I am trying to print string through a UART0 from Beaglebone Black .The bootloader initializes UART0 and I just have to write characters. I have made a simple function
void uart_put(unsigned char c)
{
while((UART0->LSR_r & 32) == 0);
UART0->THR = c;
}
From the startup code the following function is called I simply print character in this function.
#define SIZE_OF_ARRAY 7
int c_entry(void)
{
unsigned char s_name[SIZE_OF_ARRAY] = "Hello";
unsigned char a_name[SIZE_OF_ARRAY] = {'H','e','l','l','o','\0'};
unsigned int a_int[SIZE_OF_ARRAY] = {9,8,7,6,5,4};
int i = 0;
for(i = 0; i<6; i++)
{
uart_put('0'+i); /*print value of i*/
uart_put(9); /*print a tab*/
uart_put(s_name[i]); /*print char from string*/
uart_put(9); /*print a tab*/
uart_put(a_name[i]); /*print char from array*/
uart_put(9); /*print a tab*/
uart_put('0'+a_int[i]); /*print int from array*/
uart_put('\n');
uart_put('\r');
}
while(1);
return 0;
}
The function is working fine as the array of characters and the integers is printed correctly, but the string is not printed as it should be.
Within the linker script, change:
. = 0x402F0400;
to:
. = 0x80000000;
Per the memory map for the AM335X ARM processor, 0x402F0400
is the core SRAM while 0x8000000
is the DDR2 memory. Per the screenshot of the TFTP boot output, you are loading your application at 0x80000000
, but your linker script is configured to reference the memory at 0x402F04000
.
Disassembling the raw binary file download.bin
built using the original linker script yields:
% arm-none-eabi-objdump -D -b binary -marm download.bin
download.bin: file format binary
Disassembly of section .data:
00000000 <.data>:
0: e51fd000 ldr sp, [pc, #-0] ; 0x8
4: eb00000e bl 0x44
8: 402f1638 eormi r1, pc, r8, lsr r6 ; <UNPREDICTABLE>
c: e52db004 push {fp} ; (str fp, [sp, #-4]!)
[removed several lines of text]
4c: e24dd030 sub sp, sp, #48 ; 0x30
50: e300262c movw r2, #1580 ; 0x62c
54: e344202f movt r2, #16431 ; 0x402f
[remainder of dump removed]
The string is copied from memory into the local variable. Note that the address for the string copy is 0x402f062c
(the movw
and movt
commands load the address into the register). A quick scan of the omitted code does not show any other attempts to access memory.
I don't have access to a Beaglebone Black so I am unable to test this. It does explain the observed behavior. As the program is copying the string from uninitialized SRAM, there is no guarantee of what will be displayed. As there is no other attempt to access memory within the program, this is the only issue.
Changing the linker script and rebuilding results in a slightly different download.bin
. A diff between the disassembled download.bin
produced by the original linker script and my suggested change is:
10c10
< 8: 402f1638 eormi r1, pc, r8, lsr r6 ; <UNPREDICTABLE>
---
> 8: 80001238 andhi r1, r0, r8, lsr r2
28,29c28,29
< 50: e300262c movw r2, #1580 ; 0x62c
< 54: e344202f movt r2, #16431 ; 0x402f
---
> 50: e300222c movw r2, #556 ; 0x22c
> 54: e3482000 movt r2, #32768 ; 0x8000
You can clearly see the new address reference for copying the string. Unfortunately, I'm unsure what the other change is and if this change will cause any issues.
Just to verify the string is at 0x8000022c, we can use xxd to dump download.bin
. The output is:
% xxd download.bin
0000000: 00d0 1fe5 0e00 00eb 3816 2f40 04b0 2de5 ........8./@..-.
0000010: 00b0 8de2 14d0 4de2 0030 a0e1 0d30 4be5 ......M..0...0K.
[... omitted lots of lines ...]
0000220: 0500 53e3 cdff ffda feff ffea 4865 6c6c ..S.........Hell
0000230: 6f00 0000 o...
The string Hello
is visible at 0x22c
. When loaded at 0x80000000
, the address where the string is copied appears to be correct.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With