0

During the setup of a CAN transmission, a Pointer is being corrupted (it goes from a valid 0x00000bd0 to a 0x84520000 that is out of the bounds of my RAM). The pointer is also unrelated to the CAN activity. The reason for the corruption is, that a union64 is written over the address of the pointer. This union64 belongs to the CANIF object (from ASF), in sourcecode the corruption happens here:

void CAN_SendMsg_KMS(uint64_t msg)
{
    CANIF_mob_get_ptr_data(ACTIVECHANNEL,0)->data = (Union64)msg;
    AVR32_CANIF.channel[ACTIVECHANNEL].mober = 1<<0;
}

My question is, why is the memory for "data" allocated at the same address as my pointer? Or is this a wrong conclusion?

In the following screenshots, the first is immediately before the function is executed, the last is immediately after execution. The Content of "msg" is 0x8452000000000000. The content of the pointer A that is corrupted should be 0x00000bd0, as it is before the corruption happens. The 32Bit integer after the pointer A is pointer B, pointer B is pointing at pointer A, its uncorrupted content is therefore 0x00000004 (as seen in the screenshot).

Memory before corruption

Memory after corruption

I don't know if this is a useful information: According to the Datasheet the CANIF registers are at Memory address 0xFFFD1C00.

update: This is the assembly level code that corrupts the pointer:

//CANIF_mob_get_ptr_data(ACTIVECHANNEL,0)->data = (Union64)msg;

80006AC8  mov R8, -189440        
80006ACC  ld.w R9, R8[8]         
80006ACE  st.d R9[8], R5
Clifford
  • 88,407
  • 13
  • 85
  • 165
anyone
  • 157
  • 7
  • Single-step the call at the assembly level. Are you sure your target supports 64-bit integers? – unwind Apr 13 '17 at 09:07
  • Look at the update, st.d is a 64 Bit assembly operation. It seems as if everything is ok. There are two 32 Bit movements to registers and then one 64 Bit write. But its the wrong location after all. – anyone Apr 13 '17 at 09:34
  • The union cast kind of defeats the purpose of using a union in the first instance. Use: `CANIF_mob_get_ptr_data(ACTIVECHANNEL,0)->data.u64 = msg;` - not a solution, just a comment. – Clifford Apr 13 '17 at 10:46
  • It is not clear what pointer you are talking about in the context of the code fragment posted. `CANIF_mob_get_ptr_data()` is a macro defined in terms of yet another nacro that generates an address from contents of a CAN I/F register (`AVR32_CANIF.channel[ch].canramb`). Good luck debugging that, but it relies on a valid value in `canramb` presumably. So earlier initialisation may be at fault. – Clifford Apr 13 '17 at 10:56
  • I do not know AVR32 and whether it has invalid address exception, but if not, when you write to an invalid address, the high-order bits not in the address range will be ignored and the address will resolve to a real address of non-deterministic location. So my bet is still on the macro returning an invalid address because the CAN I/F is not configured correctly. Essentially the error is elsewhere in your code, not in the code you have posted - so a definitive answer is not possible from the information given. Look at the CAN register values and whatever `canramb` references. – Clifford Apr 13 '17 at 11:07
  • AVR32_CANIF_CANRAMB is teh RAM base address register. I imagine it is invalid. – Clifford Apr 13 '17 at 11:17
  • @Clifford you are right. It was a false initialization of canramb! I put a function at the top of my main that initialized all uninitialized variables. Unfortunately this function needed a CAN communication... So Damage done, If you formulate your thoughts in an answer, I'll mark it as solution. – anyone Apr 13 '17 at 12:16

1 Answers1

0

In the line:

CANIF_mob_get_ptr_data(ACTIVECHANNEL,0)->data = (Union64)msg;

CANIF_mob_get_ptr_data is a macro yielding a structure pointer, defined according to the documentation as:

#define CANIF_mob_get_ptr_data( ch, mob ) ((can_msg_t *)(CANIF_SIZE_OF_CANIF_MSG*mob+CANIF_get_ram_add(ch)))

In turn the macro CANIF_get_ram_add is a macro returning the address contained in the CAN interface register CANRAMB:

#define CANIF_get_ram_add(ch) ( AVR32_CANIF.channel[ch].canramb )

So if AVR32_CANIF_CANRAMB is not previously initialised, or incorrectly initialised, the pointer returned by CANIF_mob_get_ptr_data will not be valid, and the subsequent assignment will fail.

Even if the resolved address is invalid, the typical effect of such an access in the absence of any kind of hardware memory protection is to "wrap" the address so that it resolves to a non-deterministic real address - so corrupts unrelated memory.

Clifford
  • 88,407
  • 13
  • 85
  • 165