C 内存缓冲区破坏微 Controller 内存分配 - Atmel ATxmega

标签 c memory memory-management atmel

我正在使用 ATxmega128A1 8 位微 Controller ,我试图找出为什么我的内存缓冲区表现异常。

我有一个具有以下结构的 FIFO 缓冲区:

typedef struct
{
  FIFOid ID;                        //ID value to determine the type of FIFO being used
  BOOL LOCK;                        //A lock to prevent multiple FIFO accessing (i.e. data corruption)
  UINT16 Start, End;                //Value of the current start and end FIFO index
  UINT16 volatile NbBytes;          //Number of bytes currently inside the FIFO
  UINT8 Buffer[FIFO_SIZE];          //Memory buffer for the FIFO buffer
} TFIFO;

我定义了 2 个 FIFO:

//FIFO Buffers for USART
TFIFO RxFIFO;           //Creates the Receive FIFO
TFIFO TxFIFO;           //Creates the Transmit FIFO

FIFO_SIZE 的位置

#define FIFO_SIZE 256       

当我想从 Buffer[] 获取一个字节时,我通过此函数传递一个指向 FIFO 的指针:

BOOL FIFO_Get(TFIFO * const FIFO, UINT8 * const dataPtr);

但是,一旦我将 FIFO_SIZE 增加到约 510 字节以上,此方法就可以正常工作 - 通过此函数传递此 FIFO 指针会导致我的另一个 FIFO 缓冲区发生更改。

我在我的调试器上看到,这一行没有问题:

