Инициализируя пустой массив с плавающей точкой [512][4] равным 0, некоторые строки получают произвольные значения, такие как "nan или 1.6114932340e-43"
Env: Linux Ubuntu, кросс-компиляция с использованием gcc-arm-none-eabi-5_2-2015q4, работающей на ARM v7. NXP I.MX6 mcu, сабельный комплект. Одноядерный. Код компилируется и запускается без ошибок, но вывод неправильный.
Я выделил код следующим образом:
#include "sdk.h"
#include <float.h>
#include "filesystem/include/types.h"
#include <math.h>
#include "uart/imx_uart.h"
#include "uart/config/uart_config.h"
#include "algorithm/src/twodimprint.h"
#include "timer/epit.h"
#include "timer/timer.h"
#include "core/cortex_a9.h"
#include "core/mmu.h"
#include "registers/regsuart.h"
#define AMOUNT_X_COLUMNS 512
#define AMIN 4
int main(void)
{
enable_neon_fpu();
/* Initialize the UART port */
uart_init(uart_instance, 115200, PARITY_NONE, STOPBITS_ONE, EIGHTBITS, FLOWCTRL_OFF);
/* Set the IRQ mode for the Rx FIFO, OBS CURRENTLY DISABLED */
uart_set_FIFO_mode(uart_instance, TX_FIFO, 0, IRQ_MODE);
int i;
static float derivatives[512][AMIN];
char str1[140];
for (i = 0; i< 512; i++){
derivatives[i][0] = 0;
derivatives[i][1] = 0;
derivatives[i][2] = 0;
derivatives[i][3] = 0;
}
for(i=0; i < 512; i++){
sprintf(str1, "dvt[%d] |[0]|[1]|[2]|[3] = |%.2e | %.2e | %.2e | %.2e \n\r ", i, derivatives[i][0], derivatives[i][1] , derivatives[i][2], derivatives[i][3] );
uartWriteString(str1);
}
while(1)
{
}
return 0;
}
Вывод выглядит примерно так при интеграции в систему. Однако прочитайте комментарии ниже
dvt[482] |[0]|[1]|[2]|[3] = |0.00e+00 | 0.00e+00 | 0.00e+00 | 0.00e+00
dvt[483] |[0]|[1]|[2]|[3] = |0.00e+00 | 0.00e+00 | 0.00e+00 | 0.00e+00
dvt[484] |[0]|[1]|[2]|[3] = |0.00e+00 | 0.00e+00 | 0.00e+00 | 1.40e-45
dvt[485] |[0]|[1]|[2]|[3] = |-2.78e+11 | 2.56e-29 | 2.56e-29 | 2.56e-29
dvt[486] |[0]|[1]|[2]|[3] = |2.57e-29 | 2.57e-29 | 0.00e+00 | nan
dvt[487] |[0]|[1]|[2]|[3] = |1.60e-43 | 0.00e+00 | 4.20e-45 | 2.58e-29
dvt[488] |[0]|[1]|[2]|[3] = |4.06e-44 | 2.58e-29 | 0.00e+00 | 4.06e-44
dvt[489] |[0]|[1]|[2]|[3] = |1.40e-45 | 0.00e+00 | -1.43e+01 | 2.25e+00
dvt[490] |[0]|[1]|[2]|[3] = |4.20e-45 | 0.00e+00 | 3.69e+19 | 2.03e+00
Этот вывод не является выводом из этого кода выше. Приведенный выше код не дает неправильных значений массива, хотя код такой же, как при интеграции в систему.
Я не могу воспроизвести ошибку, не рассматривая всю систему как проблему, потому что это не код, это что-то еще, что мешает. Поэтому я хотел бы получить советы от людей, которые раньше работали со встроенным дизайном, чтобы помочь мне оценить, что потенциально может нарушить работу массива.
Поскольку это голое приложение, использующее NXP SDK, здесь это "startup.S"
/*!
* @file startup.s
* @brief this file contains startup code with support for multi-core startup
*/
#include "asm_defines.h"
// External symbol references
.global top_of_stacks
.global vectors
.global __ram_vectors_start
.global __ram_vectors_end
.global __bss_start__
.global __bss_end__
.global main
.global _sys_exit
.code 32
.section ".startup","ax"
.global _start
.func _start
.fnstart
_start:
@ save r0 for cores 1-3, r0 arg field passed by ROM
@ r0 is a function pointer for secondary cpus
mov r4, r0
@ clear some registers
mov r11,#0
mov r12,#0
mov lr,#0
ldr r0, =top_of_stacks @ symbol defined in linker file
mov r1, #EXCEPTION_STACK_SIZE
@ get cpu id, and subtract the offset from the stacks base address
mrc p15,0,r2,c0,c0,5 @ read multiprocessor affinity register
and r2, r2, #3 @ mask off, leaving CPU ID field
mov r5, r2 @ save cpu id for later
mul r3, r2, r1
sub r0, r0, r3
mov r1, r1, lsl #2
@ set stacks for all other modes
msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
msr CPSR_c, #MODE_IRQ | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
msr CPSR_c, #MODE_ABT | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
msr CPSR_c, #MODE_UND | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
@ Set SVC mode stack with interrupts disabled
msr CPSR_c, #MODE_SVC | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
@ check cpu id - cpu0 is primary cpu
cmp r5, #0
beq primary_cpu_init
bx r4 @ for secondary cpus, jump to argument function pointer passed in by ROM
@ control should not return from the secondary cpu entry point
b startup_exit
primary_cpu_init:
/*
* copy the vector table into the RAM vectors
* this assumes that the RAM vectors size is divisible by 3 words (12 bytes)
*/
ldr r1,=__ram_vectors_start
ldr r2,=__ram_vectors_end
ldr r3,=vectors
1: cmp r1,r2
ldmlt r3!,{r4,r5,r6}
stmlt r1!,{r4,r5,r6}
blt 1b
/*
* fill the stacks with a pattern
* the stack must be 8 byte aligned
*/
ldr r1,=__stacks_start @ stack region start address
ldr r2,=top_of_stacks @ stack region end address
bic r2,r2,#0x7 @ round length down to nearest 8 byte alignment
ldr r3,=.Ldeadfeed @ get fill pattern address
ldr r3,[r3] @ read fill pattern into r3
mov r4,r3 @ copy fill pattern to r4
1: cmp r1,r2 @ the fill loop
stmltia r1!,{r3-r4}
blt 1b
/* init .bss */
/* clear the .bss section (zero init) */
ldr r1,=__bss_start__
ldr r2,=__bss_end__
mov r3,#0
1: cmp r1,r2
stmltia r1!,{r3}
blt 1b
@ take care of C++ static initialization. this won't cause any harm for plain C apps.
ldr r12,=__libc_init_array
blx r12
@ branch to c library entry point
mov r0,#0 @ argc
mov r1,#0 @ argv
mov r2,#0 @ env
ldr r12, =main /* save this in register for possible long jump */
blx r12 /* branch to __main */
@ if either main() or the secondary cpu entry point return, which they should not,
@ then call _sys_exit().
startup_exit:
mov r0,#0
ldr r12,=_sys_exit
bx r12
.cantunwind
.fnend
.endfunc @ _start()
/* local label for the stack fill pattern */
.Ldeadfeed:
.word 0xdeadfeed
.end