Я создал минимальный пример своей проблемы. В c файле я инициализирую массив с 16 элементами. Затем я вызываю функцию с указателем массива и его размером в качестве параметра. Сама функция работает, я проверил это с помощью файла разборки. Также инициализация стека указателя работает нормально. Проблема в том, что параметр функции указателя массива неверен. Я проверил это, и причина сбоя находится в самом начале основного раздела. Здесь указатель хранится в стеке.
Что я не понимаю: значения массива хранятся в разделе .rodata. Этот раздел начинается с 0x1000. Таким образом, указатель на массив также должен быть 0x1000. В разборке 0x1000 загружается в a5 (правильное значение). Но затем он загружает значение адреса a5 в a4. Так что 0x1000 представляет указатель на указатель на массив, что не имеет смысла imho. Кто-нибудь знает, что я делаю не так?
Вот вся необходимая информация:
c программа:
void test(uint8_t *array, int size){
for(int i=0; i<size; ++i){
LED_ADDR = array[i];
}
}
int main(){
uint8_t buf[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
test(buf, 16);
}
скрипт компоновщика:
OUTPUT_ARCH( "riscv" )
ROMSIZE = 0x1000;
ROM_OFFSET = 0x0000;
RAMSIZE = 0x1000;
RAM_OFFSET = 0x1000;
/* provide variables for startup code (stack init) */
STACK_TOP = ( RAMSIZE + RAM_OFFSET - 4 );
ENTRY (start)
MEMORY {
rom (rx) : ORIGIN = ROM_OFFSET, LENGTH = ROMSIZE
ram (!rx) : ORIGIN = RAM_OFFSET, LENGTH = RAMSIZE
}
SECTIONS {
.reset : { <PROJECTPATH>/obj/startup.o } > rom /* startup code */
.text : { *(.text) } > rom /* executable data */
.rodata : { *(.rodata) } > ram /* read only data */
.sdata : { *(.sdata) } > ram /* init vars */
.bss (NOLOAD) : { *(.bss) FILL(0x0f); } > ram /* uninit data */
}
файл разборки важных частей:
-in .text, начало main (): указатель массива должен храниться в стеке, я полагаю:
80: 000017b7 lui a5,0x1 # a5 = first ram addr: begin of .rodata
84: 0007a703 lw a4,0(a5) # a4 = content of this addr?!?!?!
88: fee42023 sw a4,-32(s0) # a4 gets stored on stack
-. Rodata, содержит значения массива:
Disassembly of section .rodata:
00001000 <.rodata>:
1000: 0100
1002: 0302
1004: 0504
...
100e: 0f0e
EDIT:
Мой ЦП имеет архитектуру havard и не может напрямую обращаться к данным из ПЗУ. Поэтому .rodata и .data должны быть в оперативной памяти. Мой подход заключается в том, что программный процесс записывает инструкции в ПЗУ, но также записывает .rodata и .data в ОЗУ. Моя реализация аппаратного обеспечения облегчает это. (Мой скрипт разделяет эти два блока данных двоичного файла и транскодирует его в протокол, который может обрабатывать мой программный модуль.)
И в двоичном на первый взгляд это работает: .text находится в адресном пространстве ПЗУ, а .rodata и .data - в адресном пространстве ОЗУ. Но адреса к .rodata, по подсчетам компоновщика, неверны.
Эта моя программа предназначена только для проверки ее функциональности, в противном случае я бы не стал писать такой код. (Флаг оптимизации также -o0.)
Итак, прежде всего, я хотел бы понять строки в начале main (), которые должны поместить указатель массива в стек.
80: 000017b7 lui a5,0x1 # a5 = first ram addr: begin of .rodata
84: 0007a703 lw a4,0(a5) # a4 = content of this addr?!?!?!
88: fee42023 sw a4,-32(s0) # a4 gets stored on stack
Почему компоновщик рассматривает начало .rodata как указатель на массив, а не как фактический адрес массива?