Alignment of a CAN Buffer in memory for C++ project

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Alignment of a CAN Buffer in memory for C++ project

Jump to solution
1,760 Views
brian_ungar
Contributor III

The SDK for the LPCXpresso54S018 comes with an example called mcan_interrupt_transfer. It is an mcan example under the set of driver_examples. The example is written in C. I am using this example as a basis to create a C++ application that does something similar.

In the example, there is the following line of code:

SDK_ALIGN(uint8_t msgRam[MSG_RAM_SIZE], 1U << CAN_MRBA_BA_SHIFT) = {1U};

This is aligning the CAN message RAM to 0x10000.

When I specify the same line of code in my C++ code, the variable appears to locate to address zero. However, in the file fsl_mcan.h there is the following code:

static inline void MCAN_SetMsgRAMBase(CAN_Type *base, uint32_t value)
{
assert(((value >= 0x20000000U) && (value <= 0x20027FFFU)) || ((value >= 0x04000000U) && (value <= 0x04007FFFU)));

base->MRBA = CAN_MRBA_BA(value >> 16U);
}

This code causes an error to be asserted because of the address of the CAN message buffer.

I have tried using the following statement instead to align the message buffer, but it still does not put the CAN message buffer into the desired location.

__attribute__((aligned(1U << CAN_MRBA_BA_SHIFT), section(".bss_RAM2"))) uint8_t msgRam[MSG_RAM_SIZE] = {1U};

.bss_RAM2 appears to be a valid memory section from my load map and it resides at 0x20000000.

 

How to I properly align the CAN message buffer so that the check in MCAN_SetMsgRAMBase does not fail?

0 Kudos
Reply
1 Solution
1,747 Views
brian_ungar
Contributor III

After doing some more investigation, I ended up splitting the RAM area that existed at 0x20000000 into two parts (RAM2 and RAM3). This was done by editing the memory settings under the Project Settings of the project in the MCUXpresso IDE. RAM2 starts at 0x20000000 and RAM3 starts at 0x20010000. I then found a different MACRO to use instead of the SDK_ALIGN. This was the __DATA MACRO in (#include <cr_section_macros.h>). Instead of using SDK_ALIGN, the code is now:

__DATA(RAM2) uint8_t msgRamCan0[MSG_RAM_SIZE];

__DATA(RAM3) uint8_t msgRamCan1[MSG_RAM_SIZE];

This change now satisfies the bounds checking being done in MCAN_SetMsgRAMBase and creates two different arrays that are aligned on a 0x10000 boundary.

This issue can now be closed.

View solution in original post

0 Kudos
Reply
2 Replies
1,748 Views
brian_ungar
Contributor III

After doing some more investigation, I ended up splitting the RAM area that existed at 0x20000000 into two parts (RAM2 and RAM3). This was done by editing the memory settings under the Project Settings of the project in the MCUXpresso IDE. RAM2 starts at 0x20000000 and RAM3 starts at 0x20010000. I then found a different MACRO to use instead of the SDK_ALIGN. This was the __DATA MACRO in (#include <cr_section_macros.h>). Instead of using SDK_ALIGN, the code is now:

__DATA(RAM2) uint8_t msgRamCan0[MSG_RAM_SIZE];

__DATA(RAM3) uint8_t msgRamCan1[MSG_RAM_SIZE];

This change now satisfies the bounds checking being done in MCAN_SetMsgRAMBase and creates two different arrays that are aligned on a 0x10000 boundary.

This issue can now be closed.

0 Kudos
Reply
1,750 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

 Based on the MCUXpresso ver11.x tools and mscan_interrupt_transfer example in SDK package of LPC54018, with the code:

#define MSG_RAM_SIZE 1024

volatile bool txComplete = false;
volatile bool rxComplete = false;
mcan_tx_buffer_frame_t txFrame;
mcan_rx_buffer_frame_t rxFrame;
uint8_t tx_data[CAN_DATASIZE];
uint8_t rx_data[CAN_DATASIZE];
mcan_handle_t mcanHandle;
mcan_buffer_transfer_t txXfer;
mcan_fifo_transfer_t rxXfer;
uint32_t txIdentifier;
uint32_t rxIdentifier;
SDK_ALIGN(uint8_t mmsgRam[MSG_RAM_SIZE], 1U << CAN_MRBA_BA_SHIFT) = {1U};

after compiling/linking,The mmsgRAM[] array is distributed tom 0x2000_0000, the txIdentifier variable is located at 0x2000_0620, obviously, the compiler is  wrong to allocate the variable.

For the line SDK_ALIGN(uint8_t mmsgRam[MSG_RAM_SIZE], 1U << CAN_MRBA_BA_SHIFT) = {1U};

the mmsgRam[] array must be allocated with 64K Byte boundary, so I suppose the compiler is not capable to handle so large range.

As a workaround, you have to allocate an absolute memory space for the mscan memory with 64K byte boundary such as 0x2000x_0000, which will not overlap with stack, global variable space, heap and bss, as the mscan example has done.

Hope it can help yuou

BR

XiangJun Rong

 

xiangjun_rong_1-1661318766421.png

 

 

0 Kudos
Reply