Reputation:
I am writing code for a serial communication gateway using MSP430F2619 with Code Composer Studio 6.1.
The gateway has two different modes of operation:
Master this is the default mode. It will poll the data as the bus master on a RS485 bus and then send it to another board with a different protocol.
Slave in which it responds to a PC application on Serial port.
The program will be either in master or slave mode as same RS-485 bus is shared between PC application and other slave boards.
Rather than using 2 different memory buffers for each mode, I am trying to figure out whether same physical memory can be used by both buffers.
I tried to search on memory overlay feature of Code Composer Studio without success.
Essentially, I have this:
char Slaverxbuffer[2048];
char Masterrxbuffer[2048];
I want both of these buffers to share the same memory so that I will use 2KB memory instead of 4KB.
So I need a way for Slaverxbuffer
and Masterrxbuffer
to use the same memory area, something like:
char Sharedbuffer[2048];
Upvotes: 5
Views: 359
Reputation:
If, as you say, you don't want a union, you could just have a single buffer, and a separate variable to log which mode you are in?
char rxBuffer[2048];
bool rxMode; // false = master, true = slave
This way you can have the buffer in a fixed memory location (defined by the linker) and link to the buffer
Upvotes: 4
Reputation: 10918
Could you just have a single buffer and share it between the two modes of operation? That would probably be the simplest solution.
Otherwise, in C and C++, you can accomplish this by having the two buffers be fields in a union type. Each of the members in the union has the same base address in memory, and the overall size of the union is the size of the largest member.
The code would look something like this:
union OverlaidBuffer
{
char Slaverxbuffer[2048];
char Masterrxbuffer[2048];
};
union OverLaidBuffer overlay;
/* Code to use the slave buffer */
for(unsigned int index = 0; index < 2048; ++index)
{
overlay.Slaverxbuffer[index] = some_slave_value();
}
/* Code to use the master buffer */
for(unsigned int index = 0; index < 2048; ++index)
{
overlay.Masterrxbuffer[index] = some_master_value();
}
Note that you if you use a union, you should always read from the member that you most recently wrote to. Writing to one member, then reading from another is undefined behavior, and is likely to result in buggy code. For example, the code:
overlay.Slaverxbuffer[i] = 1;
overlay.Masterrxbuffer[i] = 2;
x = overlay.Slaverxbuffer[i];
may well set x
to 1 since that's “obviously” the last value stored in overlay.Slaverxbuffer[i]
, even though that memory address now contains the value 2.
Another way to accomplish this is to use compiler and linker directives to place the two buffers at specific locations in memory. Most embedded toolchains will allow you to do this via a #pragma
directive in the source code. The exact format of the directive will depend on the particular toolchain; a couple of examples are below.
TI Code Composer Studio (reference MSP430 Optimizing C/C++ Compiler User's Guide)
#pragma DATA_SECTION(Slaverxbuffer, "some_section")
char Slaverxbuffer[2048];
IAR Embedded Workbench (reference IAR C/C++ Development Guide)
#pragma section = "some_section"
char Slaverxbuffer[2048];
Then in the linker file, add directives to place the symbol at a specific location:
TI Code Composer Studio (reference MSP430 Assembly Language Tools User's Guide)
SECTIONS
{
.some_section : load = 0x12345678
}
IAR Embedded Workbench (reference IAR C/C++ Development Guide)
place at address mem:0x12345678 { readwrite section some_section };
Upvotes: 10