I'm having problems with various print commands.
Everytime I'm trying to call printf() my system just hangs or sometimes resets.
I have working UART and I can print into my console with UART_PutChar() just fine.
fprintf works in simple cases of just printing plain string fprintf(stdout, "test\n");
however formatted strings will hang my system fprintf(stdout, "test %d\n", 1);
Hangs also occur when I'm trying to print data from .data section
char* dataString = "test\n\0";
int main(){
fprintf(stdout, dataString);
}
printf will work when I print newlines printf("\n");
printf will only print newlines if I do something like
fputc('B', stdin); //notice stdin
printf("test\n"); //prints newline
In some cases when fprintf fails it will return EOF (cannot remember them now, will provide them tomorrow if it becomes relevant)
(f)printf seems to be calling putchar and I've retargeted it to UART.
Curiously I think it should be calling _write
or _write_r
routines provided by newlib-nano (and printf is not calling them).
As IDE i'm using EmBitz and toolchain provided by it (arm-none-eabi). CPU I'm using is at91sam7x128. I'm unable to debug my program with JTAG so i need to try only use UART for debugging.
char* dataSection = "data\n\0";
char* dataSingle = "A";
int bssSection = 0;
int main(){
fprintf(stdout, "plain\n"); //works
fprintf(stdout, dataSingle); //works
fprintf(stdout, *(char*)(bssSection + 0x41)); //prints A, works
printf("\n"); //works
fprintf(stdout, "%d", 1); //hangs
fprintf(stdout, dataSection); //hangs
printf("plain printf\n"); //hangs
}
UPDATE starter script: SAM7.s
/*********************************************************************
*
* Defines, used for the processor status register
*
**********************************************************************
*/
ARM_MODE_USER = 0x10 /* Normal User Mode */
ARM_MODE_FIQ = 0x11 /* FIQ Fast Interrupts Mode */
ARM_MODE_IRQ = 0x12 /* IRQ Standard Interrupts Mode */
ARM_MODE_SVC = 0x13 /* Supervisor Interrupts Mode */
ARM_MODE_ABORT = 0x17 /* Abort Processing memory Faults Mode */
ARM_MODE_UNDEF = 0x1B /* Undefined Instructions Mode */
ARM_MODE_SYS = 0x1F /* System Running in Priviledged Operating Mode */
ARM_MODE_MASK = 0x1F
I_BIT = 0x80 /* Disables IRQ when I bit is set */
F_BIT = 0x40 /* Disables FIQ when F bit is set */
/*********************************************************************
*
* Vector table
*
**********************************************************************
*/
.text
.global __vector
.global _exit
.extern Reset_Handler
.arm
.section .vectors, "ax"
__vector:
ldr pc,Reset_Addr /* RESET vector */
Reset_Addr: .word Reset_Handler
__vector_end:
/*********************************************************************
*
* Standard C (crt0) initialization function
*
**********************************************************************
*/
.global OS_GetStackInfo
.extern __low_level_init
.extern main
crt0:
/*
* Call __low_level_init to initiliaze hardware
* before calling c-standard startup
*/
ldr r0,=__low_level_init
mov lr, pc
bx r0
/*
* Relocate .data section
* (Copy from ROM to RAM)
*/
ldr r1, =_etext
ldr r2, =_data
ldr r3, =_edata
LoopRel:
cmp r2, r3
ldrlo r0, [r1], #4
strlo r0, [r2], #4
blo LoopRel
/*
* Clear .bss section
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
ldr r3, =0
bss_clear_loop:
cmp r1, r2
strne r3, [r1], #+4
bne bss_clear_loop
/*
* Prepare and call main()
*/
mrs r0, cpsr
bic r0, r0, #(I_BIT | F_BIT) /* Enable FIQ and IRQ interrupt */
msr cpsr, r0
mov r0, #0 /* No arguments are passed to main */
mov r1, #0
ldr r2, =main
mov lr, pc
bx r2
_exit: b _exit /* We should never come to here, just for sureness. */
/*********************************************************************
*
* __low_level_init
*
**********************************************************************
*/
__low_level_init:
bx lr
.weak __low_level_init
/**********************************************************************
* Reset_Handler
*
* Execution starts here.
* After a reset, the mode is ARM, Supervisor, interrupts disabled.
*/
.global Reset_Handler
.global end
.arm
.section .text, "ax"
Reset_Handler:
/*
* Setup a stack for each mode
*/
msr CPSR_c, #ARM_MODE_UNDEF | I_BIT | F_BIT /* Undefined Instruction Mode */
ldr sp, =__stack_und_end__
msr CPSR_c, #ARM_MODE_ABORT | I_BIT | F_BIT /* Abort Mode */
ldr sp, =__stack_abt_end__
msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT /* FIQ Mode */
ldr sp, =__stack_fiq_end__
msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT /* IRQ Mode */
ldr sp, =__stack_irq_end__
msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT /* Supervisor Mode */
ldr sp, =__stack_svc_end__
/*
* Now enter crt0 function,
* which does low-level and segment initialization.
* and then calls main().
*/
ldr r0, =crt0
mov lr, pc
bx r0
end: b end
.end
Linker script
ENTRY(__vector)
/*********************************************************************
*
* Define stack sizes here
*/
FIQ_STACK_SIZE = 0x0;
IRQ_STACK_SIZE = 0x1000;
ABT_STACK_SIZE = 0x0;
UND_STACK_SIZE = 0x0;
SVC_STACK_SIZE = 0x1000;
MEMORY
{
RAM (wx) : ORIGIN = 0x200000, LENGTH = 0x8000
FLASH (rx) : ORIGIN = 0x100000, LENGTH = 0x10000
}
SECTIONS
{
.text :
{
*(.vectors);
. = ALIGN(8);
*(.init);
. = ALIGN(8);
*(.text);
. = ALIGN(8);
*(.rodata);
. = ALIGN(8);
*(.rodata*);
. = ALIGN(8);
*(.glue_7t);
. = ALIGN(8);
*(.glue_7);
. = ALIGN(8);
etext = .;
} > FLASH
. = ALIGN(8);
_etext = . ;
PROVIDE (etext = .);
.data : AT (_etext)
{
PROVIDE (__data_start__ = .);
_data = . ;
*(.data)
. = ALIGN(8);
PROVIDE (__data_end__ = .);
} > RAM
. = ALIGN(8);
_edata = . ;
PROVIDE (edata = .);
.bss :
{
PROVIDE (__bss_start__ = .);
*(.bss)
*(COMMON)
. = ALIGN(8);
PROVIDE (__bss_end__ = .);
. = ALIGN(256);
PROVIDE (__stack_start__ = .);
PROVIDE (__stack_fiq_start__ = .);
. += FIQ_STACK_SIZE;
. = ALIGN(8);
PROVIDE (__stack_fiq_end__ = .);
PROVIDE (__stack_irq_start__ = .);
. += IRQ_STACK_SIZE;
. = ALIGN(8);
PROVIDE (__stack_irq_end__ = .);
PROVIDE (__stack_abt_start__ = .);
. += ABT_STACK_SIZE;
. = ALIGN(8);
PROVIDE (__stack_abt_end__ = .);
PROVIDE (__stack_und_start__ = .);
. += UND_STACK_SIZE;
. = ALIGN(8);
PROVIDE (__stack_und_end__ = .);
PROVIDE (__stack_svc_start__ = .);
PROVIDE (__stack_svc_end__ = .);
PROVIDE (__stack_end__ = .);
PROVIDE (__heap_start__ = .);
. += 0x1000;
. = ALIGN(8);
PROVIDE (__heap_end__ = .);
} > RAM
}
UPDATE 2 My quick and dirty reimplementations of syscalls.
int _write(int fd, char* buf, int len){
LED_On(1);
while(*buf){
UART_PutChar(*buf++);
}
return len;
}
void _ttywrch(int ch) {
LED_On(1);
UART_PutChar(ch);
}
signed int
putchar(signed int c)
{
return fputc(c, stdout);
}
signed int
fputs(const char* pStr, FILE* pStream)
{
signed int num = 0;
while (*pStr != 0)
{
if (fputc(*pStr, pStream) == -1)
{
return -1;
}
num++;
pStr++;
}
return num;
}
int
fputc(int c, FILE* pStream)
{
if ((pStream == stdout) || (pStream == stderr))
{
#ifdef UART_CONSOLE_CRLF
if (c == '\n')
UART_PutChar('\r');
#endif
UART_PutChar(c);
return c;
}
else
{
return EOF;
}
}