Ich versuche, eine kleine Anwendung zu schreiben, die eine Nachricht über die serielle Schnittstelle zeigt. Diese Binärdatei wird ohne Betriebssystem ausgeführt, also ist es Bare-Metal.Daten abbrechen auf A20 SoC
Der Code ist wie folgt:
#include <stdint.h>
#define FIFO 0x0
#define NOFIFO 0x1
#define FIFO_STATUS 0x0
#define THR_READY 0x1
#define THR_STATUS 0x5
#define UART_MEM 0x1C28000
volatile unsigned int *uart0 = (unsigned int *)UART_MEM;
volatile unsigned int *uart_str = (unsigned int *)(UART_MEM + 0x7c);
volatile unsigned int *uart_lstr = (unsigned int *)(UART_MEM + 0x14);
void print_smth(const char *str) {
while (*str != '\0') {
while ((*uart_lstr & (1 << THR_STATUS)) != THR_READY)
;
*uart0 = (unsigned int)(*str);
str++;
}
}
void c_entry(void) {
print_smth("Hello");
}
Ich Booten dieses binäre mit u-boot, und tatsächlich die binären Stiefel gut, bis es erreicht:
*uart0 = (unsigned int)(*str);
Sobald ich versuche, schreibe in diesen Speicher, ich bekomme einen Data Abort Error. Es sieht aus wie ich bin nicht erlaubt, an dieser Speicheradresse zu schreiben, aber einen Blick auf die A20 User Manual Ich sehe, dass tatsächlich UART0 0x01C28000 zugeordnet ist, so sollte ich Zugang zum Schreiben dort haben.
Dies ist die Ausgabe:
=> loadx
## Ready for binary (xmodem) download to 0x42000000 at 115200 bps...
CxyzModem - CRC mode, 2(SOH)/0(STX)/0(CAN) packets, 2 retries
## Total Size = 0x000000c4 = 196 Bytes
=> go 0x42000000
## Starting application at 0x42000000 ...
data abort
pc : [<4200007c>] lr : [<420000ac>]
reloc pc : [<0d0a207c>] lr : [<0d0a20ac>]
sp : 000010b0 ip : 7fe79000 fp : 000010bc
r10: 00000002 r9 : 7af3dee0 r8 : 7efb47a8
r7 : 7af3fab8 r6 : 42000000 r5 : 00000002 r4 : 7af3fabc
r3 : ee070f15 r2 : 0000001e r1 : 7af3fabc r0 : 000000b0
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
resetting ...
Haben Sie eine Idee, warum dies geschieht?
Ist es möglich, dass der Code nicht dem RAM zugeordnet wird, und deshalb bekomme ich diesen Fehler?
== == UPDATE
Nachdem die Vars als Konstante definieren arbeitet nun "besser". Es funktioniert immer noch nicht gut, weil ich Müll anstelle von meinem Text bekomme. Hier
ist der Code aktualisiert:
#include <stdint.h>
#define TEMT_STATUS (0x1 << 6)
#define UART0 0x1C28000
#define UART_LSR 0x14
volatile unsigned int *const uart0 = (unsigned int *)(UART0);
volatile unsigned int *const uart_lsr = (unsigned int *)(UART0 + UART_LSR);
void print_smth(const char *str) {
while (*str != '\0') {
while (!(*uart_lsr & TEMT_STATUS))
;
*uart0 = (unsigned int)(*str);
str++;
}
}
void c_entry(void) {
print_smth("os");
}
Und der Ausgang ist:
=> go 0x42000000
## Starting application at 0x42000000 ...
��ᚕ��
��
Ich bin sicher, dass ich etwas fehle, aber ich bin nicht sicher, was. Ich habe einen Blick auf den Fahrer, die von U-Boot verwendet wird, finden Sie unter:
arch/arm/cpu/armv7/sunxi/early_print.c
Und es ist eigentlich nicht mehr als mich zu tun. Ich frage mich, wo der Fehler ist.
Vielen Dank im Voraus Grüße
Sie haben 'stdint' bereits eingefügt. Irgendein Grund, warum Sie es nicht benutzen? Außerdem: niemals ohne Notwendigkeit oder vollständige Akzeptanz aller Implikationen. – Olaf
Nicht das eigentliche Problem: 'while ((* uart_lstr & (1 << THR_STATUS))! = THR_READY)' diese Bedingung wird niemals wahr sein: '(xxx & (1 << 5))! = 1' für jedes xxx in der Stadt. – joop
Verwenden Sie für die Registeradressen konstante Makros, keine globalen Variablen! Vielleicht sollten Sie zuerst eine professionelle Hardware-Treibersoftware lesen, bevor Sie Ihre eigene schreiben. – Olaf