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;
};
}
In the example I create a variable of the type Request (same as in my main application). This is initialized with my desired data. Then I'll call one of the following methods, which only creates a new variable on stack.
- void createUInt16Stack()
- void createUInt32Stack()
In the UInt16 case, everything is fine, but in the UInt32 case occures the problem.
UInt16 case:
In the following image, you see the stack after the initialisation of the request variable. The blue marked is the request variable. The red circeled the address where the data of request.buffer are saved (0x0000).
After i call the methode, createUInt16Stack(), this new created variable is one address behind (red font 0xFDE8) the last data of the request. So everything is fine.
UInt32 case:
In the following image, you see the stack after the initialisation of the request variable. The colors here mean the same thing.
After i call the methode, createUInt32Stack(), this new created variable is at the same address as the last data of the request and one behind. What happens: the new variables value is now part of my request values (0x8488), because it writes at the same address.
In my main application I have the same problem, only that the addresses are shifting even further and it has much more thinks to do. I suspect that the same problem is underlying this but I don't know why this is happening.