Я побеседовал с учебниками по выпечке в Кембридже (базовая разработка ОС с небольшими демонстрациями для малины pi). Только я написал код в C вместо этого. У меня есть настройка среды разработки, и я могу успешно запустить свой код с отключенной настройкой GCC, но не включен.Оптимизированная память, оптимизированная для IO и GCC
Проблема возникает с моим кодом, который использует IO с отображением памяти (если я скомпилировал все остальное, кроме следующего файла с оптимизацией, он работает). Поначалу я думал, что мои указатели не были объявлены как изменчивые, поэтому компилятор оптимизировал фактическую запись в память и вместо этого использовал регистры. Но даже когда я объявляю их неустойчивыми, проблема сохраняется.
Вот как я делаю запись в память:
#define UART0_CR ((volatile uint32_t *) (UART0_BASE + 0x30))
...
*UART_CR = 0;
указатели летучего типа, так что я не могу понять, почему GCC решит не делать фактическую запись. Есть ли что-то еще, что мне нужно для наблюдения? Я не понимаю, как использовать летучие?
Полный рабочий файл (с оптимизацией выключения в любом случае):
#include <stdint.h>
#include <uart.h>
#define GPIO_BASE 0x20200000
#define GPPUD ((volatile uint32_t *) (GPIO_BASE + 0x94))
#define GPPUDCLK0 ((volatile uint32_t *) (GPIO_BASE + 0x98))
#define UART0_BASE 0x20201000
#define UART0_DR ((volatile uint32_t *) (UART0_BASE + 0x00))
#define UART0_FR ((volatile uint32_t *) (UART0_BASE + 0x18))
#define UART0_IBRD ((volatile uint32_t *) (UART0_BASE + 0x24))
#define UART0_FBRD ((volatile uint32_t *) (UART0_BASE + 0x28))
#define UART0_LCRH ((volatile uint32_t *) (UART0_BASE + 0x2C))
#define UART0_CR ((volatile uint32_t *) (UART0_BASE + 0x30))
#define UART0_IMSC ((volatile uint32_t *) (UART0_BASE + 0x38))
#define UART0_ICR ((volatile uint32_t *) (UART0_BASE + 0x44))
static void delay(int32_t count) {
asm volatile("__delay%=: subs %[count], %[count], #1; bne __delay%=\n"
:
: [count]"r"(count)
: "cc"
);
}
void uart_init() {
*UART0_CR = 0; // Disable UART0.
*GPPUD = 0; // Disable pull up/down for all GPIO pins & delay for 150 cycles.
delay(150);
*GPPUDCLK0 = (1 << 14) | (1 << 15); // Disable pull up/down for pin 14,15 & delay for 150 cycles.
delay(150);
*GPPUDCLK0 = 0; // Write 0 to GPPUDCLK0 to make it take effect.
*UART0_ICR = 0x7FF; // Clear pending interrupts.
*UART0_IBRD = 1; //Set rate
*UART0_FBRD = 40;
*UART0_LCRH = (1 << 4) | (1 << 5) | (1 << 6); // Enable FIFO & 8 bit data transmissio (1 stop bit, no parity).
*UART0_IMSC = (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10); // Mask all interrupts.
*UART0_CR = (1 << 0) | (1 << 8) | (1 << 9); // Enable UART0, receive & transfer part of UART.
}
void uart_putc(uint8_t byte) {
while (1) { // wait for UART to become ready to transmit
if (!(*UART0_FR & (1 << 5))) break;
}
*UART0_DR = byte; // Transmit
}
void uart_puts(const char *str) {
while (*str) {
uart_putc(*str++);
}
}
EDIT:
Посмотрел, как просматривать сборки, очень полезно, большое спасибо. Если я беру первые 2 выписывает из УАПП я инициализации (до первого вызова задержки) я получаю:
Неоптимизированный:
uart_init:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
add fp, sp, #4
ldr r3, .L3
mov r2, #0
str r2, [r3, #0]
ldr r3, .L3+4
mov r2, #0
str r2, [r3, #0]
Оптимизированный:
uart_init:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldr r3, .L2
ldr r2, .L2+4
mov r1, #0
str r1, [r3, #48]
str r1, [r2, #148]
Единственное различие, кажется, что для неоптимизированного значения он не добавляет смещения меток .L2 и .L2 + 4, которые оптимизирован. Если указатели на этих ярлыках уже не подготовлены к расчетам на них.
У меня есть раздвоенный qemu (qemu-rpi), модифицированный для поддержки малины pi, поэтому я попытаюсь проверить, какие значения загружены в регистры r3 и r2, чтобы увидеть, являются ли они правильными указателями до того, как магазин произойдет и затем я иду проверить, не зацикливается ли putc на передаче, используя точки останова. Не очень разбираюсь в моей среде, но это может занять некоторое время!
Какие у вас есть доказательства того, что фактическая запись не выполнена? Вы посмотрели на сборку? – ouah
Код выглядит хорошо при первом румянце.Что происходит, когда оно оптимизировано? Цикл uart_putc() навсегда ожидает бит 5? – torek
I abstract my Mem/IO читает и пишет по этой и другим причинам, github.com/dwelch67/raspberrypi. Вы можете играть в игры до тех пор, пока не будете синими в лицо с атрибутами, специфичными для компилятора, и в конечном итоге все равно столкнуться с проблемой оптимизации. Аппаратный ввод-вывод в моем случае находится в asm, но в основном в отдельном файле, а не в части оптимизации. –