Digi 0 26 марта, 2020 Опубликовано 26 марта, 2020 · Жалоба Кто сможет объяснить особенности работы и подсказать правильную настройку компилятора и проца 1892ВМ10Я. Конфиг следующий: - Внешняя память SDRAM 32 бит, базовый адрес 0x80000000, kseg0 - ПЛИС с базовым адресом со стороны проца 0xA8000000 (обращение к её регистрам осуществляется как к памяти) Находится в не кэшируемой области. kseg1) До этого проект работал под uOS. Сейчас uOS убрал. Проблема такая: проект работает, но по не понятной причине вылетает с ошибкой Address Load, Addres Save. Вылетает очень редко, раз в несколько часов. Причём вылеты не зависят от того, что делает прога. (Хотя делает она всё время одно и то же). После того как убрал ОС, переписал обработчик прерывания, вылет локализовался. Происходит он в случае, когда я находясь в прерывании пытаюсь вызвать функцию у которой в качестве параметра передается double. Если вызываемая из прерывания функция ожидает тип данных не double, то работает нормально. Вылет (исключение) происходит с ошибкой Alddress Load и адрес указывает на стек. Та же самая функция, вызываемая не из прерывания работает нормально. double test(double a) // при вызове этой функции из прерывания - вылетает { return a*5; } double test(float a) // а эта работает нормально. { return a*5; } Кто может помочь работающими настройками, примером и.т.д. и вообще чем угодно ? PS: Я уже в полной растерянности. Кроме того как больше не применять такой проц - идей нет..... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 26 марта, 2020 Опубликовано 26 марта, 2020 · Жалоба 53 минуты назад, Digi сказал: После того как убрал ОС, переписал обработчик прерывания, вылет локализовался. Происходит он в случае, когда я находясь в прерывании пытаюсь вызвать функцию у которой в качестве параметра передается double. Стек не выровнен на 8? 56 минут назад, Digi сказал: PS: Я уже в полной растерянности. Кроме того как больше не применять такой проц - идей нет... Проц-то при чём? Он вашу программу не писал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 26 марта, 2020 Опубликовано 26 марта, 2020 · Жалоба 2 hours ago, jcxz said: Стек не выровнен на 8? Думал об этом. По идее я его задаю уже выровненым. Использовал скрипт линковщика из uOS и немного исправлял, добавив свою память и точку входа. Кстати память внешней ПЛИС я в линковщике не указывал. Это правильно ? Обращаюсь я к ПЛИС так : #define FPGA_BASE 0xA8000000 // KernekSeg2 uncashed #define MANUAL_FREQ_REGS (FPGA_BASE + 0x0004) int SetFrequency(uint32_t freq) { *(volatile unsigned*)(MANUAL_FREQ_REGS) = freq; return 1; } Привожу фрагменты кода. Вдруг что нибудь бросится в глаза. Spoiler Обработчик векторов и запуск .set mips32 .set noat .set noreorder .section .init .org 0 #------------------------------------------------ # Точка входа в программу # _start: .global _start # запрет прерываний. mfc0 $k0, $12 #C0_STATUS # Get SR nop andi $k1, $k0, 0x00000004 # check that here is after Reset/NMI bne $k1, $zero, _reset_is_by_reset_ nop la $k0, exception_refill # go to exception handle jr $k0 # Jump to _exception_TLBrefill_ nop _reset_is_by_reset_: # li $k0, -1 - 0x00000001 #ST_IE # Prepare bitmask # and $k0, $a0 # Clear IE bit # mtc0 $k0, $12 #C0_STATUS # Put SR back mtc0 $zero, $9 #C0_COUNT # Zero count registers (needed for RTL model) la $sp, _estack # Stack at end of internal SRAM lui $gp, 0xb840 # Set global pointer mfc0 $a0, $9 #C0_COUNT # Get CPU tick counter nop sw $a0, ($gp) # Store start time to XYRAM0 lui $gp, RAM_HI # Set global pointer la $t0, main # init code can be far away from reset/isr internal mem jr $t0 # Jump to _init_() nop #.org 0x180 .org 0x200 Interrupt: .globl Interrupt /* Сместить указатель стека на 31*4+24 байта вниз */ addiu $29,$29,-(31*4+24) /* Сохранить в стеке регистры 1-28,30,31 */ sw $1,(0)($29) sw $2,(4)($29) sw $3,(8)($29) sw $4,(12)($29) sw $5,(16)($29) sw $6,(20)($29) sw $7,(24)($29) sw $8,(28)($29) sw $9,(32)($29) sw $10,(36)($29) sw $11,(40)($29) sw $12,(44)($29) sw $13,(48)($29) sw $14,(52)($29) sw $15,(56)($29) sw $16,(60)($29) sw $17,(64)($29) sw $18,(68)($29) sw $19,(72)($29) sw $20,(76)($29) sw $21,(80)($29) sw $22,(84)($29) sw $23,(88)($29) sw $24,(92)($29) sw $25,(96)($29) sw $26,(100)($29) sw $27,(104)($29) sw $28,(108)($29) sw $30,(112)($29) sw $31,(116)($29) /* Вызов функции непосредственно обработчика */ la $26, int_handler jalr $26 nop /* Восстановить регистры 1-28,30,31 из стека */ lw $1,(0)($29) lw $2,(4)($29) lw $3,(8)($29) lw $4,(12)($29) lw $5,(16)($29) lw $6,(20)($29) lw $7,(24)($29) lw $8,(28)($29) lw $9,(32)($29) lw $10,(36)($29) lw $11,(40)($29) lw $12,(44)($29) lw $13,(48)($29) lw $14,(52)($29) lw $15,(56)($29) lw $16,(60)($29) lw $17,(64)($29) lw $18,(68)($29) lw $19,(72)($29) lw $20,(76)($29) lw $21,(80)($29) lw $22,(84)($29) lw $23,(88)($29) lw $24,(92)($29) lw $25,(96)($29) lw $26,(100)($29) lw $27,(104)($29) lw $28,(108)($29) lw $30,(112)($29) lw $31,(116)($29) /* Восстановить указатель стека */ addiu $29,$29,31*4+24 /* Возврат из прерывания */ eret nop Обработчик прерывания (сейчас обработчик предполагает, что прерывание могло быть только одно) void __attribute__ ((weak)) int_handler() // функция обработчика прерывваний { unsigned int ActiveIRQ0; unsigned int ActiveIRQ1; unsigned int ActiveIRQ2; volatile unsigned int tr; volatile unsigned int iir; unsigned int c_stat = mips_read_c0_register(C0_STATUS); mips_write_c0_register (C0_STATUS, c_stat & ~ST_IE); // Запрещаем прерывания ActiveIRQ0 = SYS_REG.QSTR0.data & SYS_REG.MASKR0.data; ActiveIRQ1 = SYS_REG.QSTR1.data & SYS_REG.MASKR1.data; ActiveIRQ2 = SYS_REG.QSTR2.data & SYS_REG.MASKR2.data; if ((ActiveIRQ0 & (1<<5)) !=0) //прерывание от uart422 { if((UART1.IIR.bits.IID & (1<<1)) !=0) //прерывание по приему { uart422_receiveData(); } else { uart422_transmitData(); } } else if ((ActiveIRQ0 & (1<<4)) !=0) //прерывание от uart485 { if((UART0.IIR.bits.IID & (1<<1)) !=0) //прерывание по приему uart485_receiveData (); else uart485_transmitData(); } else if (ActiveIRQ0 & (1 << 22)) // если есть прерывание от IT0 { IT0.ITCSR.bits.INT = 0; // сбрасываем флаг прерывания IT0.ITCSR.bits.EN = 1; // снова запускаем таймер ctl_task(); // -------Внутри этой функции вызывается другая функция, которая всё рушит } else { dump_of_death(); } c_stat = mips_read_c0_register(C0_STATUS); mips_write_c0_register (C0_STATUS, c_stat | ST_IE); //Enable interrupt } Инициализация CPU (тут не инициализирую внешнюю шину и PLL так как они были проинициализированы загрузчиком или отладчиком) { /* Clear CAUSE register. Use special irq vector. */ mips_write_c0_register (C0_CAUSE, CA_IV); // mips_write_c0_register (C0_CAUSE, 0); /* Initialize STATUS register: CP0 usable, * internal interrupts enabled, master interrupt enable. */ mips_write_c0_register (C0_STATUS, ST_CU0 | ST_CU1| ST_IM_QSTR0 | ST_IM_QSTR1 | ST_IM_QSTR2 | ST_IE); // Enable cache for kseg0 segment. mips_write_c0_register (C0_CONFIG, 3); MC_CSR |= MC_CSR_FLUSH_I | MC_CSR_FLUSH_D; // Jump to cached kseg0 segment. // asm volatile ( // "la $k0, 1f \n" // "jr $k0 \n" // "1:"); // mips_write_c0_register (C0_CONFIG, 2); // Diasable cache /* Clear all FPU registers. */ mips_write_fpu_control (C1_FCSR, 0); mips_write_fpu_register (0, 0); ...... mips_write_fpu_register (31, 0); /* Fixed mapping. */ MC_CSR = MC_CSR_FM; MC_ITCSR = 0; MC_ITCSR1 = 0; // MC_RTCSR = 0; MC_WTCSR = 0; MC_MASKR0 = 0; MC_MASKR1 = 0; MC_MASKR2 = 0; } И напоследок файл линкера /* * Linker script for MIPS32 Elvees Multicore */ /* Default linker script, for normal executables */ OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips", "elf32-littlemips") OUTPUT_ARCH(mips) ENTRY(_start) MEMORY { flash (rx) : ORIGIN = 0xbfc00000, LENGTH = 8M sdram_c(rwx) : ORIGIN = 0x80000000, LENGTH = 2M /* sdram_d(rwx) : ORIGIN = 0x80100000, LENGTH = 31M*/ cram (rw!x) : ORIGIN = 0x98000000, LENGTH = 128K xyram0 (rw!x) : ORIGIN = 0xb8400000, LENGTH = 128K pram0 (rw!x) : ORIGIN = 0xb8440000, LENGTH = 32K xyram1 (rw!x) : ORIGIN = 0xb8800000, LENGTH = 128K pram1 (rw!x) : ORIGIN = 0xb8840000, LENGTH = 32K xyram2 (rw!x) : ORIGIN = 0xb8c00000, LENGTH = 128K pram2 (rw!x) : ORIGIN = 0xb8c40000, LENGTH = 32K xyram3 (rw!x) : ORIGIN = 0xb9000000, LENGTH = 128K pram3 (rw!x) : ORIGIN = 0xb9040000, LENGTH = 32K } /* higher address of the user mode stack */ /*_estack = ORIGIN(sdram) + 0x10000 */ _estack = ORIGIN(cram) + LENGTH(cram); SECTIONS { /* Read-only sections, merged into text segment: */ . = 0x0000; .interp : { *(.interp) } .hash : { *(.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } .rel.init : { *(.rel.init) } .rela.init : { *(.rela.init) } .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } .rel.fini : { *(.rel.fini) } .rela.fini : { *(.rela.fini) } .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } .rel.ctors : { *(.rel.ctors) } .rela.ctors : { *(.rela.ctors) } .rel.dtors : { *(.rel.dtors) } .rela.dtors : { *(.rela.dtors) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .plt : { *(.plt) } .vecs : { *(.init) } > sdram_c .text : { _stext = .; *(.text .stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) *(.glue_7t) *(.glue_7) __rodata_start = . ; *(.rodata .rodata.* .gnu.linkonce.r.*) /* Align here to ensure that the .text section ends on word boundary. */ . = ALIGN (64 / 8); _etext = .; } > sdram_c /* Start data (internal SRAM). */ .data : AT (ADDR (.text) + SIZEOF (.text)) { __data_start = . ; _gp = .; /* We have only 32k RAM on MC-24, so no need for 0x8000 offset. */ *(.data .data.* .gnu.linkonce.d.*) /* We want the small data sections together, so single-instruction offsets can access them all, and initialized data all before uninitialized, so we can shorten the on-disk segment size. */ *(.sdata .sdata.* .gnu.linkonce.s.*) *(.eh_frame) _edata = .; } > sdram_c .bss ADDR (.data) + SIZEOF (.data) (NOLOAD) : { __bss_start = .; *(.dynbss) *(.sbss) *(.scommon) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to _end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. */ . = ALIGN (32 / 8); } > sdram_c __bss_end = . ; _end = .; .DSP0_data : { * (.DSP0_data); . = ALIGN (32 / 8); } > xyram0 .DSP0_bss ADDR(.DSP0_data) + SIZEOF(.DSP0_data) (NOLOAD) : { *(.DSP0_bss); } > xyram0 .DSP0_text : { * (.DSP0_text); } > pram0 .DSP1_data : { * (.DSP1_data); . = ALIGN (32 / 8); } > xyram1 .DSP1_bss ADDR(.DSP1_data) + SIZEOF(.DSP1_data) (NOLOAD): { *(.DSP1_bss); } > xyram1 .DSP1_text : { * (.DSP1_text); } > pram1 .DSP2_data : { * (.DSP2_data); . = ALIGN (32 / 8); } > xyram2 .DSP2_bss ADDR(.DSP2_data) + SIZEOF(.DSP2_data) (NOLOAD) : { *(.DSP2_bss); } > xyram2 .DSP2_text : { * (.DSP2_text); } > pram2 .DSP3_data : { * (.DSP3_data); . = ALIGN (32 / 8); } > xyram3 .DSP3_bss ADDR(.DSP3_data) + SIZEOF(.DSP3_data) (NOLOAD): { *(.DSP3_bss); } > xyram3 .DSP3_text : { * (.DSP3_text); } > pram3 //_estack = (ADDR (.bss) + SIZEOF (.bss) + 0x10000) & ~ (0x7) ;/* stack size */ //_mempool_start = (ADDR (.bss) + SIZEOF (.bss) + 0x7) & ~ (0x7); /*_mempool_start = (ADDR (.text) + SIZEOF (.text) + 0x7) & ~(0x7);*/ /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 26 марта, 2020 Опубликовано 26 марта, 2020 · Жалоба 4 minutes ago, Digi said: Сместить указатель стека на 31*4+24 байта вниз (31*4+24)/8=18.5 Получается, после прохождения пролога стек не выровнен? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 27 марта, 2020 Опубликовано 27 марта, 2020 · Жалоба 12 hours ago, aaarrr said: (31*4+24)/8=18.5 Получается, после прохождения пролога стек не выровнен? Оказывается - да. В Элвисовском примере оказалась засада. С этой проблемой вопрос наверное решён. ))) Всем огромное спасибо !!! Исправил вот так. Spoiler .org 0x200 Interrupt: .globl Interrupt /* Сместить указатель стека на 31*4+28 байта вниз */ addiu $29,$29,-(31*4+28) <--- /* Сохранить в стеке регистры 1-28,30,31 */ sw $1,(0)($29) sw $2,(4)($29) sw $3,(8)($29) sw $4,(12)($29) sw $5,(16)($29) sw $6,(20)($29) sw $7,(24)($29) sw $8,(28)($29) sw $9,(32)($29) sw $10,(36)($29) sw $11,(40)($29) sw $12,(44)($29) sw $13,(48)($29) sw $14,(52)($29) sw $15,(56)($29) sw $16,(60)($29) sw $17,(64)($29) sw $18,(68)($29) sw $19,(72)($29) sw $20,(76)($29) sw $21,(80)($29) sw $22,(84)($29) sw $23,(88)($29) sw $24,(92)($29) sw $25,(96)($29) sw $26,(100)($29) sw $27,(104)($29) sw $28,(108)($29) sw $30,(112)($29) sw $31,(116)($29) /* Вызов функции непосредственно обработчика */ la $26, int_handler jalr $26 nop /* Восстановить регистры 1-28,30,31 из стека */ lw $1,(0)($29) lw $2,(4)($29) lw $3,(8)($29) lw $4,(12)($29) lw $5,(16)($29) lw $6,(20)($29) lw $7,(24)($29) lw $8,(28)($29) lw $9,(32)($29) lw $10,(36)($29) lw $11,(40)($29) lw $12,(44)($29) lw $13,(48)($29) lw $14,(52)($29) lw $15,(56)($29) lw $16,(60)($29) lw $17,(64)($29) lw $18,(68)($29) lw $19,(72)($29) lw $20,(76)($29) lw $21,(80)($29) lw $22,(84)($29) lw $23,(88)($29) lw $24,(92)($29) lw $25,(96)($29) lw $26,(100)($29) lw $27,(104)($29) lw $28,(108)($29) lw $30,(112)($29) lw $31,(116)($29) /* Восстановить указатель стека */ addiu $29,$29,31*4+28 <--- /* Возврат из прерывания */ eret nop Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ELVEES R&D Center 0 27 марта, 2020 Опубликовано 27 марта, 2020 · Жалоба Добрый день! Спасибо коллегам, которые помогли решить проблему до нашего участия. Выглядит так, что проблема была действительно связана с выравниванием стека. Мы обновим процедуру сохранения контекста в наших примерах, спасибо за указание на проблему. Предполагаемый обновленный обработчик прилагаем. Там также добавлен сброс кэша, сохранение части регистров CP0 и некоторые другие вещи. Если планируется работать с float/double - нужно также сохранять в обработчике регистры FPU. Пока мы этого не добавили в обработчик, чтобы не перегружать его. Возможно, добавим. Если кому-то интересна причина, почему сейчас такое сохранение контекста в примерах, то даём пояснение: он создавался достаточно давно, когда в наших чипах CPU-ядро не имело сопроцессора FPU. Соответственно, у CPU не было 64-разрядных обращений в память, только 32-разрядные (инструкции LW/SW) - и выравнивания по 32-разрядному слову было достаточно. С появлением FPU появились 64-разрядные обращения (SDC1/LDC1) - появилась необходимость выравнивать стек по границе 64-разрядного слова. Но поскольку примеры в составе IDE демонстрируют узконаправленную работу с конкретным блоком - в примерах этой проблемы не всплывало. Теперь обновим, еще раз спасибо за указание на проблему. hb80000180.s Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 27 марта, 2020 Опубликовано 27 марта, 2020 · Жалоба Тем не менее проблема сохранилась, но уже более сложно диагностируемая. Опять появляется ошибка, но теперь - Address Save и указывает на адреса 0x0000****. Пока пытаюсь найти, что вызывает эту ошибку. Проявляется достаточно редко. Попробую добавить так же и сохранение регистров FPU Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ELVEES R&D Center 0 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба 1) Включено ли кэширование в Вашем проекте? Если включено - то сбрасывается ли кэш в обработчике прерываний? 2) Вероятно, стоит сразу указывать, какое значение у регистра CP0.EPC при возникновении исключения? Что за код находится по этому адресу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба 2 hours ago, ELVEES R&D Center said: 1) Включено ли кэширование в Вашем проекте? Если включено - то сбрасывается ли кэш в обработчике прерываний? 2) Вероятно, стоит сразу указывать, какое значение у регистра CP0.EPC при возникновении исключения? Что за код находится по этому адресу? 1) Да, кэширование включено. Использую сейчас ваш обработчик прерываний. В нём кэш сбразывается. 2) Возникновение исключения - это уже следствие. Перед тем как возникнуть исключению, происходит изменение переменной, которое меняться не должно. Это происходит через случайное время и только если я из прерывания пытаюсь вызывать какую либо функцию. Даже пустую. void int_handler() // функция обработчика прерывваний { ActiveIRQ0 = SYS_REG.QSTR0.data & SYS_REG.MASKR0.data; ActiveIRQ1 = SYS_REG.QSTR1.data & SYS_REG.MASKR1.data; ActiveIRQ2 = SYS_REG.QSTR2.data & SYS_REG.MASKR2.data; if (ActiveIRQ0 & (1 << 22)) // если есть прерывание от IT0 { IT0.ITCSR.bits.INT = 0; // сбрасываем флаг прерывания IT0.ITCSR.bits.EN = 1; // снова запускаем таймер timer_update(); } volatile unsigned int curr_time_msec; void timer_update() { // curr_time_msec++; } Если timer_update() не вызывать, а вместо этого написать curr_time_msec++ то работает. Но стоит вызвать любую функцию из прерывания, то через некоторое время - ошибка. А почему не сохраняются регистры k0 и k1, разве они в основном Си коде не используются ? timer_update: 800012d4: addiu sp,sp,-8 800012d8: sw s8,4(sp) 800012dc: move s8,sp 30 } 800012e0: move sp,s8 800012e4: lw s8,4(sp) 800012e8: nop 800012ec: addiu sp,sp,8 800012f0: jr ra 800012f4: nop В функции timer_update ничего криминального не вижу. Ещё вопрос, почему после eret ещё есть команды , если я правильно понимаю, то после eret ничего не будет выполнятся. ...... addi $sp, 32*4 # Deallocate saved context # Return from exception .set mips3 sync # settle things down eret # PC <= EPC; EXL <= 0 nop # just to be safe mfc0 $k1, $14 #save epc in gp 27 mfc0 $k0, $12 # Get STATUS xori $k0, 0x2 # allow interupts after eret mtc0 $k0, $12 # Put SR back nop j $k1 #go continue nop .set mips0 fault_exeption: FLUSH_CACHE SAVE_REGS # Save all registers in stack move $a0, $sp # Arg0: pointer to saved state lui $gp, RAM_HI # Set global pointer la $k0, fault_handler #exception code can be far away from internal memory jr $k0 # Jump to C code, no return Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ELVEES R&D Center 0 30 марта, 2020 Опубликовано 30 марта, 2020 (изменено) · Жалоба Тут сложный момент. С одной стороны, правильнее сохранять все регистры. С другой стороны, кэш надо сбрасывать сразу при входе в обработчик. Здесь нам на помощь приходит MIPS ABI (application binary interface) - соглашение, по которому регистры k0, k1 используются именно что в обработчиках, а в основной программе не используются. Поэтому мы вроде бы безбоязненно можем "портить" эти регистры. По факту GCC по умолчанию это требование не выполняет и вполне может использовать эти регистры. Чтобы он этого не делал, есть ключ -ffixed. В наших проектах для MCStudio 4 как раз по умолчанию выставлены ключи GCC " -ffixed-k0 -ffixed-k1". Возможно, их по какой-то причине нет в Вашем проекте? Покажете лог сборки на всякий случай? Еще как вариант - может, просто где-то что-то не так с сохранением и восстановлением стека? В какой-то момент он сдвигается за границы допустимого и все портится? Или, совсем уж простое - размер стека физически "вылезает" за границы доступной физически памяти? Чему равно значение sp в момент исключения? Чему равно значение символа _stack и размер стека в настройках проекта? В функции действительно ничего криминального нет. Изменено 30 марта, 2020 пользователем ELVEES R&D Center Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба 15 minutes ago, ELVEES R&D Center said: В наших проектах для MCStudio 4 как раз по умолчанию выставлены ключи GCC " -ffixed-k0 -ffixed-k1". Возможно, их по какой-то причине нет в Вашем проекте? Покажете лог сборки на всякий случай? Еще как вариант - может, просто где-то что-то не так с сохранением и восстановлением стека? В какой-то момент он сдвигается за границы допустимого и все портится? Или, совсем уж простое - размер стека физически "вылезает" за границы доступной физически памяти? Чему равно значение sp в момент исключения? Чему равно значение символа _stack и размер стека в настройках проекта? Когда значение переменной уже испорчено стек равен 0x9801ffe8. Вроде в норме. cram (rw!x) : ORIGIN = 0x98000000, LENGTH = 128K _estack = ORIGIN(cram) + LENGTH(cram); В CRAM кроме стека никто больше не обращается и не находится. Весь код и переменные в SDRAM. Видимо не там ищу. В коде используются некоторые моменты типа for (set = 0; n = *p++;) ... while (ch = *p++) ... это не ошибка, вроде так задумано (взято из готовых библиотек), проверю на всякий случай. Spoiler 17:53:22 **** Build of configuration MultiCore_Configuration_Debug for project PRIN_v2 **** make pre-build main-build Update version cmd /c "..\nbuild.bat" Building file: ../S_FIR.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "S_FIR.o" "../S_FIR.c" Finished building: ../S_FIR.c Building file: ../_main.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "_main.o" "../_main.c" ../_main.c: In function 'dump_of_death': ../_main.c:182:3: warning: implicit declaration of function 'debug_printf' [-Wimplicit-function-declaration] debug_printf ("'%s'\n", code); ^ Finished building: ../_main.c Building file: ../control.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "control.o" "../control.c" ../control.c: In function 'createVersionAns': ../control.c:76:26: warning: comparison between pointer and integer [enabled by default] if (current_uart->port ==1) ^ ../control.c:77:6: warning: implicit declaration of function 'uart422_startTransmit' [-Wimplicit-function-declaration] uart422_startTransmit(); ^ ../control.c:79:6: warning: implicit declaration of function 'uart485_startTransmit' [-Wimplicit-function-declaration] uart485_startTransmit(); ^ ../control.c:37:16: warning: unused variable 'time_day' [-Wunused-variable] unsigned long time_day; ^ ../control.c:670:5: warning: implicit declaration of function 'memcpy' [-Wimplicit-function-declaration] memcpy( uart422.tx_packet.pkt_buffer.p_buffer, ^ ../control.c:670:5: warning: incompatible implicit declaration of built-in function 'memcpy' [enabled by default] ../control.c:685:3: warning: incompatible implicit declaration of built-in function 'memcpy' [enabled by default] memcpy( uart485.tx_packet.pkt_buffer.p_buffer, ^ Finished building: ../control.c Building file: ../dprint.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "dprint.o" "../dprint.c" ../dprint.c:6:10: warning: type defaults to 'int' in declaration of 'debug_lock' [-Wimplicit-int] volatile debug_lock=0; ^ ../dprint.c: In function 'dprintf': ../dprint.c:224:4: warning: suggest parentheses around assignment used as truth value [-Wparentheses] for (set = 0; n = *p++;) { ^ ../dprint.c:242:4: warning: suggest parentheses around assignment used as truth value [-Wparentheses] while (ch = *p++) ^ ../dprint.c:276:2: warning: implicit declaration of function 'va_end' [-Wimplicit-function-declaration] va_end(ap); ^ ../dprint.c: In function 'debug_printf': ../dprint.c:314:4: warning: suggest parentheses around assignment used as truth value [-Wparentheses] for (set = 0; n = *p++;) { ^ ../dprint.c:332:4: warning: suggest parentheses around assignment used as truth value [-Wparentheses] while (ch = *p++) ^ Finished building: ../dprint.c Building file: ../format.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "format.o" "../format.c" Finished building: ../format.c Building file: ../handler.s Invoking: RISC Assembler - mipsel-elf32-as "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-as -G0 -mips32 --mc24r2 --defsym ELVEES_NVCOM02T=1 -EL -mhard-float -g --gdwarf-2 -o "handler.o" "../handler.s" Finished building: ../handler.s Building file: ../hardware.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "hardware.o" "../hardware.c" ../hardware.c: In function 'SetGlobalShift': ../hardware.c:153:2: warning: type defaults to 'int' in type name [-Wimplicit-int] *(volatile *)(GLOBAL_SHIFT_REGS) = stim; ^ ../hardware.c: In function 'WatchdogEnable': ../hardware.c:684:2: warning: implicit declaration of function 'dprintf' [-Wimplicit-function-declaration] dprintf(" !!!! WARNING Watchdog is DISABLED !!!! "); ^ Finished building: ../hardware.c Building file: ../reciever.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "reciever.o" "../reciever.c" ../reciever.c:111:1: warning: missing braces around initializer [-Wmissing-braces] -1.46356292920526, 0.979887134766506, //канал А ^ ../reciever.c:111:1: warning: (near initialization for 'coeffA[0]') [-Wmissing-braces] ../reciever.c: In function 'calcTime': ../reciever.c:742:49: warning: variable 'point_left' set but not used [-Wunused-but-set-variable] int point_1, point_2, hires_point, point_right, point_left; ^ ../reciever.c: In function 'checkNoiseInPause': ../reciever.c:798:2: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses] if ( (st_state_bits & 0x1 == 1) && (head_stat_data.n_good_comps >=2) ) //как только найдем ВЩ станцию ^ ../reciever.c: In function 'CalcStatusNemanSignal': ../reciever.c:858:28: warning: unused variable 'lidx' [-Wunused-variable] uint32_t m_start, m_end, lidx; ^ ../reciever.c:858:21: warning: unused variable 'm_end' [-Wunused-variable] uint32_t m_start, m_end, lidx; ^ ../reciever.c:858:12: warning: unused variable 'm_start' [-Wunused-variable] uint32_t m_start, m_end, lidx; ^ ../reciever.c:856:17: warning: unused variable 'ival1' [-Wunused-variable] int32_t ival, ival1; ^ ../reciever.c: In function 'AnalizNemanSignal': ../reciever.c:1143:1: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses] if (st_state_bits & 0x7f == 0x7f) LedOn(1); ^ ../reciever.c:1143:1: warning: implicit declaration of function 'LedOn' [-Wimplicit-function-declaration] ../reciever.c:1144:2: warning: implicit declaration of function 'LedOff' [-Wimplicit-function-declaration] else LedOff(1); ^ ../reciever.c:1158:12: warning: implicit declaration of function 'abs' [-Wimplicit-function-declaration] if (abs(cycle_error_time) > 400000 ) { ^ ../reciever.c:961:11: warning: unused variable 'peak_point' [-Wunused-variable] uint32_t peak_point, peak_level, avr_level; ^ ../reciever.c: In function 'SearchNemanSignal': ../reciever.c:1480:27: warning: unused variable 'msx_lev_prev' [-Wunused-variable] uint32_t max_lev, msx_lev_prev; ^ ../reciever.c:1479:83: warning: unused variable 'corr_point' [-Wunused-variable] uint32_t m_start, m_end, ncomp, n_st, det_ncomp[6][23*3], max_point, ptr, corr_point[6][23*3]; ^ ../reciever.c:1479:67: warning: variable 'max_point' set but not used [-Wunused-but-set-variable] uint32_t m_start, m_end, ncomp, n_st, det_ncomp[6][23*3], max_point, ptr, corr_point[6][23*3]; ^ ../reciever.c:1363:22: warning: unused variable 'n_cmp' [-Wunused-variable] int i, j, k, n_stn, n_cmp; ^ ../reciever.c:1363:15: warning: unused variable 'n_stn' [-Wunused-variable] int i, j, k, n_stn, n_cmp; ^ ../reciever.c: In function 'rcv_task': ../reciever.c:1618:7: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses] if ( (!auto_set_oi_freq) && (st_state_bits & 0x1 == 1) && (head_stat_data.n_good_comps >=2) ) ^ ../reciever.c:1876:18: warning: implicit declaration of function 'createEndCalibrAns' [-Wimplicit-function-declaration] createEndCalibrAns(); ^ ../reciever.c:1899:12: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses] if ( (!auto_set_oi_freq) && (st_state_bits & 0x1 == 1) && (head_stat_data.n_good_comps >=2) ) //если найдена ВЩ станция ^ ../reciever.c:1977:12: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses] if ( (auto_set_oi_freq) && (st_state_bits & 0x1 == 1) && (head_stat_data.n_good_comps >=2) ) //если найдена ВЩ станция и вкл подстройка частоты ои ^ ../reciever.c:1990:16: warning: implicit declaration of function 'createAutoFreqOIAns' [-Wimplicit-function-declaration] createAutoFreqOIAns(); ^ ../reciever.c:2064:4: warning: passing argument 2 of 'S_FIR_Filtering' from incompatible pointer type [enabled by default] fl_im_bank[size_bank] = S_FIR_Filtering(im_dat, i_state); ^ In file included from ../reciever.c:6:0: ../S_FIR.h:44:5: note: expected 'S_FIR_State' but argument is of type 'I32 **' I32 S_FIR_Filtering (I32 sampleIn, S_FIR_State state); ^ ../reciever.c:2065:4: warning: passing argument 2 of 'S_FIR_Filtering' from incompatible pointer type [enabled by default] fl_re_bank[size_bank] = S_FIR_Filtering(re_dat, q_state); ^ In file included from ../reciever.c:6:0: ../S_FIR.h:44:5: note: expected 'S_FIR_State' but argument is of type 'I32 **' I32 S_FIR_Filtering (I32 sampleIn, S_FIR_State state); ^ ../reciever.c:2070:4: warning: passing argument 2 of 'S_FIR_Filtering' from incompatible pointer type [enabled by default] fl_im_bank2[size_bank] = S_FIR_Filtering(im_dat2, i_state2); ^ In file included from ../reciever.c:6:0: ../S_FIR.h:44:5: note: expected 'S_FIR_State' but argument is of type 'I32 **' I32 S_FIR_Filtering (I32 sampleIn, S_FIR_State state); ^ ../reciever.c:2071:4: warning: passing argument 2 of 'S_FIR_Filtering' from incompatible pointer type [enabled by default] fl_re_bank2[size_bank] = S_FIR_Filtering(re_dat2, q_state2); ^ In file included from ../reciever.c:6:0: ../S_FIR.h:44:5: note: expected 'S_FIR_State' but argument is of type 'I32 **' I32 S_FIR_Filtering (I32 sampleIn, S_FIR_State state); ^ ../reciever.c: In function 'reciever_task_init': ../reciever.c:2128:2: warning: passing argument 1 of 'S_FIR_InitState' from incompatible pointer type [enabled by default] S_FIR_InitState (i_state); ^ In file included from ../reciever.c:6:0: ../S_FIR.h:41:6: note: expected 'S_FIR_State' but argument is of type 'I32 **' void S_FIR_InitState (S_FIR_State state); ^ ../reciever.c:2129:2: warning: passing argument 1 of 'S_FIR_InitState' from incompatible pointer type [enabled by default] S_FIR_InitState (q_state); ^ In file included from ../reciever.c:6:0: ../S_FIR.h:41:6: note: expected 'S_FIR_State' but argument is of type 'I32 **' void S_FIR_InitState (S_FIR_State state); ^ Finished building: ../reciever.c Building file: ../system.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "system.o" "../system.c" ../system.c: In function 'initMport1': ../system.c:49:5: warning: large integer implicitly truncated to unsigned type [-Woverflow] MFBSP1.DIR.bits.LDAT_DIR = 0x3ff; // Линия управления RX/TX на RS485 ^ Finished building: ../system.c Building file: ../uart422.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "uart422.o" "../uart422.c" ../uart422.c: In function 'uart422_receiveData': ../uart422.c:8:3: warning: implicit declaration of function 'uart422_receiveByte' [-Wimplicit-function-declaration] unsigned char c= uart422_receiveByte(); ^ ../uart422.c: In function 'uart422_startTransmit': ../uart422.c:68:2: warning: implicit declaration of function 'uart422_sendByte' [-Wimplicit-function-declaration] uart422_sendByte (0xff); // Send start marker ^ ../uart422.c: In function 'uart422_transmitData': ../uart422.c:80:4: warning: implicit declaration of function 'disable_transmit_interrupt_uart422' [-Wimplicit-function-declaration] disable_transmit_interrupt_uart422(); ^ ../uart422.c:82:4: warning: 'return' with a value, in function returning void [enabled by default] return 0; ^ ../uart422.c:105:5: warning: 'return' with a value, in function returning void [enabled by default] return 1; // и выходим, потому что отправка должна быть толлько один раз за прерывание ^ ../uart422.c: In function 'uart422_init': ../uart422.c:148:15: warning: assignment makes pointer from integer without a cast [enabled by default] uart422.port = 1; ^ ../uart422.c:150:2: warning: implicit declaration of function 'uart422_conf' [-Wimplicit-function-declaration] uart422_conf( baud, hz); ^ Finished building: ../uart422.c Building file: ../uart485.c Invoking: RISC C Compiler - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -DELVEES_NVCOM02T -O0 -g -gdwarf-2 -Wall -EL -mhard-float -DARCH_HAVE_FPU -c -fmessage-length=0 -G0 -mips32 -ffixed-k0 -ffixed-k1 -mno-check-zero-division -fno-delayed-branch -Xassembler --mc24r2 -o "uart485.o" "../uart485.c" ../uart485.c: In function 'uart485_receiveData': ../uart485.c:9:3: warning: implicit declaration of function 'uart485_receiveByte' [-Wimplicit-function-declaration] unsigned char c=uart485_receiveByte(); ^ ../uart485.c:20:4: warning: implicit declaration of function 'LedOn' [-Wimplicit-function-declaration] LedOn(4); ^ ../uart485.c:36:7: warning: implicit declaration of function 'LedOff' [-Wimplicit-function-declaration] LedOff(4); ^ ../uart485.c: In function 'uart485_startTransmit': ../uart485.c:67:2: warning: implicit declaration of function 'RS485_SetTxMode' [-Wimplicit-function-declaration] RS485_SetTxMode(); ^ ../uart485.c:73:2: warning: implicit declaration of function 'uart485_sendByte' [-Wimplicit-function-declaration] uart485_sendByte (0xff); // Send start marker ^ ../uart485.c: In function 'uart485_transmitData': ../uart485.c:88:6: warning: implicit declaration of function 'disable_transmit_interrupt_uart485' [-Wimplicit-function-declaration] disable_transmit_interrupt_uart485(); ^ ../uart485.c:90:6: warning: implicit declaration of function 'RS485_SetRxMode' [-Wimplicit-function-declaration] RS485_SetRxMode(); ^ ../uart485.c:91:6: warning: 'return' with a value, in function returning void [enabled by default] return 0; ^ ../uart485.c:129:5: warning: 'return' with a value, in function returning void [enabled by default] return 1; // и выходим, потому что отправка должна быть только один раз за прерывание ^ ../uart485.c: In function 'uart485_init': ../uart485.c:175:2: warning: implicit declaration of function 'initMport1' [-Wimplicit-function-declaration] initMport1(); // Init RX/TX control ^ ../uart485.c:180:2: warning: implicit declaration of function 'uart485_conf' [-Wimplicit-function-declaration] uart485_conf( baud, hz); ^ Finished building: ../uart485.c Building file: ../Dsp0.s0 Invoking: DSP0 Assembler - elcore-elvees-elf32-as "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcore-elvis-elf-as -mcx7b --gdwarf-2 -o "Dsp0.x0" "../Dsp0.s0" Finished building: ../Dsp0.s0 Invoking: DSP0 Linker - elcore-elvis-elf-ld "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcore-elvis-elf-ld -e 0 -t -N --no-warn-mismatch -T DSP0.xl __DSPX__.xx -o "__DSP0__.o0" ./Dsp0.x0 c:\elvees\MCStudio4_NVCom-02T_2019.07_175\ToolsDSP\bin\elcore-elvis-elf-ld.exe: mode elf32elcore ./Dsp0.x0 __DSPX__.xx Finished building: __DSP0__.o0 Invoking: DSP0 Objcopy - elcopy "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcopy -L xxx --strip-debug __DSP0__.o0 "__DSP0__.o" Finished building: __DSP0__.o Building file: ../Dsp1.s1 Invoking: DSP1 Assembler - elcore-elvees-elf32-as "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcore-elvis-elf-as -mcx7b --gdwarf-2 -o "Dsp1.x1" "../Dsp1.s1" Finished building: ../Dsp1.s1 Invoking: DSP1 Linker - elcore-elvis-elf-ld "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcore-elvis-elf-ld -e 0 -t -N --no-warn-mismatch -T DSP1.xl __DSPX__.xx -o "__DSP1__.o1" ./Dsp1.x1 c:\elvees\MCStudio4_NVCom-02T_2019.07_175\ToolsDSP\bin\elcore-elvis-elf-ld.exe: mode elf32elcore ./Dsp1.x1 __DSPX__.xx Finished building: __DSP1__.o1 Invoking: DSP1 Objcopy - elcopy "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcopy -L xxx --strip-debug __DSP1__.o1 "__DSP1__.o" Finished building: __DSP1__.o Invoking: DSP2 Linker - elcore-elvis-elf-ld "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcore-elvis-elf-ld -e 0 -t -N --no-warn-mismatch -T DSP2.xl __DSPX__.xx -o "__DSP2__.o2" c:\elvees\MCStudio4_NVCom-02T_2019.07_175\ToolsDSP\bin\elcore-elvis-elf-ld.exe: mode elf32elcore __DSPX__.xx Finished building: __DSP2__.o2 Invoking: DSP2 Objcopy - elcopy "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcopy -L xxx --strip-debug __DSP2__.o2 "__DSP2__.o" BFD: __DSP2__.o2: warning: Empty loadable segment detected, is this intentional ? Finished building: __DSP2__.o Invoking: DSP3 Linker - elcore-elvis-elf-ld "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcore-elvis-elf-ld -e 0 -t -N --no-warn-mismatch -T DSP3.xl __DSPX__.xx -o "__DSP3__.o3" c:\elvees\MCStudio4_NVCom-02T_2019.07_175\ToolsDSP\bin\elcore-elvis-elf-ld.exe: mode elf32elcore __DSPX__.xx Finished building: __DSP3__.o3 Invoking: DSP3 Objcopy - elcopy "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsDSP/bin/elcopy -L xxx --strip-debug __DSP3__.o3 "__DSP3__.o" BFD: __DSP3__.o3: warning: Empty loadable segment detected, is this intentional ? Finished building: __DSP3__.o Building target: PRIN_v2.elf Invoking: MultiCore Linker - mipsel-elf32-gcc "c:\\elvees\\MCStudio4_NVCom-02T_2019.07_175"/ToolsMGCC/bin/mipsel-elf32-gcc -nostartfiles -LD:\elvees\MCStudio4_NVCom-02T_2019.07_175\ToolsMGCC\mipsel-elf32\lib\ -T ../ldscripts/code-sdram-data-sdram-i-d-cache.ld -Xlinker -Map=output.map -EL -mhard-float -o "PRIN_v2.elf" ./S_FIR.o ./_main.o ./control.o ./dprint.o ./format.o ./handler.o ./hardware.o ./math.o ./reciever.o ./stdc.o ./system.o ./uart422.o ./uart485.o __DSP0__.o __DSP1__.o __DSP2__.o __DSP3__.o -lm -lc c:/elvees/mcstudio4_nvcom-02t_2019.07_175/toolsmgcc/bin/../lib/gcc/mipsel-elf32/4.8.1/../../../../mipsel-elf32/bin/ld.exe: warning: ../ldscripts/code-sdram-data-sdram-i-d-cache.ld contains output sections; did you forget -T? Finished building target: PRIN_v2.elf 17:53:29 Build Finished (took 6s.883ms) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ELVEES R&D Center 0 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба 1) Значение указателя стека в пределах, но как-то очень уж маленькое. Верхушка стека, выходит, 0x9802_0000, а указатель сдвинут на 0x18 байт. Маловато как-то. Вход в каждую функцию сдвигает указатель стека еще немного вниз относительно верхушки. Если исключение происходит, когда мы находимся в main(), то выглядит нормой, а если хоть немного "глубже" в функциях - то уже нет. Пока выглядит лишним аргументом в пользу некорректного восстановления контекста. Можно поставить точки останова перед сохранением и после восстановления контекста, убедиться, что значение sp не меняется. Ну и надо понять, какое штатное значение указателя стека при штатном входе в функцию, из которой происходит исключение. 2) По логу сборки вроде особо нечего пока сказать. 3) По коду после ERET - штатно он действительно не исполняется. Введён из каких-то соображений, которые сейчас нет смысла уточнять, а навскидку вспомнить не получается. Это скорее всего никак не связано с обсуждаемой проблемой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 31 марта, 2020 Опубликовано 31 марта, 2020 · Жалоба Причину падения нашёл. Её вызывает эта строчка st_stat_data[0].peak_levels[9] = 155; При её вызове перезаписывается переменная volatile uint16_t period_ms_cdg5; Разве я делаю неправильное обращение ? При выполнении записи пишет по адресу 0x8001d7f4 хотя, судя по регистрам, должен по другому адресу записать. Описана структура вот так: volatile typedef struct _station_status { double mean_comp_shift; uint32_t mean_levels[23]; uint32_t peak_levels[23]; uint32_t noise_levels[23]; uint8_t good_comps[23]; uint32_t comp_edges[23*2]; uint8_t n_good; uint8_t status_synhro[3]; //1й бит - цикл найден, 2й - точная подстройка выполнена, 3й - подстройка ои выполнена //float mean_phases[23]; } station_status; station_status st_stat_data[4]; map файл .scommon 0x000000008001d7e8 0x2c ./control.o 0x000000008001d7e8 alive_skip 0x000000008001d7ec portAnsCalibr 0x000000008001d7f0 prev_xtime 0x000000008001d7f4 period_ms_cdg5 0x000000008001d7f6 portAnsAutoFreqOI 0x000000008001d7f8 xtick_cntr 0x000000008001d7fc curr_time_msec 0x000000008001d800 addrDSTAnsAutoFreqOI 0x000000008001d804 xtime .... *(COMMON) COMMON 0x000000008001d940 0x7d0 ./_main.o 0x000000008001d940 st_stat_data 0x000000008001e100 head_stat_data COMMON 0x000000008001e110 0x80000 ./dprint.o 0x000000008001e110 Data COMMON 0x000000008009e110 0x0 ./hardware.o COMMON 0x000000008009e110 0x145478 ./reciever.o 0x000000008009e110 re_bank2 Дизассемблер: 999 st_stat_data[0].peak_levels[9] = 155; 0x8000fd0c: lui v0,0x8002 0x8000fd10: addiu v0,v0,-10600 0x8000fd14: li v1,155 0x8000fd18: sw v1,136(v0) v0 = 0x8001d698 v1 = 155 Вот ещё добавил запись двух переменных, пишет в одно и тоже место. В симуляторе эффект тот же. 366 period_ms_cdg5 =154; 0x800012ac: lui v0,0x8002 0x800012b0: li v1,154 0x800012b4: sh v1,-10440(v0) 367 st_stat_data[0].peak_levels[9] = 155; 0x800012b8: lui v0,0x8002 0x800012bc: addiu v0,v0,-10576 0x800012c0: li v1,155 0x800012c4: sw v1,136(v0) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ELVEES R&D Center 0 31 марта, 2020 Опубликовано 31 марта, 2020 · Жалоба Судя по приведенным кускам дизассемблера в конце, тут вопрос не к процессору, а к компоновке программы. Потому что обе записи происходят по адресу (0x8002_0000-10440). По какой-то причине при сборке обоим символам назначаются одинаковые адреса. Процессор лишь исправно выполняет запись по неправильно указанному адресу, что в симуляторе, что на живом чипе :) Я бы сказал, что MAP-файл тут малоинформативен. Можете дать ELF-файл или (лучше) проект целиком? Можно на [email protected]. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Digi 0 31 марта, 2020 Опубликовано 31 марта, 2020 · Жалоба Попробую упростить проект и перешлю. Но описание структуры и обращение к ней у меня правильно реализовано ? Или я что то не так понял и делаю недопустимые действия ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться