Я пытаюсь написать небольшое приложение, которое показывает сообщение через последовательный порт. Этот двоичный файл выполняется без ОС, поэтому он голый металл.Data Abort on A20 SoC
Код выглядит следующим образом:
#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");
}
Я загрузке этот двоичный файл с U-Boot, а на самом деле бинарные сапоги хорошо, пока он не достигнет:
*uart0 = (unsigned int)(*str);
После того, как я пытаюсь напишите в эту память, я получаю сообщение Abort Error. Похоже, я не могу писать по этому адресу памяти, но взглянув на A20 User Manual, я вижу, что на самом деле UART0 сопоставляется с 0x01C28000, поэтому у меня должен быть доступ для записи там.
Это выход:
=> 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 ...
ли вам представление о том, почему это происходит?
Возможно, что код не отображается в ОЗУ, и именно поэтому я получаю эту ошибку?
== UPDATE ==
После определения ВАРА как постоянные теперь работает "лучше". Это все еще не работает нормально, потому что вместо моего текста я получаю мусор.
Вот код обновления:
#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");
}
И выход:
=> go 0x42000000
## Starting application at 0x42000000 ...
��ᚕ��
��
Я уверен, что я что-то отсутствует, но я не уверен, что. Я посмотрел на водителя, который в настоящее время используется U-Boot, расположенного по адресу:
arch/arm/cpu/armv7/sunxi/early_print.c
И на самом деле это не делает больше, чем меня. Поэтому мне интересно, где неудача.
Заранее спасибо С уважением
Вы уже включили 'stdint'. По какой причине вы его не используете? Также: никогда не бросайте без необходимости или полностью принимайте все последствия. – Olaf
Не настоящая проблема: 'while ((* uart_lstr & (1 << THR_STATUS))! = THR_READY)' это условие никогда не будет правдой: '(xxx & (1 << 5))! = 1' для каждого xxx в городе. – joop
Используйте константные макросы для адресов регистров, а не глобальных переменных! Возможно, сначала вы должны прочитать профессиональное программное обеспечение для аппаратного обеспечения, прежде чем писать свои собственные. – Olaf