Jump to content

    
Sign in to follow this  
Digi

Нужна помощь по MIPS точнее 1892ВМ10Я

Recommended Posts

Кто сможет объяснить особенности работы и подсказать правильную настройку компилятора и проца 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: Я уже в полной растерянности.  Кроме того как больше не применять такой проц - идей нет.....

Share this post


Link to post
Share on other sites
53 минуты назад, Digi сказал:

После того как убрал ОС, переписал обработчик прерывания, вылет локализовался. Происходит он в случае, когда я находясь в прерывании пытаюсь вызвать функцию у которой в качестве параметра передается double.

Стек не выровнен на 8?

56 минут назад, Digi сказал:

PS: Я уже в полной растерянности.  Кроме того как больше не применять такой проц - идей нет...

Проц-то при чём? Он вашу программу не писал.

Share this post


Link to post
Share on other sites
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) }
} 

 

Share this post


Link to post
Share on other sites
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

 

 

 

Share this post


Link to post
Share on other sites

Добрый день!

Спасибо коллегам, которые помогли решить проблему до нашего участия. Выглядит так, что проблема была действительно связана с выравниванием стека. Мы обновим процедуру сохранения контекста в наших примерах, спасибо за указание на проблему. 

Предполагаемый обновленный обработчик прилагаем. Там также добавлен сброс кэша, сохранение части регистров CP0 и некоторые другие вещи. Если планируется работать с float/double - нужно также сохранять в обработчике регистры FPU. Пока мы этого не добавили в обработчик, чтобы не перегружать его. Возможно, добавим.

Если кому-то интересна причина, почему сейчас такое сохранение контекста в примерах, то даём пояснение: он создавался достаточно давно, когда в наших чипах CPU-ядро не имело сопроцессора FPU. Соответственно, у CPU не было 64-разрядных обращений в память, только 32-разрядные (инструкции LW/SW) - и выравнивания по 32-разрядному слову было достаточно. С появлением FPU появились 64-разрядные обращения (SDC1/LDC1) - появилась необходимость выравнивать стек по границе 64-разрядного слова. Но поскольку примеры в составе IDE демонстрируют узконаправленную работу с конкретным блоком - в примерах этой проблемы не всплывало. Теперь обновим, еще раз спасибо за указание на проблему.

hb80000180.s

Share this post


Link to post
Share on other sites

Тем не менее проблема сохранилась, но уже более сложно диагностируемая. Опять появляется ошибка, но теперь - Address Save и указывает на адреса 0x0000****. Пока пытаюсь найти, что вызывает эту ошибку. Проявляется достаточно редко. 

Попробую добавить так же и сохранение регистров FPU

Share this post


Link to post
Share on other sites

1) Включено ли кэширование в Вашем проекте? Если включено - то сбрасывается ли кэш в обработчике прерываний?

2) Вероятно, стоит сразу указывать, какое значение у регистра CP0.EPC при возникновении исключения? Что за код находится по этому адресу?

Share this post


Link to post
Share on other sites
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

 

 

Share this post


Link to post
Share on other sites

Тут сложный момент. С одной стороны, правильнее сохранять все регистры. С другой стороны, кэш надо сбрасывать сразу при входе в обработчик.

Здесь нам на помощь приходит MIPS ABI (application binary interface) - соглашение, по которому регистры k0, k1 используются именно что в обработчиках, а в основной программе не используются. Поэтому мы вроде бы безбоязненно можем "портить" эти регистры. По факту GCC по умолчанию это требование не выполняет и вполне может использовать эти регистры. Чтобы он этого не делал, есть ключ -ffixed. В наших проектах для MCStudio 4 как раз по умолчанию выставлены ключи GCC " -ffixed-k0 -ffixed-k1". Возможно, их по какой-то причине нет в Вашем проекте? Покажете лог сборки на всякий случай?

 

Еще как вариант - может, просто где-то что-то не так с сохранением и восстановлением стека? В какой-то момент он сдвигается за границы допустимого и все портится? Или, совсем уж простое - размер стека физически "вылезает" за границы доступной физически памяти? Чему равно значение sp в момент исключения? Чему равно значение символа _stack и размер стека в настройках проекта?

 

В функции действительно ничего криминального нет.

Edited by ELVEES R&D Center

Share this post


Link to post
Share on other sites
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)

 

Share this post


Link to post
Share on other sites

1) Значение указателя стека в пределах, но как-то очень уж маленькое. Верхушка стека, выходит, 0x9802_0000, а указатель сдвинут на 0x18 байт. Маловато как-то. Вход в каждую функцию сдвигает указатель стека еще немного вниз относительно верхушки. Если исключение происходит, когда мы находимся в main(), то выглядит нормой, а если хоть немного "глубже" в функциях - то уже нет. Пока выглядит лишним аргументом в пользу некорректного восстановления контекста. Можно поставить точки останова перед сохранением и после восстановления контекста, убедиться, что значение sp не меняется. Ну и надо понять, какое штатное значение указателя стека при штатном входе в функцию, из которой происходит исключение.

2) По логу сборки вроде особо нечего пока сказать.

3) По коду после ERET - штатно он действительно не исполняется. Введён из каких-то соображений, которые сейчас нет смысла уточнять, а навскидку вспомнить не получается. Это скорее всего никак не связано с обсуждаемой проблемой.

Share this post


Link to post
Share on other sites

Причину падения нашёл.  Её вызывает эта строчка  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)

 

 

Share this post


Link to post
Share on other sites

Судя по приведенным кускам дизассемблера в конце, тут вопрос не к процессору, а к компоновке программы. Потому что обе записи происходят по адресу (0x8002_0000-10440). По какой-то причине при сборке обоим символам назначаются одинаковые адреса.  Процессор лишь исправно выполняет запись по неправильно указанному адресу, что в симуляторе, что на живом  чипе :)

Я бы сказал, что MAP-файл тут малоинформативен. Можете дать ELF-файл или (лучше) проект целиком? Можно на support@elvees.com.

Share this post


Link to post
Share on other sites

Попробую упростить проект и перешлю.

Но описание структуры и обращение к ней у меня правильно реализовано ? Или я что то не так понял и делаю недопустимые действия ?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this