if(FIFO_Get(&TxFIFO, &data)){       //Get a byte from TxFIFO

一旦我跨过,并将其传递给函数,RxFIFO->Buffer[] 数组就会被修改,即较大的地址值。 FIFO_Get函数:

// ----------------------------------------
// FIFO_Get
// ----------------------------------------
// Remove one character from the FIFO
// Input: 
//   FIFO is a  pointer to a FIFO struct with data to be retrieved
//   dataPtr is a pointer to a memory location to place the retrieved byte
// Output:
//   TRUE if the operation was successful and the data is valid
// Conditions:
//   Assumes that FIFO_Init has been called

BOOL FIFO_Get(TFIFO * const FIFO, UINT8 * const dataPtr)
{
    BOOL FIFOGetSuccess;
    FIFOGetSuccess = bFALSE;

    //disable interrupts
    //if we're GETTING from the USART receive FIFO
    //we need to disable the receive interrupt so
    //there is no data being 'Put' during a 'Get'
    if(FIFO->ID == URX){
        USARTD0.CTRLA = USART_RXCINTLVL_OFF_gc; //Rx interrupts off
        USARTD1.CTRLA = USART_RXCINTLVL_OFF_gc; //Rx interrupts off
    }

    //Attempt to get a byte from the FIFO
    if(FIFO->LOCK == bFALSE){                           //Check that the FIFO is not locked
        FIFO->LOCK = bTRUE;                             //lock the FIFO
        if (FIFO->NbBytes == 0){                        //Checks whether FIFO is empty; number of bytes in FIFO = 0
            FIFOGetSuccess = bFALSE;                    //If empty, false is Returned
        }else{
            *dataPtr = FIFO->Buffer[FIFO->Start];       //Reads the byte in the FIFO start position, and saves it to the location of the data pointer
            if (FIFO->Start == (FIFO_SIZE - 1)){        //Checks whether the start position is equal to FIFO size, the last valid 8 bit number
                FIFO->Start = 0;                        //If so, the position is set to 0
            }else{                                      //If not fifo size;
                FIFO->Start++;                          //Increments the start position by 1
            }
            FIFO->NbBytes--;                            //Decrements the number of bytes in the FIFO by 1
            FIFOGetSuccess =  bTRUE;                    //Returns true if this is successful
        }
        FIFO->LOCK = bFALSE;                            //unlock the FIFO
    }

    //re-enable interrupts
    if(FIFO->ID == URX){
        USARTD0.CTRLA = USART_RXCINTLVL_LO_gc;  //low level interrupts on Rx
        USARTD1.CTRLA = USART_RXCINTLVL_LO_gc;  //low level interrupts on Rx        
    }

    return FIFOGetSuccess;
}

我的猜测是,我没有在微 Controller 中安全地分配内存,但是在构建之后,芯片中似乎还留有足够的内存:

        Program Memory Usage    :   21460 bytes   15.4 % Full
        Data Memory Usage       :   6967 bytes   12.1 % Full

我该如何解决这个问题以及我做错了什么?

编辑:

我发现增加 FIFO SIZE 会将 FIFO 缓冲区映射到 SRAM 地址范围(ATxmega128A1 的 SRAM 从 0x2000 到 0x3FFF)

FIFO address mapping

当另一个 FIFO 通过函数传递时,地址 0x3FF7 到 0x3FFF 正在发生变化

编辑2: Elf Files

最佳答案

从ELF文件中,我可以看到这个内存映射:

00802000 B __bss_start
00802000 D __data_end
00802000 D __data_start
00802000 D _edata
00802000 00000002 b n.4418
00802002 00000001 b packetEnd.1686
00802003 00000002 b byteCount.1684
00802005 00000002 b StepsCounted.4253
00802007 00000001 b ErrorCode.4252
00802008 00000001 b SuccessNb.4251
00802009 00000001 b ReturnNb.4250
0080200a 00000004 b stepsOutOpto.4211
0080200e 00000004 b HomingError.4212
00802012 00000008 b stepscounted.4210
0080201a 00000004 b CntHomeState.4209
0080201e 00000001 b byteCount.4166
0080201f 00000002 B EjectMsgID
00802021 00000001 B VersionMinor
00802022 00000002 B QueueEnd
00802024 00000001 B VersionMonth
00802025 00000001 B ACC1_IN
00802026 0000001f B PacketQRx
00802045 0000001f B PacketTx
00802064 00000001 B VersionMajor
00802065 00000001 B DeviceTypeId
00802066 00000001 B debugCycler_bytes
00802067 00000001 B debugAXIS_ACK
00802068 000000d4 B AXIS
0080213c 00000001 B LVL_SENSE_IN
0080213d 00000001 B LID_DETECTION_ON
0080213e 00000001 B readyimmediateTx
0080213f 0000001f B PacketQTx
0080215e 00000004 B RobotSerialNumber
00802162 00000001 B USBIN
00802163 00000001 B startupComplete
00802164 000007c0 B PacketQueue
00802924 0000001f B PacketRx
00802943 00000001 B ACC2_IN
00802944 00000002 B QueueNb
00802946 00000001 B QueuedCommandCalled
00802947 0000001f B dummyPkt
00802966 00000001 B CYCLER_IN
00802967 00000002 B QueueStart
00802969 00000001 B HardwareRevision
0080296a 00000001 B VersionYear
0080296b 00000980 B AXISRxFIFO
008032eb 00000004 B RTS
008032ef 00000980 B AXISTxFIFO
00803c6f 00000068 B AXIS_SPI_Tx_Packet
00803cd7 00000004 B ReturnPacketMissed
00803cdb 00000068 B AXIS_SPI_Rx_Packet
00803d43 00000004 B NbPacketsInAxisFIFO
00803d47 00000100 B CyclerEEPROM
00803e47 00000260 B TxFIFO
008040a7 00000260 B RxFIFO
00804307 B __bss_end

注意:我获得此 map 的方式是使用 nm 和命令 nm -S -n MotorBoard\Xmega\Large\FIFO.elf。第一列是地址,第二列是变量的大小。

ATMEL ATxmega128A1 Datasheet表示您在 0x20000x3FFF 之间有 8KB SRAM。正如您所看到的,您的两个 FIFO 缓冲区都重叠了 0x3FFF 限制(TxFIFO0x3E470x40A7 >RxFIFO)。

解决问题的一种方法是将某些变量声明为 const,将其移至 ROM 中。例如,我可以看到 VersionMonthVersionMajor 可能是恒定的。

关于C 内存缓冲区破坏微 Controller 内存分配 - Atmel ATxmega,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44381487/

相关文章:

objective-c - 如何在 iOS/Cocoa 中找到集合对象的内存占用

java - 在java中从c读取长字节

c - 最高有效半字节的十六进制

c++ - 作为微优化,是否值得用 C 而不是 C++ 编写部分代码?

c - 在 FPGA 设备上编程

java - JDOM需要多少 "overhead"内存来生成XML文件?

c - 分配时为空*

c++ - 内存访问回调?

java - 两个内容相同的字符串会存储在同一个内存位置吗?

java - 从静态 Map 中删除对象时是否会收集垃圾?