This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28388D:堆栈会覆盖我稍后需要的数据

Guru**** 2614265 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1010540/tms320f28388d-stack-overwrites-my-data-that-will-be-needed-later

器件型号:TMS320F28388D

I am currently developing the SPI communication between CPU1 and an ADC converter.

When calling a method (was called multiple times in a do while, in my scenareo 2 times), I always have the problem, that in the second call of the methode in the return data on the stack is interpreted as return addresses and i land somewhere in the memory after this return. As result of this, it runs in an ESTOP0 with illegal operation interrupt.

 

I broke the problem down as far as possible, because it is to much code to show here. But I still have an problem on the stack. I suspect that the same problem is underlying this but I don't know why this is happening.

#define SYSTEM_STATUS_REGISTER_ADDRESS 0x0

#define NO_COMMAND        0x0
#define READ_COMMAND      0x10

typedef unsigned char UInt8;
typedef unsigned int UInt16;


void createUInt16Stack()
{
    uint16_t test = 65000;
}

void createUInt32Stack()
{
    uint32_t test = 165000;
}




enum Command
{
    /// a write command shall be performed, i.e. send data to device.
    /// (everything without a response from device)
    COMMAND_WRITE,
    /// a read command shall be executed, i.e. receive data from device.
    COMMAND_READ,
    /// the spi response shall be compared with a buffer
    COMMAND_COMPARE,
};

struct Buffer
{
    UInt16 *data;
    UInt16 lengthBytes;
};

struct Request
{
    Command command;
    UInt16 bytesSent;
    UInt16 bytesReceived;
    UInt16 bytesToSend;
    Buffer header;
    Buffer buffer;
};


Buffer getADCHeader(UInt8 command, UInt8 address)
 {
     static UInt16 header[1];
     Buffer buffer;
     header[0] = (command << 8) & 0xFF00;
     header[0] |= (address) & 0xFF;

     buffer.data        = header;
     buffer.lengthBytes = 2;
     return buffer;
 }

Request getReadRegisterRequest(UInt8 address)
{
    Request requestRegister;
    UInt16 readNullBuffer[1];
    readNullBuffer[0] = NO_COMMAND;

    requestRegister.header = getADCHeader(READ_COMMAND, address);
    requestRegister.command = COMMAND_READ;
    requestRegister.buffer.data = readNullBuffer;
    requestRegister.buffer.lengthBytes = 1;
    requestRegister.bytesToSend = 0;
    requestRegister.bytesSent = 0;
    requestRegister.bytesReceived = 0;

    return requestRegister;
}


void main(void)
{
    Request request = getReadRegisterRequest(SYSTEM_STATUS_REGISTER_ADDRESS);
    //createUInt16Stack(); // works correct
    createUInt32Stack(); // override parts of statusRegisterRequest variable

    Buffer data;

    while (true)
    {
        data = request.buffer;
    };
}

在示例中、我创建了类型请求的变量(与主应用程序中的变量相同)。 这是使用我所需的数据进行初始化的。 然后、我将调用以下方法之一、该方法仅在堆栈上创建新变量。

  • void createUInt16Stack()
  • void createUInt32Stack()

在 uint16情况下、一切都正常、但在 uint32情况下可以解决问题。

 


uint16情况:

 

在下图中、您可以在初始化 request 变量后看到栈。 标记的蓝色是请求变量。 红色标记了保存 request.buffer 数据的地址(0x0000)。

在我调用 metode createUInt16Stack()后,这个新创建的变量是请求最后一个数据后面的一个地址(红色字体0xFDE8)。 一切都很好。


uint32情况:

 

在下图中、您可以在初始化 request 变量后看到栈。 这里的颜色意味着相同的东西。

在我调用 metode createUInt32Stack()后,这个新创建的变量与请求的最后一个数据位于同一地址,后面一个地址。 发生什么情况:新变量值现在是我的请求值(0x8488)的一部分、因为它在同一地址写入。

在我的主应用程序中、我有同样的问题、只是地址在进一步移动、而且它有更多的想法要做。 我怀疑同样的问题也是这种情况的根源、但我不知道为什么会发生这种情况。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Christopher、

    很抱歉、我在理解内存视图时遇到了一些问题。 如果我遇到问题、请更正。 蓝色数据是整个请求变量、您圈出的数据是不属于请求结构的不同变量。 此变量(圆圈中的变量)是否在范围内? 请注意、如果在函数中创建局部变量、则会将其分配给栈、但一旦返回该函数、就会消失。 这意味着、该地址可用于新的局部变量。

    最好在 CCS 中共享 Variables 视图。

    此致、

    Veena

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复。

    我圈出的变量是创建缓冲区数据的地址。这意味着我的请求中有一个缓冲区、而在该缓冲区中是指向数据的指针。  在我的请求中、地址0x00000040C 是我的数据地址(0412)。 这是我在堆栈中的位置。

    是的、当然、我立即为您提供变量视图  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    将初始化 Moment 请求。 它们应该是怎样的。

    在堆栈上的新变量之后。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Christopher、

    那么、我的问题是、0x416处的变量分配在哪里? 我在 main 中看不到这一点。 它是否在 getReadRegisterRequest 中作为局部变量分配?

    如果在函数内声明局部变量、则该分配将在函数返回后清除。

    假设当您调用 Function1时、SP (栈指针)位于0x1000。 Function1分配一些局部变量、SP 递增到0x1010。  一旦 Function1返回、SP 被重置回0x1000。 地址0x1000-0x1010现在将打开以分配新的局部变量。  调用 Function2时、其中的局部变量将被分配到地址0x1000之后的位置。

    强烈建议不要让函数返回局部变量的地址。 局部变量的范围在该函数内。

    此致、

    Veena

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Veena 的帮助。 解决了我的测试项目中的问题。 我将尝试将其集成到我的主应用中。