Skip to content

Commit

Permalink
arm/crt0.c: Print register dumps without using printf
Browse files Browse the repository at this point in the history
Users optimizing for size might well want to leave printf out of their
link completely, if their I/O needs are not complicated. But if
they're using the fault reporting functions in arm/crt0.c, then they
get printf pulled in anyway by `arm_fault()`.

This patch reworks `arm_fault()` to use only `fputs` and `putchar`,
and to do its hex number formatting by hand in as little code as
possible.

(I considered using `utoa` for the number formatting, but it has the
wrong feature set: here we don't need its support for arbitrary number
bases, and on the other hand, we do want fixed-width hex numbers
instead of minimal-width.)
  • Loading branch information
statham-arm committed Apr 15, 2024
1 parent 58d6157 commit 9adab07
Showing 1 changed file with 39 additions and 21 deletions.
60 changes: 39 additions & 21 deletions picocrt/machine/arm/crt0.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ _start(void)
#define _REASON(r) #r
#define REASON(r) _REASON(r)

static void arm_fault_write_reg(const char *prefix, unsigned reg)
{
fputs(prefix, stdout);

for (unsigned i = 0; i < 8; i++) {
unsigned digitval = 0xF & (reg >> (28 - 4*i));
char digitchr = '0' + digitval + (digitval >= 10 ? 'a'-'0'-10 : 0);
putchar(digitchr);
}

putchar('\n');
}

#if __ARM_ARCH_PROFILE == 'M'

#define GET_SP struct fault *sp; __asm__ ("mov %0, sp" : "=r" (sp))
Expand All @@ -167,10 +180,10 @@ struct fault {
};

static const char *const reasons[] = {
"hardfault",
"memmanage",
"busfault",
"usagefault"
"hardfault\n",
"memmanage\n",
"busfault\n",
"usagefault\n"
};

#define REASON_HARDFAULT 0
Expand All @@ -181,15 +194,16 @@ static const char *const reasons[] = {
static void __attribute__((used))
arm_fault(struct fault *f, int reason)
{
printf("ARM fault: %s\n", reasons[reason]);
printf("\tR0: 0x%08x\n", f->r0);
printf("\tR1: 0x%08x\n", f->r1);
printf("\tR2: 0x%08x\n", f->r2);
printf("\tR3: 0x%08x\n", f->r3);
printf("\tR12: 0x%08x\n", f->r12);
printf("\tLR: 0x%08x\n", f->lr);
printf("\tPC: 0x%08x\n", f->pc);
printf("\tXPSR: 0x%08x\n", f->xpsr);
fputs("ARM fault: ", stdout);
fputs(reasons[reason], stdout);
arm_fault_write_reg("\tR0: 0x", f->r0);
arm_fault_write_reg("\tR1: 0x", f->r1);
arm_fault_write_reg("\tR2: 0x", f->r2);
arm_fault_write_reg("\tR3: 0x", f->r3);
arm_fault_write_reg("\tR12: 0x", f->r12);
arm_fault_write_reg("\tLR: 0x", f->lr);
arm_fault_write_reg("\tPC: 0x", f->pc);
arm_fault_write_reg("\tXPSR: 0x", f->xpsr);
_exit(1);
}

Expand Down Expand Up @@ -233,10 +247,10 @@ struct fault {
};

static const char *const reasons[] = {
"undef",
"svc",
"prefetch_abort",
"data_abort"
"undef\n",
"svc\n",
"prefetch_abort\n",
"data_abort\n"
};

#define REASON_UNDEF 0
Expand All @@ -248,10 +262,14 @@ static void __attribute__((used))
arm_fault(struct fault *f, int reason)
{
int r;
printf("ARM fault: %s\n", reasons[reason]);
for (r = 0; r <= 6; r++)
printf("\tR%d: 0x%08x\n", r, f->r[r]);
printf("\tPC: 0x%08x\n", f->pc);
fputs("ARM fault: ", stdout);
fputs(reasons[reason], stdout);
char prefix[] = "\tR#: 0x";
for (r = 0; r <= 6; r++) {
prefix[2] = '0' + r; /* overwrite # with register number */
arm_fault_write_reg(prefix, f->r[r]);
}
arm_fault_write_reg("\tPC: 0x", f->pc);
_exit(1);
}

Expand Down

0 comments on commit 9adab07

Please sign in to comment.