1

我正在经历变量随机变化的极其奇怪的行为。

我将其提炼为最简单的示例,encoder_1_position并使用函数encoder_2_position内的随机值进行更新 NVIC_SetPriority(UART_IRQn,2);。我已经对文件中的全局变量的声明进行了重新排序,我注意到它对于添加什么/是否添加垃圾会有所不同。我在链接器命令中禁用了“删除未使用的部分”,它似乎解决了问题(显然 BSS 部分被丢弃了),但我不明白为什么,特别是因为我拥有的每个全局变量都是用 volatile 声明的。

将缓冲区大小从 1000 减少到 100 似乎可以纠正编码器变量的随机变化,但我不相信这是一个实际的修复,也不应该是必需的。SAM3X8E 有 65kbytes 的内存——无论如何堆栈都不会溢出。

#include "sam.h"

#define HEAP_SIZE 0x500
#define STACK_SIZE 0x3500

int encoder_1_position = 0;
int encoder_2_position = 0;

void IntializeWatchdogTimer(void)
{
    // disable watchdog timer
    WDT->WDT_MR =  WDT_MR_WDDIS;
}

void InitializeUart(void)
{
    PMC->PMC_PCER0 = PMC_PCER0_PID8;// ID_UART 8
    // baud rate is 84Mhz/(16*45) = 116667
    UART->UART_BRGR = uint32_t(45);
    // set to no parity
    UART->UART_MR = UART_MR_PAR_NO;
    // Enable transmit and receive
    UART->UART_CR = UART_CR_TXEN|UART_CR_RXEN;
    // Enable UART control of port A pin 8, 9
    PIOA->PIO_PDR = PIO_PER_P8|PIO_PER_P9;
    // Enable UART interrupt on RX RDY
    UART->UART_IER = UART_IER_RXRDY;
    
    // Set priority
    NVIC_SetPriority(UART_IRQn,2);
    NVIC_EnableIRQ(UART_IRQn);
}




int main(void)
{
    __disable_irq();
    IntializeWatchdogTimer();
    SystemInit();
    InitializeUart();
    __enable_irq();
    /* Initialize the SAM system */
    
    //char* RX_message;
    char TX_message[1000];
    
    while (true)
    {
        int a = encoder_1_position;
        int b = encoder_2_position;
    }

}

自述输出:

Elf file type is EXEC (Executable file)
Entry point 0x80000
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x010000 0x00080000 0x00080000 0x02a58 0x02a58 R E 0x10000
  LOAD           0x020000 0x20000000 0x00082a58 0x001d4 0x00808 RW  0x10000

 Section to Segment mapping:
  Segment Sections...
   00     .text
   01     .relocate .bss .stack .heap
4

1 回答 1

2

我在链接器命令中禁用了“删除未使用的部分”,它似乎解决了问题(显然 BSS 部分被丢弃了)

这只是一个猜测,但这可能意味着您的程序加载器没有正确处理 BSS 部分。它应该分配链接器分配给 BSS 的内存区域并将其归零,即使没有可从可执行映像复制到该范围的位。(它比这更复杂一点,但除非你自己编写加载程序,否则应该给你足够的想法。)

但我不明白为什么特别是因为我拥有的每个全局变量都是用 volatile 声明的。

volatile不做你认为它做的事。更详细。)

于 2022-01-10T00:58:53.520 回答